commit: try hard to reuse p1 manifest if nothing changed
This is all for commit reproducibility on "hg convert".
With this change, p1 manifest is reused if ctx.files() *to be committed* is
empty, and if new manifest entry is identical to p1. This is important
property for "hg convert" since memctx.files() built from a convert source
may be either a) more narrowed thanks to a committed ctx.files() which
provides more accurate status, or b) containing redundant files because of
sloppy filtering on e.g. octopus merge.
--- a/mercurial/localrepo.py Sun Aug 12 18:44:42 2018 +0900
+++ b/mercurial/localrepo.py Sat Jul 07 22:40:39 2018 +0900
@@ -2039,6 +2039,11 @@
def commitctx(self, ctx, error=False):
"""Add a new revision to current repository.
Revision information is passed via the context argument.
+
+ ctx.files() should list all files involved in this commit, i.e.
+ modified/added/removed files. On merge, it may be wider than the
+ ctx.files() to be committed, since any file nodes derived directly
+ from p1 or p2 are excluded from the committed ctx.files().
"""
tr = None
@@ -2091,15 +2096,29 @@
raise
# update manifest
- self.ui.note(_("committing manifest\n"))
removed = [f for f in sorted(removed) if f in m1 or f in m2]
drop = [f for f in removed if f in m]
for f in drop:
del m[f]
- mn = mctx.write(trp, linkrev,
- p1.manifestnode(), p2.manifestnode(),
- added, drop)
files = changed + removed
+ md = None
+ if not files:
+ # if no "files" actually changed in terms of the changelog,
+ # try hard to detect unmodified manifest entry so that the
+ # exact same commit can be reproduced later on convert.
+ md = m1.diff(m, scmutil.matchfiles(self, ctx.files()))
+ if not files and md:
+ self.ui.debug('not reusing manifest (no file change in '
+ 'changelog, but manifest differs)\n')
+ if files or md:
+ self.ui.note(_("committing manifest\n"))
+ mn = mctx.write(trp, linkrev,
+ p1.manifestnode(), p2.manifestnode(),
+ added, drop)
+ else:
+ self.ui.debug('reusing manifest form p1 (listed files '
+ 'actually unchanged)\n')
+ mn = p1.manifestnode()
else:
self.ui.debug('reusing manifest from p1 (no file change)\n')
mn = p1.manifestnode()
--- a/tests/test-convert-bzr-merges.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-convert-bzr-merges.t Sat Jul 07 22:40:39 2018 +0900
@@ -83,20 +83,17 @@
$ hg -R hg2hg out source-hg -T compact
comparing with source-hg
searching for changes
- 5[tip]:4,3 6bd55e826939 2009-10-10 08:00 +0100 foo
- (octopus merge fixup)
-
-XXX: The manifest lines should probably agree, to avoid changing the hash when
-converting hg -> hg
+ no changes found
+ [1]
$ hg -R source-hg log --debug -r tip
- changeset: 5:b209510f11b2c987f920749cd8e352aa4b3230f2
+ changeset: 5:6bd55e8269392769783345686faf7ff7b3b0215d
branch: source
tag: tip
phase: draft
parent: 4:1dc38c377bb35eeea4fa955056fbe4440d54a743
parent: 3:4aaba1bfb426b8941bbf63f9dd52301152695164
- manifest: 5:1109e42bdcbd1f51baa69bc91079011d77057dbb
+ manifest: 4:daa315d56a98ba20811fdd0d9d575861f65cfa8c
user: Foo Bar <foo.bar@example.com>
date: Sat Oct 10 08:00:04 2009 +0100
extra: branch=source
--- a/tests/test-convert-filemap.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-convert-filemap.t Sat Jul 07 22:40:39 2018 +0900
@@ -780,7 +780,7 @@
converting...
0 3
$ hg -R .-hg log -G -T '{shortest(node)} {desc}\n{files % "- {file}\n"}\n'
- o e9ed 3
+ o bbfe 3
|\
| o 33a0 2
| | - f
--- a/tests/test-convert-svn-branches.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-convert-svn-branches.t Sat Jul 07 22:40:39 2018 +0900
@@ -85,8 +85,8 @@
$ hg branches
newbranch 11:a6d7cc050ad1
default 10:6e2b33404495
- old 9:93c4b0f99529
- old2 8:b52884d7bead (inactive)
+ old 9:1b494af68c0b
+ old2 8:5be40b8dcbf6 (inactive)
$ hg tags -q
tip
$ cd ..
--- a/tests/test-fix.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-fix.t Sat Jul 07 22:40:39 2018 +0900
@@ -851,9 +851,9 @@
$ hg fix -r 0:2
$ hg log --graph --template '{node|shortest} {files}'
- o 3801 bar.whole
+ o b4e2 bar.whole
|
- o 38cc
+ o 59f4
|
| @ bc05 bar.whole
| |
--- a/tests/test-graft.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-graft.t Sat Jul 07 22:40:39 2018 +0900
@@ -699,8 +699,23 @@
summary: 2
... grafts of grafts unfortunately can't
- $ hg graft -q 13
+ $ hg graft -q 13 --debug
+ scanning for duplicate grafts
+ grafting 13:7a4785234d87 "2"
+ searching for copies back to rev 12
+ unmatched files in other (from topological common ancestor):
+ g
+ unmatched files new in both:
+ b
+ resolving manifests
+ branchmerge: True, force: True, partial: False
+ ancestor: b592ea63bb0c, local: 7e61b508e709+, remote: 7a4785234d87
+ committing files:
+ b
warning: can't find ancestor for 'b' copied from 'a'!
+ reusing manifest form p1 (listed files actually unchanged)
+ committing changelog
+ updating the branch cache
$ hg log -r 'destination(13)'
All copies of a cset
$ hg log -r 'origin(13) or destination(origin(13))'
@@ -731,7 +746,7 @@
date: Thu Jan 01 00:00:00 1970 +0000
summary: 2
- changeset: 22:d1cb6591fa4b
+ changeset: 22:3a4e92d81b97
branch: dev
tag: tip
user: foo
@@ -743,8 +758,8 @@
$ hg graft 'origin(13) or destination(origin(13))'
skipping ancestor revision 21:7e61b508e709
- skipping ancestor revision 22:d1cb6591fa4b
- skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
+ skipping ancestor revision 22:3a4e92d81b97
+ skipping revision 2:5c095ad7e90f (already grafted to 22:3a4e92d81b97)
grafting 7:ef0ef43d49e7 "2"
warning: can't find ancestor for 'b' copied from 'a'!
grafting 13:7a4785234d87 "2"
@@ -758,7 +773,7 @@
$ hg graft 19 0 6
skipping ungraftable merge revision 6
skipping ancestor revision 0:68795b066622
- skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
+ skipping already grafted revision 19:9627f653b421 (22:3a4e92d81b97 also has origin 2:5c095ad7e90f)
[255]
$ hg graft 19 0 6 --force
skipping ungraftable merge revision 6
@@ -773,12 +788,12 @@
$ hg ci -m 28
$ hg backout 28
reverting a
- changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
+ changeset 29:9d95e865b00c backs out changeset 28:cc20d29aec8d
$ hg graft 28
- skipping ancestor revision 28:50a516bb8b57
+ skipping ancestor revision 28:cc20d29aec8d
[255]
$ hg graft 28 --force
- grafting 28:50a516bb8b57 "28"
+ grafting 28:cc20d29aec8d "28"
merging a
$ cat a
abc
@@ -788,7 +803,7 @@
$ echo def > a
$ hg ci -m 31
$ hg graft 28 --force --tool internal:fail
- grafting 28:50a516bb8b57 "28"
+ grafting 28:cc20d29aec8d "28"
abort: unresolved conflicts, can't continue
(use 'hg resolve' and 'hg graft --continue')
[255]
@@ -801,7 +816,7 @@
(no more unresolved files)
continue: hg graft --continue
$ hg graft -c
- grafting 28:50a516bb8b57 "28"
+ grafting 28:cc20d29aec8d "28"
$ cat a
abc
@@ -822,8 +837,8 @@
$ hg tag -f something
$ hg graft -qr 27
$ hg graft -f 27
- grafting 27:ed6c7e54e319 "28"
- note: graft of 27:ed6c7e54e319 created no changes to commit
+ grafting 27:17d42b8f5d50 "28"
+ note: graft of 27:17d42b8f5d50 created no changes to commit
$ cd ..
--- a/tests/test-merge-no-file-change.t Sun Aug 12 18:44:42 2018 +0900
+++ b/tests/test-merge-no-file-change.t Sat Jul 07 22:40:39 2018 +0900
@@ -30,6 +30,7 @@
$ hg ci --debug -m merge
committing files:
b
+ not reusing manifest (no file change in changelog, but manifest differs)
committing manifest
committing changelog
updating the branch cache
@@ -136,12 +137,12 @@
$ hg ci --debug -m merge
committing files:
b
- committing manifest
+ reusing manifest form p1 (listed files actually unchanged)
committing changelog
updating the branch cache
- committed changeset 3:4bfaad7f925b7f17f60524dc5d4e605f7bfbba3f
+ committed changeset 3:c8d50407916ef8a5a97cb6e36ca9bc844a6ee13e
$ hg log -GTl
- @ 3:4bfaad7f925b p=2,1 m=3:a3a9fe23a5b8 f=[]
+ @ 3:c8d50407916e p=2,1 m=2:36b69ba4b24b f=[]
|\
| o 2:99451f16b3f5 p=0,-1 m=2:36b69ba4b24b f=["b"]
| |
@@ -155,16 +156,6 @@
$ cd ..
$ check_convert_identity flag-change-take-p1
- 3:c8d50407916e
- *** BUG: hash changes on convert ***
- o 3:c8d50407916e p=2,1 m=2:36b69ba4b24b f=[]
- |\
- | o 2:99451f16b3f5 p=0,-1 m=2:36b69ba4b24b f=["b"]
- | |
- o | 1:64d01526d4c2 p=0,-1 m=1:686dbf0aeca4 f=["b"]
- |/
- o 0:487a0a245cea p=-1,-1 m=0:8515d4bfda76 f=["a"]
-
An identical file added at both parents, but the flag differs. Take other:
@@ -226,6 +217,7 @@
$ hg ci --debug -m merge
committing files:
c
+ not reusing manifest (no file change in changelog, but manifest differs)
committing manifest
committing changelog
updating the branch cache
@@ -299,6 +291,7 @@
$ hg ci --debug -m merge
committing files:
b
+ not reusing manifest (no file change in changelog, but manifest differs)
committing manifest
committing changelog
updating the branch cache