15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""An adapter between a Git control dir and a Bazaar BzrDir."""
18
"""An adapter between a Git control dir and a Bazaar ControlDir."""
20
20
from bzrlib import (
22
21
errors as bzr_errors,
28
27
LockWarner = getattr(lockable_files, "_LockWarner", None)
30
29
from bzrlib.plugins.git import (
30
LocalGitControlDirFormat,
33
from bzrlib.controldir import (
39
from bzrlib.bzrdir import (
35
46
class GitLock(object):
69
80
self._lock_warner = LockWarner(repr(self))
72
class GitDir(bzrdir.BzrDir):
83
class GitDirConfig(object):
85
def get_default_stack_on(self):
88
def set_default_stack_on(self, value):
89
raise bzr_errors.BzrError("Cannot set configuration")
92
class GitDir(ControlDir):
73
93
"""An adapter to the '.git' dir used by git."""
75
95
def is_supported(self):
98
def can_convert_format(self):
101
def break_lock(self):
78
104
def cloning_metadir(self, stacked=False):
79
return bzrdir.format_registry.make_bzrdir("default")
105
return format_registry.make_bzrdir("default")
81
107
def _branch_name_to_ref(self, name):
82
108
raise NotImplementedError(self._branch_name_to_ref)
84
110
if bzrlib_version >= (2, 2):
85
def open_branch(self, name=None, ignore_fallbacks=None,
111
def open_branch(self, name=None, unsupported=False,
112
ignore_fallbacks=None):
87
113
return self._open_branch(name=name,
88
114
ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
91
117
return self._open_branch(name=None,
92
118
ignore_fallbacks=ignore_fallbacks, unsupported=unsupported)
120
def get_config(self):
121
return GitDirConfig()
95
124
class LocalGitDir(GitDir):
96
125
"""An adapter to the '.git' dir used by git."""
102
131
_gitrepository_class = property(_get_gitrepository_class)
134
def user_transport(self):
135
return self.root_transport
138
def control_transport(self):
139
return self.transport
104
141
def __init__(self, transport, lockfiles, gitrepo, format):
105
142
self._format = format
106
143
self.root_transport = transport
144
self._mode_check_done = False
107
145
self._git = gitrepo
109
147
self.transport = transport
125
163
def is_control_filename(self, filename):
126
164
return filename == '.git' or filename.startswith('.git/')
128
def get_branch_transport(self, branch_format, name):
166
def get_branch_transport(self, branch_format, name=None):
129
167
if branch_format is None:
130
168
return self.transport
131
if isinstance(branch_format, LocalGitBzrDirFormat):
169
if isinstance(branch_format, LocalGitControlDirFormat):
132
170
return self.transport
133
171
raise bzr_errors.IncompatibleFormat(branch_format, self._format)
135
173
def get_repository_transport(self, format):
136
174
if format is None:
137
175
return self.transport
138
if isinstance(format, LocalGitBzrDirFormat):
176
if isinstance(format, LocalGitControlDirFormat):
139
177
return self.transport
140
178
raise bzr_errors.IncompatibleFormat(format, self._format)
142
180
def get_workingtree_transport(self, format):
143
181
if format is None:
144
182
return self.transport
145
if isinstance(format, LocalGitBzrDirFormat):
183
if isinstance(format, LocalGitControlDirFormat):
146
184
return self.transport
147
185
raise bzr_errors.IncompatibleFormat(format, self._format)
156
194
def destroy_branch(self, name=None):
157
del self._git.refs[self._branch_name_to_ref(name)]
195
refname = self._branch_name_to_ref(name)
196
if not refname in self._git.refs:
197
raise bzr_errors.NotBranchError(self.root_transport.base,
199
del self._git.refs[refname]
201
def destroy_repository(self):
202
raise bzr_errors.UnsupportedOperation(self.destroy_repository, self)
204
def destroy_workingtree(self):
205
raise bzr_errors.UnsupportedOperation(self.destroy_workingtree, self)
207
def needs_format_conversion(self, format=None):
208
return not isinstance(self._format, format.__class__)
159
210
def list_branches(self):
218
269
return self.open_workingtree()
271
def find_repository(self):
272
"""Find the repository that should be used.
274
This does not require a branch as we use it to find the repo for
275
new branches as well as to hook existing branches up to their
278
return self.open_repository()
280
def _find_creation_modes(self):
281
"""Determine the appropriate modes for files and directories.
283
They're always set to be consistent with the base directory,
284
assuming that this transport allows setting modes.
286
# TODO: Do we need or want an option (maybe a config setting) to turn
287
# this off or override it for particular locations? -- mbp 20080512
288
if self._mode_check_done:
290
self._mode_check_done = True
292
st = self.transport.stat('.')
293
except TransportNotPossible:
294
self._dir_mode = None
295
self._file_mode = None
297
# Check the directory mode, but also make sure the created
298
# directories and files are read-write for this user. This is
299
# mostly a workaround for filesystems which lie about being able to
300
# write to a directory (cygwin & win32)
301
if (st.st_mode & 07777 == 00000):
302
# FTP allows stat but does not return dir/file modes
303
self._dir_mode = None
304
self._file_mode = None
306
self._dir_mode = (st.st_mode & 07777) | 00700
307
# Remove the sticky and execute bits for files
308
self._file_mode = self._dir_mode & ~07111
310
def _get_file_mode(self):
311
"""Return Unix mode for newly created files, or None.
313
if not self._mode_check_done:
314
self._find_creation_modes()
315
return self._file_mode
317
def _get_dir_mode(self):
318
"""Return Unix mode for newly created directories, or None.
320
if not self._mode_check_done:
321
self._find_creation_modes()
322
return self._dir_mode