/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.30 by Ian Clatworthy
add heads analysis to info processor
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
0.64.32 by Ian Clatworthy
move single_plural into helpers
17
"""Miscellaneous useful stuff."""
18
19
20
def single_plural(n, single, plural):
21
    """Return a single or plural form of a noun based on number."""
22
    if n == 1:
23
        return single
24
    else:
25
        return plural
0.64.30 by Ian Clatworthy
add heads analysis to info processor
26
27
0.64.38 by Ian Clatworthy
clean-up doc ready for initial release
28
def defines_to_dict(defines):
29
    """Convert a list of definition strings to a dictionary."""
30
    if defines is None:
31
        return None
32
    result = {}
33
    for define in defines:
34
        kv = define.split('=', 1)
35
        if len(kv) == 1:
36
            result[define.strip()] = 1
37
        else:
38
            result[kv[0].strip()] = kv[1].strip()
39
    return result
40
41
0.64.30 by Ian Clatworthy
add heads analysis to info processor
42
def invert_dict(d):
43
    """Invert a dictionary with keys matching each value turned into a list."""
44
    # Based on recipe from ASPN
45
    result = {}
46
    for k, v in d.iteritems():
47
        keys = result.setdefault(v, [])
48
        keys.append(k)
49
    return result
0.75.1 by Brian de Alwis
Add support for multiple branches by supporting the 'reset' command.
50
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
51
0.75.1 by Brian de Alwis
Add support for multiple branches by supporting the 'reset' command.
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
55
    result = {}
56
    for k, c in d.iteritems():
57
        for v in c:
58
            keys = result.setdefault(v, [])
59
            keys.append(k)
60
    return result
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
61
62
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
63
def _common_path_and_rest(l1, l2, common=[]):
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
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)
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
68
    return _common_path_and_rest(l1[1:], l2[1:], common+[l1[0]])
69
70
71
def common_path(path1, path2):
72
    """Find the common bit of 2 paths."""
73
    return ''.join(_common_path_and_rest(path1, path2)[0])
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
74
75
76
def common_directory(paths):
77
    """Find the deepest common directory of a list of paths.
78
    
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
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.
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
82
    """
83
    from bzrlib import osutils
84
    def get_dir_with_slash(path):
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
85
        if path == '' or path.endswith('/'):
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
86
            return path
87
        else:
88
            dirname, basename = osutils.split(path)
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
89
            if dirname == '':
90
                return dirname
91
            else:
92
                return dirname + '/'
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
93
94
    if not paths:
95
        return None
96
    elif len(paths) == 1:
97
        return get_dir_with_slash(paths[0])
98
    else:
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
99
        common = common_path(paths[0], paths[1])
0.77.8 by Ian Clatworthy
include subdir & multiple files tests
100
        for path in paths[2:]:
101
            common = common_path(common, path)
0.77.9 by Ian Clatworthy
common_directory tests & tweaks
102
        return get_dir_with_slash(common)
0.78.2 by Ian Clatworthy
move escape_commit_message into helpers
103
104
105
def escape_commit_message(message):
106
    """Replace xml-incompatible control characters."""
107
    # This really ought to be provided by bzrlib.
108
    # Code copied from bzrlib.commit.
109
    
110
    # Python strings can include characters that can't be
111
    # represented in well-formed XML; escape characters that
112
    # aren't listed in the XML specification
113
    # (http://www.w3.org/TR/REC-xml/#NT-Char).
114
    import re
115
    message, _ = re.subn(
116
        u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
117
        lambda match: match.group(0).encode('unicode_escape'),
118
        message)
119
    return message
0.84.2 by Ian Clatworthy
make sure fast-export uses a binary stream on Windows
120
121
122
def binary_stream(stream):
123
    """Ensure a stream is binary on Windows.
124
125
    :return: the stream
126
    """
127
    try:
128
        import os
129
        if os.name == 'nt':
130
            fileno = getattr(stream, 'fileno', None)
131
            if fileno:
132
                no = fileno()
133
                if no >= 0:     # -1 means we're working as subprocess
134
                    import msvcrt
135
                    msvcrt.setmode(no, os.O_BINARY)
136
    except ImportError:
137
        pass
138
    return stream
0.64.193 by Ian Clatworthy
Smarter selection of branch format based on shared repository format
139
140
141
def best_format_for_objects_in_a_repository(repo):
142
    """Find the high-level format for branches and trees given a repository.
143
144
    When creating branches and working trees within a repository, Bazaar
145
    defaults to using the default format which may not be the best choice.
146
    This routine does a reverse lookup of the high-level format registry
147
    to find the high-level format that a shared repository was most likely
148
    created via.
149
150
    :return: the BzrDirFormat or None if no matches were found.
151
    """
152
    # Based on code from bzrlib/info.py ...
153
    from bzrlib import bzrdir
154
    repo_format = repo._format
155
    candidates  = []
156
    non_aliases = set(bzrdir.format_registry.keys())
157
    non_aliases.difference_update(bzrdir.format_registry.aliases())
158
    for key in non_aliases:
159
        format = bzrdir.format_registry.make_bzrdir(key)
160
        if format.repository_format == repo_format:
161
            candidates.append((key, format))
162
    if len(candidates):
163
        # Assume the first one. Is there any reason not to do that?
164
        name, format = candidates[0]
165
        return format
166
    else:
167
        return None
0.95.1 by Ian Clatworthy
Create a repository implicitly if one doesn't already exist
168
169
170
def open_destination_directory(location, format=None, verbose=True):
171
    """Open a destination directory and return the BzrDir.
172
173
    If destination has a control directory, it will be returned.
174
    Otherwise, the destination should be empty or non-existent and
175
    a shared repository will be created there.
176
177
    :param location: the destination directory
178
    :param format: the format to use or None for the default
179
    :param verbose: display the format used if a repository is created.
180
    :return: BzrDir for the destination
181
    """
182
    import os
183
    from bzrlib import bzrdir, errors, transport
184
    try:
185
        control, relpath = bzrdir.BzrDir.open_containing(location)
186
        # XXX: Check the relpath is None here?
187
        return control
188
    except errors.NotBranchError:
189
        pass
190
191
    # If the directory exists, check it is empty. Otherwise create it.
192
    if os.path.exists(location):
193
        contents = os.listdir(location)
194
        if contents:
195
            errors.BzrCommandError("Destination must have a .bzr directory, "
196
                " not yet exist or be empty - files found in %s" % (location,))
197
    else:
198
        try:
199
            os.mkdir(location)
200
        except IOError, ex:
201
            errors.BzrCommandError("Unable to create %s: %s" %
202
                (location, ex))
203
204
    # Create a repository for the nominated format.
205
    if format is None:
206
        format = bzrdir.format_registry.make_bzrdir('default')
207
    to_transport = transport.get_transport(location)
208
    to_transport.ensure_base()
209
    control = format.initialize_on_transport(to_transport)
210
    repo = control.create_repository(shared=True)
211
    if verbose:
212
        from bzrlib.info import show_bzrdir_info
213
        show_bzrdir_info(repo.bzrdir, verbose=0)
214
    return control