templatefilters: add commonprefix
The commonprefix filter takes a list of files names like files() and
returns the longest directory name common to all elements.
Differential Revision: https://phab.mercurial-scm.org/D3439
--- a/mercurial/templatefilters.py Sun May 20 19:07:51 2018 +0530
+++ b/mercurial/templatefilters.py Fri Apr 20 15:21:03 2018 +0200
@@ -99,6 +99,45 @@
"""
return os.path.basename(path)
+@templatefilter('commonprefix')
+def commonprefix(filelist):
+ """List of text. Treats each list item as file name with /
+ as path separator and returns the longest common directory
+ prefix shared by all list items.
+ Returns the empty string if no common prefix exists.
+
+ The list items are not normalized, i.e. "foo/../bar" is handled as
+ file "bar" in the directory "foo/..". Leading slashes are ignored.
+
+ For example, ["foo/bar/baz", "foo/baz/bar"] becomes "foo" and
+ ["foo/bar", "baz"] becomes "".
+ """
+ def common(a, b):
+ if len(a) > len(b):
+ a = b[:len(a)]
+ elif len(b) > len(a):
+ b = b[:len(a)]
+ if a == b:
+ return a
+ for i in xrange(len(a)):
+ if a[i] != b[i]:
+ return a[:i]
+ return a
+ try:
+ if not filelist:
+ return ""
+ dirlist = [f.lstrip('/').split('/')[:-1] for f in filelist]
+ if len(dirlist) == 1:
+ return '/'.join(dirlist[0])
+ a = min(dirlist)
+ b = max(dirlist)
+ # The common prefix of a and b is shared with all
+ # elements of the list since Python sorts lexicographical
+ # and [1, x] after [1].
+ return '/'.join(common(a, b))
+ except TypeError:
+ raise error.ParseError(_('argument is not a list of text'))
+
@templatefilter('count')
def count(i):
"""List or text. Returns the length as an integer."""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-template-filters.t Fri Apr 20 15:21:03 2018 +0200
@@ -0,0 +1,23 @@
+ $ hg debugtemplate '{""|splitlines|commonprefix}\n'
+
+ $ hg debugtemplate '{"foo/bar\nfoo/baz\nfoo/foobar\n"|splitlines|commonprefix}\n'
+ foo
+ $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commonprefix}\n'
+ foo
+ $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commonprefix}\n'
+ foo
+ $ hg debugtemplate '{"/foo\n/foo\n"|splitlines|commonprefix}\n'
+
+ $ hg debugtemplate '{"foo/bar\nbar/baz"|splitlines|commonprefix}\n'
+
+ $ hg debugtemplate '{"foo/bar\nbar/baz\nbar/foo\n"|splitlines|commonprefix}\n'
+
+ $ hg debugtemplate '{"foo/../bar\nfoo/bar"|splitlines|commonprefix}\n'
+ foo
+ $ hg debugtemplate '{"foo\n/foo"|splitlines|commonprefix}\n'
+
+ $ hg init
+ $ hg log -r null -T '{rev|commonprefix}'
+ hg: parse error: argument is not a list of text
+ (template filter 'commonprefix' is not compatible with keyword 'rev')
+ [255]