mercurial/templatefilters.py
changeset 38201 56dd15178190
parent 38024 f5a1aa8c6987
child 38287 0fe65bb7e160
--- 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."""