--- a/hgext/graphlog.py Sat Feb 25 22:11:35 2012 +0100
+++ b/hgext/graphlog.py Sat Feb 25 22:11:36 2012 +0100
@@ -241,9 +241,6 @@
if op in opts and opts[op]:
raise util.Abort(_("-G/--graph option is incompatible with --%s")
% op.replace("_", "-"))
- if pats and opts.get('follow'):
- raise util.Abort(_("-G/--graph option is incompatible with --follow "
- "with file argument"))
def revset(repo, pats, opts):
"""Return revset str built of revisions, log options and file patterns.
@@ -256,6 +253,7 @@
'date': ('date(%(val)r)', None),
'branch': ('branch(%(val)r)', ' or '),
'_patslog': ('filelog(%(val)r)', ' or '),
+ '_patsfollow': ('follow(%(val)r)', ' or '),
'keyword': ('keyword(%(val)r)', ' or '),
'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
'user': ('user(%(val)r)', ' or '),
@@ -268,22 +266,35 @@
if 'branch' in opts and 'only_branch' in opts:
opts['branch'] = opts['branch'] + opts.pop('only_branch')
+ follow = opts.get('follow')
+ if 'follow' in opts:
+ del opts['follow']
# pats/include/exclude are passed to match.match() directly in
# _matchfile() revset but walkchangerevs() builds its matcher with
# scmutil.match(). The difference is input pats are globbed on
# platforms without shell expansion (windows).
- match, pats = scmutil.matchandpats(repo[None], pats, opts)
+ pctx = repo[None]
+ match, pats = scmutil.matchandpats(pctx, pats, opts)
slowpath = match.anypats() or (match.files() and opts.get('removed'))
if not slowpath:
for f in match.files():
+ if follow and f not in pctx:
+ raise util.Abort(_('cannot follow file not in parent '
+ 'revision: "%s"') % f)
filelog = repo.file(f)
if not len(filelog):
# A zero count may be a directory or deleted file, so
# try to find matching entries on the slow path.
+ if follow:
+ raise util.Abort(
+ _('cannot follow nonexistent file: "%s"') % f)
slowpath = True
if slowpath:
# See cmdutil.walkchangerevs() slow path.
#
+ if follow:
+ raise util.Abort(_('can only follow copies/renames for explicit '
+ 'filenames'))
# pats/include/exclude cannot be represented as separate
# revset expressions as their filtering logic applies at file
# level. For instance "-I a -X a" matches a revision touching
@@ -298,7 +309,13 @@
matchargs = ','.join(('%r' % p) for p in matchargs)
opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs]
else:
- opts['_patslog'] = list(pats)
+ if follow:
+ if pats:
+ opts['_patsfollow'] = list(pats)
+ else:
+ opts['follow'] = True
+ else:
+ opts['_patslog'] = list(pats)
revset = []
for op, val in opts.iteritems():
--- a/tests/test-glog.t Sat Feb 25 22:11:35 2012 +0100
+++ b/tests/test-glog.t Sat Feb 25 22:11:36 2012 +0100
@@ -1454,8 +1454,6 @@
('group', ('group', ('or', ('or', ('func', ('symbol', 'branch'), ('string', 'default')), ('func', ('symbol', 'branch'), ('string', 'branch'))), ('func', ('symbol', 'branch'), ('string', 'branch')))))
$ testlog -k expand -k merge
('group', ('group', ('or', ('func', ('symbol', 'keyword'), ('string', 'expand')), ('func', ('symbol', 'keyword'), ('string', 'merge')))))
- $ hg log -G --follow --template 'nodetag {rev}\n' | grep nodetag | wc -l
- \s*36 (re)
$ hg log -G --removed --template 'nodetag {rev}\n' | grep nodetag | wc -l
\s*0 (re)
$ hg log -G --only-merges --template 'nodetag {rev}\n' | grep nodetag | wc -l
@@ -1492,27 +1490,30 @@
[255]
$ testlog --prune 31 --prune 32
('group', ('group', ('and', ('not', ('group', ('or', ('string', '31'), ('func', ('symbol', 'ancestors'), ('string', '31'))))), ('not', ('group', ('or', ('string', '32'), ('func', ('symbol', 'ancestors'), ('string', '32'))))))))
- $ hg log -G --follow a
- abort: -G/--graph option is incompatible with --follow with file argument
- [255]
-
-Dedicated repo for --follow and paths filtering
+Dedicated repo for --follow and paths filtering. The g is crafted to
+have 2 filelog topological heads in a linear changeset graph.
$ cd ..
$ hg init follow
$ cd follow
$ echo a > a
$ echo aa > aa
+ $ echo f > f
$ hg ci -Am "add a"
adding a
adding aa
+ adding f
$ hg cp a b
+ $ hg cp f g
$ hg ci -m "copy a b"
$ mkdir dir
$ hg mv b dir
+ $ echo g >> g
+ $ echo f >> f
$ hg ci -m "mv b dir/b"
$ hg mv a b
+ $ hg cp -f f g
$ echo a > d
$ hg add d
$ hg ci -m "mv a b; add d"
@@ -1555,3 +1556,65 @@
> testlog a*;
> fi;
('group', ('group', ('func', ('symbol', 'filelog'), ('string', 'aa'))))
+
+Test --follow on a directory
+
+ $ testlog -f dir
+ abort: cannot follow file not in parent revision: "dir"
+ abort: cannot follow file not in parent revision: "dir"
+ abort: cannot follow file not in parent revision: "dir"
+
+Test --follow on file not in parent revision
+
+ $ testlog -f a
+ abort: cannot follow file not in parent revision: "a"
+ abort: cannot follow file not in parent revision: "a"
+ abort: cannot follow file not in parent revision: "a"
+
+Test --follow and patterns
+
+ $ testlog -f 'glob:*'
+ abort: can only follow copies/renames for explicit filenames
+ abort: can only follow copies/renames for explicit filenames
+ abort: can only follow copies/renames for explicit filenames
+
+Test --follow on a single rename
+
+ $ hg up -q 2
+ $ testlog -f a
+ ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'a'))))
+
+Test --follow and multiple renames
+
+ $ hg up -q tip
+ $ testlog -f e
+ ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'e'))))
+
+Test --follow and multiple filelog heads
+
+ $ hg up -q 2
+ $ testlog -f g
+ ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'g'))))
+ $ cat log.nodes
+ nodetag 2
+ nodetag 1
+ nodetag 0
+ $ hg up -q tip
+ $ testlog -f g
+ ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'g'))))
+ $ cat log.nodes
+ nodetag 3
+ nodetag 2
+ nodetag 0
+
+Test --follow and multiple files
+
+ $ testlog -f g e
+ ('group', ('group', ('or', ('func', ('symbol', 'follow'), ('string', 'g')), ('func', ('symbol', 'follow'), ('string', 'e')))))
+ $ cat log.nodes
+ nodetag 4
+ nodetag 3
+ nodetag 2
+ nodetag 1
+ nodetag 0
+