The commonprefix filter takes a list of files names like files() and
returns the longest directory name common to all elements.
Details
- Reviewers
- None
- Group Reviewers
hg-reviewers - Commits
- rHG56dd15178190: templatefilters: add commonprefix
Diff Detail
- Repository
- rHG Mercurial
- Lint
Automatic diff as part of commit; lint not applicable. - Unit
Automatic diff as part of commit; unit tests not applicable.
Event Timeline
Can you add test for failure cases? such as
- str|commonprefix
- int|commonprefix
- nothing common (e.g. ["/foo", "bar"])
- empty list
- paths normalized by os.path.normcase()
os.path.commonprefix() isn't what we want, but it might provide some hints.
"os.path.commonprefix() isn't what we want, but it might provide some hints."
Perhaps os.path.commonprefix() could be used with conditional
fixup by os.path.dirname()?
prefix = os.path.commonprefix(files) if prefix isn't a valid path: prefix = os.path.dirname(prefix)
This way, we can remove normpath() which has a side effect s|/|\\|g
on Windows.
Please add tests of edge cases.
- str|commonprefix
- infinite loop (e.g. ["/foo", "bar"])
- exact match (e.g. ["/foo"] and ["/foo", "/foo"])
- empty list
os.path.commonprefix() will provide some hints to avoid comparison of
all list elements by using min()/max().
{str|commonprefix} is not really interesting since it is naturally an iterable of text. The others are covered, the routine tries to optimize a couple of common cases as well now.
+ $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commonprefix}\n'
+ foo
should be "foo/bar"
+ $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commonprefix}\n'
+ foo
should be "/foo/bar"
+ $ hg debugtemplate '{"/foo\n/foo\n"|splitlines|commonprefix}\n'
+
should e "/foo"
FWIW, I doubt if scanning all elements with the seen set is faster than
calling min()/max() to pick the farthest pair because Python is slow.
{str|commonprefix} is not really interesting since it is naturally an
iterable of text.
I think it's better to error out, but that could be addressed later.
For the record, I still believe the commonprefix of a pair of identical paths
should be the path itself as it is the longest sub-component of these paths.
+ $ hg debugtemplate '{"foo/bar\nfoo/bar\n"|splitlines|commonprefix}\n'
+ fooshould be "foo/bar"
And removing the leading slash is awkward.
+ $ hg debugtemplate '{"/foo/bar\n/foo/bar\n"|splitlines|commonprefix}\n'
+ fooshould be "/foo/bar"
Do you think we should call it commonpath() or commondir() instead in case we want commonprefix() to work for any string in the future (and not care about path separators)?
commondir() would be fine as well. commonpath() doesn't feel better. I'm ambivalent about either name.
I'd vote for changing it then. Both because I think it might make it clearer that it's the common prefix of "foo/bar" and "food" is not "foo" and because, as I said, we might want such a function later and it would be unfortunate if the name was taken. Btw, I just checked and we already have dirname() and stripdir() functions that would match commondir().
> `commondir()` would be fine as well. `commonpath()` doesn't feel better. I'm ambivalent about either nam> I'd vote for changing it then. Both because I think it might make it clearer that it's the common prefix of "foo/bar" and "food" is not "foo" and because, as I said, we might want such a function later and it would be unfortunate if the name was taken. Btw, I just checked and we already have `dirname()` and `stripdir()` functions that would match `commondir()`.
+1 for commondir(). It matches the actual behavior, which is the last filename
part is always stripped.