From 4e8b320cc8f8d8389510c861893bb2f2e8f9e1ef Mon Sep 17 00:00:00 2001 From: Zhaolong Zhu Date: Tue, 10 Dec 2024 14:15:13 -0800 Subject: [PATCH] merge: fix path-remapping for merge.ACTION_CREATED Summary: When doing merge with `sl merge --from-path foo --to-path bar -r A`, the diff operation produces paths like "bar/file", but we need to recover the original path "foo/file" to look up the file context in A. The ACTION_CREATED action did not support a different "local" and "remote" filename. Extend their args to include the remote file name (which differs when merging between directories). This diff is similar to D60027064, which extended the args of actions like ACTION_CREATED_MERGE. Besides that, this diff also fix a bug in checkpathconflicts(). The ACTION_CREATED_MERGE's `args[0]` was not flags anymore after D60027064. Reviewed By: quark-zju Differential Revision: D66986091 fbshipit-source-id: 0c983e294dc6899bcc61ec3465d8dbd041112114 --- .../scm/sapling/ext/remotefilelog/__init__.py | 3 ++- eden/scm/sapling/merge.py | 23 ++++++++++++------- eden/scm/tests/test-subtree-merge.t | 12 +++++++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/eden/scm/sapling/ext/remotefilelog/__init__.py b/eden/scm/sapling/ext/remotefilelog/__init__.py index a358d3d9cb66d..6670ee9f4992d 100644 --- a/eden/scm/sapling/ext/remotefilelog/__init__.py +++ b/eden/scm/sapling/ext/remotefilelog/__init__.py @@ -332,7 +332,8 @@ def checkunknownfiles(orig, repo, wctx, mctx, force, actions, *args, **kwargs): if sparsematch and not sparsematch(f): continue if m == merge.ACTION_CREATED: - files.append((f, mctx.filenode(f))) + f2 = actionargs[0] + files.append((f, mctx.filenode(f2))) elif m == merge.ACTION_DELETED_CHANGED: f2 = actionargs[1] files.append((f, mctx.filenode(f2))) diff --git a/eden/scm/sapling/merge.py b/eden/scm/sapling/merge.py index 8f3f0a7d3d0eb..bd23a63e17794 100644 --- a/eden/scm/sapling/merge.py +++ b/eden/scm/sapling/merge.py @@ -650,7 +650,8 @@ def collectconflicts(conflicts, config): for f, (m, args, msg) in progiter(actions.items()): if m in (ACTION_CREATED, ACTION_DELETED_CHANGED): count += 1 - if _checkunknownfile(repo, wctx, mctx, f): + f2 = args[0] if m == ACTION_CREATED else args[1] + if _checkunknownfile(repo, wctx, mctx, f, f2): fileconflicts.add(f) elif pathconfig and f not in wctx: path = checkunknowndirs(repo, wctx, f) @@ -731,8 +732,8 @@ def collectconflicts(conflicts, config): or f in pathconflicts or any(p in pathconflicts for p in util.finddirs(f)) ) - (flags,) = args - actions[f] = (ACTION_GET, (f, flags, backup), msg) + (f2, flags) = args + actions[f] = (ACTION_GET, (f2, flags, backup), msg) def _forgetremoved(wctx, mctx, branchmerge): @@ -884,14 +885,16 @@ def checkpathconflicts(repo, wctx, mctx, actions): if m in (ACTION_DELETED_CHANGED, ACTION_MERGE): # Action was merge, just update target. actions[pnew] = (m, args, msg) - else: + elif m in (ACTION_CREATED, ACTION_CREATED_MERGE): # Action was create, change to renamed get action. - fl = args[0] + fl = args[1] actions[pnew] = ( ACTION_LOCAL_DIR_RENAME_GET, (p, fl), "remote path conflict", ) + else: + raise error.ProgrammingError(f"unexpected action type '{m}'") actions[p] = (ACTION_PATH_CONFLICT, (pnew, "r"), "path conflict") remoteconflicts.remove(p) break @@ -1164,9 +1167,9 @@ def handle_file_on_other_side(f, diff, reverse_copies): # Checking whether the files are different is expensive, so we # don't do that when we can avoid it. if not force: - actions[f1] = (ACTION_CREATED, (fl2,), "remote created") + actions[f1] = (ACTION_CREATED, (f2, fl2), "remote created") elif not branchmerge: - actions[f1] = (ACTION_CREATED, (fl2,), "remote created") + actions[f1] = (ACTION_CREATED, (f2, fl2), "remote created") else: actions[f1] = ( ACTION_CREATED_MERGE, @@ -1175,7 +1178,11 @@ def handle_file_on_other_side(f, diff, reverse_copies): ) elif n2 != ma[fa]: if acceptremote: - actions[f1] = (ACTION_CREATED, (fl2,), "remote recreating") + actions[f1] = ( + ACTION_CREATED, + (f2, fl2), + "remote recreating", + ) else: actions[f1] = ( ACTION_DELETED_CHANGED, diff --git a/eden/scm/tests/test-subtree-merge.t b/eden/scm/tests/test-subtree-merge.t index 230ad757740e3..08c41e4e04c3a 100644 --- a/eden/scm/tests/test-subtree-merge.t +++ b/eden/scm/tests/test-subtree-merge.t @@ -96,13 +96,19 @@ test subtree merge from copy dest -> copy source, with new file in copy dest copying foo to foo2 $ echo 1 >> foo2/new $ hg ci -Aqm "add foo2/new" -tofix: should not abort with not found in manifest $ hg subtree merge --from-path foo2 --to-path foo merge base: 9998a5c40732 - abort: foo/new@b25c37d96b54: not found in manifest! - [255] + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (subtree merge, don't forget to commit) $ hg st + M foo/new $ hg diff + diff --git a/foo/new b/foo/new + new file mode 100644 + --- /dev/null + +++ b/foo/new + @@ -0,0 +1,1 @@ + +1 test subtree merge from copy dest -> copy source with conflicts $ newclientrepo