[PATCH 3 of 3] Add a normalize() method to dirstate

Matt Mackall mpm at selenic.com
Thu May 22 21:46:23 UTC 2008


On Thu, 2008-05-22 at 21:20 +0100, Paul Moore wrote:
> 2008/5/21 Matt Mackall <mpm at selenic.com>:
> >
> > On Wed, 2008-05-21 at 22:49 +0100, Paul Moore wrote:
> >> +    def normalize(self, path):
> >> +        if not self._folding or path in self._map:
> >> +            return path
> >> +        elif path in self._folded:
> >> +            return self._folded[path]
> >> +        elif os.path.exists(path):
> >> +            return self._folded.setdefault(path, util.fspath(path, self._root))
> >
> > What if another variant of path is in self._map?
> 
> But I thought that self._map was the actual dirstate contents, and
> hence case sensitive? So given a pathname, we normalize it by
> returning it unchanged if we're on a case sensitive filesystem, or if
> the case matches the dirstate (regardless of the filesystem). It's
> only if the path as given isn't in the dirstate, *and* it exists in
> the filesystem, that we need to return the form actually stored in the
> filesystem.

Consider:

$ touch a
$ hg add a
$ hg ci

$ mv a A
$ echo new > A
$ hg ci A

Since Mercurial wasn't explicitly told about changing 'a' to 'A', we
need to treat all references to 'A' (whether from the command line or on
disk) as references to 'a' because 'a' is the case of the file we've
been told about.

Thus, to 'normalize' the file, we have to search the dirstate in a case
insensitive manner for the file we're interested in.

> > I think what's needed rather than _folding or _folded is something like:
> 
> Well, _folding tells us if we're on a case-insensitive system where we
> don't need any of this - so it's an optimization shortcut, and _folded
> is simply a cache of the results, so again it's for optimization.

And I'm taking it one step further. We only need one variable: _foldmap.
If _foldmap == {}, folding is not in effect.

In fact, we can do even better still: define normalize() dynamically:

if name == "normalize":
    if not checkfolding(...):
        self.normalize = self._fixcase()
    else:
        self.normalize = lambda x: x

And _fixcase() then never needs to check for case-sensitive filesystems,
because it only gets called on case-folding filesystems.

-- 
Mathematics is the supreme nostalgia of our time.




More information about the Mercurial-devel mailing list