views:

687

answers:

3

I'm using TortoiseHg 0.5 (which includes Mercurial 1.0.2) on Vista64. My understanding from the Mercurial Book is that Mercurial should handle filenames in a case-insensitive manner on a case-insensitive filesystem (such as NTFS, which is what I'm on). However I find that my installation of Mercurial is in fact sensitive to case:

>hg status -A foo
C foo
>hg status -A FOO
? FOO

Could this be a bug in Mercurial, a bug in the TortoiseHg build of Mercurial, or is it something else? How can I achieve case-insensitive filename handling from Mercurial on Windows?

+4  A: 

I think you misread the hgbook. The intro to section 7.7 is just describing the three different types of case sensitivity that exist in OSs, not saying that mercurial will mirror those semantics.

Later in section 7.7.2 'Detecting case conflicts' it says:

When operating in the working directory, Mercurial honours the naming policy of the filesystem where the working directory is located. If the filesystem is case preserving, but insensitive, Mercurial will treat names that differ only in case as the same.

When you do hg status -A FOO the process that's happening within mercurial is:

  1. Check if a file exists on the file system matching the file argument, 'FOO', -- and at this point it's being case insensitive so it finds 'foo' and says "yup, I've got a file"
  2. Check if there's an entry in the file manifest matching the file argument, 'FOO', and there isn't, so status shows a '?' saying it's a file on disk that hg isn't tracking

To better see mercurial not caring about case on NTFS try these steps:

  1. hg init
  2. echo line > Foo
  3. hg add Foo
  4. hg commit -m 'committed Foo'
  5. move Foo not-foo
  6. move not-foo FOO
  7. hg status

and you should see hg saying that nothing has changed because the only thing that has changed is the case which hg is ignoring for you.

When I do the same thing on linux I instead see:

! Foo
? FOO
Ry4an
A: 

Hi, thanks for your response. It was indeed this line that I was referring to: "If the filesystem is case preserving, but insensitive, Mercurial will treat names that differ only in case as the same." That is is exactly the behaviour I am desiring, and expecting, but not getting.

The result I get from step 7 of your example is:

? FOO

This is confusing. Does it not mean that Mercurial thinks the original file "Foo" has not been changed (indeed, this is true) but there is now a new unknown file "FOO" (false, if case is ignored)?

Further, if I then do the following:

  1. echo bleh > foo
  2. hg status

The result is:

M Foo
? FOO

So it sort of works, in that it does detect the change in the file. But there's still that spurious FOO, even though there's only 1 file in the directory! Surely this cannot be correct behaviour?

Mentat
I think that is the correct (if admittedly confusing) behavior. Mercurial will ignore case enough to connect a file in its manifest with a mis-cased files on your disk (the 'M' from above for 'Foo') but sees the differently cased version as another, possibly new file that is easy to ignore.
Ry4an
+6  A: 

This issue has been resolved in Mercurial 1.1! From the release notes: "Improved correctness in the face of casefolding filesystems".

On Windows, Mercurial now ignores case in its command line arguments:

>hg status -A foo
C foo
>hg status -A FOO
C foo

And it also is aware that filename changes that only involve case are not new files:

>ren foo FOO
>hg status -A fOO
C foo

Thus there's no longer any risk of overlooking changes due to mistypes on the command line.

However, be aware that the contents of the .hgignore file remain case sensitive. This is an issue only if you're using glob syntax; with regexp syntax you can put (?i) at the beginning of patterns to make them insensitive.

Mentat