[PATCH 3 of 3] test-convert: demonstrate an unstable hash issue for bzr -> hg -> hg

Yuya Nishihara yuya at tcha.org
Sat Jul 7 10:47:17 EDT 2018


On Sat, 07 Jul 2018 00:19:33 -0400, Matt Harbison wrote:
> On Fri, 06 Jul 2018 11:51:07 -0400, Yuya Nishihara <yuya at tcha.org> wrote:
> > On Thu, 05 Jul 2018 22:11:35 -0400, Matt Harbison wrote:
> >> # HG changeset patch
> >> # User Matt Harbison <matt_harbison at yahoo.com>
> >> # Date 1530817649 14400
> >> #      Thu Jul 05 15:07:29 2018 -0400
> >> # Node ID 7ba60a5ffc69e2fc713f0510a7b53e36b3dbdc10
> >> # Parent  7871e05503668294a5cf35697fe51db0045d8086
> >> test-convert: demonstrate an unstable hash issue for bzr -> hg -> hg
> >>
> >> It looks like the manifest value changing is the only difference, but  
> >> I'm not
> >> sure why it's happening.  I've got a similar divergence in a production  
> >> repo
> >> that was also converted from bzr and has an octopus merge[1].  Unlike  
> >> here, the
> >> manifest values for the destination merge commits reflect the initial  
> >> merge
> >> only, instead of all four merges agreeing like this test.
> >>
> >>     $ hg -R src_repo manifest -r 310 --debug | grep file  # octopus  
> >> fixup merge
> >>     2d8775bc2481bd28ac87038ecdf33e1dbddc80e9 644   file1
> >>     6adb9353a55bb8be76e71382efc724ec3ccf7ed5 644   file2
> >>
> >>     $ hg -R src_repo manifest -r 309 --debug | grep file  # first merge
> >>     362e7cb5163153c4989daad1a834871ae849f205 644   file1
> >>     2c65d947191938c3ea616b7ceb7648ff3843261f 644   file2
> >>
> >>     $ hg -R dst_repo manifest -r 273 --debug | grep file  # octopus  
> >> fixup merge
> >>     362e7cb5163153c4989daad1a834871ae849f205 644   file1
> >>     2c65d947191938c3ea616b7ceb7648ff3843261f 644   file2
> >>
> >>     $ hg -R dst_repo manifest -r 272 --debug | grep file  # first merge
> >>     362e7cb5163153c4989daad1a834871ae849f205 644   file1
> >>     2c65d947191938c3ea616b7ceb7648ff3843261f 644   file2
> >>
> >> This divergence is espcially annoying because unlike changelog  
> >> differences, I
> >> haven't figured out a way to fix this in code.  The only way I found to  
> >> work
> >> around it is to convert up to the point of divergence, `hg bundle` the  
> >> bad
> >> revision in the source, apply it to the destination, add a line to the  
> >> shamap,
> >> and fire off the conversion again.
> >>
> >> But I suspect that there's more to it than just the octopus merge  
> >> because
> >> I also have a commit in the same repo, done in Mercurial (well after the
> >> conversion) that is exhibiting a similar issue (and it's not a merge  
> >> commit).
> >> I'm almost positive that it was created with 4.4 or later.  Any ideas?
> >>
> >> [1]  
> >> https://www.mercurial-scm.org/pipermail/mercurial/2018-June/050924.html
> >
> >> +  $ hg -R source-hg manifest --debug -r tip
> >> +  cdf31ed9242b209cd94697112160e2c5b37a667d 644   file
> >> +  5108144f585149b29779d7c7e51d61dd22303ffe 644   file-branch1
> >> +  80753c4a9ac3806858405b96b24a907b309e3616 644   file-branch2
> >> +  7108421418404a937c684d2479a34a24d2ce4757 644   file-parent
> >> +  $ hg -R source-hg manifest --debug -r 'tip^'
> >> +  cdf31ed9242b209cd94697112160e2c5b37a667d 644   file
> >> +  5108144f585149b29779d7c7e51d61dd22303ffe 644   file-branch1
> >> +  80753c4a9ac3806858405b96b24a907b309e3616 644   file-branch2
> >> +  7108421418404a937c684d2479a34a24d2ce4757 644   file-parent
> >> +
> >> +  $ hg -R hg2hg manifest --debug -r tip
> >> +  cdf31ed9242b209cd94697112160e2c5b37a667d 644   file
> >> +  5108144f585149b29779d7c7e51d61dd22303ffe 644   file-branch1
> >> +  80753c4a9ac3806858405b96b24a907b309e3616 644   file-branch2
> >> +  7108421418404a937c684d2479a34a24d2ce4757 644   file-parent
> >> +  $ hg -R hg2hg manifest --debug -r 'tip^'
> >> +  cdf31ed9242b209cd94697112160e2c5b37a667d 644   file
> >> +  5108144f585149b29779d7c7e51d61dd22303ffe 644   file-branch1
> >> +  80753c4a9ac3806858405b96b24a907b309e3616 644   file-branch2
> >> +  7108421418404a937c684d2479a34a24d2ce4757 644   file-parent
> >
> > Appears that the source-hg repository contains an unchanged manifest  
> > entry
> > in a way that ctx.files() will get empty (and thus p1 manifest will be  
> > reused)
> > on hg2hg conversion.
> >
> > https://www.mercurial-scm.org/repo/hg/file/4.6.2/mercurial/localrepo.py#l2031
> >
> >    $ hg -R source-hg debugindex -m
> >     rev linkrev nodeid       p1           p2
> >       0       0 4c7fb614fc68 000000000000 000000000000
> >       1       1 f75efda72db5 4c7fb614fc68 000000000000
> >       2       2 bdc9800ba402 4c7fb614fc68 000000000000
> >       3       3 59e0bab8c58e bdc9800ba402 000000000000
> >       4       4 daa315d56a98 bdc9800ba402 f75efda72db5
> >       5       5 1109e42bdcbd daa315d56a98 59e0bab8c58e
> >    $ hg -R hg2hg debugindex -m
> >     rev linkrev nodeid       p1           p2
> >       0       0 4c7fb614fc68 000000000000 000000000000
> >       1       1 f75efda72db5 4c7fb614fc68 000000000000
> >       2       2 bdc9800ba402 4c7fb614fc68 000000000000
> >       3       3 59e0bab8c58e bdc9800ba402 000000000000
> >       4       4 daa315d56a98 bdc9800ba402 f75efda72db5
> >
> > I don't know where things goes wrong, but I suspect that a commit using  
> > memctx
> > could make such entry somehow.
> 
> Thanks, I wasn't aware of this command.
> 
> It looks like in the test case, the dict of files passed to  
> sink.putcommit() is empty for the fixup merge in hg2hg.  In the initial  
> bzr -> hg processing, the octopus merge gets a list of files on input, and  
> both loop iterations in putcommit() use that same list.  So memctx doesn't  
> seem to be the issue here, and it seems like the source class decided  
> nothing changed.

I mean memctx can create a bad manifest entry since it doesn't compute
status of files which are said to be "changed" in the commit. If provided
files are valid (i.e. hg source), the result is also valid.

This is a hack to detect rogue ctx.files(). Appears that we have some
problems in convert, graft, mq, and fix.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -2065,14 +2065,23 @@ 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)
+                # if no files actually changed, try hard to detect unmodified
+                # manifest entry caused by error in memctx or workingcommitctx
+                # with bad copy information
+                if (changed or removed
+                    or m1.diff(m, scmutil.matchfiles(self, ctx.files()))):
+                    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 (inconsistency '
+                                  'found in %r)\n' % ctx)
+                    mn = p1.manifestnode()
                 files = changed + removed
             else:
                 self.ui.debug('reusing manifest from p1 (no file change)\n')


More information about the Mercurial-devel mailing list