diff --git a/bundle2_resolver/src/resolver.rs b/bundle2_resolver/src/resolver.rs index 3050ed8fcf..3e249650ce 100644 --- a/bundle2_resolver/src/resolver.rs +++ b/bundle2_resolver/src/resolver.rs @@ -73,7 +73,7 @@ pub fn resolve( phases_hint: Arc, readonly: RepoReadOnly, maybe_full_content: Option>>, - _pure_push_allowed: bool, + pure_push_allowed: bool, ) -> BoxFuture { let resolver = Bundle2Resolver::new( ctx.clone(), @@ -144,6 +144,9 @@ pub fn resolve( lca_hint, ) } else { + fn changegroup_always_unacceptable() -> bool { + false + }; resolve_pushrebase( ctx, commonheads, @@ -153,6 +156,7 @@ pub fn resolve( lca_hint, phases_hint, maybe_full_content, + changegroup_always_unacceptable, ) } } else { @@ -163,6 +167,7 @@ pub fn resolve( allow_non_fast_forward, maybe_full_content, lca_hint, + move || pure_push_allowed, ) } }, @@ -177,9 +182,10 @@ fn resolve_push( allow_non_fast_forward: bool, maybe_full_content: Option>>, lca_hint: Arc, + changegroup_acceptable: impl FnOnce() -> bool + Send + Sync + 'static, ) -> BoxFuture { resolver - .maybe_resolve_changegroup(ctx.clone(), bundle2) + .maybe_resolve_changegroup(ctx.clone(), bundle2, changegroup_acceptable) .and_then({ cloned!(resolver); move |(cg_push, bundle2)| { @@ -289,6 +295,7 @@ fn resolve_pushrebase( lca_hint: Arc, phases_hint: Arc, maybe_full_content: Option>>, + changegroup_acceptable: impl FnOnce() -> bool + Send + Sync + 'static, ) -> BoxFuture { resolver .resolve_b2xtreegroup2(ctx.clone(), bundle2) @@ -296,7 +303,7 @@ fn resolve_pushrebase( cloned!(ctx, resolver); move |(manifests, bundle2)| { resolver - .maybe_resolve_changegroup(ctx, bundle2) + .maybe_resolve_changegroup(ctx, bundle2, changegroup_acceptable) .map(move |(cg_push, bundle2)| (cg_push, manifests, bundle2)) } }) @@ -859,10 +866,13 @@ impl Bundle2Resolver { /// The Changesets should be parsed as RevlogChangesets and used for uploading changesets /// The Filelogs should be scheduled for uploading to BlobRepo and the Future resolving in /// their upload should be used for uploading changesets + /// `pure_push_allowed` argument is responsible for allowing + /// pure (non-pushrebase and non-infinitepush) pushes fn maybe_resolve_changegroup( &self, ctx: CoreContext, bundle2: BoxStream, + changegroup_acceptable: impl FnOnce() -> bool + Send + Sync + 'static, ) -> BoxFuture<(Option, BoxStream), Error> { let repo = self.repo.clone(); @@ -873,6 +883,11 @@ impl Bundle2Resolver { Some(Bundle2Item::Changegroup(header, parts)) | Some(Bundle2Item::B2xInfinitepush(header, parts)) | Some(Bundle2Item::B2xRebase(header, parts)) => { + if header.part_type() == &PartHeaderType::Changegroup && !changegroup_acceptable() { + // Changegroup part type signals that we are in a pure push scenario + return err(format_err!("Pure pushes are disallowed in this repo")) + .boxify(); + } let (c, f) = split_changegroup(parts); convert_to_revlog_changesets(c) .collect() diff --git a/metaconfig/parser/src/repoconfig.rs b/metaconfig/parser/src/repoconfig.rs index 7397a94730..dc956f6ef6 100644 --- a/metaconfig/parser/src/repoconfig.rs +++ b/metaconfig/parser/src/repoconfig.rs @@ -27,6 +27,7 @@ use metaconfig_types::{ HookType, InfinitepushNamespace, InfinitepushParams, LfsParams, MetadataDBConfig, PushParams, PushrebaseParams, RepoConfig, RepoReadOnly, ShardedFilenodesParams, StorageConfig, WhitelistEntry, + }; use regex::Regex; use toml; diff --git a/tests/integration/library.sh b/tests/integration/library.sh index 27877e281f..cb75b73d6f 100644 --- a/tests/integration/library.sh +++ b/tests/integration/library.sh @@ -398,6 +398,13 @@ preserve_raw_bundle2 = true CONFIG fi +if [[ -v DISALLOW_NON_PUSHREBASE ]]; then + cat >> "repos/$reponame/server.toml" <> "repos/$reponame/server.toml" < a + $ hg add a + $ hg ci -ma + $ hg bookmark master_bookmark -r 'tip' + +verify content + $ hg log + changeset: 0:0e7ec5675652 + bookmark: master_bookmark + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +blobimport the repo + $ cd $TESTTMP + $ blobimport repo-hg-server/.hg repo + +start mononoke + + $ mononoke + $ wait_for_mononoke $TESTTMP/repo + +setup the client repo + $ cd $TESTTMP + $ hgclone_treemanifest ssh://user@dummy/repo-hg-server client --noupdate --config extensions.remotenames= -q + +create new hg commits + $ cd $TESTTMP/client + $ hg up -q 0 + $ echo b > b && hg ci -Am b + adding b + +try doing a non-pushrebase push with the new commits + $ hgmn push --force ssh://user@dummy/repo + pushing to ssh://user@dummy/repo + searching for changes + remote: Command failed + remote: Error: + remote: bundle2_resolver error + remote: Root cause: + remote: ErrorMessage { + remote: msg: "Pure pushes are disallowed in this repo", + remote: } + remote: Caused by: + remote: While resolving Changegroup + remote: Caused by: + remote: Pure pushes are disallowed in this repo + abort: stream ended unexpectedly (got 0 bytes, expected 4) + [255] + +try doing a pushrebase push with the new commits + $ hgmn push ssh://user@dummy/repo --config extensions.pushrebase= --config extensions.remotenames= --to master_bookmark + pushing rev * to destination ssh://user@dummy/repo bookmark master_bookmark (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 0 changesets with 0 changes to 0 files + updating bookmark master_bookmark