[PATCH 4 of 5] introduce fncache repository layout

Adrian Buehlmann adrian at cadifra.com
Wed Jul 30 13:48:16 CDT 2008


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1217441567 -7200
# Node ID 5a75f1b9baed4710671f992e57e73c418f875497
# Parent  91e2878421f5dcb13da92366c9864431e35b79d8
introduce fncache repository layout

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

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

The mapping to the new disk directories is done by the new path encoding
function store.hybridencode, 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.

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.hybridencode, hashed, non-reversible):

 (A1) data/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT.i
 (B1) dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i

 (A2) data/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider.i
 (B2) dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i

 (A3) data/AUX.THE-QUICK-BROWN-FOX-JU:MPS-OVER-THE-LAZY-DOG-THE-QUICK-BROWN-FOX-JUMPS-OVER-THE-LAZY-DOG.TXT.i
 (B3) dh/au~78.the-quick-brown-fox-ju~3amps-over-the-lazy-dog-the-quick-brown-fox-jud4dcadd033000ab2b26eb66bae1906bcb15d4a70.i

A list of all filelog files is now maintained in the file '.hg/store/fncache',
("filename cache") which contains a \n separated list of all A-paths in the
repository.

fncache may contain extra entries after a rollback/strip/qpop. These are
removed by rewriting the fncache in store.fncachestore.datafiles.

diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -198,6 +198,8 @@
             dest_lock = lock.lock(os.path.join(dest_store, "lock"))
 
             files = ("data",
+                     "df", "dh",  # for fncache repos
+                     "fncache",
                      "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', 'fncache')
 
     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("fncache")
                     # create an invalid changelog
                     self.opener("00changelog.i", "a").write(
                         '\0\0\0\2' # represents revlogv2
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -6,7 +6,7 @@
 # of the GNU General Public License, incorporated herein by reference.
 
 from i18n import _
-import os, stat, osutil, util
+import os, stat, sha, osutil, util
 
 def _buildencodefun():
     e = '_'
@@ -36,6 +36,94 @@
 
 encodefilename, decodefilename = _buildencodefun()
 
+def _build_lower_encodefun():
+    win_reserved = [ord(x) for x in '\\:*?"<>|']
+    cmap = dict([ (chr(x), chr(x)) for x in xrange(127) ])
+    for x in (range(32) + range(126, 256) + win_reserved):
+        cmap[chr(x)] = "~%02x" % x
+    for x in range(ord("A"), ord("Z")+1):
+        cmap[chr(x)] = chr(x).lower()
+    return lambda s: "".join([cmap[c] for c in s])
+
+lowerencode = _build_lower_encodefun()
+
+_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 hybridencode(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 lowerencoded 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 lowerencoded 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/'):]
+    res = 'df/' + auxencode(encodefilename(ndpath))
+    if len(res) > MAX_PATH_LEN_IN_HGSTORE:
+        digest = sha.new(path).hexdigest()
+        aep = auxencode(lowerencode(ndpath))
+        _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)'''
     for e, kind, st in osutil.listdir(path, stat=True):
@@ -119,14 +207,83 @@
     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
+
+    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/'):
+            fnc = util.opener.__call__(self, 'fncache', mode='a+')
+            fnc.write(path + '\n')
+            # we deliberately don't add fncache to the transaction, which means
+            # there may be duplicate/nonexistent entries (e.g. after rollback)
+            fnc.close()
+        return fp
+
+class fncachestore(_store):
+    def __init__(self, path):
+        _store.__init__(self, os.path.join(path, 'store'))
+        self.encodefn = hybridencode
+        self.opener = loggingopener(self.encodefn, self.path, self.createmode)
+
+    def join(self, f):
+        return os.path.join(self.path, self.encodefn(f))
+
+    def datafiles(self, reporterror=None):
+        try:
+            fp = self.opener('fncache', mode='rb')
+        except IOError:
+            # skip nonexistent file
+            return
+        rewrite = False
+        errors = 0
+        unique = {}
+        existing = []
+        for n, line in enumerate(fp):
+            if (len(line) < 2) or (line[-1] != '\n'):
+                errors += 1
+                t = _('invalid entry in fncache, line %s') % (n + 1)
+                if not reporterror:
+                    raise util.Abort(t)
+                reporterror(t)
+            else:
+                f = line[:-1]
+                if unique.setdefault(f, n) != n:
+                    # duplicate entry
+                    rewrite = True
+                else:
+                    try:
+                        st = os.stat(self.join(f))
+                        yield f, st.st_size
+                        existing.append(f)
+                    except OSError:
+                        # nonexistent entry
+                        rewrite = True
+        fp.close()
+
+        if rewrite and (errors == 0):
+            fp = self.opener('fncache', mode='wb')
+            for p in existing:
+                fp.write(p + '\n')
+            fp.close()
+
 def encodefn(requirements):
     if 'store' not in requirements:
         return lambda x: x
+    elif 'fncache' in requirements:
+        return hybridencode
     else:
         return encodefilename
 
 def store(requirements, path):
     if 'store' not in requirements:
         return directstore(path)
+    elif 'fncache' in requirements:
+        return fncachestore(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/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-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-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/fncache
 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/fncache
 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
+fncache
 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
diff --git a/tests/test-verify b/tests/test-verify
--- a/tests/test-verify
+++ b/tests/test-verify
@@ -14,7 +14,7 @@
 
 echo
 echo % introduce some bugs in repo
-cd .hg/store/data
+cd .hg/store/df
 mv _f_o_o.txt.i X_f_o_o.txt.i
 mv bar.txt.i xbar.txt.i
 rm _q_u_i_c_k.txt.i
diff --git a/tests/test-verify.out b/tests/test-verify.out
--- a/tests/test-verify.out
+++ b/tests/test-verify.out
@@ -17,7 +17,6 @@
 checking manifests
 crosschecking files in changesets and manifests
 checking files
- store: cannot decode filename 'data/X_f_o_o.txt.i'
  0: empty or missing FOO.txt
  store: missing entry 'FOO.txt'
  FOO.txt at 0: f62022d3d590 in manifests not found
@@ -28,5 +27,5 @@
  store: missing entry 'bar.txt'
  bar.txt at 0: 256559129457 in manifests not found
 3 files, 1 changesets, 0 total revisions
-10 integrity errors encountered!
+9 integrity errors encountered!
 (first damaged changeset appears to be 0)


More information about the Mercurial-devel mailing list