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
cat <<EOF >> $HGRCPATH
[extensions]
hgext.purge=
EOF
echo % init
hg init t
cd t
echo % setup
echo r1 > r1
hg ci -qAmr1 -d'0 0'
mkdir directory
echo r2 > directory/r2
hg ci -qAmr2 -d'1 0'
echo 'ignored' > .hgignore
hg ci -qAmr3 -d'2 0'
echo % delete an empty directory
mkdir empty_dir
hg purge -p
hg purge -v
ls
echo % delete an untracked directory
mkdir untracked_dir
touch untracked_dir/untracked_file1
touch untracked_dir/untracked_file2
hg purge -p
hg purge -v
ls
echo % delete an untracked file
touch untracked_file
hg purge -p
hg purge -v
ls
echo % delete an untracked file in a tracked directory
touch directory/untracked_file
hg purge -p
hg purge -v
ls
echo % delete nested directories
mkdir -p untracked_directory/nested_directory
hg purge -p
hg purge -v
ls
echo % delete nested directories from a subdir
mkdir -p untracked_directory/nested_directory
cd directory
hg purge -p
hg purge -v
cd ..
ls
echo % delete only part of the tree
mkdir -p untracked_directory/nested_directory
touch directory/untracked_file
cd directory
hg purge -p ../untracked_directory
hg purge -v ../untracked_directory
cd ..
ls
ls directory/untracked_file
rm directory/untracked_file
echo % skip ignored files if --all not specified
touch ignored
hg purge -p
hg purge -v
ls
hg purge -p --all
hg purge -v --all
ls
echo % abort with missing files until we support name mangling filesystems
touch untracked_file
rm r1
# hide error messages to avoid changing the output when the text changes
hg purge -p 2> /dev/null
if [ $? -ne 0 ]; then
echo "refused to run"
fi
if [ -f untracked_file ]; then
echo "untracked_file still around"
fi
hg purge -p --force
hg purge -v 2> /dev/null
if [ $? -ne 0 ]; then
echo "refused to run"
fi
if [ -f untracked_file ]; then
echo "untracked_file still around"
fi
hg purge -v --force
hg revert --all --quiet
ls
echo % skip excluded files
touch excluded_file
hg purge -p -X excluded_file
hg purge -v -X excluded_file
ls
rm excluded_file
echo % skip files in excluded dirs
mkdir excluded_dir
touch excluded_dir/file
hg purge -p -X excluded_dir
hg purge -v -X excluded_dir
ls
ls excluded_dir
rm -R excluded_dir
echo % skip excluded empty dirs
mkdir excluded_dir
hg purge -p -X excluded_dir
hg purge -v -X excluded_dir
ls
rmdir excluded_dir
echo % skip patterns
mkdir .svn
touch .svn/foo
mkdir directory/.svn
touch directory/.svn/foo
hg purge -p -X .svn -X '*/.svn'
hg purge -p -X re:.*.svn