[PATCH accept-scripts] land: fix bug we see when we merge, rather than rebase
Kevin Bullock
kbullock+mercurial at ringworld.org
Fri Apr 27 11:30:18 EDT 2018
> On Apr 26, 2018, at 10:59, Augie Fackler <raf at durin42.com> wrote:
>
> # HG changeset patch
> # User Augie Fackler <raf at durin42.com>
> # Date 1524713796 14400
> # Wed Apr 25 23:36:36 2018 -0400
> # Node ID c8dd55d63f9e56d62db3ff1e1b0a8fef228fd19f
> # Parent 66e6638d2a6e78f3af813a274eadbd90679b888e
> land: fix bug we see when we merge, rather than rebase
>
> I triggered this when I tagged 4.6rc1 concurrent with 8c8b6d13949a
> being landed and accepted. That change was only a doc change, so it
> wasn't worth redoing the RC, but then the tagging revision got stuck
> because it wasn't a child of a head in the repo.
>
> Unfortunately, I couldn't figure out how to fix this bug without what
> amounts to a ground-up rewrite of the land script. Sigh.
Thanks for poking at this. Code LGTM but I'm getting weird test failures:
---------- test output
--- /Users/kbullock/Source/Projects/hg/accept/tests/test-land.t
+++ /Users/kbullock/Source/Projects/hg/accept/tests/test-land.t.err
@@ -23,15 +23,8 @@
More complicated example built using debugbuilddag. This emulates a bug
encountered during the hg 4.6 freeze.
>>> import os
- >>> with open(os.environ['HG_ACCEPT_CONFIG']) as f:
- ... cfg = f.read()
- >>> cfglines = cfg.splitlines()
- >>> cfglines[-2] = cfglines[-2][:-len('source')] + 'complexsrc'
- >>> cfglines[-1] = cfglines[-1][:-len('target')] + 'complextgt'
- >>> with open(os.environ['HG_ACCEPT_CONFIG'], 'w') as f:
- ... f.write('\n'.join(cfglines))
-
- $ hg init complexsrc
+ /usr/bin/python: No module named heredoctest
+ [1]
$ hg init complextgt
$ cd complexsrc
$ hg debugbuilddag '. @stable +2 :pubhead <2 +2 :daggyfix /3 +1 :accepted +3'
@@ -81,20 +74,26 @@
We expect to get the hash of 7 as blocker
$ blocker
- 38e0ccfa60f109f813eba32713eada1543664dbf alice
+ ff05b7beb4519606efcf1cf8ccf7964280e566e9 alice
We expect to land 3::6.
$ land
+ hg: parse error: empty query
+ Traceback (most recent call last):
+ File "/Users/kbullock/Source/Projects/hg/accept/tests/../land", line 50, in <module>
+ conf.source, ' + '.join(all_accepted))))
+ File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 290, in load
+ **kw)
+ File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 338, in loads
+ return _default_decoder.decode(s)
+ File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 366, in decode
+ obj, end = self.raw_decode(s, idx=_w(s, 0).end())
+ File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 384, in raw_decode
+ raise ValueError("No JSON object could be decoded")
+ ValueError: No JSON object could be decoded
+ [1]
$ hg log -G -T'{rev}:{node|shortest} {branch} {tags}\n'
- o 6:ee2d stable tip
+ o 2:f3cf stable tip
|
- o 5:4721 stable
- |\
- | o 4:6cfb stable
- | |
- | o 3:0ccc stable
- | |
- o | 2:f3cf stable
- |/
o 1:a079 stable
|
o 0:1ea7 default
ERROR: test-land.t output changed
!
Failed test-land.t: output changed
# Ran 1 tests, 0 skipped, 1 failed.
python hash seed: 3774207118
---------- /test output
Also some nitpicks/suggestions, none blocking.
> @@ -32,29 +35,64 @@ for l in os.popen("hg log -R %s -r 'defa
>
> take = []
> takelog = ""
> -while True:
> - hit = False
> - for n in cq.draft():
> - a = cq.accepted(n)
> - if not a:
> - logging.debug("%s not accepted, skipping", n)
> - continue
> +
> +def _destcontains(node):
> + try:
> + return subprocess.check_output(
> + ['hg', 'log', '-R', dest, '-r', node, '-T.'],
> + stderr=subprocess.STDOUT) == '.'
Would be nice if this took a list of nodes.
> + except subprocess.CalledProcessError:
> + return False
> +
> +# Find all accepted revisions
> +all_accepted = [n for n in cq.draft() if cq.accepted(n)]
> +info = json.load(os.popen("hg log -R %s -r '%s' -Tjson" % (
> + conf.source, ' + '.join(all_accepted))))
You're using ' + '.join(all_accepted) enough times that it probably merits a name. Maybe also a helper function for doing 'hg log -R {conf.source} -r {revset} -T {template}'.
> +# dict of node: its parents.
> +parents = {i['node']: i['parents'] for i in info}
>
> - if cq.parent(n) not in heads:
> - logging.debug("last public ancestor of %s not in %s, skipping",
> - n, dest)
> - continue
> +# Identify heads and roots of accepted revision ranges
> +accepted_roots = {r.strip() for r in os.popen(
> + "hg log -R %s -r 'roots(%s)' -T'{node}\\n'" % (
> + conf.source, ' + '.join(all_accepted)))}
> +accepted_heads = [h.strip() for h in os.popen(
> + "hg log -R %s -r 'heads(%s)' -T'{node}\\n'" % (
> + conf.source, ' + '.join(all_accepted)))]
> +# Condense accepted revisions down into accepted ranges
> +range_ = collections.namedtuple('range', 'roots head')
A more specific name would be nice here.
pacem in terris / мир / शान्ति / سَلاَم / 平和
Kevin R. Bullock
More information about the Mercurial-devel
mailing list