Patchwork [4,of,4,RFC,V2] annotate: add option to annotate working-directory files

login
register
mail settings
Submitter Yuya Nishihara
Date March 16, 2015, 2:04 p.m.
Message ID <62c566cdb357056fa62c.1426514673@mimosa>
Download mbox | patch
Permalink /patch/8095/
State Superseded
Commit 77881cade20e19b699a2d87d65c4816913d61a4c
Headers show

Comments

Yuya Nishihara - March 16, 2015, 2:04 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1408179055 -32400
#      Sat Aug 16 17:50:55 2014 +0900
# Node ID 62c566cdb357056fa62c5ca08d113ed54935ea35
# Parent  cdf011561f3cac5e4f44a9811ec4354ebb471867
annotate: add option to annotate working-directory files

Working revision or node is displayed with "+" suffix in plain output, but
null/None in machine-readable format.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -266,6 +266,9 @@  def annotate(ui, repo, *pats, **opts):
     anyway, although the results will probably be neither useful
     nor desirable.
 
+    By default, annotate files in the parent of the working directory.
+    Use -r wc to annotate the working directory files.
+
     Returns 0 on success.
     """
     if not pats:
@@ -276,13 +279,41 @@  def annotate(ui, repo, *pats, **opts):
         # to mimic the behavior of Mercurial before version 1.5
         opts['file'] = True
 
+    ctx = scmutil.revsingle(repo, opts.get('rev'))
+
     fm = ui.formatter('annotate', opts)
     datefunc = ui.quiet and util.shortdate or util.datestr
-    hexfn = fm.hexfunc
+    if ctx.rev() is None:
+        def hexfn(node):
+            if node is None:
+                return None
+            else:
+                return fm.hexfunc(node)
+        if opts.get('changeset'):
+            # omit "+" suffix which is appended to node hex
+            def formatrev(rev):
+                if rev is None:
+                    return '%d' % ctx.p1().rev()
+                else:
+                    return '%d' % rev
+        else:
+            def formatrev(rev):
+                if rev is None:
+                    return '%d+' % ctx.p1().rev()
+                else:
+                    return '%d ' % rev
+        def formathex(hex):
+            if hex is None:
+                return '%s+' % fm.hexfunc(ctx.p1().node())
+            else:
+                return '%s ' % hex
+    else:
+        hexfn = fm.hexfunc
+        formatrev = formathex = str
 
     opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
-             ('number', ' ', lambda x: x[0].rev(), str),
-             ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
+             ('number', ' ', lambda x: x[0].rev(), formatrev),
+             ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
              ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
              ('file', ' ', lambda x: x[0].path(), str),
              ('line_number', ':', lambda x: x[1], str),
@@ -312,7 +343,6 @@  def annotate(ui, repo, *pats, **opts):
     def bad(x, y):
         raise util.Abort("%s: %s" % (x, y))
 
-    ctx = scmutil.revsingle(repo, opts.get('rev'))
     m = scmutil.match(ctx, pats, opts)
     m.bad = bad
     follow = not opts.get('no_follow')
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -913,7 +913,10 @@  class basefilectx(object):
 
         # use linkrev to find the first changeset where self appeared
         base = self
-        introrev = self.introrev()
+        if self.rev() is None:
+            introrev = None  # uncommitted file has no linkrev
+        else:
+            introrev = self.introrev()
         if self.rev() != introrev:
             base = self.filectx(self.filenode(), changeid=introrev)
 
diff --git a/tests/test-annotate.t b/tests/test-annotate.t
--- a/tests/test-annotate.t
+++ b/tests/test-annotate.t
@@ -398,6 +398,76 @@  and its ancestor by overriding "repo._fi
   20: 4 baz:4
   16: 5
 
+annotate clean file
+
+  $ hg annotate -ncr wc foo
+  11 472b18db256d : foo
+
+annotate modified file
+
+  $ echo foofoo >> foo
+  $ hg annotate -r wc foo
+  11 : foo
+  20+: foofoo
+
+  $ hg annotate -cr wc foo
+  472b18db256d : foo
+  b6bedd5477e7+: foofoo
+
+  $ hg annotate -ncr wc foo
+  11 472b18db256d : foo
+  20 b6bedd5477e7+: foofoo
+
+  $ hg annotate --debug -ncr wc foo
+  11 472b18db256d1e8282064eab4bfdaf48cbfe83cd : foo
+  20 b6bedd5477e797f25e568a6402d4697f3f895a72+: foofoo
+
+  $ hg annotate -udr wc foo
+  test Thu Jan 01 00:00:00 1970 +0000: foo
+  test [A-Za-z0-9:+ ]+: foofoo (re)
+
+  $ hg annotate -ncr wc -Tjson foo
+  [
+   {
+    "line": "foo\n",
+    "node": "472b18db256d1e8282064eab4bfdaf48cbfe83cd",
+    "rev": 11
+   },
+   {
+    "line": "foofoo\n",
+    "node": null,
+    "rev": null
+   }
+  ]
+
+annotate added file
+
+  $ echo bar > bar
+  $ hg add bar
+  $ hg annotate -ncr wc bar
+  20 b6bedd5477e7+: bar
+
+annotate renamed file
+
+  $ hg rename foo renamefoo2
+  $ hg annotate -ncr wc renamefoo2
+  11 472b18db256d : foo
+  20 b6bedd5477e7+: foofoo
+
+annotate missing file
+
+  $ rm baz
+  $ hg annotate -ncr wc baz
+  abort: No such file or directory: $TESTTMP/repo/baz
+  [255]
+
+annotate removed file
+
+  $ hg rm baz
+  $ hg annotate -ncr wc baz
+  abort: No such file or directory: $TESTTMP/repo/baz
+  [255]
+
 Test annotate with whitespace options
 
   $ cd ..