17
17
"""Miscellaneous useful stuff."""
20
def single_plural(n, single, plural):
21
"""Return a single or plural form of a noun based on number."""
28
def defines_to_dict(defines):
29
"""Convert a list of definition strings to a dictionary."""
33
for define in defines:
34
kv = define.split('=', 1)
36
result[define.strip()] = 1
38
result[kv[0].strip()] = kv[1].strip()
43
"""Invert a dictionary with keys matching each value turned into a list."""
44
# Based on recipe from ASPN
46
for k, v in d.iteritems():
47
keys = result.setdefault(v, [])
52
def invert_dictset(d):
53
"""Invert a dictionary with keys matching a set of values, turned into lists."""
54
# Based on recipe from ASPN
56
for k, c in d.iteritems():
58
keys = result.setdefault(v, [])
63
def _common_path_and_rest(l1, l2, common=[]):
64
# From http://code.activestate.com/recipes/208993/
65
if len(l1) < 1: return (common, l1, l2)
66
if len(l2) < 1: return (common, l1, l2)
67
if l1[0] != l2[0]: return (common, l1, l2)
68
return _common_path_and_rest(l1[1:], l2[1:], common+[l1[0]])
71
def common_path(path1, path2):
72
"""Find the common bit of 2 paths."""
73
return ''.join(_common_path_and_rest(path1, path2)[0])
76
def common_directory(paths):
77
"""Find the deepest common directory of a list of paths.
79
:return: if no paths are provided, None is returned;
80
if there is no common directory, '' is returned;
81
otherwise the common directory with a trailing / is returned.
83
from bzrlib import osutils
84
def get_dir_with_slash(path):
85
if path == '' or path.endswith('/'):
88
dirname, basename = osutils.split(path)
97
return get_dir_with_slash(paths[0])
99
common = common_path(paths[0], paths[1])
100
for path in paths[2:]:
101
common = common_path(common, path)
102
return get_dir_with_slash(common)
105
22
def escape_commit_message(message):
106
23
"""Replace xml-incompatible control characters."""
107
24
# This really ought to be provided by bzrlib.
108
25
# Code copied from bzrlib.commit.
110
27
# Python strings can include characters that can't be
111
28
# represented in well-formed XML; escape characters that
112
29
# aren't listed in the XML specification
122
def binary_stream(stream):
123
"""Ensure a stream is binary on Windows.
130
fileno = getattr(stream, 'fileno', None)
133
if no >= 0: # -1 means we're working as subprocess
135
msvcrt.setmode(no, os.O_BINARY)
141
39
def best_format_for_objects_in_a_repository(repo):
142
40
"""Find the high-level format for branches and trees given a repository.
215
113
from bzrlib.info import show_bzrdir_info
216
114
show_bzrdir_info(repo.bzrdir, verbose=0)
118
def kind_to_mode(kind, executable):
120
if executable == True:
121
return stat.S_IFREG | 0755
122
elif executable == False:
123
return stat.S_IFREG | 0644
125
raise AssertionError("Executable %r invalid" % executable)
126
elif kind == "symlink":
128
elif kind == "directory":
130
elif kind == "tree-reference":
133
raise AssertionError("Unknown file kind '%s'" % kind)
136
def mode_to_kind(mode):
137
# Note: Output from git-fast-export slightly different to spec
138
if mode in (0644, 0100644):
140
elif mode in (0755, 0100755):
142
elif mode == 0040000:
143
return 'directory', False
144
elif mode == 0120000:
145
return 'symlink', False
146
elif mode == 0160000:
147
return 'tree-reference', False
149
raise AssertionError("invalid mode %o" % mode)