phases: use revision number in new_heads
All graph operations will be done using revision numbers, so passing nodes only
means they will eventually get converted to revision numbers internally.
As part of an effort to align the code on using revision number we make the
`phases.newheads` function operated on revision number, taking them as input
and using them in returns, instead of the node-id it used to consume and
produce.
This is part of multiple changesets effort to translate more part of the logic,
but is done step by step to facilitate the identification of issue that might
arise in mercurial core and extensions.
To make the change simpler to handle for third party extensions, we also rename
the function, using a more modern form. This will help detecting the different
between the node-id version and the rev-num version.
I also take this as an opportunity to add some comment about possible
performance improvement for the future. They don't matter too much now, but they
are worse exploring in a while.
A python hook for "hg fix" that prints out the number of files and revisions
that were affected, along with which fixer tools were applied. Also checks how
many times it sees a specific key generated by one of the fixer tools defined
below.
$ cat >> $TESTTMP/postfixhook.py <<EOF
> import collections
> def file(ui, repo, rev=None, path=b'', metadata=None, **kwargs):
> ui.status(b'fixed %s in revision %d using %s\n' %
> (path, rev, b', '.join(metadata.keys())))
> def summarize(ui, repo, replacements=None, wdirwritten=False,
> metadata=None, **kwargs):
> counts = collections.defaultdict(int)
> keys = 0
> for fixername, metadatalist in metadata.items():
> for metadata in metadatalist:
> if metadata is None:
> continue
> counts[fixername] += 1
> if 'key' in metadata:
> keys += 1
> ui.status(b'saw "key" %d times\n' % (keys,))
> for name, count in sorted(counts.items()):
> ui.status(b'fixed %d files with %s\n' % (count, name))
> if replacements:
> ui.status(b'fixed %d revisions\n' % (len(replacements),))
> if wdirwritten:
> ui.status(b'fixed the working copy\n')
> EOF
Some mock output for fixer tools that demonstrate what could go wrong with
expecting the metadata output format.
$ printf 'new content\n' > $TESTTMP/missing
$ printf 'not valid json\0new content\n' > $TESTTMP/invalid
$ printf '{"key": "value"}\0new content\n' > $TESTTMP/valid
Configure some fixer tools based on the output defined above, and enable the
hooks defined above. Disable parallelism to make output of the parallel file
processing phase stable.
$ cat >> $HGRCPATH <<EOF
> [extensions]
> fix =
> [fix]
> metadatafalse:command=cat $TESTTMP/missing
> metadatafalse:pattern=metadatafalse
> metadatafalse:metadata=false
> missing:command=cat $TESTTMP/missing
> missing:pattern=missing
> missing:metadata=true
> invalid:command=cat $TESTTMP/invalid
> invalid:pattern=invalid
> invalid:metadata=true
> valid:command=cat $TESTTMP/valid
> valid:pattern=valid
> valid:metadata=true
> [hooks]
> postfixfile = python:$TESTTMP/postfixhook.py:file
> postfix = python:$TESTTMP/postfixhook.py:summarize
> [worker]
> enabled=false
> EOF
See what happens when we execute each of the fixer tools. Some print warnings,
some write back to the file.
$ hg init repo
$ cd repo
$ printf "old content\n" > metadatafalse
$ printf "old content\n" > invalid
$ printf "old content\n" > missing
$ printf "old content\n" > valid
$ hg add -q
$ hg fix -w
ignored invalid output from fixer tool: invalid
fixed metadatafalse in revision 2147483647 using metadatafalse
ignored invalid output from fixer tool: missing
fixed valid in revision 2147483647 using valid
saw "key" 1 times
fixed 1 files with valid
fixed the working copy
$ cat metadatafalse
new content
$ cat missing
old content
$ cat invalid
old content
$ cat valid
new content
$ cd ..