/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)
0.98.3 by Gonéri Le Bouder
LocalGitBzrDirFormat has no repository_format
160
        # LocalGitBzrDirFormat has no repository_format
161
        if hasattr(format, "repository_format"):
162
            if format.repository_format == repo_format:
163
                candidates.append((key, format))
0.64.193 by Ian Clatworthy
Smarter selection of branch format based on shared repository format
164
    if len(candidates):
165
        # Assume the first one. Is there any reason not to do that?
166
        name, format = candidates[0]
167
        return format
168
    else:
169
        return None
0.95.1 by Ian Clatworthy
Create a repository implicitly if one doesn't already exist
170
171
172
def open_destination_directory(location, format=None, verbose=True):
173
    """Open a destination directory and return the BzrDir.
174
175
    If destination has a control directory, it will be returned.
176
    Otherwise, the destination should be empty or non-existent and
177
    a shared repository will be created there.
178
179
    :param location: the destination directory
180
    :param format: the format to use or None for the default
181
    :param verbose: display the format used if a repository is created.
182
    :return: BzrDir for the destination
183
    """
184
    import os
0.64.213 by Ian Clatworthy
Smarter blob tracking by implicitly collecting statistics before starting the import
185
    from bzrlib import bzrdir, errors, trace, transport
0.95.1 by Ian Clatworthy
Create a repository implicitly if one doesn't already exist
186
    try:
187
        control, relpath = bzrdir.BzrDir.open_containing(location)
188
        # XXX: Check the relpath is None here?
189
        return control
190
    except errors.NotBranchError:
191
        pass
192
193
    # If the directory exists, check it is empty. Otherwise create it.
194
    if os.path.exists(location):
195
        contents = os.listdir(location)
196
        if contents:
197
            errors.BzrCommandError("Destination must have a .bzr directory, "
198
                " not yet exist or be empty - files found in %s" % (location,))
199
    else:
200
        try:
201
            os.mkdir(location)
202
        except IOError, ex:
203
            errors.BzrCommandError("Unable to create %s: %s" %
204
                (location, ex))
205
206
    # Create a repository for the nominated format.
0.64.213 by Ian Clatworthy
Smarter blob tracking by implicitly collecting statistics before starting the import
207
    trace.note("Creating destination repository ...")
0.95.1 by Ian Clatworthy
Create a repository implicitly if one doesn't already exist
208
    if format is None:
209
        format = bzrdir.format_registry.make_bzrdir('default')
210
    to_transport = transport.get_transport(location)
211
    to_transport.ensure_base()
212
    control = format.initialize_on_transport(to_transport)
213
    repo = control.create_repository(shared=True)
214
    if verbose:
215
        from bzrlib.info import show_bzrdir_info
216
        show_bzrdir_info(repo.bzrdir, verbose=0)
217
    return control