# HG changeset patch # User Yuya Nishihara # Date 2018-07-07 13:40:39 # Node ID 46da52f4b820f2668b120fcf93f09fb730065da6 # Parent f0c2653ca7060e5ea7b66b3fb51569c5b230d9db 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. diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2039,6 +2039,11 @@ class localrepository(object): 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 @@ class localrepository(object): 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() diff --git a/tests/test-convert-bzr-merges.t b/tests/test-convert-bzr-merges.t --- a/tests/test-convert-bzr-merges.t +++ b/tests/test-convert-bzr-merges.t @@ -83,20 +83,17 @@ test multiple merges at once $ 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 date: Sat Oct 10 08:00:04 2009 +0100 extra: branch=source diff --git a/tests/test-convert-filemap.t b/tests/test-convert-filemap.t --- a/tests/test-convert-filemap.t +++ b/tests/test-convert-filemap.t @@ -780,7 +780,7 @@ example because filemap changed. 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 diff --git a/tests/test-convert-svn-branches.t b/tests/test-convert-svn-branches.t --- a/tests/test-convert-svn-branches.t +++ b/tests/test-convert-svn-branches.t @@ -85,8 +85,8 @@ Convert again $ 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 .. diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -851,9 +851,9 @@ no ancestors that are replaced. $ 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 | | diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -699,8 +699,23 @@ Transplants of grafts can find a destina 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 @@ All copies of a cset 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 @@ graft works on complex revset $ 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 @@ graft with --force (still doesn't graft $ 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 @@ graft --force after backout $ 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 @@ graft --continue after --force $ 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 @@ graft --continue after --force (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 @@ Empty graft $ 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 .. diff --git a/tests/test-merge-no-file-change.t b/tests/test-merge-no-file-change.t --- a/tests/test-merge-no-file-change.t +++ b/tests/test-merge-no-file-change.t @@ -30,6 +30,7 @@ Files added at both parents: $ 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 @@ An identical file added at both parents, $ 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 @@ An identical file added at both parents, $ 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 @@ An identical file added at both parents, $ 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 @@ A file added at p2, a named branch creat $ 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