diff --git a/eden/scm/sapling/localrepo.py b/eden/scm/sapling/localrepo.py index d57e803c0e5d1..9f6de390e7298 100644 --- a/eden/scm/sapling/localrepo.py +++ b/eden/scm/sapling/localrepo.py @@ -75,6 +75,7 @@ from .i18n import _, _n from .node import bin, hex, nullhex, nullid from .pycompat import range +from .utils import subtreeutil release = lockmod.release urlerr = util.urlerr @@ -2825,6 +2826,12 @@ def commitctx(self, ctx, error=False): extra = ctx.extra().copy() if isgit: git.update_extra_with_git_committer(self.ui, ctx, extra) + + if subtreeutil.extra_contains_shallow_copy(extra): + # the file list can be large for a shallow copy, so don't + # put it in the files of commit text + files = [] + n = self.changelog.add( mn, files, diff --git a/eden/scm/sapling/utils/subtreeutil.py b/eden/scm/sapling/utils/subtreeutil.py index 765a192c68fbc..e641db0a75095 100644 --- a/eden/scm/sapling/utils/subtreeutil.py +++ b/eden/scm/sapling/utils/subtreeutil.py @@ -406,6 +406,20 @@ def contains_shallow_copy(repo, node): return False +def extra_contains_shallow_copy(extra) -> bool: + """Check if the given commitctx extra contains any shallow copy metadata. + + N.B. This function does not apply to "v0" subtree metadata because "v0" does + not have shallow copy type. It is used for newly incoming commits. + """ + shallow_copy_key = BranchType.SHALLOW_COPY.to_key() + if metadata_list := _get_subtree_metadata(extra, SUBTREE_KEY): + for metadata in metadata_list: + if shallow_copy_key in metadata: + return True + return False + + def check_commit_splitability(repo, node): """Check if the given commit can be split into multiple commits. diff --git a/eden/scm/tests/test-subtree-shallow-copy.t b/eden/scm/tests/test-subtree-shallow-copy.t new file mode 100644 index 0000000000000..125a0dcb3bbf3 --- /dev/null +++ b/eden/scm/tests/test-subtree-shallow-copy.t @@ -0,0 +1,29 @@ + $ setconfig diff.git=True + $ setconfig subtree.copy-reuse-tree=True + $ setconfig subtree.allow-any-source-commit=True + +test subtree copy + $ newclientrepo + $ drawdag <<'EOS' + > B # B/foo/x = bbb\n + > | + > A # A/foo/x = aaa\n + > # drawdag.defaultfiles=false + > EOS + $ hg go $B -q + $ hg subtree cp -r $A --from-path foo --to-path bar -m "subtree copy foo -> bar" + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg dbsh -c 'print(repo["."].extra())' + {'branch': 'default', 'test_subtree': '[{"copies":[{"from_commit":"d908813f0f7c9078810e26aad1e37bdb32013d4b","from_path":"foo","to_path":"bar"}],"v":1}]'} + $ hg dbsh -c 'print(repo["."].changeset().files)' + () + +files list is still empty after amending the shallow copy commit + $ echo ccc >> bar/x + $ hg amend + $ hg dbsh -c 'print(repo["."].extra())' + {'branch': 'default', 'amend_source': '075709eca377ab1f8a1e6a31b7970d26ff9ec935', 'test_subtree': '[{"copies":[{"from_commit":"d908813f0f7c9078810e26aad1e37bdb32013d4b","from_path":"foo","to_path":"bar"}],"v":1}]'} + $ hg dbsh -c 'print(repo["."].changeset().files)' + () + $ hg dbsh -c 'print(repo["."].files())' + ['bar/x']