[Updated] D12119: narrow: allow merging non-conflicting change outside of the narrow spec
marmoute (Pierre-Yves David)
phabricator at mercurial-scm.org
Fri Feb 4 10:31:57 UTC 2022
Closed by commit rHGf1eb77dceb36: narrow: allow merging non-conflicting change outside of the narrow spec (authored by marmoute).
This revision was automatically updated to reflect the committed changes.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D12119?vs=32058&id=32077
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D12119/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D12119
AFFECTED FILES
mercurial/commit.py
mercurial/merge.py
tests/test-narrow-merge.t
CHANGE DETAILS
diff --git a/tests/test-narrow-merge.t b/tests/test-narrow-merge.t
--- a/tests/test-narrow-merge.t
+++ b/tests/test-narrow-merge.t
@@ -83,12 +83,67 @@
TODO: Can merge non-conflicting changes outside narrow spec
$ hg update -q 'desc("modify inside/f1")'
+
+#if flat
+
$ hg merge 'desc("modify outside/f1")'
- abort: merge affects file 'outside/f1' outside narrow, which is not yet supported (flat !)
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+
+status should be clean
+
+ $ hg status
+ ? inside/f1.orig
+
+file out of the spec should still not be in the dirstate at all
+
+ $ hg debugdirstate | grep outside/f1
+ [1]
+
+Commit that merge
+
+ $ hg ci -m 'merge from outside to inside'
+
+status should be clean
+
+ $ hg status
+ ? inside/f1.orig
+
+file out of the spec should not be in the mergestate anymore
+
+ $ hg debugmergestate | grep outside/f1
+ [1]
+
+file out of the spec should still not be in the dirstate at all
+
+ $ hg debugdirstate | grep outside/f1
+ [1]
+
+The filenode used should come from p2
+
+ $ hg manifest --debug --rev . | grep outside/f1
+ 83cd11431a3b2aff8a3995e5f27bcf33cdb5be98 644 outside/f1
+ $ hg manifest --debug --rev 'p1(.)' | grep outside/f1
+ c6b956c48be2cd4fa94be16002aba311143806fa 644 outside/f1
+ $ hg manifest --debug --rev 'p2(.)' | grep outside/f1
+ 83cd11431a3b2aff8a3995e5f27bcf33cdb5be98 644 outside/f1
+
+
+remove the commit to get in the previous situation again
+
+ $ hg debugstrip -r .
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/48eb25338b19-a1bb8350-backup.hg
+
+#else
+
+ $ hg merge 'desc("modify outside/f1")'
abort: merge affects file 'outside/' outside narrow, which is not yet supported (tree !)
(merging in the other direction may work)
[255]
+#endif
+
$ hg update -q 'desc("modify outside/f1")'
$ hg merge 'desc("modify inside/f1")'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -518,13 +518,23 @@
mresult.removefile(f) # just updating, ignore changes outside clone
elif action[0].no_op:
mresult.removefile(f) # merge does not affect file
- elif action[0].narrow_safe: # TODO: handle these cases
- msg = _(
- b'merge affects file \'%s\' outside narrow, '
- b'which is not yet supported'
- )
- hint = _(b'merging in the other direction may work')
- raise error.Abort(msg % f, hint=hint)
+ elif action[0].narrow_safe:
+ if (
+ not f.endswith(b'/')
+ and action[0].changes == mergestatemod.CHANGE_MODIFIED
+ ):
+ mresult.removefile(f) # merge won't affect on-disk files
+
+ mresult.addcommitinfo(
+ f, b'outside-narrow-merge-action', action[0].changes
+ )
+ else: # TODO: handle the tree case
+ msg = _(
+ b'merge affects file \'%s\' outside narrow, '
+ b'which is not yet supported'
+ )
+ hint = _(b'merging in the other direction may work')
+ raise error.Abort(msg % f, hint=hint)
else:
msg = _(b'conflict in file \'%s\' is outside narrow clone')
raise error.StateError(msg % f)
diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -134,7 +134,13 @@
for s in salvaged:
files.mark_salvaged(s)
- if ctx.manifestnode():
+ narrow_files = {}
+ if not ctx.repo().narrowmatch().always():
+ for f, e in ms.allextras().items():
+ action = e.get(b'outside-narrow-merge-action')
+ if action is not None:
+ narrow_files[f] = action
+ if ctx.manifestnode() and not narrow_files:
# reuse an existing manifest revision
repo.ui.debug(b'reusing known manifest\n')
mn = ctx.manifestnode()
@@ -142,11 +148,11 @@
if writechangesetcopy:
files.update_added(ctx.filesadded())
files.update_removed(ctx.filesremoved())
- elif not ctx.files():
+ elif not ctx.files() and not narrow_files:
repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
mn = p1.manifestnode()
else:
- mn = _process_files(tr, ctx, ms, files, error=error)
+ mn = _process_files(tr, ctx, ms, files, narrow_files, error=error)
if origctx and origctx.manifestnode() == mn:
origfiles = origctx.files()
@@ -177,7 +183,7 @@
return salvaged
-def _process_files(tr, ctx, ms, files, error=False):
+def _process_files(tr, ctx, ms, files, narrow_files=None, error=False):
repo = ctx.repo()
p1 = ctx.p1()
p2 = ctx.p2()
@@ -198,8 +204,24 @@
linkrev = len(repo)
repo.ui.note(_(b"committing files:\n"))
uipathfn = scmutil.getuipathfn(repo)
- for f in sorted(ctx.modified() + ctx.added()):
+ all_files = ctx.modified() + ctx.added()
+ all_files.extend(narrow_files.keys())
+ all_files.sort()
+ for f in all_files:
repo.ui.note(uipathfn(f) + b"\n")
+ if f in narrow_files:
+ narrow_action = narrow_files.get(f)
+ if narrow_action == mergestate.CHANGE_MODIFIED:
+ files.mark_touched(f)
+ added.append(f)
+ m[f] = m2[f]
+ flags = m2ctx.find(f)[1] or b''
+ m.setflag(f, flags)
+ else:
+ msg = _(b"corrupted mergestate, unknown narrow action: %b")
+ hint = _(b"restart the merge")
+ raise error.Abort(msg, hint=hint)
+ continue
try:
fctx = ctx[f]
if fctx is None:
@@ -239,7 +261,17 @@
if not rf(f):
files.mark_removed(f)
- mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop)
+ mn = _commit_manifest(
+ tr,
+ linkrev,
+ ctx,
+ mctx,
+ m,
+ files.touched,
+ added,
+ drop,
+ bool(narrow_files),
+ )
return mn
@@ -409,7 +441,17 @@
return fnode, touched
-def _commit_manifest(tr, linkrev, ctx, mctx, manifest, files, added, drop):
+def _commit_manifest(
+ tr,
+ linkrev,
+ ctx,
+ mctx,
+ manifest,
+ files,
+ added,
+ drop,
+ has_some_narrow_action=False,
+):
"""make a new manifest entry (or reuse a new one)
given an initialised manifest context and precomputed list of
@@ -451,6 +493,10 @@
# at this point is merges, and we already error out in the
# case where the merge has files outside of the narrowspec,
# so this is safe.
+ if has_some_narrow_action:
+ match = None
+ else:
+ match = repo.narrowmatch()
mn = mctx.write(
tr,
linkrev,
@@ -458,7 +504,7 @@
p2.manifestnode(),
added,
drop,
- match=repo.narrowmatch(),
+ match=match,
)
else:
repo.ui.debug(
To: marmoute, durin42, #hg-reviewers, Alphare
Cc: Alphare, mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20220204/3265c88a/attachment-0002.html>
More information about the Mercurial-patches
mailing list