Release 0.11.0.
[bzr-fastimport.git] / helpers.py
blobafc867d3ba1a3aeea71180456490fb2a18d7fe3b
1 # Copyright (C) 2008 Canonical Ltd
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.
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.
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
17 """Miscellaneous useful stuff."""
19 import stat
22 def escape_commit_message(message):
23 """Replace xml-incompatible control characters."""
24 # This really ought to be provided by bzrlib.
25 # Code copied from bzrlib.commit.
27 # Python strings can include characters that can't be
28 # represented in well-formed XML; escape characters that
29 # aren't listed in the XML specification
30 # (http://www.w3.org/TR/REC-xml/#NT-Char).
31 import re
32 message, _ = re.subn(
33 u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
34 lambda match: match.group(0).encode('unicode_escape'),
35 message)
36 return message
39 def best_format_for_objects_in_a_repository(repo):
40 """Find the high-level format for branches and trees given a repository.
42 When creating branches and working trees within a repository, Bazaar
43 defaults to using the default format which may not be the best choice.
44 This routine does a reverse lookup of the high-level format registry
45 to find the high-level format that a shared repository was most likely
46 created via.
48 :return: the BzrDirFormat or None if no matches were found.
49 """
50 # Based on code from bzrlib/info.py ...
51 from bzrlib import bzrdir
52 repo_format = repo._format
53 candidates = []
54 non_aliases = set(bzrdir.format_registry.keys())
55 non_aliases.difference_update(bzrdir.format_registry.aliases())
56 for key in non_aliases:
57 format = bzrdir.format_registry.make_bzrdir(key)
58 # LocalGitBzrDirFormat has no repository_format
59 if hasattr(format, "repository_format"):
60 if format.repository_format == repo_format:
61 candidates.append((key, format))
62 if len(candidates):
63 # Assume the first one. Is there any reason not to do that?
64 name, format = candidates[0]
65 return format
66 else:
67 return None
70 def open_destination_directory(location, format=None, verbose=True):
71 """Open a destination directory and return the BzrDir.
73 If destination has a control directory, it will be returned.
74 Otherwise, the destination should be empty or non-existent and
75 a shared repository will be created there.
77 :param location: the destination directory
78 :param format: the format to use or None for the default
79 :param verbose: display the format used if a repository is created.
80 :return: BzrDir for the destination
81 """
82 import os
83 from bzrlib import bzrdir, errors, trace, transport
84 try:
85 control, relpath = bzrdir.BzrDir.open_containing(location)
86 # XXX: Check the relpath is None here?
87 return control
88 except errors.NotBranchError:
89 pass
91 # If the directory exists, check it is empty. Otherwise create it.
92 if os.path.exists(location):
93 contents = os.listdir(location)
94 if contents:
95 errors.BzrCommandError("Destination must have a .bzr directory, "
96 " not yet exist or be empty - files found in %s" % (location,))
97 else:
98 try:
99 os.mkdir(location)
100 except IOError, ex:
101 errors.BzrCommandError("Unable to create %s: %s" %
102 (location, ex))
104 # Create a repository for the nominated format.
105 trace.note("Creating destination repository ...")
106 if format is None:
107 format = bzrdir.format_registry.make_bzrdir('default')
108 to_transport = transport.get_transport(location)
109 to_transport.ensure_base()
110 control = format.initialize_on_transport(to_transport)
111 repo = control.create_repository(shared=True)
112 if verbose:
113 from bzrlib.info import show_bzrdir_info
114 show_bzrdir_info(repo.bzrdir, verbose=0)
115 return control
118 def kind_to_mode(kind, executable):
119 if kind == "file":
120 if executable == True:
121 return stat.S_IFREG | 0755
122 elif executable == False:
123 return stat.S_IFREG | 0644
124 else:
125 raise AssertionError("Executable %r invalid" % executable)
126 elif kind == "symlink":
127 return stat.S_IFLNK
128 elif kind == "directory":
129 return stat.S_IFDIR
130 elif kind == "tree-reference":
131 return 0160000
132 else:
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):
139 return 'file', False
140 elif mode in (0755, 0100755):
141 return 'file', True
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
148 else:
149 raise AssertionError("invalid mode %o" % mode)