Bug 4578 - hg add is case sensitive on bare directory names
Summary: hg add is case sensitive on bare directory names
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 3.3.2
Hardware: PC Windows
: normal bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-03-28 11:23 UTC by Deanna Earley
Modified: 2015-04-08 01:00 UTC (History)
5 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Deanna Earley 2015-03-28 11:23 UTC
hg add seems to require exact case matching to add files.

D:\Projects\Media\MediaSharp>hg add common

D:\Projects\Media\MediaSharp>hg add Common
adding Common\MediaFrame.cs
adding Common\MediaSharpCommon.csproj
adding Common\MediaSink.cs
adding Common\MediaSource.cs
adding Common\Properties\AssemblyInfo.cs

D:\Projects\Media\MediaSharp>hg status common

D:\Projects\Media\MediaSharp>hg status Common
A Common\MediaFrame.cs
A Common\MediaSharpCommon.csproj
A Common\MediaSink.cs
A Common\MediaSource.cs
A Common\Properties\AssemblyInfo.cs

D:\Projects\Media\MediaSharp>

While I understand case sensitivity when referring to files already tracked, adding them from the file system should match the underlying file system's characteristics.

This seems to be a regression from past behaviour (http://bz.selenic.com/show_bug.cgi?id=3576#c4).
Comment 1 Matt Harbison 2015-03-28 13:15 UTC
(In reply to comment #0)

It's not a regression, because that fix only applied to the commit.

FWIW, I think it's reasonable that we normalize() for add and remove (or any wdir path?) if we do it for commits.  It can't be done for non wdir files though as you point out, so maybe it gets confusing for commands that operate on both (like status, diff)?  I'll let someone else mark it confirmed if they agree, in case there's a usability issue here.
Comment 2 Matt Mackall 2015-03-30 18:27 UTC
Actually, the cited bug has this bit:

Config\AddMeToTheRepo.txt

hg add config\addmetotherepo.txt
adding Config/AddMeToTheRepo.txt

..which shows hg normalizing the provided directory to match what's on the filesystem. So this does in fact sound like a regression. Needs bisecting.
Comment 3 Matt Harbison 2015-03-30 22:26 UTC
It looks like not matching the case when naming a file still works in 3.3.2, as it does in the referenced bug:

diff --git a/tests/test-add.t b/tests/test-add.t
--- a/tests/test-add.t
+++ b/tests/test-add.t
@@ -169,4 +169,16 @@
   $ cat d
   file d

+  $ mkdir CapsDir
+  $ echo abc > CapsDir/A.txt
+  $ hg add capsdir/a.txt
+  adding CapsDir\A.txt
+
+  $ hg forget capsdir/a.txt
+  not removing capsdir\a.txt: file is already untracked
+  removing CapsDir\A.txt
+  [1]
+
+  $ hg add -v capsdir
+
   $ cd ..

The problem is adding a directory that doesn't match the case.  That doesn't work in 2.2.1 either.  (Or 1.7 or 1.3.)  Also note the goofiness with forget when the file case isn't matched.

I'll dig further into this, but have no idea if I can figure this out by 4/1.
Comment 4 Matt Harbison 2015-03-30 23:14 UTC
It looks like things go awry dirstate.walk(), specifically step #2.

For 'hg add -v capsdir', results is {'.hg': None} and 'work' is 'CapsDir'.  In the "for f, kind, st in entries" loop, nf is normalized to 'CapsDir/A.txt'.  Skip down to the 'kind == regkind' branch.  nf is not in dmap, and it doesn't match the provided matcher, so it is dropped.

It seems to me that the matcher can't be tweaked to handle this, so it doesn't break non wdir cases.  And the file isn't in dmap, because it is currently unknown.
Comment 5 Matt Mackall 2015-03-31 05:50 UTC
Ok, downgrading from regression, thanks Matt! Trying to adjust the subject to capture this more precisely.

(adding Sid and Martin in case they're interested.)
Comment 6 Matt Harbison 2015-03-31 10:48 UTC
It looks like the easiest thing to do is change 'work' from a list of normalized directories, to a list of tuples: (normalized, notnormalized), and pass notnormalized to the matcher.  I'll have a patch after the full test suite finishes.
Comment 7 HG Bot 2015-03-31 17:16 UTC
Fixed by http://selenic.com/repo/hg/rev/2bb13f2b778c
Matt Harbison <matt_harbison@yahoo.com>
dirstate: don't require exact case when adding dirs on icasefs (issue4578)

We don't require it when adding files on a case insensitive filesystem, so don't
require it to add directories for consistency.

The problem with the previous code was that _walkexplicit() was only returning
the normalized directory.  The file(s) in the directory are then appended, and
passed to the matcher.  But if the user asks for 'capsdir1/capsdir', the matcher
will not accept 'CapsDir1/CapsDir/AbC.txt', and the name is dropped.  Matching
based on the non-normalized name is required.

If not normalizing, skip the extra string building for efficiency.  '.' is
replaced with '' so that the path being tested when no file is specified, isn't
prefixed with './' (and therefore fail the match).

(please test the fix)
Comment 8 Bugzilla 2015-04-08 01:00 UTC
Bug was set to TESTING for 7 days, resolving