dev: format code using "garden fmt" (black)
[git-cola.git] / cola / display.py
blobdcd68cf038c5f387ed59df402e5c2a1d1d97bd31
1 """Display models and utility functions"""
2 from __future__ import absolute_import, division, print_function, unicode_literals
3 import collections
6 def shorten_paths(source_paths):
7 """Shorten a sequence of paths into unique strings for display"""
8 result = {}
9 # Start by assuming that all paths are in conflict.
10 # On each iteration we will collect all the path suffixes, move the newly
11 # unique entries to the result, and repeat until no conflicts remain.
12 count = 0
13 conflicts = list(source_paths)
14 in_conflict = True
15 while in_conflict:
16 count += 1
17 # Gather the suffixes for the current paths in conflict
18 suffixes = collections.defaultdict(list)
19 for path in conflicts:
20 suffix = path_suffix(path, count)
21 suffixes[suffix].append(path)
23 # Loop over the suffixes to gather new conflicts and unique entries.
24 conflicts = []
25 in_conflict = False
27 for suffix, paths in suffixes.items():
28 # If only a single path exists for the suffix then no conflict
29 # exists, and the suffix is valid.
30 if len(paths) == 1:
31 result[paths[0]] = suffix
32 # If this loop runs too long then bail out by using the full path.
33 elif count >= 128:
34 for path in paths:
35 result[path] = path
36 # If multiple paths map to the same suffix then the paths are
37 # considered in conflict, and will be reprocessed.
38 else:
39 conflicts.extend(paths)
40 in_conflict = True
42 return result
45 def path_suffix(path, count):
46 """Return `count` number of trailing path components"""
47 path = normalize_path(path)
48 components = path.split('/')[-count:]
49 return '/'.join(components)
52 def normalize_path(path):
53 """Normalize a path so that only "/" is used as a separator"""
54 return path.replace('\\', '/')