convert: add a mode where mercurial_sink skips empty revisions.
The getchanges function of some converter_source classes can return
some false positives. I.e. they sometimes claim that a file "foo"
was changed in some revision, even though its contents are still the
same.
convert_svn is particularly bad, but I think this can also happen with
convert_cvs and, at least in theory, with mercurial_source.
For regular conversions this is not really a problem - as long as
getfile returns the right contents, we'll get a converted revision
with the right contents. But when we use --filemap, this could lead
to superfluous revisions being converted.
Instead of fixing every converter_source, I decided to change
mercurial_sink to work around this problem.
When --filemap is used, we're interested only in revisions that touch
some specific files. If a revision doesn't change any of these files,
then we're not interested in it (at least for revisions with a single
parent; merges are special).
For mercurial_sink, we abuse this property and rollback a commit if
the manifest text hasn't changed. This avoids duplicating the logic
from localrepo.filecommit to detect unchanged files.
#!/bin/sh
HGMERGE=true; export HGMERGE
hg init basic
cd basic
echo '# should complain'
hg backout
hg backout -r 0 0
echo '# basic operation'
echo a > a
hg commit -d '0 0' -A -m a
echo b >> a
hg commit -d '1 0' -m b
hg backout -d '2 0' tip
cat a
echo '# file that was removed is recreated'
cd ..
hg init remove
cd remove
echo content > a
hg commit -d '0 0' -A -m a
hg rm a
hg commit -d '1 0' -m b
hg backout -d '2 0' --merge tip
cat a
echo '# backout of backout is as if nothing happened'
hg backout -d '3 0' --merge tip
cat a 2>/dev/null || echo cat: a: No such file or directory
echo '# backout with merge'
cd ..
hg init merge
cd merge
echo line 1 > a
hg commit -d '0 0' -A -m a
echo line 2 >> a
hg commit -d '1 0' -m b
echo line 3 >> a
hg commit -d '2 0' -m c
hg backout --merge -d '3 0' 1
hg commit -d '4 0' -m d
cat a
echo '# backout should not back out subsequent changesets'
hg init onecs
cd onecs
echo 1 > a
hg commit -d '0 0' -A -m a
echo 2 >> a
hg commit -d '1 0' -m b
echo 1 > b
hg commit -d '2 0' -A -m c
hg backout -d '3 0' 1
hg locate b
cd ..
hg init m
cd m
echo a > a
hg commit -d '0 0' -A -m a
echo b > b
hg commit -d '1 0' -A -m b
echo c > c
hg commit -d '2 0' -A -m b
hg update 1
echo d > d
hg commit -d '3 0' -A -m c
hg merge 2
hg commit -d '4 0' -A -m d
echo '# backout of merge should fail'
hg backout 4
echo '# backout of merge with bad parent should fail'
hg backout --parent 0 4
echo '# backout of non-merge with parent should fail'
hg backout --parent 0 3
echo '# backout with valid parent should be ok'
hg backout -d '5 0' --parent 2 4
hg rollback
hg update -C
hg backout -d '6 0' --parent 3 4
exit 0