match: add a subclass for dirstate normalizing of the matched patterns
This class is only needed on case insensitive filesystems, and only
for wdir context matches. It allows the user to not match the case of
the items in the filesystem- especially for naming directories, which
dirstate doesn't handle[1]. Making dirstate handle mismatched
directory cases is too expensive[2].
Since dirstate doesn't apply to committed csets, this is only created by
overriding basectx.match() in workingctx, and only on icasefs. The default
arguments have been dropped, because the ctx must be passed to the matcher in
order to function.
For operations that can apply to both wdir and some other context, this ends up
normalizing the filename to the case as it exists in the filesystem, and using
that case for the lookup in the other context. See the diff example in the
test.
Previously, given a directory with an inexact case:
- add worked as expected
- diff, forget and status would silently ignore the request
- files would exit with 1
- commit, revert and remove would fail (even when the commands leading up to
them worked):
$ hg ci -m "AbCDef" capsdir1/capsdir
abort: CapsDir1/CapsDir: no match under directory!
$ hg revert -r '.^' capsdir1/capsdir
capsdir1\capsdir: no such file in rev
64dae27060b7
$ hg remove capsdir1/capsdir
not removing capsdir1\capsdir: no tracked files
[1]
Globs are normalized, so that the -I and -X don't need to be specified with a
case match. Without that, the second last remove (with -X) removes the files,
leaving nothing for the last remove. However, specifying the files as
'glob:**.Txt' does not work. Perhaps this requires 're.IGNORECASE'?
There are only a handful of places that create matchers directly, instead of
being routed through the context.match() method. Some may benefit from changing
over to using ctx.match() as a factory function:
revset.checkstatus()
revset.contains()
revset.filelog()
revset._matchfiles()
localrepository._loadfilter()
ignore.ignore()
fileset.subrepo()
filemerge._picktool()
overrides.addlargefiles()
lfcommands.lfconvert()
kwtemplate.__init__()
eolfile.__init__()
eolfile.checkrev()
acl.buildmatch()
Currently, a toplevel subrepo can be named with an inexact case. However, the
path auditor gets in the way of naming _anything_ in the subrepo if the top
level case doesn't match. That is trickier to handle, because there's the user
provided case, the case in the filesystem, and the case stored in .hgsub. This
can be fixed next cycle.
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -170,8 +170,15 @@
R sub1/sub2/test.txt
$ hg update -Cq
$ touch sub1/sub2/folder/bar
+#if icasefs
+ $ hg addremove Sub1/sub2
+ abort: path 'Sub1\sub2' is inside nested repo 'Sub1'
+ [255]
+ $ hg -q addremove sub1/sub2
+#else
$ hg addremove sub1/sub2
adding sub1/sub2/folder/bar (glob)
+#endif
$ hg status -S
A sub1/sub2/folder/bar
? foo/bar/abc
The narrowmatcher class may need to be tweaked when that is fixed.
[1] http://www.selenic.com/pipermail/mercurial-devel/2015-April/068183.html
[2] http://www.selenic.com/pipermail/mercurial-devel/2015-April/068191.html
#require darcs
$ echo "[extensions]" >> $HGRCPATH
$ echo "convert=" >> $HGRCPATH
$ DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
initialize darcs repo
$ mkdir darcs-repo
$ cd darcs-repo
$ darcs init
$ echo a > a
$ darcs record -a -l -m p0
Finished recording patch 'p0'
$ cd ..
branch and update
$ darcs get -q darcs-repo darcs-clone >/dev/null
$ cd darcs-clone
$ echo c >> a
$ echo c > c
$ darcs record -a -l -m p1.1
Finished recording patch 'p1.1'
$ cd ..
skip if we can't import elementtree
$ if hg convert darcs-repo darcs-dummy 2>&1 | grep ElementTree > /dev/null; then
> echo 'skipped: missing feature: elementtree module'
> exit 80
> fi
update source
$ cd darcs-repo
$ echo b >> a
$ echo b > b
$ darcs record -a -l -m p1.2
Finished recording patch 'p1.2'
$ darcs pull -q -a --no-set-default ../darcs-clone
Backing up ./a(*) (glob)
We have conflicts in the following files:
./a
$ sleep 1
$ echo e > a
$ echo f > f
$ mkdir dir
$ echo d > dir/d
$ echo d > dir/d2
$ darcs record -a -l -m p2
Finished recording patch 'p2'
test file and directory move
$ darcs mv f ff
Test remove + move
$ darcs remove dir/d2
$ rm dir/d2
$ darcs mv dir dir2
$ darcs record -a -l -m p3
Finished recording patch 'p3'
The converter does not currently handle patch conflicts very well.
When they occur, it reverts *all* changes and moves forward,
letting the conflict resolving patch fix collisions.
Unfortunately, non-conflicting changes, like the addition of the
"c" file in p1.1 patch are reverted too.
Just to say that manifest not listing "c" here is a bug.
$ cd ..
$ hg convert darcs-repo darcs-repo-hg
initializing destination darcs-repo-hg repository
scanning source...
sorting...
converting...
4 p0
3 p1.2
2 p1.1
1 p2
0 p3
$ hg log -R darcs-repo-hg -g --template '{rev} "{desc|firstline}" ({author}) files: {files}\n' "$@"
4 "p3" (test@example.org) files: dir/d dir/d2 dir2/d f ff
3 "p2" (test@example.org) files: a dir/d dir/d2 f
2 "p1.1" (test@example.org) files:
1 "p1.2" (test@example.org) files: a b
0 "p0" (test@example.org) files: a
$ hg up -q -R darcs-repo-hg
$ hg -R darcs-repo-hg manifest --debug
7225b30cdf38257d5cc7780772c051b6f33e6d6b 644 a
1e88685f5ddec574a34c70af492f95b6debc8741 644 b
37406831adc447ec2385014019599dfec953c806 644 dir2/d
b783a337463792a5c7d548ad85a7d3253c16ba8c 644 ff
#if no-outer-repo
try converting darcs1 repository
$ hg clone -q "$TESTDIR/bundles/darcs1.hg" darcs
$ hg convert -s darcs darcs/darcs1 2>&1 | grep darcs-1.0
darcs-1.0 repository format is unsupported, please upgrade
#endif