[PATCH] changeset_printer and changeset_templater updated to work with contexts

Alexander Solovyov piranha at piranha.org.ua
Mon Oct 13 13:55:31 CDT 2008


# HG changeset patch
# User Alexander Solovyov <piranha at piranha.org.ua>
# Date 1223922011 -10800
# Node ID 6a0d77cb345de9ac967a278d692c4bda031171b0
# Parent  a4769dec7773e119c812af7d4cb88fceda3a0f03
changeset_printer and changeset_templater updated to work with contexts

Commands, which are using them, updated too, as long as extensions. Two tests are updated because now they fail earlier (because of context initialization).

diff --git a/hgext/children.py b/hgext/children.py
--- a/hgext/children.py
+++ b/hgext/children.py
@@ -23,13 +23,14 @@
     """
     rev = opts.get('rev')
     if file_:
-        ctx = repo.filectx(file_, changeid=rev)
+        children = [c.changectx() for c in
+                    repo.filectx(file_, changeid=rev).children()]
     else:
-        ctx = repo[rev]
+        children = repo[rev].children()
 
     displayer = cmdutil.show_changeset(ui, repo, opts)
-    for node in [cp.node() for cp in ctx.children()]:
-        displayer.show(changenode=node)
+    for cp in children:
+        displayer.show(cp)
 
 
 cmdtable = {
diff --git a/hgext/churn.py b/hgext/churn.py
--- a/hgext/churn.py
+++ b/hgext/churn.py
@@ -65,7 +65,7 @@
         tmpl = maketemplater(ui, repo, tmpl)
         def getkey(ctx):
             ui.pushbuffer()
-            tmpl.show(changenode=ctx.node())
+            tmpl.show(ctx)
             return ui.popbuffer()
 
     count = pct = 0
diff --git a/hgext/graphlog.py b/hgext/graphlog.py
--- a/hgext/graphlog.py
+++ b/hgext/graphlog.py
@@ -229,7 +229,7 @@
         # log_strings is the list of all log strings to draw alongside
         # the graph.
         ui.pushbuffer()
-        cs_printer.show(rev, node)
+        cs_printer.show(changenode=node)
         log_strings = ui.popbuffer().split("\n")[:-1]
 
         if n_columns_diff == -1:
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -593,103 +593,95 @@
             return 1
         return 0
 
-    def show(self, rev=0, changenode=None, copies=(), **props):
+    def show(self, ctx=None, changenode=None, copies=(), **props):
+        assert ctx is not None or changenode
+        if ctx is None:
+            ctx = self.repo[changenode]
         if self.buffered:
             self.ui.pushbuffer()
-            self._show(rev, changenode, copies, props)
-            self.hunk[rev] = self.ui.popbuffer()
+            self._show(ctx, copies, props)
+            self.hunk[ctx.rev()] = self.ui.popbuffer()
         else:
-            self._show(rev, changenode, copies, props)
+            self._show(ctx, copies, props)
 
-    def _show(self, rev, changenode, copies, props):
+    def _show(self, ctx, copies, props):
         '''show a single changeset or file revision'''
-        log = self.repo.changelog
-        if changenode is None:
-            changenode = log.node(rev)
-        elif not rev:
-            rev = log.rev(changenode)
-
         if self.ui.quiet:
-            self.ui.write("%d:%s\n" % (rev, short(changenode)))
+            self.ui.write("%d:%s\n" % (ctx.rev(), short(ctx.node())))
             return
 
-        changes = log.read(changenode)
-        date = util.datestr(changes[2])
-        extra = changes[5]
-        branch = extra.get("branch")
-
+        date = util.datestr(ctx.date())
         hexfunc = self.ui.debugflag and hex or short
-
-        parents = [(p, hexfunc(log.node(p)))
-                   for p in self._meaningful_parentrevs(log, rev)]
-
-        self.ui.write(_("changeset:   %d:%s\n") % (rev, hexfunc(changenode)))
+        self.ui.write(_("changeset:   %d:%s\n") % (ctx.rev(),
+                                                   hexfunc(ctx.node())))
 
         # don't show the default branch name
-        if branch != 'default':
-            branch = util.tolocal(branch)
+        if ctx.branch() != 'default':
+            branch = util.tolocal(ctx.branch())
             self.ui.write(_("branch:      %s\n") % branch)
-        for tag in self.repo.nodetags(changenode):
+        for tag in ctx.tags():
             self.ui.write(_("tag:         %s\n") % tag)
-        for parent in parents:
-            self.ui.write(_("parent:      %d:%s\n") % parent)
+        for parent in self._meaningful_parents(ctx):
+            self.ui.write(_("parent:      %d:%s\n") % (parent.rev(),
+                                                       hexfunc(parent.node())))
 
         if self.ui.debugflag:
+            mnode = ctx.changeset()[0]
             self.ui.write(_("manifest:    %d:%s\n") %
-                          (self.repo.manifest.rev(changes[0]), hex(changes[0])))
-        self.ui.write(_("user:        %s\n") % changes[1])
+                          (self.repo.manifest.rev(mnode), hex(mnode)))
+        self.ui.write(_("user:        %s\n") % ctx.user())
         self.ui.write(_("date:        %s\n") % date)
 
         if self.ui.debugflag:
-            files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
+            files = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3]
             for key, value in zip([_("files:"), _("files+:"), _("files-:")],
                                   files):
                 if value:
                     self.ui.write("%-12s %s\n" % (key, " ".join(value)))
-        elif changes[3] and self.ui.verbose:
-            self.ui.write(_("files:       %s\n") % " ".join(changes[3]))
+        elif ctx.files() and self.ui.verbose:
+            self.ui.write(_("files:       %s\n") % " ".join(ctx.files()))
         if copies and self.ui.verbose:
             copies = ['%s (%s)' % c for c in copies]
             self.ui.write(_("copies:      %s\n") % ' '.join(copies))
 
-        if extra and self.ui.debugflag:
-            for key, value in util.sort(extra.items()):
+        if ctx.extra() and self.ui.debugflag:
+            for key, value in util.sort(ctx.extra().items()):
                 self.ui.write(_("extra:       %s=%s\n")
                               % (key, value.encode('string_escape')))
 
-        description = changes[4].strip()
-        if description:
+        if ctx.description():
             if self.ui.verbose:
                 self.ui.write(_("description:\n"))
-                self.ui.write(description)
+                self.ui.write(ctx.description())
                 self.ui.write("\n\n")
             else:
                 self.ui.write(_("summary:     %s\n") %
-                              description.splitlines()[0])
+                              ctx.description().splitlines()[0])
         self.ui.write("\n")
 
-        self.showpatch(changenode)
+        self.showpatch(ctx)
 
-    def showpatch(self, node):
+    def showpatch(self, ctx):
         if self.patch:
-            prev = self.repo.changelog.parents(node)[0]
-            patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui,
+            prev = ctx.parents()[0]
+            patch.diff(self.repo, prev.node(), ctx.node(), match=self.patch, fp=self.ui,
                        opts=patch.diffopts(self.ui))
             self.ui.write("\n")
 
-    def _meaningful_parentrevs(self, log, rev):
+    def _meaningful_parents(self, ctx):
         """Return list of meaningful (or all if debug) parentrevs for rev.
 
         For merges (two non-nullrev revisions) both parents are meaningful.
         Otherwise the first parent revision is considered meaningful if it
         is not the preceding revision.
         """
-        parents = log.parentrevs(rev)
-        if not self.ui.debugflag and parents[1] == nullrev:
-            if parents[0] >= rev - 1:
-                parents = []
-            else:
-                parents = [parents[0]]
+        parents = ctx.parents()
+        if (not self.ui.debugflag and len(parents) != 2 and
+            parents[0].rev() >= ctx.rev() - 1):
+                return []
+        # NOTE: do we need this?
+        if self.ui.debugflag and len(parents) != 2:
+            parents.append(self.repo[-1])
         return parents
 
 
@@ -711,15 +703,8 @@
         '''set template string to use'''
         self.t.cache['changeset'] = t
 
-    def _show(self, rev, changenode, copies, props):
+    def _show(self, ctx, copies, props):
         '''show a single changeset or file revision'''
-        log = self.repo.changelog
-        if changenode is None:
-            changenode = log.node(rev)
-        elif not rev:
-            rev = log.rev(changenode)
-
-        changes = log.read(changenode)
 
         def showlist(name, values, plural=None, **args):
             '''expand set of values.
@@ -783,21 +768,21 @@
                 yield self.t(endname, **args)
 
         def showbranches(**args):
-            branch = changes[5].get("branch")
+            branch = ctx.branch()
             if branch != 'default':
                 branch = util.tolocal(branch)
                 return showlist('branch', [branch], plural='branches', **args)
 
         def showparents(**args):
-            parents = [[('rev', p), ('node', hex(log.node(p)))]
-                       for p in self._meaningful_parentrevs(log, rev)]
+            parents = [[('rev', p.rev()), ('node', p.hex())]
+                       for p in self._meaningful_parents(ctx)]
             return showlist('parent', parents, **args)
 
         def showtags(**args):
-            return showlist('tag', self.repo.nodetags(changenode), **args)
+            return showlist('tag', ctx.tags(), **args)
 
         def showextras(**args):
-            for key, value in util.sort(changes[5].items()):
+            for key, value in util.sort(ctx.extra().items()):
                 args = args.copy()
                 args.update(dict(key=key, value=value))
                 yield self.t('extra', **args)
@@ -810,10 +795,10 @@
         def getfiles():
             if not files:
                 files[:] = self.repo.status(
-                    log.parents(changenode)[0], changenode)[:3]
+                    ctx.parents()[0].node(), ctx.node())[:3]
             return files
         def showfiles(**args):
-            return showlist('file', changes[3], **args)
+            return showlist('file', ctx.files(), **args)
         def showmods(**args):
             return showlist('file_mod', getfiles()[0], **args)
         def showadds(**args):
@@ -822,24 +807,24 @@
             return showlist('file_del', getfiles()[2], **args)
         def showmanifest(**args):
             args = args.copy()
-            args.update(dict(rev=self.repo.manifest.rev(changes[0]),
-                             node=hex(changes[0])))
+            args.update(dict(rev=self.repo.manifest.rev(ctx.changeset()[0]),
+                             node=hex(ctx.changeset()[0])))
             return self.t('manifest', **args)
 
         defprops = {
-            'author': changes[1],
+            'author': ctx.user(),
             'branches': showbranches,
-            'date': changes[2],
-            'desc': changes[4].strip(),
+            'date': ctx.date(),
+            'desc': ctx.description().strip(),
             'file_adds': showadds,
             'file_dels': showdels,
             'file_mods': showmods,
             'files': showfiles,
             'file_copies': showcopies,
             'manifest': showmanifest,
-            'node': hex(changenode),
+            'node': ctx.hex(),
             'parents': showparents,
-            'rev': rev,
+            'rev': ctx.rev(),
             'tags': showtags,
             'extras': showextras,
             }
@@ -860,7 +845,7 @@
             if key:
                 h = templater.stringify(self.t(key, **props))
                 if self.buffered:
-                    self.header[rev] = h
+                    self.header[ctx.rev()] = h
                 else:
                     self.ui.write(h)
             if self.ui.debugflag and 'changeset_debug' in self.t:
@@ -872,7 +857,7 @@
             else:
                 key = 'changeset'
             self.ui.write(templater.stringify(self.t(key, **props)))
-            self.showpatch(changenode)
+            self.showpatch(ctx)
         except KeyError, inst:
             raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
                                                            inst.args[0]))
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1776,37 +1776,14 @@
         endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
     else:
         endrev = len(repo)
-    rcache = {}
-    ncache = {}
-    def getrenamed(fn, rev):
-        '''looks up all renames for a file (up to endrev) the first
-        time the file is given. It indexes on the changerev and only
-        parses the manifest if linkrev != changerev.
-        Returns rename info for fn at changerev rev.'''
-        if fn not in rcache:
-            rcache[fn] = {}
-            ncache[fn] = {}
-            fl = repo.file(fn)
-            for i in fl:
-                node = fl.node(i)
-                lr = fl.linkrev(node)
-                renamed = fl.renamed(node)
-                rcache[fn][lr] = renamed
-                if renamed:
-                    ncache[fn][node] = renamed
-                if lr >= endrev:
-                    break
-        if rev in rcache[fn]:
-            return rcache[fn][rev]
 
-        # If linkrev != rev (i.e. rev not found in rcache) fallback to
-        # filectx logic.
-
-        try:
-            return repo[rev][fn].renamed()
-        except revlog.LookupError:
-            pass
-        return None
+    def getrenamed(ctx):
+        for f in ctx.files():
+            if not f in ctx.manifest():
+                continue
+            cp = ctx.filectx(f).renamed()
+            if cp:
+                yield (f, cp[0])
 
     df = False
     if opts["date"]:
@@ -1817,43 +1794,31 @@
     displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
     for st, rev, fns in changeiter:
         if st == 'add':
-            changenode = repo.changelog.node(rev)
-            parents = [p for p in repo.changelog.parentrevs(rev)
-                       if p != nullrev]
-            if opts['no_merges'] and len(parents) == 2:
+            ctx = repo[rev]
+            if opts['no_merges'] and len(ctx.parents()) == 2:
                 continue
-            if opts['only_merges'] and len(parents) != 2:
+            if opts['only_merges'] and len(ctx.parents()) != 2:
                 continue
 
-            if only_branches:
-                revbranch = get(rev)[5]['branch']
-                if revbranch not in only_branches:
-                    continue
+            if only_branches and ctx.branch() not in only_branches:
+                continue
 
-            if df:
-                changes = get(rev)
-                if not df(changes[2][0]):
-                    continue
+            if df and not df(ctx.date()[0]):
+                continue
 
             if opts['keyword']:
-                changes = get(rev)
                 miss = 0
                 for k in [kw.lower() for kw in opts['keyword']]:
-                    if not (k in changes[1].lower() or
-                            k in changes[4].lower() or
-                            k in " ".join(changes[3]).lower()):
+                    if not (k in ctx.user().lower() or
+                            k in ctx.description().lower() or
+                            k in " ".join(ctx.files()).lower()):
                         miss = 1
                         break
                 if miss:
                     continue
 
-            copies = []
-            if opts.get('copies') and rev:
-                for fn in get(rev)[3]:
-                    rename = getrenamed(fn, rev)
-                    if rename:
-                        copies.append((fn, rename[0]))
-            displayer.show(rev, changenode, copies=copies)
+            copies = opts.get('copies') and getrenamed(ctx) or []
+            displayer.show(ctx, copies=copies)
         elif st == 'iter':
             if count == limit: break
             if displayer.flush(rev):
@@ -1962,11 +1927,11 @@
     for n in o:
         if count >= limit:
             break
-        parents = [p for p in repo.changelog.parents(n) if p != nullid]
-        if opts['no_merges'] and len(parents) == 2:
+        ctx = repo[n]
+        if opts['no_merges'] and len(ctx.parents()) == 2:
             continue
         count += 1
-        displayer.show(changenode=n)
+        displayer.show(ctx)
 
 def parents(ui, repo, file_=None, **opts):
     """show the parents of the working dir or revision
@@ -1999,14 +1964,14 @@
         if not filenodes:
             raise util.Abort(_("'%s' not found in manifest!") % file_)
         fl = repo.file(file_)
-        p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
+        p = [repo[fl.linkrev(fn)] for fn in filenodes]
     else:
-        p = [cp.node() for cp in ctx.parents()]
+        p = ctx.parents()
 
     displayer = cmdutil.show_changeset(ui, repo, opts)
-    for n in p:
-        if n != nullid:
-            displayer.show(changenode=n)
+    for c in p:
+        if c.node() != nullid:
+            displayer.show(c)
 
 def paths(ui, repo, search=None):
     """show definition of symbolic path names
@@ -2785,7 +2750,7 @@
     that repository becomes the current tip. The "tip" tag is special
     and cannot be renamed or assigned to a different changeset.
     """
-    cmdutil.show_changeset(ui, repo, opts).show(len(repo) - 1)
+    cmdutil.show_changeset(ui, repo, opts).show(repo['tip'])
 
 def unbundle(ui, repo, fname1, *fnames, **opts):
     """apply one or more changegroup files
diff --git a/tests/test-mq.out b/tests/test-mq.out
--- a/tests/test-mq.out
+++ b/tests/test-mq.out
@@ -299,8 +299,8 @@
 2 qtip bar tip
 % bad node in status
 Now at: foo
+mq status file refers to unknown node
 changeset:   0:cb9a9f314b8b
-mq status file refers to unknown node
 tag:         tip
 user:        test
 date:        Thu Jan 01 00:00:00 1970 +0000
diff --git a/tests/test-tags.out b/tests/test-tags.out
--- a/tests/test-tags.out
+++ b/tests/test-tags.out
@@ -29,11 +29,11 @@
 localtags, line 1: tag 'invalid' refers to unknown node
 tip                                8:4ca6f1b1a68c
 first                              0:0acdaf898367
-changeset:   8:4ca6f1b1a68c
 .hgtags at c071f74ab5eb, line 2: cannot parse entry
 .hgtags at c071f74ab5eb, line 4: node 'foo' is not well formed
 .hgtags at 4ca6f1b1a68c, line 2: node 'x' is not well formed
 localtags, line 1: tag 'invalid' refers to unknown node
+changeset:   8:4ca6f1b1a68c
 tag:         tip
 parent:      3:b2ef3841386b
 user:        test


More information about the Mercurial-devel mailing list