Mercurial > hg
view contrib/genosxversion.py @ 38573:050fbd9d103a
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
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 05 Jul 2018 15:07:29 -0400 |
parents | 283a7da602ae |
children | 25880ddf9a86 |
line wrap: on
line source
#!/usr/bin/env python2 from __future__ import absolute_import, print_function import argparse import json import os import subprocess import sys # Always load hg libraries from the hg we can find on $PATH. hglib = json.loads(subprocess.check_output( ['hg', 'debuginstall', '-Tjson']))[0]['hgmodules'] sys.path.insert(0, os.path.dirname(hglib)) from mercurial import util ap = argparse.ArgumentParser() ap.add_argument('--paranoid', action='store_true', help=("Be paranoid about how version numbers compare and " "produce something that's more likely to sort " "reasonably.")) ap.add_argument('--selftest', action='store_true', help='Run self-tests.') ap.add_argument('versionfile', help='Path to a valid mercurial __version__.py') def paranoidver(ver): """Given an hg version produce something that distutils can sort. Some Mac package management systems use distutils code in order to figure out upgrades, which makes life difficult. The test case is a reduced version of code in the Munki tool used by some large organizations to centrally manage OS X packages, which is what inspired this kludge. >>> paranoidver('3.4') '3.4.0' >>> paranoidver('3.4.2') '3.4.2' >>> paranoidver('3.0-rc+10') '2.9.9999-rc+10' >>> paranoidver('4.2+483-5d44d7d4076e') '4.2.0+483-5d44d7d4076e' >>> paranoidver('4.2.1+598-48d1e1214d8c') '4.2.1+598-48d1e1214d8c' >>> paranoidver('4.3-rc') '4.2.9999-rc' >>> paranoidver('4.3') '4.3.0' >>> from distutils import version >>> class LossyPaddedVersion(version.LooseVersion): ... '''Subclass version.LooseVersion to compare things like ... "10.6" and "10.6.0" as equal''' ... def __init__(self, s): ... self.parse(s) ... ... def _pad(self, version_list, max_length): ... 'Pad a version list by adding extra 0 components to the end' ... # copy the version_list so we don't modify it ... cmp_list = list(version_list) ... while len(cmp_list) < max_length: ... cmp_list.append(0) ... return cmp_list ... ... def __cmp__(self, other): ... if isinstance(other, str): ... other = MunkiLooseVersion(other) ... max_length = max(len(self.version), len(other.version)) ... self_cmp_version = self._pad(self.version, max_length) ... other_cmp_version = self._pad(other.version, max_length) ... return cmp(self_cmp_version, other_cmp_version) >>> def testver(older, newer): ... o = LossyPaddedVersion(paranoidver(older)) ... n = LossyPaddedVersion(paranoidver(newer)) ... return o < n >>> testver('3.4', '3.5') True >>> testver('3.4.0', '3.5-rc') True >>> testver('3.4-rc', '3.5') True >>> testver('3.4-rc+10-deadbeef', '3.5') True >>> testver('3.4.2', '3.5-rc') True >>> testver('3.4.2', '3.5-rc+10-deadbeef') True >>> testver('4.2+483-5d44d7d4076e', '4.2.1+598-48d1e1214d8c') True >>> testver('4.3-rc', '4.3') True >>> testver('4.3', '4.3-rc') False """ major, minor, micro, extra = util.versiontuple(ver, n=4) if micro is None: micro = 0 if extra: if extra.startswith('rc'): if minor == 0: major -= 1 minor = 9 else: minor -= 1 micro = 9999 extra = '-' + extra else: extra = '+' + extra else: extra = '' return '%d.%d.%d%s' % (major, minor, micro, extra) def main(argv): opts = ap.parse_args(argv[1:]) if opts.selftest: import doctest doctest.testmod() return with open(opts.versionfile) as f: for l in f: if l.startswith('version = '): # version number is entire line minus the quotes ver = l[len('version = ') + 1:-2] break if opts.paranoid: print(paranoidver(ver)) else: print(ver) if __name__ == '__main__': main(sys.argv)