Patchwork [5,of,5] manifestv2: add support for writing new manifest format

login
register
mail settings
Submitter Martin von Zweigbergk
Date April 1, 2015, 5:34 p.m.
Message ID <2fbe921fa4f43a3897d4.1427909690@martinvonz.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/8423/
State Accepted
Headers show

Comments

Martin von Zweigbergk - April 1, 2015, 5:34 p.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1427835693 25200
#      Tue Mar 31 14:01:33 2015 -0700
# Node ID 2fbe921fa4f43a3897d4c74ce74cafd73f0deddb
# Parent  aca6ee57dddf4b39732833a2bb603dcd19148754
manifestv2: add support for writing new manifest format

If .hg/requires has 'manifestv2', the manifest will be written using
the new format.
Matt Mackall - April 1, 2015, 10:54 p.m.
On Wed, 2015-04-01 at 10:34 -0700, Martin von Zweigbergk wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1427835693 25200
> #      Tue Mar 31 14:01:33 2015 -0700
> # Node ID 2fbe921fa4f43a3897d4c74ce74cafd73f0deddb
> # Parent  aca6ee57dddf4b39732833a2bb603dcd19148754
> manifestv2: add support for writing new manifest format

These are queued for default, thanks. Dropped this bit since it seems to
be debugging for the current OS X test failure:

> 74 57361477c778 000000000000
> diff -r aca6ee57dddf -r 2fbe921fa4f4 tests/test-subrepo-git.t
> --- a/tests/test-subrepo-git.t	Fri Mar 27 22:26:41 2015 -0700
> +++ b/tests/test-subrepo-git.t	Tue Mar 31 14:01:33 2015 -0700
> @@ -978,6 +978,7 @@
>    adding s/c.c (glob)
>    adding s/cpp.cpp (glob)
>    adding s/foobar.orig (glob)
> +  $ ls -l s/.hg
>    $ hg st --subrepos s
>    A s/.gitignore
>    A s/snake.python
> @@ -987,9 +988,11 @@
>    ? s/foobar.orig
>  
>  error given when adding an already tracked file
> +  $ ls -l s/.hg
>    $ hg add s/.gitignore
>    s/.gitignore already tracked!
>    [1]
> +  $ ls -l s/.hg
>    $ hg add s/g
>    s/g already tracked!
>    [1]
> @@ -997,9 +1000,11 @@
>  removed files can be re-added
>  removing files using 'rm' or 'git rm' has the same effect,
>  since we ignore the staging area
> +  $ ls -l s/.hg
>    $ hg ci --subrepos -m 'snake'
>    committing subrepository s
>    $ cd s
> +  $ ls -l .hg
>    $ rm snake.python
>  (remove leftover .hg so Mercurial doesn't look for a root here)
>    $ rm -r .hg
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Martin von Zweigbergk - April 1, 2015, 11:02 p.m.
On Wed, Apr 1, 2015 at 3:54 PM Matt Mackall <mpm@selenic.com> wrote:

> On Wed, 2015-04-01 at 10:34 -0700, Martin von Zweigbergk wrote:
> > # HG changeset patch
> > # User Martin von Zweigbergk <martinvonz@google.com>
> > # Date 1427835693 25200
> > #      Tue Mar 31 14:01:33 2015 -0700
> > # Node ID 2fbe921fa4f43a3897d4c74ce74cafd73f0deddb
> > # Parent  aca6ee57dddf4b39732833a2bb603dcd19148754
> > manifestv2: add support for writing new manifest format
>
> These are queued for default, thanks. Dropped this bit since it seems to
> be debugging for the current OS X test failure:
>

Oops, yes. Thanks.

Patch

diff -r aca6ee57dddf -r 2fbe921fa4f4 mercurial/manifest.py
--- a/mercurial/manifest.py	Fri Mar 27 22:26:41 2015 -0700
+++ b/mercurial/manifest.py	Tue Mar 31 14:01:33 2015 -0700
@@ -8,6 +8,7 @@ 
 from i18n import _
 import mdiff, parsers, error, revlog, util, scmutil
 import array, struct
+import os
 
 propertycache = util.propertycache
 
@@ -58,9 +59,15 @@ 
     else:
         return iter(_parsev1(data))
 
-def _text(it):
+def _text(it, usemanifestv2):
     """Given an iterator over (path, node, flags) tuples, returns a manifest
     text"""
+    if usemanifestv2:
+        return _textv2(it)
+    else:
+        return _textv1(it)
+
+def _textv1(it):
     files = []
     lines = []
     _hex = revlog.hex
@@ -73,6 +80,19 @@ 
     _checkforbidden(files)
     return ''.join(lines)
 
+def _textv2(it):
+    files = []
+    lines = ['\0\n']
+    prevf = ''
+    for f, n, fl in it:
+        files.append(f)
+        stem = os.path.commonprefix([prevf, f])
+        stemlen = min(len(stem), 255)
+        lines.append("%c%s\0%s\n%s\n" % (stemlen, f[stemlen:], fl, n))
+        prevf = f
+    _checkforbidden(files)
+    return ''.join(lines)
+
 class _lazymanifest(dict):
     """This is the pure implementation of lazymanifest.
 
@@ -134,7 +154,7 @@ 
 
     def text(self):
         """Get the full data of this manifest as a bytestring."""
-        return _text(self.iterentries())
+        return _textv1(self.iterentries())
 
 try:
     _lazymanifest = parsers.lazymanifest
@@ -259,8 +279,12 @@ 
     def iteritems(self):
         return (x[:2] for x in self._lm.iterentries())
 
-    def text(self):
-        return self._lm.text()
+    def text(self, usemanifestv2=False):
+        if usemanifestv2:
+            return _textv2(self._lm.iterentries())
+        else:
+            # use (probably) native version for v1
+            return self._lm.text()
 
     def fastdelta(self, base, changes):
         """Given a base manifest text as an array.array and a list of changes
@@ -621,10 +645,11 @@ 
         _diff(self, m2)
         return result
 
-    def text(self):
+    def text(self, usemanifestv2=False):
         """Get the full data of this manifest as a bytestring."""
         flags = self.flags
-        return _text((f, self[f], flags(f)) for f in self.keys())
+        return _text(((f, self[f], flags(f)) for f in self.keys()),
+                     usemanifestv2)
 
 class manifest(revlog.revlog):
     def __init__(self, opener):
@@ -720,7 +745,7 @@ 
             # just encode a fulltext of the manifest and pass that
             # through to the revlog layer, and let it handle the delta
             # process.
-            text = m.text()
+            text = m.text(self._usemanifestv2)
             arraytext = array.array('c', text)
             cachedelta = None
 
diff -r aca6ee57dddf -r 2fbe921fa4f4 tests/test-manifest.py
--- a/tests/test-manifest.py	Fri Mar 27 22:26:41 2015 -0700
+++ b/tests/test-manifest.py	Tue Mar 31 14:01:33 2015 -0700
@@ -146,6 +146,12 @@ 
         self.assertIn('bar/qux/foz.py', m)
         self.assertIn(256 * 'x' + '/x', m)
         self.assertIn(256 * 'x' + '/y', m)
+        self.assertEqual(A_STEM_COMPRESSED_MANIFEST, m.text(usemanifestv2=True))
+
+    def testTextV2(self):
+        m1 = parsemanifest(A_SHORT_MANIFEST)
+        v2text = m1.text(usemanifestv2=True)
+        self.assertEqual(A_SHORT_MANIFEST_V2, v2text)
 
     def testSetItem(self):
         want = BIN_HASH_1
diff -r aca6ee57dddf -r 2fbe921fa4f4 tests/test-manifestv2.t
--- a/tests/test-manifestv2.t	Fri Mar 27 22:26:41 2015 -0700
+++ b/tests/test-manifestv2.t	Tue Mar 31 14:01:33 2015 -0700
@@ -23,9 +23,9 @@ 
   checking files
   3 files, 2 changesets, 4 total revisions
 
-TODO: Check that manifest revlog is smaller than for v1
+Check that manifest revlog is smaller than for v1
 
   $ hg debugindex -m
      rev    offset  length   base linkrev nodeid       p1           p2
-       0         0     106      0       0 f6279f9f8b31 000000000000 000000000000
-       1       106      59      0       1 cd20459b75e6 f6279f9f8b31 000000000000
+       0         0      81      0       0 57361477c778 000000000000 000000000000
+       1        81      33      0       1 aeaab5a2ef74 57361477c778 000000000000
diff -r aca6ee57dddf -r 2fbe921fa4f4 tests/test-subrepo-git.t
--- a/tests/test-subrepo-git.t	Fri Mar 27 22:26:41 2015 -0700
+++ b/tests/test-subrepo-git.t	Tue Mar 31 14:01:33 2015 -0700
@@ -978,6 +978,7 @@ 
   adding s/c.c (glob)
   adding s/cpp.cpp (glob)
   adding s/foobar.orig (glob)
+  $ ls -l s/.hg
   $ hg st --subrepos s
   A s/.gitignore
   A s/snake.python
@@ -987,9 +988,11 @@ 
   ? s/foobar.orig
 
 error given when adding an already tracked file
+  $ ls -l s/.hg
   $ hg add s/.gitignore
   s/.gitignore already tracked!
   [1]
+  $ ls -l s/.hg
   $ hg add s/g
   s/g already tracked!
   [1]
@@ -997,9 +1000,11 @@ 
 removed files can be re-added
 removing files using 'rm' or 'git rm' has the same effect,
 since we ignore the staging area
+  $ ls -l s/.hg
   $ hg ci --subrepos -m 'snake'
   committing subrepository s
   $ cd s
+  $ ls -l .hg
   $ rm snake.python
 (remove leftover .hg so Mercurial doesn't look for a root here)
   $ rm -r .hg