[PATCH 3 of 3] introduce filenamelog repository layout

Adrian Buehlmann adrian at cadifra.com
Tue Jul 22 16:42:35 UTC 2008


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1216744401 -7200
# Node ID dae37f36c374f86e9547a54e00238076bdfc8140
# Parent  96e83d0c1cda5e4ae5082c9f253211e266643578
introduce filenamelog repository layout

* adds a new entry 'filenamelog' to '.hg/requires' for new repos
* writes new file '.hg/store/filenamelog'
* hash-encodes filenames with long paths (issue839)
* encodes Windows reserved filenames (issue793)
* provides a new command 'debugfilenamelog'
* adds new test-filenamelog

The new repository layout uses the following directories to store filelog
files on disk:

  directory       content

  .hg/store/df    filelog files with full (unhashed) filenames
  .hg/store/dh    filelog files with hashed filenames

filelog.filelog internally still uses the current path naming scheme
('.hg/store/data/...', A-paths below).

The mapping to the new disk directories is done by the new path encoding
function store.fnlogencode, which uses a hybrid path encoding scheme that
switches to non-reversible hashed paths if the reversible encoding
(store.auxencode) would result in a path part below '.hg/store' that is longer
than store.MAX_PATH_LEN_IN_HGSTORE.

If filelog.filelog wants to open a path A, the path is mapped to the disk
path B by the opener. Note that A-paths are already encoded by
filelog.filelog.encodedir, which for example encodes directory
'foo.i' to 'foo.i.hg' to avoid colliding an implicitly tracked directory
'foo.i' with a tracked file 'foo' (which would be stored as 'foo.i' and
'foo.d').

Encoding example for a short path (store.auxencode, non-hashed, reversible):

 (A) data/aux.bla/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c.i
 (B) df/au~78.bla/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i

Encoding examples for long paths (store.fnlogencode, hashed, non-reversible):

 (A1) data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT.i
 (B1) dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m_iba080978ea6d02c60ae2fe111568dd5f14461c8c.i

 (A2) data/enterprise/openesbaddons/contrib-imola/corba-bc/nbp/ext/src/main/java/it/imolinfo/jbi4corba/netbeansplugin/wsdlextension/resources/onmessage16x16.png.i
 (B2) dh/enterpri/openesba/contrib-/corba-bc/nbp/ext/src/main/java/it/onmessage16x16df735b8ce33061a8c8a420542372154b3400400b.i

 (A3) data/THE-QUICK-BROWN-FOX-JUMPS-OVER-THE-LAZY-DOG-THE-QUICK-BROWN-FOX-JUMPS-OVER-THE-LAZY-DOG.TXT.i
 (B3) dh/_t_h_e-_q_u_i_c_k-_b_r_o_w_n-_f_o_x-_j_u_m_p_s-_o_v_e_r-_t_h_e-_l_a_z_y-_d_da1f286dbbd35cd830e0e7feb4c79e887e60543d.i

Since a hashing encoding is not reversible, a decoding function for the B-paths
is not provided. The only part that needed the reversible encoding was
streamclone, which walked the directory tree under '.hg/store/data' to enumerate
all filelog files on disk and decoded their path names, in order to send the
unencoded A-names over the wire.

Instead of a reverse path encoding function, a list of all filelog files is now
maintained in the new file '.hg/store/filenamelog', which simply contains a \n
separated list of all A-paths in the repository.

If a new *.i or *.d file is created in the store, a new entry is appended to
'.hg/store/filenamelog'. That file is checked for completeness by hg verify.

streamclone now uses the filenamelog and thus doesn't need to walk the store and
no longer depends on having a reversible filename encoding.

As a side effect, streamclone now no longer needs to lock the repo for doing a
lengthy directory tree walk. The effect of this is that when doing a
'hg clone --uncompressed' on the client side, for example the output

  streaming all changes
  5318 files to transfer, 59.6 MB of data

appears quickly, whereas, before this change, it took a couple of seconds to
complete the directory walk on the server, before these lines appeared on the
client side. This also reduces the locking time on the server repo.
Note: To enable streamcloning, '[server] uncompressed = True' in the hgrc
on the server side is needed, which defaults to 'False' if omitted.

This change depends on the fact that 'hg strip' truncates filelog files to zero
length instead of deleting them. If strip should ever start deleting empty
filelogs, there will be duplicate entries in the filenamelog if filelogs are
recreated.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -635,6 +635,31 @@
         return
 
     ui.write("%s\n" % "\n".join(util.sort(cmdutil.findpossible(ui, cmd, table))))
+
+def debugfilenamelog(ui, repo, **opts):
+    """dumps the filenamelog, showing the encoded filename for each entry
+
+    Writes two lines of output per filenamelog entry: The first line is the
+    filenamelog entry itself, the second line is the encoded filename.
+
+    By default, outputs the hashed filenames only. Specify -f to output
+    only the full name (non-hased) filenames, or -a to get both.
+
+    Specify -q to suppress the statistic printed at the end.
+    """
+    all = opts["all"]
+    fullonly = opts["full"]
+    n = 0
+    nh = 0
+    for f in repo.store.readfnlog():
+        ef = repo.store.encodefn(f)
+        hashed = ef.startswith('dh/')
+        if hashed:
+          nh += 1
+        if all or (hashed and not fullonly) or (fullonly and not hashed):
+            ui.write("   '%s'\n-> '%s'\n" % (f, ef))
+        n += 1
+    ui.status("(filenamelog has %i filenames, %i hashed)\n" % (n, nh))
 
 def debugfsinfo(ui, path = "."):
     file('.debugfsinfo', 'w').write('')
@@ -3023,6 +3048,11 @@
          [('e', 'extended', None, _('try extended date formats'))],
          _('hg debugdate [-e] DATE [RANGE]')),
     "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
+    "debugfilenamelog": 
+        (debugfilenamelog,
+         [('a', 'all', None, _('list all entries')),
+          ('f', 'full', None, _('list only the full name entries'))],
+         _('hg debugfilenamelog [OPTION]')),
     "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
     "debugindex": (debugindex, [], _('hg debugindex FILE')),
     "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
diff --git a/mercurial/filenamelog.py b/mercurial/filenamelog.py
new file mode 100644
--- /dev/null
+++ b/mercurial/filenamelog.py
@@ -0,0 +1,44 @@
+# filenamelog.py - logging all filenames of a Mercurial repository
+#
+# Copyright 2008 Matt Mackall <mpm at selenic.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+from i18n import _
+import util
+
+LOGNAME = 'filenamelog'
+
+def abort(text, linenum = None):
+    lineinfo = ""
+    if (linenum != None):
+        lineinfo = ", line %i" % linenum
+    raise util.Abort("%s%s: %s" % (LOGNAME, lineinfo, text))
+
+def append(opener, entries, transaction):
+    if len(entries) == 0:
+        return
+    fp = opener(LOGNAME, mode='a+')
+    fp.seek(0, 2)
+    offset = fp.tell()
+    if transaction != None:
+        transaction.add(LOGNAME, offset)
+    for p in entries:
+        fp.write(p + '\n') # assuming that filenames don't contain '\n'
+    fp.close()
+
+def entries(opener):
+    # yields: path, line number
+    n = 1
+    try:
+        fp = opener(LOGNAME, mode='rb')
+    except IOError:
+        # skip nonexisting file
+        return
+    n = 1
+    for line in fp:
+        if (len(line) < 2) or (line[-1] != '\n'):
+            abort(_('invalid entry'), LOGNAME, n)
+        yield line[:-1], n
+        n += 1
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -197,7 +197,9 @@
             # we lock here to avoid premature writing to the target
             dest_lock = lock.lock(os.path.join(dest_store, "lock"))
 
-            files = ("data",
+            files = ("data",              # for old non-filenamelog repos
+                     "df", "dh",          # for filenamelog repos
+                     "filenamelog",
                      "00manifest.d", "00manifest.i",
                      "00changelog.d", "00changelog.i")
             for f in files:
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -15,7 +15,7 @@
 
 class localrepository(repo.repository):
     capabilities = util.set(('lookup', 'changegroupsubset'))
-    supported = ('revlogv1', 'store')
+    supported = ('revlogv1', 'store', 'filenamelog')
 
     def __init__(self, parentui, path=None, create=0):
         repo.repository.__init__(self)
@@ -34,6 +34,7 @@
                 if parentui.configbool('format', 'usestore', True):
                     os.mkdir(os.path.join(self.path, "store"))
                     requirements.append("store")
+                    requirements.append("filenamelog")
                     # create an invalid changelog
                     self.opener("00changelog.i", "a").write(
                         '\0\0\0\2' # represents revlogv2
@@ -62,6 +63,7 @@
 
         self.store = store.store(requirements, self.path)
 
+        self.spath = self.store.path
         self.sopener = self.store.opener
         self.sjoin = self.store.join
         self._createmode = self.store.createmode
@@ -892,6 +894,7 @@
 
             n = self.changelog.add(mn, changed + removed, text, trp, p1, p2,
                                    user, wctx.date(), extra)
+            self.store.addnewfiles(tr)
             self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
                       parent2=xp2)
             tr.close()
@@ -1963,6 +1966,8 @@
             # make changelog see real files again
             cl.finalize(trp)
 
+            self.store.addnewfiles(tr)
+
             newheads = len(self.changelog.heads())
             heads = ""
             if oldheads and newheads != oldheads:
@@ -2037,6 +2042,7 @@
             for chunk in util.filechunkiter(fp, limit=size):
                 ofp.write(chunk)
             ofp.close()
+        self.store.addnewfiles(None)
         elapsed = time.time() - start
         if elapsed <= 0:
             elapsed = 0.001
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
 
-import os, stat, osutil, util
+import os, stat, sha, osutil, util, filenamelog
 
 def _buildencodefun():
     e = '_'
@@ -34,6 +34,83 @@
             lambda s: "".join(list(decode(s))))
 
 encodefilename, decodefilename = _buildencodefun()
+
+_windows_reserved_filenames = '''con prn aux nul
+    com1 com2 com3 com4 com5 com6 com7 com8 com9
+    lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
+def auxencode(path):
+    res = []
+    for n in path.split('/'):
+        if n:
+            base = n.split('.')[0]
+            if base and (base in _windows_reserved_filenames):
+                # encode third letter ('aux' -> 'au~78')
+                ec = "~%02x" % ord(n[2])
+                n = n[0:2] + ec + n[3:]
+        res.append(n)
+    return '/'.join(res)
+
+MAX_PATH_LEN_IN_HGSTORE = 120
+DIR_PREFIX_LEN = 8
+_MAX_SHORTED_DIRS_LEN = 8 * (DIR_PREFIX_LEN + 1) - 4
+def fnlogencode(path):
+    '''encodes path with a length limit
+
+    Encodes all paths that begin with 'data/', according to the following.
+
+    Default encoding (reversible):
+
+    Encodes all uppercase letters 'X' as '_x'. All reserved or illegal
+    characters are encoded as '~xx', where xx is the two digit hex code
+    of the character (see encodefilename).
+    Relevant path components consisting of Windows reserved filenames are
+    masked by encoding the third character ('aux' -> 'au~78', see auxencode).
+
+    Hashed encoding (not reversible):
+
+    If the default-encoded path is longer than MAX_PATH_LEN_IN_HGSTORE, a
+    non-reversible hybrid hashing of the path is done instead.
+    This encoding uses up to DIR_PREFIX_LEN characters of all directory
+    levels of the default encoded path, but not more levels than can fit into
+    _MAX_SHORTED_DIRS_LEN.
+    Then follows the filler followed by the sha digest of the full path.
+    The filler is the beginning of the basename of the default-encoded path
+    (the basename is everything after the last path separator). The filler
+    is as long as possible, filling in characters from the basename until
+    the encoded path has MAX_PATH_LEN_IN_HGSTORE characters (or all chars
+    of the basename have been taken).
+    The extension (e.g. '.i' or '.d') is preserved.
+
+    The string 'data/' at the beginning is replaced with 'df/', if the default
+    encoding was used. If the hashed encoding was used, it is replaced with
+    'dh/'
+    '''
+    if not path.startswith('data/'):
+        return path
+    ndpath = path[len('data/'):]
+    aep = auxencode(encodefilename(ndpath))
+    res = 'df/' + aep
+    if len(res) > MAX_PATH_LEN_IN_HGSTORE:
+        digest = sha.new(path).hexdigest()
+        root, ext = os.path.splitext(aep)
+        parts = aep.split('/')
+        basename = parts[-1]
+        shorteddirs = []
+        for p in parts[:-1]:
+            d = p[:DIR_PREFIX_LEN]
+            t = '/'.join(shorteddirs) + '/' + d
+            if len(t) > _MAX_SHORTED_DIRS_LEN:
+                break
+            shorteddirs.append(d)
+        dirs = '/'.join(shorteddirs)
+        if len(dirs) > 0:
+            dirs += '/'
+        res = 'dh/' + dirs + digest + ext
+        space_left = MAX_PATH_LEN_IN_HGSTORE - len(res)
+        if space_left > 0:
+            filler = basename[:space_left]
+            res = 'dh/' + dirs + filler + digest + ext
+    return res
 
 def _dirwalk(path, recurse):
     '''yields (filename, size)'''
@@ -90,6 +167,16 @@
         for x in meta:
             yield x
 
+    def addnewfiles(self, transaction):
+        pass
+
+    def hasfnlog(self):
+        return False
+
+    def readfnlog(self):
+        res = {}
+        return res
+
 class directstore(_store):
     def __init__(self, path):
         _store.__init__(self, path)
@@ -112,14 +199,66 @@
     def join(self, f):
         return os.path.join(self.path, self.encodefn(f))
 
+class _loggingopener(util.opener):
+    '''encoding COW opener which logs new files'''
+    def __init__(self, encodefn, base, createmode):
+        util.opener.__init__(self, base)
+        self.encodefn = encodefn
+        self.createmode = createmode
+        self.reset()
+
+    def reset(self):
+        self._newfiles = []
+
+    def __call__(self, path, mode="r", text=False, atomictemp=False):
+        epath = self.encodefn(path)
+        fp, nlink = self.open(epath, mode, text, atomictemp)
+        if (nlink == 0) and path.startswith('data/'):
+            self._newfiles.append(path)
+        return fp
+
+    def addnewfiles(self, tr):
+        filenamelog.append(self, self._newfiles, tr)
+        self.reset()
+
+class fnlogstore(_store):
+    def __init__(self, path):
+        _store.__init__(self, os.path.join(path, 'store'))
+        self.encodefn = fnlogencode
+        self.opener = _loggingopener(self.encodefn, self.path, self.createmode)
+
+    def _datafiles(self):
+        for p, n in filenamelog.entries(self.opener):
+            st = os.stat(self.join(p))
+            yield p, st.st_size
+
+    def join(self, f):
+        return os.path.join(self.path, self.encodefn(f))
+
+    def addnewfiles(self, transaction):
+        self.opener.addnewfiles(transaction)
+
+    def hasfnlog(self):
+        return True
+
+    def readfnlog(self):
+        res = {}
+        for p, n in filenamelog.entries(self.opener):
+            res[p] = n
+        return res
+
 def encodefn(requirements):
     if 'store' not in requirements:
         return lambda x: x
+    elif 'filenamelog' in requirements:
+        return fnlogencode
     else:
         return encodefilename
 
 def store(requirements, path):
     if 'store' not in requirements:
         return directstore(path)
+    elif 'filenamelog' in requirements:
+        return fnlogstore(path)
     else:
         return encodedstore(path)
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1459,7 +1459,7 @@
             return
         os.chmod(name, self.createmode & 0666)
 
-    def __call__(self, path, mode="r", text=False, atomictemp=False):
+    def open(self, path, mode, text, atomictemp):
         self.audit_path(path)
         f = os.path.join(self.base, path)
 
@@ -1476,13 +1476,16 @@
                 if not os.path.isdir(d):
                     makedirs(d, self.createmode)
             if atomictemp:
-                return atomictempfile(f, mode, self.createmode)
+                return atomictempfile(f, mode, self.createmode), nlink
             if nlink > 1:
                 rename(mktempcopy(f), f)
         fp = posixfile(f, mode)
         if nlink == 0:
             self._fixfilemode(f)
-        return fp
+        return fp, nlink
+
+    def __call__(self, path, mode="r", text=False, atomictemp=False):
+        return self.open(path, mode, text, atomictemp)[0]
 
     def symlink(self, src, dst):
         self.audit_path(dst)
diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -93,6 +93,23 @@
         seen[n] = i
         return lr
 
+    def filenamelogchecker(repo):
+        if not repo.store.hasfnlog():
+            return lambda fl, f: None
+        fnlog = repo.store.readfnlog()
+        def err(text):
+            ui.warn(" filenamelog: %s\n" % text)
+            errors[0] += 1
+        def checkidfile(fl, f, type):
+            idfile = getattr(fl, type + 'file')
+            if not idfile in fnlog:
+                err("missing %sfile entry for '%s'" % (type, f))
+        def check(fl, f):
+            checkidfile(fl, f, 'index')
+            if not fl._inline:
+                checkidfile(fl, f, 'data')
+        return check
+
     revlogv1 = cl.version != revlog.REVLOGV0
     if ui.verbose or not revlogv1:
         ui.status(_("repository uses revlog format %d\n") %
@@ -158,9 +175,11 @@
                 err(lr, _("in manifest but not in changeset"), f)
 
     ui.status(_("checking files\n"))
+    checkfnlog = filenamelogchecker(repo)
     files = util.sort(util.unique(filenodes.keys() + filelinkrevs.keys()))
     for f in files:
         fl = repo.file(f)
+        checkfnlog(fl, f)
         checklog(fl, f)
         seen = {}
         for i in fl:
diff --git a/tests/test-bundle-r b/tests/test-bundle-r
--- a/tests/test-bundle-r
+++ b/tests/test-bundle-r
@@ -41,10 +41,10 @@
 hg update -C 3
 hg mv afile anotherfile
 hg commit -m "0.3m" -d "1000000 0"
-hg debugindex .hg/store/data/afile.i
-hg debugindex .hg/store/data/adifferentfile.i
-hg debugindex .hg/store/data/anotherfile.i
-hg debugindex .hg/store/data/fred.i
+hg debugindex .hg/store/df/afile.i
+hg debugindex .hg/store/df/adifferentfile.i
+hg debugindex .hg/store/df/anotherfile.i
+hg debugindex .hg/store/df/fred.i
 hg debugindex .hg/store/00manifest.i
 hg verify
 cd ..
diff --git a/tests/test-changelog-exec b/tests/test-changelog-exec
--- a/tests/test-changelog-exec
+++ b/tests/test-changelog-exec
@@ -29,4 +29,4 @@
 echo '% this should not mention bar:'
 hg tip -v
 
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
diff --git a/tests/test-clone-r b/tests/test-clone-r
--- a/tests/test-clone-r
+++ b/tests/test-clone-r
@@ -41,10 +41,10 @@
 hg update -C 3
 hg mv afile anotherfile
 hg commit -m "0.3m"
-hg debugindex .hg/store/data/afile.i
-hg debugindex .hg/store/data/adifferentfile.i
-hg debugindex .hg/store/data/anotherfile.i
-hg debugindex .hg/store/data/fred.i
+hg debugindex .hg/store/df/afile.i
+hg debugindex .hg/store/df/adifferentfile.i
+hg debugindex .hg/store/df/anotherfile.i
+hg debugindex .hg/store/df/fred.i
 hg debugindex .hg/store/00manifest.i
 hg verify
 cd ..
diff --git a/tests/test-commit-copy b/tests/test-commit-copy
--- a/tests/test-commit-copy
+++ b/tests/test-commit-copy
@@ -11,4 +11,4 @@
 hg ci -m 'cp bar foo; change bar'
 
 hg debugrename foo
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
diff --git a/tests/test-copy b/tests/test-copy
--- a/tests/test-copy
+++ b/tests/test-copy
@@ -13,16 +13,16 @@
 echo "we should see one log entry for a"
 hg log a
 echo "this should show a revision linked to changeset 0"
-hg debugindex .hg/store/data/a.i
+hg debugindex .hg/store/df/a.i
 echo "we should see one log entry for b"
 hg log b
 echo "this should show a revision linked to changeset 1"
-hg debugindex .hg/store/data/b.i
+hg debugindex .hg/store/df/b.i
 
 echo "this should show the rename information in the metadata"
-hg debugdata .hg/store/data/b.d 0 | head -3 | tail -2
+hg debugdata .hg/store/df/b.d 0 | head -3 | tail -2
 
-$TESTDIR/md5sum.py .hg/store/data/b.i
+$TESTDIR/md5sum.py .hg/store/df/b.i
 hg cat b > bsum
 $TESTDIR/md5sum.py bsum
 hg cat a > asum
diff --git a/tests/test-copy.out b/tests/test-copy.out
--- a/tests/test-copy.out
+++ b/tests/test-copy.out
@@ -41,7 +41,7 @@
 this should show the rename information in the metadata
 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
 copy: a
-ed156f22f0a6fde642de0b5eba0cbbb2  .hg/store/data/b.i
+ed156f22f0a6fde642de0b5eba0cbbb2  .hg/store/df/b.i
 60b725f10c9c85c70d97880dfe8191b3  bsum
 60b725f10c9c85c70d97880dfe8191b3  asum
 checking changesets
diff --git a/tests/test-copy2 b/tests/test-copy2
--- a/tests/test-copy2
+++ b/tests/test-copy2
@@ -31,7 +31,7 @@
 hg st -C
 
 echo "# should match"
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 hg debugrename bar
 
 echo bleah > foo
@@ -47,9 +47,9 @@
 hg commit -m3 -d"0 0"
 
 echo "# should show no parents for tip"
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 echo "# should match"
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 hg debugrename bar
 
 echo "# should show no copies"
diff --git a/tests/test-debugcomplete.out b/tests/test-debugcomplete.out
--- a/tests/test-debugcomplete.out
+++ b/tests/test-debugcomplete.out
@@ -64,6 +64,7 @@
 debugconfig
 debugdata
 debugdate
+debugfilenamelog
 debugfsinfo
 debugindex
 debugindexdot
diff --git a/tests/test-debugindexdot b/tests/test-debugindexdot
--- a/tests/test-debugindexdot
+++ b/tests/test-debugindexdot
@@ -14,4 +14,4 @@
 HGMERGE=true hg merge -q
 hg ci -m merge -d '3 0'
 
-hg debugindexdot .hg/store/data/a.i
+hg debugindexdot .hg/store/df/a.i
diff --git a/tests/test-dumprevlog b/tests/test-dumprevlog
--- a/tests/test-dumprevlog
+++ b/tests/test-dumprevlog
@@ -2,6 +2,7 @@
 
 CONTRIBDIR=$TESTDIR/../contrib
 
+echo % prepare repo-a
 mkdir repo-a
 cd repo-a
 hg init
@@ -18,11 +19,13 @@
 
 hg verify
 
-echo dumping revlog of file a to stdout:
-python $CONTRIBDIR/dumprevlog .hg/store/data/a.i
-echo dumprevlog done
+echo
+echo % dumping revlog of file a to stdout
+python $CONTRIBDIR/dumprevlog .hg/store/df/a.i
+echo % dumprevlog done
 
-# dump all revlogs to file repo.dump
+echo
+echo % dump all revlogs to file repo.dump
 find .hg/store -name "*.i" | sort | xargs python $CONTRIBDIR/dumprevlog > ../repo.dump
 
 cd ..
@@ -31,17 +34,28 @@
 cd repo-b
 hg init
 
-echo undumping:
+echo
+echo % undumping into repo-b
 python $CONTRIBDIR/undumprevlog < ../repo.dump
-echo undumping done
+echo % undumping done
 
+cd ..
+
+echo
+echo % clone --pull repo-b repo-c  to rebuild filenamelog
+hg clone --pull -U repo-b repo-c
+
+cd repo-c
+
+echo
+echo % verify repo-c
 hg verify
 
 cd ..
 
-echo comparing repos:
-hg -R repo-b incoming repo-a
-hg -R repo-a incoming repo-b
-echo comparing done
+echo
+echo % comparing repos
+hg -R repo-c incoming repo-a
+hg -R repo-a incoming repo-c
 
 exit 0
diff --git a/tests/test-dumprevlog.out b/tests/test-dumprevlog.out
--- a/tests/test-dumprevlog.out
+++ b/tests/test-dumprevlog.out
@@ -1,10 +1,12 @@
+% prepare repo-a
 checking changesets
 checking manifests
 crosschecking files in changesets and manifests
 checking files
 1 files, 3 changesets, 3 total revisions
-dumping revlog of file a to stdout:
-file: .hg/store/data/a.i
+
+% dumping revlog of file a to stdout
+file: .hg/store/df/a.i
 node: 183d2312b35066fb6b3b449b84efc370d50993d0
 linkrev: 0
 parents: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
@@ -32,22 +34,34 @@
 adding more to file a
 
 -end-
-dumprevlog done
-undumping:
+% dumprevlog done
+
+% dump all revlogs to file repo.dump
+
+% undumping into repo-b
 .hg/store/00changelog.i
 .hg/store/00manifest.i
-.hg/store/data/a.i
-undumping done
+.hg/store/df/a.i
+% undumping done
+
+% clone --pull repo-b repo-c to rebuild filenamelog
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 3 changes to 1 files
+
+% verify repo-c
 checking changesets
 checking manifests
 crosschecking files in changesets and manifests
 checking files
 1 files, 3 changesets, 3 total revisions
-comparing repos:
+
+% comparing repos
 comparing with repo-a
 searching for changes
 no changes found
-comparing with repo-b
+comparing with repo-c
 searching for changes
 no changes found
-comparing done
diff --git a/tests/test-encode b/tests/test-encode
--- a/tests/test-encode
+++ b/tests/test-encode
@@ -22,7 +22,7 @@
 hg status
 
 echo %% uncompressed contents in repo
-hg debugdata .hg/store/data/a.gz.d 0
+hg debugdata .hg/store/df/a.gz.d 0
 
 echo %% uncompress our working dir copy
 gunzip < a.gz
diff --git a/tests/test-excessive-merge b/tests/test-excessive-merge
--- a/tests/test-excessive-merge
+++ b/tests/test-excessive-merge
@@ -41,6 +41,6 @@
 
 echo
 
-hg debugindex .hg/store/data/a.i
+hg debugindex .hg/store/df/a.i
 
 hg verify
diff --git a/tests/test-extra-filelog-entry b/tests/test-extra-filelog-entry
--- a/tests/test-extra-filelog-entry
+++ b/tests/test-extra-filelog-entry
@@ -16,4 +16,4 @@
 hg qnew -f foo.diff
 echo b > b
 hg qrefresh
-hg debugindex .hg/store/data/b.i
+hg debugindex .hg/store/df/b.i
diff --git a/tests/test-filebranch b/tests/test-filebranch
--- a/tests/test-filebranch
+++ b/tests/test-filebranch
@@ -59,16 +59,16 @@
 hg log -v -r tip
 
 echo "foo: we should have a merge here"
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 
 echo "bar: we shouldn't have a merge here"
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 
 echo "baz: we shouldn't have a merge here"
-hg debugindex .hg/store/data/baz.i
+hg debugindex .hg/store/df/baz.i
 
 echo "quux: we shouldn't have a merge here"
-hg debugindex .hg/store/data/quux.i
+hg debugindex .hg/store/df/quux.i
 
 echo "manifest entries should match tips of all files"
 hg manifest --debug
diff --git a/tests/test-filenamelog b/tests/test-filenamelog
new file mode 100755
--- /dev/null
+++ b/tests/test-filenamelog
@@ -0,0 +1,133 @@
+#!/bin/sh
+
+LONGDIR1=FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH
+LONGDIR2=FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH
+
+echo % init repo1
+hg init repo1
+cd repo1
+echo % verify empty repo
+hg verify
+echo % filenamelog
+hg debugfilenamelog -a
+
+echo
+echo % adding \$LONGDIR1/LOREM.TXT
+mkdir -p $LONGDIR1
+echo sometext > $LONGDIR1/LOREM.TXT
+hg add
+hg ci -m1
+echo % filenamelog
+hg debugfilenamelog -a
+
+echo
+echo % adding \$LONGDIR2/LOREM.TXT
+mkdir -p $LONGDIR2
+echo sometext > $LONGDIR2/LOREM.TXT
+hg add
+hg ci -m2
+echo % manifest tip
+hg manifest tip
+echo % filenamelog
+hg debugfilenamelog -a
+
+echo
+echo % verify
+hg verify
+
+echo
+echo % rename filenamelog and verify
+mv .hg/store/filenamelog .hg/store/filenamelog.hidden
+hg verify
+mv .hg/store/filenamelog.hidden .hg/store/filenamelog
+
+cd ..
+
+echo
+echo "% clone -U repo1 repo1c  (using hardlinks)"
+hg clone --debug -U repo1 repo1c
+cd repo1c
+echo % manifest tip
+hg manifest tip
+echo % filenamelog
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+cd ..
+
+cd repo1
+echo
+echo % rollback repo1
+hg rollback
+echo % filenamelog
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+cd ..
+
+cd repo1c
+echo
+echo "% filenamelog of repo1c (must be unaffected by previous rollback in repo1)"
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+cd ..
+
+LONGNAME1=LOREM-IPSUM-DOLOR-SIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR
+LONGNAME2=LOREM-IPSUM-DOLO-RSIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR
+
+echo
+echo % init repo2
+hg init repo2
+cd repo2
+echo % adding foo/\$LONGNAME1.java foo/\$LONGNAME2.java
+mkdir foo
+echo sometext > foo/$LONGNAME1.java
+echo sometext > foo/$LONGNAME2.java
+hg add
+hg ci -m3
+echo % manifest tip
+hg manifest tip
+echo % filenamelog
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+
+cd ..
+
+AUXPATH1=aux.bla/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL
+
+echo
+echo % init repo3
+hg init repo3
+cd repo3
+echo % adding windows reserved names
+mkdir -p $AUXPATH1
+echo sometext > $AUXPATH1/normal.c
+hg add
+hg ci -m4
+echo % manifest tip
+hg manifest tip
+echo % filenamelog
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+cd ..
+
+echo
+echo % init repo4
+hg init repo4
+cd repo4
+echo % adding direncode test names
+DIR=foo.i/bar.d
+mkdir -p $DIR
+echo sometext > $DIR/bla.i
+hg add
+hg ci -m5
+echo % manifest tip
+hg manifest tip
+echo % filenamelog
+hg debugfilenamelog -a
+echo % verify -q
+hg verify -q
+cd ..
diff --git a/tests/test-filenamelog.out b/tests/test-filenamelog.out
new file mode 100644
--- /dev/null
+++ b/tests/test-filenamelog.out
@@ -0,0 +1,110 @@
+% init repo1
+% verify empty repo
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+0 files, 0 changesets, 0 total revisions
+% filenamelog
+(filenamelog has 0 filenames, 0 hashed)
+
+% adding $LONGDIR1/LOREM.TXT
+adding FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+% filenamelog
+   'data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._213bfeabe713cd5571ac605bbc0cf5de4e682b43.i'
+(filenamelog has 1 filenames, 1 hashed)
+
+% adding $LONGDIR2/LOREM.TXT
+adding FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+% manifest tip
+FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+% filenamelog
+   'data/FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_fx_f_t_/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._d4a02d94ca0f37bd974027fd1d5a3fe4a668b431.i'
+   'data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._213bfeabe713cd5571ac605bbc0cf5de4e682b43.i'
+(filenamelog has 2 filenames, 2 hashed)
+
+% verify
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+2 files, 2 changesets, 2 total revisions
+
+% rename filenamelog and verify
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+ filenamelog: missing indexfile entry for 'FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT'
+ filenamelog: missing indexfile entry for 'FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT'
+2 files, 2 changesets, 2 total revisions
+2 integrity errors encountered!
+
+% clone -U repo1 repo1c  (using hardlinks)
+% manifest tip
+FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT
+% filenamelog
+   'data/FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_fx_f_t_/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._d4a02d94ca0f37bd974027fd1d5a3fe4a668b431.i'
+   'data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._213bfeabe713cd5571ac605bbc0cf5de4e682b43.i'
+(filenamelog has 2 filenames, 2 hashed)
+% verify -q
+
+% rollback repo1
+rolling back last transaction
+% filenamelog
+   'data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._213bfeabe713cd5571ac605bbc0cf5de4e682b43.i'
+(filenamelog has 1 filenames, 1 hashed)
+% verify -q
+
+% filenamelog of repo1c (must be unaffected by previous rollback in repo1)
+   'data/FIRST/SECOND/THIRD/FOURTH/FxFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_fx_f_t_/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._d4a02d94ca0f37bd974027fd1d5a3fe4a668b431.i'
+   'data/FIRST/SECOND/THIRD/FOURTH/FIFTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREM.TXT.i'
+-> 'dh/_f_i_r_s/_s_e_c_o/_t_h_i_r/_f_o_u_r/_f_i_f_t/_s_i_x_t/_s_e_v_e/_l_o_r_e_m._213bfeabe713cd5571ac605bbc0cf5de4e682b43.i'
+(filenamelog has 2 filenames, 2 hashed)
+% verify -q
+
+% init repo2
+% adding foo/$LONGNAME1.java foo/$LONGNAME2.java
+adding foo/LOREM-IPSUM-DOLO-RSIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java
+adding foo/LOREM-IPSUM-DOLOR-SIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java
+% manifest tip
+foo/LOREM-IPSUM-DOLO-RSIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java
+foo/LOREM-IPSUM-DOLOR-SIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java
+% filenamelog
+   'data/foo/LOREM-IPSUM-DOLO-RSIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java.i'
+-> 'dh/foo/_l_o_r_e_m-_i_p_s_u_m-_d_o_l_o-_r_s_i_t-_a_m_e_t-_c_o_n_s_e_c_t_e_t_u_r293f6048aee1f01a3b00d016d9fe695b623140c4.i'
+   'data/foo/LOREM-IPSUM-DOLOR-SIT-AMET-CONSECTETUR-ADIPISICING-ELIT-SED-DO-EIUSMOD-TEMPOR.java.i'
+-> 'dh/foo/_l_o_r_e_m-_i_p_s_u_m-_d_o_l_o_r-_s_i_t-_a_m_e_t-_c_o_n_s_e_c_t_e_t_u_re6aeea8466f809b57d3a69cf3f16be864c74e413.i'
+(filenamelog has 2 filenames, 2 hashed)
+% verify -q
+
+% init repo3
+% adding windows reserved names
+adding aux.bla/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
+% manifest tip
+aux.bla/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
+% filenamelog
+   'data/aux.bla/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c.i'
+-> 'df/au~78.bla/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i'
+(filenamelog has 1 filenames, 0 hashed)
+% verify -q
+
+% init repo4
+% adding direncode test names
+adding foo.i/bar.d/bla.i
+% manifest tip
+foo.i/bar.d/bla.i
+% filenamelog
+   'data/foo.i.hg/bar.d.hg/bla.i.i'
+-> 'df/foo.i.hg/bar.d.hg/bla.i.i'
+(filenamelog has 1 filenames, 0 hashed)
+% verify -q
diff --git a/tests/test-flags b/tests/test-flags
--- a/tests/test-flags
+++ b/tests/test-flags
@@ -45,6 +45,6 @@
 ls -l ../test[123]/a > foo
 cut -b 1-10 < foo
 
-hg debugindex .hg/store/data/a.i
-hg debugindex ../test2/.hg/store/data/a.i
-hg debugindex ../test1/.hg/store/data/a.i
+hg debugindex .hg/store/df/a.i
+hg debugindex ../test2/.hg/store/df/a.i
+hg debugindex ../test1/.hg/store/df/a.i
diff --git a/tests/test-http-clone-r b/tests/test-http-clone-r
--- a/tests/test-http-clone-r
+++ b/tests/test-http-clone-r
@@ -42,10 +42,10 @@
 hg update -C 3
 hg mv afile anotherfile
 hg commit -m "0.3m"
-hg debugindex .hg/store/data/afile.i
-hg debugindex .hg/store/data/adifferentfile.i
-hg debugindex .hg/store/data/anotherfile.i
-hg debugindex .hg/store/data/fred.i
+hg debugindex .hg/store/df/afile.i
+hg debugindex .hg/store/df/adifferentfile.i
+hg debugindex .hg/store/df/anotherfile.i
+hg debugindex .hg/store/df/fred.i
 hg debugindex .hg/store/00manifest.i
 hg verify
 echo "# Starting server"
diff --git a/tests/test-inherit-mode b/tests/test-inherit-mode
--- a/tests/test-inherit-mode
+++ b/tests/test-inherit-mode
@@ -84,7 +84,7 @@
 touch dir/file
 hg ci -qAm 'add dir/file'
 storemode=`python ../mode.py .hg/store`
-dirmode=`python ../mode.py .hg/store/data/dir`
+dirmode=`python ../mode.py .hg/store/df/dir`
 if [ "$storemode" != "$dirmode" ]; then
     echo "$storemode != $dirmode"
 fi
diff --git a/tests/test-inherit-mode.out b/tests/test-inherit-mode.out
--- a/tests/test-inherit-mode.out
+++ b/tests/test-inherit-mode.out
@@ -18,10 +18,11 @@
 00770 ./.hg/store/
 00660 ./.hg/store/00changelog.i
 00660 ./.hg/store/00manifest.i
-00770 ./.hg/store/data/
-00770 ./.hg/store/data/dir/
-00660 ./.hg/store/data/dir/bar.i
-00660 ./.hg/store/data/foo.i
+00770 ./.hg/store/df/
+00770 ./.hg/store/df/dir/
+00660 ./.hg/store/df/dir/bar.i
+00660 ./.hg/store/df/foo.i
+00660 ./.hg/store/filenamelog
 00660 ./.hg/store/undo
 00660 ./.hg/undo.branch
 00660 ./.hg/undo.dirstate
@@ -45,10 +46,11 @@
 00770 ../push/.hg/store/
 00660 ../push/.hg/store/00changelog.i
 00660 ../push/.hg/store/00manifest.i
-00770 ../push/.hg/store/data/
-00770 ../push/.hg/store/data/dir/
-00660 ../push/.hg/store/data/dir/bar.i
-00660 ../push/.hg/store/data/foo.i
+00770 ../push/.hg/store/df/
+00770 ../push/.hg/store/df/dir/
+00660 ../push/.hg/store/df/dir/bar.i
+00660 ../push/.hg/store/df/foo.i
+00660 ../push/.hg/store/filenamelog
 00660 ../push/.hg/store/undo
 00660 ../push/.hg/undo.branch
 00660 ../push/.hg/undo.dirstate
diff --git a/tests/test-init.out b/tests/test-init.out
--- a/tests/test-init.out
+++ b/tests/test-init.out
@@ -3,6 +3,7 @@
 00changelog.i created
 revlogv1
 store
+filenamelog
 adding foo
 # creating repo with old format
 revlogv1
diff --git a/tests/test-issue522 b/tests/test-issue522
--- a/tests/test-issue522
+++ b/tests/test-issue522
@@ -27,5 +27,5 @@
 hg ci -d '0 0' -m 'merge'
 
 hg manifest --debug | grep foo
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 
diff --git a/tests/test-merge-commit b/tests/test-merge-commit
--- a/tests/test-merge-commit
+++ b/tests/test-merge-commit
@@ -23,9 +23,9 @@
 echo '% contents of bar should be line0 line1 line2'
 cat bar
 hg ci -m '3: merge with local rename' -d '0 0'
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 hg debugrename bar
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 
 # revert the content change from rev 2
 hg up -C 2
@@ -39,7 +39,7 @@
 echo '% contents of bar should be line1 line2'
 cat bar
 hg ci -m '5: merge' -d '0 0'
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 
 
 # same thing, but with the merge on 3 having the rename on the remote parent
@@ -54,9 +54,9 @@
 echo '% contents of bar should be line0 line1 line2'
 cat bar
 hg ci -m '3: merge with remote rename' -d '0 0'
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 hg debugrename bar
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
 
 # revert the content change from rev 2
 hg up -C 2
@@ -70,5 +70,5 @@
 echo '% contents of bar should be line1 line2'
 cat bar
 hg ci -m '5: merge' -d '0 0'
-hg debugindex .hg/store/data/bar.i
+hg debugindex .hg/store/df/bar.i
 
diff --git a/tests/test-merge7 b/tests/test-merge7
--- a/tests/test-merge7
+++ b/tests/test-merge7
@@ -61,6 +61,6 @@
 
 cat test.txt
 
-hg debugindex .hg/store/data/test.txt.i
+hg debugindex .hg/store/df/test.txt.i
 
 hg log
diff --git a/tests/test-permissions b/tests/test-permissions
--- a/tests/test-permissions
+++ b/tests/test-permissions
@@ -6,11 +6,11 @@
 hg add a
 hg commit -m "1" -d "1000000 0"
 hg verify
-chmod -r .hg/store/data/a.i
+chmod -r .hg/store/df/a.i
 hg verify 2>/dev/null || echo verify failed
-chmod +r .hg/store/data/a.i
+chmod +r .hg/store/df/a.i
 hg verify 2>/dev/null || echo verify failed
-chmod -w .hg/store/data/a.i
+chmod -w .hg/store/df/a.i
 echo barber > a
 hg commit -m "2" -d "1000000 0" 2>/dev/null || echo commit failed
 chmod -w .
diff --git a/tests/test-push-r b/tests/test-push-r
--- a/tests/test-push-r
+++ b/tests/test-push-r
@@ -41,10 +41,10 @@
 hg update -C 3
 hg mv afile anotherfile
 hg commit -m "0.3m"
-hg debugindex .hg/store/data/afile.i
-hg debugindex .hg/store/data/adifferentfile.i
-hg debugindex .hg/store/data/anotherfile.i
-hg debugindex .hg/store/data/fred.i
+hg debugindex .hg/store/df/afile.i
+hg debugindex .hg/store/df/adifferentfile.i
+hg debugindex .hg/store/df/anotherfile.i
+hg debugindex .hg/store/df/fred.i
 hg debugindex .hg/store/00manifest.i
 hg verify
 cd ..
diff --git a/tests/test-rename-merge1 b/tests/test-rename-merge1
--- a/tests/test-rename-merge1
+++ b/tests/test-rename-merge1
@@ -23,5 +23,5 @@
 hg status -AC
 cat b
 hg ci -m "merge" -d "0 0"
-hg debugindex .hg/store/data/b.i
+hg debugindex .hg/store/df/b.i
 hg debugrename b
\ No newline at end of file
diff --git a/tests/test-revlog-packentry b/tests/test-revlog-packentry
--- a/tests/test-revlog-packentry
+++ b/tests/test-revlog-packentry
@@ -11,4 +11,4 @@
 echo foo bar baz > foo
 hg ci -Am 'add foo again'
 
-hg debugindex .hg/store/data/foo.i
+hg debugindex .hg/store/df/foo.i
diff --git a/tests/test-ssh-clone-r b/tests/test-ssh-clone-r
--- a/tests/test-ssh-clone-r
+++ b/tests/test-ssh-clone-r
@@ -67,10 +67,10 @@
 hg update -C 3
 hg mv afile anotherfile
 hg commit -m "0.3m"
-hg debugindex .hg/store/data/afile.i
-hg debugindex .hg/store/data/adifferentfile.i
-hg debugindex .hg/store/data/anotherfile.i
-hg debugindex .hg/store/data/fred.i
+hg debugindex .hg/store/df/afile.i
+hg debugindex .hg/store/df/adifferentfile.i
+hg debugindex .hg/store/df/anotherfile.i
+hg debugindex .hg/store/df/fred.i
 hg debugindex .hg/store/00manifest.i
 hg verify
 cd ..
diff --git a/tests/test-strip-cross b/tests/test-strip-cross
--- a/tests/test-strip-cross
+++ b/tests/test-strip-cross
@@ -51,7 +51,7 @@
 cd ..
 hg clone -q -U -r -1 -r -2 -r -3 -r -4 -r -6 orig crossed
 
-for i in crossed/.hg/store/00manifest.i crossed/.hg/store/data/*.i; do
+for i in crossed/.hg/store/00manifest.i crossed/.hg/store/df/*.i; do
     echo $i
     hg debugindex $i
     echo
diff --git a/tests/test-strip-cross.out b/tests/test-strip-cross.out
--- a/tests/test-strip-cross.out
+++ b/tests/test-strip-cross.out
@@ -6,43 +6,43 @@
      3       291     122      1       2 f0ef8726ac4f 000000000000 000000000000
      4       413      87      4       4 0b76e38b4070 000000000000 000000000000
 
-crossed/.hg/store/data/012.i
+crossed/.hg/store/df/012.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       0 b8e02f643373 000000000000 000000000000
      1         3       3      1       1 5d9299349fc0 000000000000 000000000000
      2         6       3      2       2 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/021.i
+crossed/.hg/store/df/021.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       0 b8e02f643373 000000000000 000000000000
      1         3       3      1       2 5d9299349fc0 000000000000 000000000000
      2         6       3      2       1 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/102.i
+crossed/.hg/store/df/102.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       1 b8e02f643373 000000000000 000000000000
      1         3       3      1       0 5d9299349fc0 000000000000 000000000000
      2         6       3      2       2 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/120.i
+crossed/.hg/store/df/120.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       1 b8e02f643373 000000000000 000000000000
      1         3       3      1       2 5d9299349fc0 000000000000 000000000000
      2         6       3      2       0 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/201.i
+crossed/.hg/store/df/201.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       2 b8e02f643373 000000000000 000000000000
      1         3       3      1       0 5d9299349fc0 000000000000 000000000000
      2         6       3      2       1 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/210.i
+crossed/.hg/store/df/210.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       2 b8e02f643373 000000000000 000000000000
      1         3       3      1       1 5d9299349fc0 000000000000 000000000000
      2         6       3      2       0 2661d26c6496 000000000000 000000000000
 
-crossed/.hg/store/data/manifest-file.i
+crossed/.hg/store/df/manifest-file.i
    rev    offset  length   base linkrev nodeid       p1           p2
      0         0       3      0       3 b8e02f643373 000000000000 000000000000
      1         3       3      1       4 5d9299349fc0 000000000000 000000000000


More information about the Mercurial-devel mailing list