[PATCH] Issue #839: prevent any file paths under .hg/store/data/ from getting too long

Adrian Buehlmann adrian at cadifra.com
Mon Jun 30 17:30:25 CDT 2008


On 30.06.2008 21:32, Jesse Glick wrote:
> # HG changeset patch
> # User Jesse Glick <jesse.glick at sun.com>
> # Date 1214853828 14400
> # Node ID 486d249d8e2188bf8309f2cad5f8b7024f06ec24
> # Parent  88a1bcc5c6a7b1729eb97d0509531c0f9f4a606e
> Issue #839: prevent any file paths under .hg/store/data/ from getting too long.

[snip]

> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py

[snip]

> @@ -101,6 +79,94 @@
>          self.filterpats = {}
>          self._datafilters = {}
>          self._transref = self._lockref = self._wlockref = None
> +
> +    def _setup_store(self, requirements, opener, pathjoiner):
> +        if "store" in requirements:
> +            self._longnames = None
> +            def load_longnames():
> +                if self._longnames == None:
> +                    self._longnames = {}
> +                    self._longnames_transient = {}
> +                    try:
> +                        self._longnames_file = opener(self.spath)('longnames',
> +                                                                  mode='a+')
> +                        for line in self._longnames_file:
> +                            datapath = line[0:-1]
> +                            sha1 = sha.new(datapath).hexdigest()
> +                            self._longnames[sha1] = datapath
> +                    except IOError, err:
> +                        if err.errno != errno.ENOENT:
> +                            raise
> +            maxlen = 150 - len('.hg/store/')
> +            def encode(s, write=False):
> +                r = util.encodefilename(s)
> +                if not s.startswith('data/'):
> +                    return r
> +                if len(r) <= maxlen:
> +                    return r
> +                try:
> +                    opener(self.spath)(r, "rb").close()
> +                    return r
> +                except IOError:
> +                    pass
> +                datapath = s[5:]
> +                sha1 = sha.new(datapath).hexdigest()
> +                load_longnames()

This is unneeded. We should only ever need to read the longnames file
during a streamclone.stream_out. That's the only use case which needs
the decoded filename. So we can at least defer reading the longnames file
until that happens.

> +                if not sha1 in self._longnames:
> +                    if write:
> +                        self._longnames[sha1] = datapath

I think this is unneeded. As it is, this line is executed for every
write access to a filelog.

We need to record a datapath only when a filelog file is newly created, and
that obviously happens only once per filelog, on the first filelog.add (that's
for example when then revlog.revlogio.packentry is called with rev == 0, which
packs the revlog header).

So we can append the datapath right away to the longnames file at that point.

Therefore, we should be able to eliminate self._longnames.

BTW, the longnames file needs to be added to the transaction.

[snipped the rest for now]


More information about the Mercurial-devel mailing list