treemanifest: add --dir option to debug{revlog,data,index}
authorMartin von Zweigbergk <martinvonz@google.com>
Sun, 12 Apr 2015 23:51:06 -0700
changeset 25181 49c583ca48c4f53f34151bcce13729913feaac9b
parent 25180 e632a2429982fca1251ef65099bdd3668fa4f58a
child 25182 a7701001c829838e01f5317ea494c54c981a50a4
push id13
push usergszorc@mozilla.com
push dateTue, 26 May 2015 00:39:25 +0000
treemanifest: add --dir option to debug{revlog,data,index} It should be possible to debug the submanifest revlogs without having to know where they are stored (in .hg/store/meta/), so let's add a --dir option for this purpose.
mercurial/cmdutil.py
mercurial/commands.py
mercurial/localrepo.py
mercurial/manifest.py
tests/test-completion.t
tests/test-treemanifest.t
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -445,32 +445,42 @@ def makefileobj(repo, pat, node=None, de
         if mode == 'wb':
             modemap[fn] = 'ab'
     return open(fn, mode)
 
 def openrevlog(repo, cmd, file_, opts):
     """opens the changelog, manifest, a filelog or a given revlog"""
     cl = opts['changelog']
     mf = opts['manifest']
+    dir = opts['dir']
     msg = None
     if cl and mf:
         msg = _('cannot specify --changelog and --manifest at the same time')
+    elif cl and dir:
+        msg = _('cannot specify --changelog and --dir at the same time')
     elif cl or mf:
         if file_:
             msg = _('cannot specify filename with --changelog or --manifest')
         elif not repo:
-            msg = _('cannot specify --changelog or --manifest '
+            msg = _('cannot specify --changelog or --manifest or --dir '
                     'without a repository')
     if msg:
         raise util.Abort(msg)
 
     r = None
     if repo:
         if cl:
             r = repo.unfiltered().changelog
+        elif dir:
+            if 'treemanifest' not in repo.requirements:
+                raise util.Abort(_("--dir can only be used on repos with "
+                                   "treemanifest enabled"))
+            dirlog = repo.dirlog(file_)
+            if len(dirlog):
+                r = dirlog
         elif mf:
             r = repo.manifest
         elif file_:
             filelog = repo.file(file_)
             if len(filelog):
                 r = filelog
     if not r:
         if not file_:
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2051,17 +2051,18 @@ def debugdag(ui, repo, file_=None, *revs
                                        wrapnonlinear=dots,
                                        usedots=dots,
                                        maxlinewidth=70):
         ui.write(line)
         ui.write("\n")
 
 @command('debugdata',
     [('c', 'changelog', False, _('open changelog')),
-     ('m', 'manifest', False, _('open manifest'))],
+     ('m', 'manifest', False, _('open manifest')),
+     ('', 'dir', False, _('open directory manifest'))],
     _('-c|-m|FILE REV'))
 def debugdata(ui, repo, file_, rev=None, **opts):
     """dump the contents of a data file revision"""
     if opts.get('changelog') or opts.get('manifest'):
         file_, rev = None, file_
     elif rev is None:
         raise error.CommandError('debugdata', _('invalid arguments'))
     r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
@@ -2222,16 +2223,17 @@ def debugignore(ui, repo, *values, **opt
     if includepat is not None:
         ui.write("%s\n" % includepat)
     else:
         raise util.Abort(_("no ignore patterns found"))
 
 @command('debugindex',
     [('c', 'changelog', False, _('open changelog')),
      ('m', 'manifest', False, _('open manifest')),
+     ('', 'dir', False, _('open directory manifest')),
      ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
     _('[-f FORMAT] -c|-m|FILE'),
     optionalrepo=True)
 def debugindex(ui, repo, file_=None, **opts):
     """dump the contents of an index file"""
     r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
     format = opts.get('format', 0)
     if format not in (0, 1):
@@ -2724,16 +2726,17 @@ def debugrename(ui, repo, file1, *pats, 
         if o:
             ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
         else:
             ui.write(_("%s not renamed\n") % rel)
 
 @command('debugrevlog',
     [('c', 'changelog', False, _('open changelog')),
      ('m', 'manifest', False, _('open manifest')),
+     ('', 'dir', False, _('open directory manifest')),
      ('d', 'dump', False, _('dump index data'))],
     _('-c|-m|FILE'),
     optionalrepo=True)
 def debugrevlog(ui, repo, file_=None, **opts):
     """show data and statistics about a revlog"""
     r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
 
     if opts.get("dump"):
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -455,16 +455,19 @@ class localrepository(object):
             if p.startswith(self.root):
                 c.readpending('00changelog.i.a')
         return c
 
     @storecache('00manifest.i')
     def manifest(self):
         return manifest.manifest(self.svfs)
 
+    def dirlog(self, dir):
+        return manifest.manifest(self.svfs, dir)
+
     @repofilecache('dirstate')
     def dirstate(self):
         warned = [0]
         def validate(node):
             try:
                 self.changelog.rev(node)
                 return node
             except error.LookupError:
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -810,16 +810,18 @@ class manifest(revlog.revlog):
             usemanifestv2 = opts.get('manifestv2', usemanifestv2)
         self._mancache = util.lrucachedict(cachesize)
         self._treeinmem = usetreemanifest
         self._treeondisk = usetreemanifest
         self._usemanifestv2 = usemanifestv2
         indexfile = "00manifest.i"
         if dir:
             assert self._treeondisk
+            if not dir.endswith('/'):
+                dir = dir + '/'
             indexfile = "meta/" + dir + "00manifest.i"
         revlog.revlog.__init__(self, opener, indexfile)
         self._dir = dir
 
     def _newmanifest(self, data=''):
         if self._treeinmem:
             return treemanifest(self._dir, data)
         return manifestdict(data)
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -229,38 +229,38 @@ Show all commands + options
   copy: after, force, include, exclude, dry-run
   debugancestor: 
   debugbuilddag: mergeable-file, overwritten-file, new-file
   debugbundle: all
   debugcheckstate: 
   debugcommands: 
   debugcomplete: options
   debugdag: tags, branches, dots, spaces
-  debugdata: changelog, manifest
+  debugdata: changelog, manifest, dir
   debugdate: extended
   debugdirstate: nodates, datesort
   debugdiscovery: old, nonheads, ssh, remotecmd, insecure
   debugfileset: rev
   debugfsinfo: 
   debuggetbundle: head, common, type
   debugignore: 
-  debugindex: changelog, manifest, format
+  debugindex: changelog, manifest, dir, format
   debugindexdot: 
   debuginstall: 
   debugknown: 
   debuglabelcomplete: 
   debuglocks: force-lock, force-wlock
   debugnamecomplete: 
   debugobsolete: flags, record-parents, rev, date, user
   debugpathcomplete: full, normal, added, removed
   debugpushkey: 
   debugpvec: 
   debugrebuilddirstate: rev
   debugrename: rev
-  debugrevlog: changelog, manifest, dump
+  debugrevlog: changelog, manifest, dir, dump
   debugrevspec: optimize
   debugsetparents: 
   debugsub: rev
   debugsuccessorssets: 
   debugwalk: include, exclude
   debugwireargs: three, four, five, ssh, remotecmd, insecure
   files: rev, print0, include, exclude, template, subrepos
   graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
--- a/tests/test-treemanifest.t
+++ b/tests/test-treemanifest.t
@@ -25,17 +25,17 @@ Submanifest is stored in separate revlog
   $ echo 1 > dir1/b
   $ echo 1 > e
   $ hg ci -Aqm 'add dir1'
   $ hg debugdata -m 1
   a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
   b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
   dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44ed (esc)
   e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
-  $ hg debugdata .hg/store/meta/dir1/00manifest.i 0
+  $ hg debugdata --dir dir1 0
   a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
   b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
 
 Can add nested directories
 
   $ mkdir dir1/dir1
   $ echo 2 > dir1/dir1/a
   $ echo 2 > dir1/dir1/b
@@ -55,30 +55,30 @@ Can add nested directories
   e
 
 Revision is not created for unchanged directory
 
   $ mkdir dir2
   $ echo 3 > dir2/a
   $ hg add dir2
   adding dir2/a
-  $ hg debugindex .hg/store/meta/dir1/00manifest.i > before
+  $ hg debugindex --dir dir1 > before
   $ hg ci -qm 'add dir2'
-  $ hg debugindex .hg/store/meta/dir1/00manifest.i > after
+  $ hg debugindex --dir dir1 > after
   $ diff before after
   $ rm before after
 
 Removing directory does not create an revlog entry
 
   $ hg rm dir1/dir1
   removing dir1/dir1/a
   removing dir1/dir1/b
-  $ hg debugindex .hg/store/meta/dir1/dir1/00manifest.i > before
+  $ hg debugindex --dir dir1/dir1 > before
   $ hg ci -qm 'remove dir1/dir1'
-  $ hg debugindex .hg/store/meta/dir1/dir1/00manifest.i > after
+  $ hg debugindex --dir dir1/dir1 > after
   $ diff before after
   $ rm before after
 
 Check that hg files (calls treemanifest.walk()) works
 
   $ hg co 'desc("add dir2")'
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg files -r . dir1
@@ -108,17 +108,17 @@ Merge creates 2-parent revision of direc
   $ hg merge 'desc("modify dir1/a")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg ci -m 'conflict-free merge involving dir1/'
   $ cat dir1/a
   5
   $ cat dir1/b
   6
-  $ hg debugindex .hg/store/meta/dir1/00manifest.i
+  $ hg debugindex --dir dir1
      rev    offset  length   base linkrev nodeid       p1           p2
        0         0      54      0       1 8b3ffd73f901 000000000000 000000000000
        1        54      68      0       2 b66d046c644f 8b3ffd73f901 000000000000
        2       122      12      0       4 b87265673c8a b66d046c644f 000000000000
        3       134      95      0       5 aa5d3adcec72 b66d046c644f 000000000000
        4       229      81      0       6 e29b066b91ad b66d046c644f 000000000000
        5       310     107      5       7 a120ce2b83f5 e29b066b91ad aa5d3adcec72
 
@@ -126,41 +126,41 @@ Merge keeping directory from parent 1 do
 dir1's manifest does change, but only because dir1/a's filelog changes.)
 
   $ hg co 'desc("add dir2")'
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo 8 > dir2/a
   $ hg ci -m 'modify dir2/a'
   created new head
 
-  $ hg debugindex .hg/store/meta/dir2/00manifest.i > before
+  $ hg debugindex --dir dir2 > before
   $ hg merge 'desc("modify dir1/a")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg revert -r 'desc("modify dir2/a")' .
   reverting dir1/a (glob)
   $ hg ci -m 'merge, keeping parent 1'
-  $ hg debugindex .hg/store/meta/dir2/00manifest.i > after
+  $ hg debugindex --dir dir2 > after
   $ diff before after
   $ rm before after
 
 Merge keeping directory from parent 2 does not create revlog entry. (Note that
 dir2's manifest does change, but only because dir2/a's filelog changes.)
 
   $ hg co 'desc("modify dir2/a")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg debugindex .hg/store/meta/dir1/00manifest.i > before
+  $ hg debugindex --dir dir1 > before
   $ hg merge 'desc("modify dir1/a")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg revert -r 'desc("modify dir1/a")' .
   reverting dir2/a (glob)
   $ hg ci -m 'merge, keeping parent 2'
   created new head
-  $ hg debugindex .hg/store/meta/dir1/00manifest.i > after
+  $ hg debugindex --dir dir1 > after
   $ diff before after
   $ rm before after
 
 Create flat source repo for tests with mixed flat/tree manifests
 
   $ cd ..
   $ hg init repo-flat
   $ cd repo-flat