1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
90
90
BzrDir instances let you create or open any of the things that can be
91
91
found within .bzr - checkouts, branches and repositories.
94
94
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
96
96
a transport connected to the directory this bzr was opened from
97
97
(i.e. the parent directory holding the .bzr directory).
99
Everything in the bzrdir should have the same file permissions.
100
102
def break_lock(self):
583
584
guaranteed to point to an existing directory ready for use.
585
586
raise NotImplementedError(self.get_branch_transport)
588
def _find_creation_modes(self):
589
"""Determine the appropriate modes for files and directories.
591
They're always set to be consistent with the base directory,
592
assuming that this transport allows setting modes.
594
# TODO: Do we need or want an option (maybe a config setting) to turn
595
# this off or override it for particular locations? -- mbp 20080512
596
if self._mode_check_done:
598
self._mode_check_done = True
600
st = self.transport.stat('.')
601
except errors.TransportNotPossible:
602
self._dir_mode = None
603
self._file_mode = None
605
# Check the directory mode, but also make sure the created
606
# directories and files are read-write for this user. This is
607
# mostly a workaround for filesystems which lie about being able to
608
# write to a directory (cygwin & win32)
609
self._dir_mode = (st.st_mode & 07777) | 00700
610
# Remove the sticky and execute bits for files
611
self._file_mode = self._dir_mode & ~07111
613
def _get_file_mode(self):
614
"""Return Unix mode for newly created files, or None.
616
if not self._mode_check_done:
617
self._find_creation_modes()
618
return self._file_mode
620
def _get_dir_mode(self):
621
"""Return Unix mode for newly created directories, or None.
623
if not self._mode_check_done:
624
self._find_creation_modes()
625
return self._dir_mode
587
627
def get_repository_transport(self, repository_format):
588
628
"""Get the transport for use by repository format in this BzrDir.
622
662
self._format = _format
623
663
self.transport = _transport.clone('.bzr')
624
664
self.root_transport = _transport
665
self._mode_check_done = False
626
667
def is_control_filename(self, filename):
627
668
"""True if filename is the name of a path which is reserved for bzrdir's.
1046
1087
except errors.NotLocalUrl:
1047
1088
# but we cannot do it for remote trees.
1048
1089
to_branch = result.open_branch()
1049
WorkingTreeFormat2().stub_initialize_remote(to_branch.control_files)
1090
WorkingTreeFormat2()._stub_initialize_remote(to_branch)
1052
1093
def create_branch(self):
1507
1548
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1508
1549
file_mode = temp_control._file_mode
1509
1550
del temp_control
1510
mutter('created control directory in ' + transport.base)
1511
control = transport.clone('.bzr')
1512
utf8_files = [('README',
1551
bzrdir_transport = transport.clone('.bzr')
1552
utf8_files = [('README',
1513
1553
"This is a Bazaar control directory.\n"
1514
1554
"Do not change any files in this directory.\n"
1515
1555
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1516
1556
('branch-format', self.get_format_string()),
1518
1558
# NB: no need to escape relative paths that are url safe.
1519
control_files = lockable_files.LockableFiles(control,
1520
self._lock_file_name, self._lock_class)
1559
control_files = lockable_files.LockableFiles(bzrdir_transport,
1560
self._lock_file_name, self._lock_class)
1521
1561
control_files.create_lock()
1522
1562
control_files.lock_write()
1524
for file, content in utf8_files:
1525
control_files.put_utf8(file, content)
1564
for (filename, content) in utf8_files:
1565
bzrdir_transport.put_bytes(filename, content,
1527
1568
control_files.unlock()
1528
1569
return self.open(transport, _found=True)
1722
1763
except errors.NotLocalUrl:
1723
1764
# Even though we can't access the working tree, we need to
1724
1765
# create its control files.
1725
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1766
WorkingTreeFormat2()._stub_initialize_remote(branch)
1728
1769
def _open(self, transport):
1781
1822
except errors.NotLocalUrl:
1782
1823
# Even though we can't access the working tree, we need to
1783
1824
# create its control files.
1784
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1825
WorkingTreeFormat2()._stub_initialize_remote(branch)
1787
1828
def _open(self, transport):
1968
2009
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
1969
2010
self.pb.note(' %6d texts', self.text_count)
1970
2011
self._cleanup_spare_files_after_format4()
1971
self.branch.control_files.put_utf8('branch-format', BzrDirFormat5().get_format_string())
2012
self.branch._transport.put_bytes(
2014
BzrDirFormat5().get_format_string(),
2015
mode=self.bzrdir._get_file_mode())
1973
2017
def _cleanup_spare_files_after_format4(self):
1974
2018
# FIXME working tree upgrade foo.
1984
2028
def _convert_working_inv(self):
1985
2029
inv = xml4.serializer_v4.read_inventory(
1986
self.branch.control_files.get('inventory'))
2030
self.branch._transport.get('inventory'))
1987
2031
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
1988
# FIXME inventory is a working tree change.
1989
self.branch.control_files.put('inventory', StringIO(new_inv_xml))
2032
self.branch._transport.put_bytes('inventory', new_inv_xml,
2033
mode=self.bzrdir._get_file_mode())
1991
2035
def _write_all_weaves(self):
1992
2036
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2202
2246
except errors.NoSuchFile: # catches missing dirs strangely enough
2203
2247
store_transport.mkdir(osutils.dirname(new_name))
2204
2248
store_transport.move(filename, new_name)
2205
self.bzrdir._control_files.put_utf8('branch-format', BzrDirFormat6().get_format_string())
2249
self.bzrdir.transport.put_bytes(
2251
BzrDirFormat6().get_format_string(),
2252
mode=self.bzrdir._get_file_mode())
2208
2255
class ConvertBzrDir6ToMeta(Converter):
2218
2265
self.total = 20 # the steps we know about
2219
2266
self.garbage_inventories = []
2267
self.dir_mode = self.bzrdir._get_dir_mode()
2268
self.file_mode = self.bzrdir._get_file_mode()
2221
2270
self.pb.note('starting upgrade from format 6 to metadir')
2222
self.bzrdir._control_files.put_utf8('branch-format', "Converting to format 6")
2271
self.bzrdir.transport.put_bytes(
2273
"Converting to format 6",
2274
mode=self.file_mode)
2223
2275
# its faster to move specific files around than to open and use the apis...
2224
2276
# first off, nuke ancestry.weave, it was never used.
2235
2287
if name.startswith('basis-inventory.'):
2236
2288
self.garbage_inventories.append(name)
2237
2289
# create new directories for repository, working tree and branch
2238
self.dir_mode = self.bzrdir._control_files._dir_mode
2239
self.file_mode = self.bzrdir._control_files._file_mode
2240
2290
repository_names = [('inventory.weave', True),
2241
2291
('revision-store', True),
2242
2292
('weaves', True)]
2290
2340
for entry in checkout_files:
2291
2341
self.move_entry('checkout', entry)
2292
2342
if last_revision is not None:
2293
self.bzrdir._control_files.put_utf8(
2343
self.bzrdir.transport.put_bytes(
2294
2344
'checkout/last-revision', last_revision)
2295
self.bzrdir._control_files.put_utf8(
2296
'branch-format', BzrDirMetaFormat1().get_format_string())
2345
self.bzrdir.transport.put_bytes(
2347
BzrDirMetaFormat1().get_format_string(),
2348
mode=self.file_mode)
2297
2349
return BzrDir.open(self.bzrdir.root_transport.base)
2299
2351
def make_lock(self, name):
2319
2371
def put_format(self, dirname, format):
2320
self.bzrdir._control_files.put_utf8('%s/format' % dirname, format.get_format_string())
2372
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2373
format.get_format_string(),
2323
2377
class ConvertMetaToMeta(Converter):
2393
2447
medium = transport.get_smart_medium()
2394
2448
except (NotImplementedError, AttributeError,
2395
errors.TransportNotPossible, errors.NoSmartMedium):
2449
errors.TransportNotPossible, errors.NoSmartMedium,
2450
errors.SmartProtocolError):
2396
2451
# no smart server, so not a branch for this format type.
2397
2452
raise errors.NotBranchError(path=transport.base)
2399
2454
# Decline to open it if the server doesn't support our required
2400
# version (2) so that the VFS-based transport will do it.
2402
server_version = medium.protocol_version()
2403
except errors.SmartProtocolError:
2404
# Apparently there's no usable smart server there, even though
2405
# the medium supports the smart protocol.
2406
raise errors.NotBranchError(path=transport.base)
2407
if server_version != 2:
2408
raise errors.NotBranchError(path=transport.base)
2455
# version (3) so that the VFS-based transport will do it.
2456
if medium.should_probe():
2458
server_version = medium.protocol_version()
2459
except errors.SmartProtocolError:
2460
# Apparently there's no usable smart server there, even though
2461
# the medium supports the smart protocol.
2462
raise errors.NotBranchError(path=transport.base)
2463
if server_version != '2':
2464
raise errors.NotBranchError(path=transport.base)
2411
2467
def initialize_on_transport(self, transport):
2416
2472
# TODO: lookup the local format from a server hint.
2417
2473
local_dir_format = BzrDirMetaFormat1()
2418
2474
return local_dir_format.initialize_on_transport(transport)
2419
client = _SmartClient(client_medium, transport.base)
2475
client = _SmartClient(client_medium)
2420
2476
path = client.remote_path_from_transport(transport)
2421
2477
response = client.call('BzrDirFormat.initialize', path)
2422
2478
if response[0] != 'ok':