comparison mercurial/templatefilters.py @ 38987:56dd15178190

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
author Joerg Sonnenberger <joerg@bec.de>
date Fri, 20 Apr 2018 15:21:03 +0200
parents f5a1aa8c6987
children 0fe65bb7e160
comparison
equal deleted inserted replaced
38986:c019db5ccfa1 38987:56dd15178190
96 """Any text. Treats the text as a path, and returns the last 96 """Any text. Treats the text as a path, and returns the last
97 component of the path after splitting by the path separator. 97 component of the path after splitting by the path separator.
98 For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "". 98 For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
99 """ 99 """
100 return os.path.basename(path) 100 return os.path.basename(path)
101
102 @templatefilter('commonprefix')
103 def commonprefix(filelist):
104 """List of text. Treats each list item as file name with /
105 as path separator and returns the longest common directory
106 prefix shared by all list items.
107 Returns the empty string if no common prefix exists.
108
109 The list items are not normalized, i.e. "foo/../bar" is handled as
110 file "bar" in the directory "foo/..". Leading slashes are ignored.
111
112 For example, ["foo/bar/baz", "foo/baz/bar"] becomes "foo" and
113 ["foo/bar", "baz"] becomes "".
114 """
115 def common(a, b):
116 if len(a) > len(b):
117 a = b[:len(a)]
118 elif len(b) > len(a):
119 b = b[:len(a)]
120 if a == b:
121 return a
122 for i in xrange(len(a)):
123 if a[i] != b[i]:
124 return a[:i]
125 return a
126 try:
127 if not filelist:
128 return ""
129 dirlist = [f.lstrip('/').split('/')[:-1] for f in filelist]
130 if len(dirlist) == 1:
131 return '/'.join(dirlist[0])
132 a = min(dirlist)
133 b = max(dirlist)
134 # The common prefix of a and b is shared with all
135 # elements of the list since Python sorts lexicographical
136 # and [1, x] after [1].
137 return '/'.join(common(a, b))
138 except TypeError:
139 raise error.ParseError(_('argument is not a list of text'))
101 140
102 @templatefilter('count') 141 @templatefilter('count')
103 def count(i): 142 def count(i):
104 """List or text. Returns the length as an integer.""" 143 """List or text. Returns the length as an integer."""
105 try: 144 try: