89
90
from bzrlib.lockdir import LockDir
90
91
import bzrlib.mutabletree
91
92
from bzrlib.mutabletree import needs_tree_write_lock
92
from bzrlib import osutils
93
93
from bzrlib.osutils import (
120
123
ERROR_PATH_NOT_FOUND = 3 # WindowsError errno code, equivalent to ENOENT
126
@deprecated_function(zero_thirteen)
127
def gen_file_id(name):
128
"""Return new file id for the basename 'name'.
130
Use bzrlib.generate_ids.gen_file_id() instead
132
return generate_ids.gen_file_id(name)
135
@deprecated_function(zero_thirteen)
137
"""Return a new tree-root file id.
139
This has been deprecated in favor of bzrlib.generate_ids.gen_root_id()
141
return generate_ids.gen_root_id()
123
144
class TreeEntry(object):
124
145
"""An entry that implements the minimum interface used by commands.
201
222
if not _internal:
202
223
raise errors.BzrError("Please use bzrdir.open_workingtree or "
203
224
"WorkingTree.open() to obtain a WorkingTree.")
225
assert isinstance(basedir, basestring), \
226
"base directory %r is not a string" % basedir
204
227
basedir = safe_unicode(basedir)
205
228
mutter("opening working tree %r", basedir)
206
229
if deprecated_passed(branch):
214
237
self._control_files = self.branch.control_files
216
239
# assume all other formats have their own control files.
240
assert isinstance(_control_files, LockableFiles), \
241
"_control_files must be a LockableFiles, not %r" \
217
243
self._control_files = _control_files
218
self._transport = self._control_files._transport
219
244
# update the whole cache up front and write to disk if anything changed;
220
245
# in the future we might want to do this more selectively
221
246
# two possible ways offer themselves : in self._unlock, write the cache
225
250
wt_trans = self.bzrdir.get_workingtree_transport(None)
226
251
cache_filename = wt_trans.local_abspath('stat-cache')
227
252
self._hashcache = hashcache.HashCache(basedir, cache_filename,
228
self.bzrdir._get_file_mode())
253
self._control_files._file_mode)
229
254
hc = self._hashcache
231
256
# is this scan needed ? it makes things kinda slow.
245
270
# the Format factory and creation methods that are
246
271
# permitted to do this.
247
272
self._set_inventory(_inventory, dirty=False)
248
self._detect_case_handling()
249
self._rules_searcher = None
251
def _detect_case_handling(self):
252
wt_trans = self.bzrdir.get_workingtree_transport(None)
254
wt_trans.stat("FoRMaT")
255
except errors.NoSuchFile:
256
self.case_sensitive = True
258
self.case_sensitive = False
260
self._setup_directory_is_tree_reference()
262
274
branch = property(
263
275
fget=lambda self: self._branch,
335
348
return WorkingTree.open(path, _unsupported=True)
338
def find_trees(location):
339
def list_current(transport):
340
return [d for d in transport.list_dir('') if d != '.bzr']
341
def evaluate(bzrdir):
343
tree = bzrdir.open_workingtree()
344
except errors.NoWorkingTree:
348
transport = get_transport(location)
349
iterator = bzrdir.BzrDir.find_bzrdirs(transport, evaluate=evaluate,
350
list_current=list_current)
351
return [t for t in iterator if t is not None]
353
350
# should be deprecated - this is slow and in any case treating them as a
354
351
# container is (we now know) bad style -- mbp 20070302
355
352
## @deprecated_method(zero_fifteen)
364
361
if osutils.lexists(self.abspath(path)):
367
def all_file_ids(self):
368
"""See Tree.iter_all_file_ids"""
369
return set(self.inventory)
371
364
def __repr__(self):
372
365
return "<%s of %s>" % (self.__class__.__name__,
373
366
getattr(self, 'basedir', None))
397
390
# at this point ?
399
392
return self.branch.repository.revision_tree(revision_id)
400
except (errors.RevisionNotPresent, errors.NoSuchRevision):
393
except errors.RevisionNotPresent:
401
394
# the basis tree *may* be a ghost or a low level error may have
402
395
# occured. If the revision is present, its a problem, if its not
409
402
def _cleanup(self):
410
403
self._flush_ignore_list_cache()
406
@deprecated_method(zero_eight)
407
def create(branch, directory):
408
"""Create a workingtree for branch at directory.
410
If existing_directory already exists it must have a .bzr directory.
411
If it does not exist, it will be created.
413
This returns a new WorkingTree object for the new checkout.
415
TODO FIXME RBC 20060124 when we have checkout formats in place this
416
should accept an optional revisionid to checkout [and reject this if
417
checking out into the same dir as a pre-checkout-aware branch format.]
419
XXX: When BzrDir is present, these should be created through that
422
warnings.warn('delete WorkingTree.create', stacklevel=3)
423
transport = get_transport(directory)
424
if branch.bzrdir.root_transport.base == transport.base:
426
return branch.bzrdir.create_workingtree()
427
# different directory,
428
# create a branch reference
429
# and now a working tree.
430
raise NotImplementedError
433
@deprecated_method(zero_eight)
434
def create_standalone(directory):
435
"""Create a checkout and a branch and a repo at directory.
437
Directory must exist and be empty.
439
please use BzrDir.create_standalone_workingtree
441
return bzrdir.BzrDir.create_standalone_workingtree(directory)
412
443
def relpath(self, path):
413
444
"""Return the local path portion from a given path.
445
476
basis = self.basis_tree()
446
477
basis.lock_read()
448
changes = self.iter_changes(basis, True, [self.id2path(file_id)],
479
changes = self._iter_changes(basis, True, [self.id2path(file_id)],
449
480
require_versioned=True).next()
450
481
changed_content, kind = changes[2], changes[6]
451
482
if not changed_content:
520
551
and this one merged in.
522
553
# assumes the target bzr dir format is compatible.
523
result = to_bzrdir.create_workingtree()
554
result = self._format.initialize(to_bzrdir)
524
555
self.copy_content_into(result, revision_id)
555
586
__contains__ = has_id
557
588
def get_file_size(self, file_id):
558
"""See Tree.get_file_size"""
560
return os.path.getsize(self.id2abspath(file_id))
562
if e.errno != errno.ENOENT:
589
return os.path.getsize(self.id2abspath(file_id))
568
592
def get_file_sha1(self, file_id, path=None, stat_value=None):
608
632
# function - they should be part of lock_write and unlock.
609
633
inv = self.inventory
610
634
for f, file_id, kind in zip(files, ids, kinds):
635
assert kind is not None
611
636
if file_id is None:
612
637
inv.add_path(f, kind=kind)
679
704
self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
681
def path_content_summary(self, path, _lstat=os.lstat,
706
def path_content_summary(self, path, _lstat=osutils.lstat,
682
707
_mapper=osutils.file_kind_from_stat_mode):
683
708
"""See Tree.path_content_summary."""
684
709
abspath = self.abspath(path)
709
734
return (kind, None, None, None)
736
@deprecated_method(zero_eleven)
738
def pending_merges(self):
739
"""Return a list of pending merges.
741
These are revisions that have been merged into the working
742
directory but not yet committed.
744
As of 0.11 this is deprecated. Please see WorkingTree.get_parent_ids()
745
instead - which is available on all tree objects.
747
return self.get_parent_ids()[1:]
711
749
def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
712
750
"""Common ghost checking functionality from set_parent_*.
723
761
def _set_merges_from_parent_ids(self, parent_ids):
724
762
merges = parent_ids[1:]
725
self._transport.put_bytes('pending-merges', '\n'.join(merges),
726
mode=self._control_files._file_mode)
728
def _filter_parent_ids_by_ancestry(self, revision_ids):
729
"""Check that all merged revisions are proper 'heads'.
731
This will always return the first revision_id, and any merged revisions
734
if len(revision_ids) == 0:
736
graph = self.branch.repository.get_graph()
737
heads = graph.heads(revision_ids)
738
new_revision_ids = revision_ids[:1]
739
for revision_id in revision_ids[1:]:
740
if revision_id in heads and revision_id not in new_revision_ids:
741
new_revision_ids.append(revision_id)
742
if new_revision_ids != revision_ids:
743
trace.mutter('requested to set revision_ids = %s,'
744
' but filtered to %s', revision_ids, new_revision_ids)
745
return new_revision_ids
763
self._control_files.put_bytes('pending-merges', '\n'.join(merges))
747
765
@needs_tree_write_lock
748
766
def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
762
780
for revision_id in revision_ids:
763
781
_mod_revision.check_not_reserved_id(revision_id)
765
revision_ids = self._filter_parent_ids_by_ancestry(revision_ids)
767
783
if len(revision_ids) > 0:
768
784
self.set_last_revision(revision_ids[0])
781
797
self._check_parents_for_ghosts(parent_ids,
782
798
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
784
parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
786
800
if len(parent_ids) == 0:
787
801
leftmost_parent_id = _mod_revision.NULL_REVISION
788
802
leftmost_parent_tree = None
828
842
def _put_rio(self, filename, stanzas, header):
829
843
self._must_be_locked()
830
844
my_file = rio_file(stanzas, header)
831
self._transport.put_file(filename, my_file,
832
mode=self._control_files._file_mode)
845
self._control_files.put(filename, my_file)
834
847
@needs_write_lock # because merge pulls data into the branch.
835
848
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
967
980
other_tree.unlock()
968
981
other_tree.bzrdir.retire_bzrdir()
970
def _setup_directory_is_tree_reference(self):
971
if self._branch.repository._format.supports_tree_reference:
972
self._directory_is_tree_reference = \
973
self._directory_may_be_tree_reference
975
self._directory_is_tree_reference = \
976
self._directory_is_never_tree_reference
978
def _directory_is_never_tree_reference(self, relpath):
981
def _directory_may_be_tree_reference(self, relpath):
983
def _directory_is_tree_reference(self, relpath):
982
984
# as a special case, if a directory contains control files then
983
985
# it's a tree reference, except that the root of the tree is not
984
986
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1011
1013
sub_path = self.id2path(file_id)
1012
1014
branch_transport = mkdirs(sub_path)
1013
1015
if format is None:
1014
format = self.bzrdir.cloning_metadir()
1016
format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
1015
1017
branch_transport.ensure_base()
1016
1018
branch_bzrdir = format.initialize_on_transport(branch_transport)
1018
1020
repo = branch_bzrdir.find_repository()
1019
1021
except errors.NoRepositoryPresent:
1020
1022
repo = branch_bzrdir.create_repository()
1021
if not repo.supports_rich_root():
1022
raise errors.RootNotRich()
1023
assert repo.supports_rich_root()
1025
if not repo.supports_rich_root():
1026
raise errors.RootNotRich()
1023
1027
new_branch = branch_bzrdir.create_branch()
1024
1028
new_branch.pull(self.branch)
1025
1029
for parent_id in self.get_parent_ids():
1057
1061
sio = StringIO()
1058
1062
self._serialize(self._inventory, sio)
1060
self._transport.put_file('inventory', sio,
1061
mode=self._control_files._file_mode)
1064
self._control_files.put('inventory', sio)
1062
1065
self._inventory_is_modified = False
1064
1067
def _kind(self, relpath):
1225
1228
DeprecationWarning)
1227
1230
# check destination directory
1228
if isinstance(from_paths, basestring):
1231
assert not isinstance(from_paths, basestring)
1230
1232
inv = self.inventory
1231
1233
to_abs = self.abspath(to_dir)
1232
1234
if not isdir(to_abs):
1316
1318
only_change_inv = True
1317
1319
elif self.has_filename(from_rel) and not self.has_filename(to_rel):
1318
1320
only_change_inv = False
1319
elif (not self.case_sensitive
1320
and from_rel.lower() == to_rel.lower()
1321
and self.has_filename(from_rel)):
1322
only_change_inv = False
1324
1322
# something is wrong, so lets determine what exactly
1325
1323
if not self.has_filename(from_rel) and \
1328
1326
errors.PathsDoNotExist(paths=(str(from_rel),
1331
raise errors.RenameFailedFilesExist(from_rel, to_rel)
1329
raise errors.RenameFailedFilesExist(from_rel, to_rel,
1330
extra="(Use --after to update the Bazaar id)")
1332
1331
rename_entry.only_change_inv = only_change_inv
1333
1332
return rename_entries
1496
1495
# - RBC 20060907
1497
1496
self._write_inventory(self._inventory)
1498
@deprecated_method(zero_eight)
1499
def iter_conflicts(self):
1500
"""List all files in the tree that have text or content conflicts.
1501
DEPRECATED. Use conflicts instead."""
1502
return self._iter_conflicts()
1499
1504
def _iter_conflicts(self):
1500
1505
conflicted = set()
1501
1506
for info in self.list_files():
1536
1541
change_reporter=change_reporter)
1537
1542
if (basis_tree.inventory.root is None and
1538
1543
new_basis_tree.inventory.root is not None):
1539
self.set_root_id(new_basis_tree.get_root_id())
1544
self.set_root_id(new_basis_tree.inventory.root.file_id)
1542
1547
basis_tree.unlock()
1592
1597
if subf == '.bzr':
1594
1599
if subf not in dir_entry.children:
1597
can_access) = osutils.normalized_filename(subf)
1598
except UnicodeDecodeError:
1599
path_os_enc = path.encode(osutils._fs_enc)
1600
relpath = path_os_enc + '/' + subf
1601
raise errors.BadFilenameEncoding(relpath,
1600
subf_norm, can_access = osutils.normalized_filename(subf)
1603
1601
if subf_norm != subf and can_access:
1604
1602
if subf_norm not in dir_entry.children:
1605
1603
fl.append(subf_norm)
1660
1658
def kind(self, file_id):
1661
1659
return file_kind(self.id2abspath(file_id))
1663
def stored_kind(self, file_id):
1664
"""See Tree.stored_kind"""
1665
return self.inventory[file_id].kind
1667
1661
def _comparison_data(self, entry, path):
1668
1662
abspath = self.abspath(path)
1751
1745
def _reset_data(self):
1752
1746
"""Reset transient data that cannot be revalidated."""
1753
1747
self._inventory_is_modified = False
1754
result = self._deserialize(self._transport.get('inventory'))
1748
result = self._deserialize(self._control_files.get('inventory'))
1755
1749
self._set_inventory(result, dirty=False)
1757
1751
@needs_tree_write_lock
1779
1773
def _write_basis_inventory(self, xml):
1780
1774
"""Write the basis inventory XML to the basis-inventory file"""
1775
assert isinstance(xml, str), 'serialised xml must be bytestring.'
1781
1776
path = self._basis_inventory_name()
1782
1777
sio = StringIO(xml)
1783
self._transport.put_file(path, sio,
1784
mode=self._control_files._file_mode)
1778
self._control_files.put(path, sio)
1786
1780
def _create_basis_xml_from_inventory(self, revision_id, inventory):
1787
1781
"""Create the text that will be saved in basis-inventory"""
1818
1812
def read_basis_inventory(self):
1819
1813
"""Read the cached basis inventory."""
1820
1814
path = self._basis_inventory_name()
1821
return self._transport.get_bytes(path)
1815
return self._control_files.get(path).read()
1823
1817
@needs_read_lock
1824
1818
def read_working_inventory(self):
1834
1828
if self._inventory_is_modified:
1835
1829
raise errors.InventoryModified(self)
1836
result = self._deserialize(self._transport.get('inventory'))
1830
result = self._deserialize(self._control_files.get('inventory'))
1837
1831
self._set_inventory(result, dirty=False)
1859
1853
# Recurse directory and add all files
1860
1854
# so we can check if they have changed.
1861
1855
for parent_info, file_infos in\
1862
self.walkdirs(directory):
1863
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1856
osutils.walkdirs(self.abspath(directory),
1858
for relpath, basename, kind, lstat, abspath in file_infos:
1864
1859
# Is it versioned or ignored?
1865
1860
if self.path2id(relpath) or self.is_ignored(relpath):
1866
1861
# Add nested content for deletion.
1891
1887
has_changed_files = len(unknown_nested_files) > 0
1892
1888
if not has_changed_files:
1893
1889
for (file_id, path, content_change, versioned, parent_id, name,
1894
kind, executable) in self.iter_changes(self.basis_tree(),
1890
kind, executable) in self._iter_changes(self.basis_tree(),
1895
1891
include_unchanged=True, require_versioned=False,
1896
1892
want_unversioned=True, specific_files=files):
1897
if versioned == (False, False):
1898
# The record is unknown ...
1899
if not self.is_ignored(path[1]):
1900
# ... but not ignored
1901
has_changed_files = True
1903
elif content_change and (kind[1] is not None):
1904
# Versioned and changed, but not deleted
1893
# Check if it's an unknown (but not ignored) OR
1894
# changed (but not deleted) :
1895
if not self.is_ignored(path[1]) and (
1896
versioned == (False, False) or
1897
content_change and kind[1] != None):
1905
1898
has_changed_files = True
1986
1979
self.set_parent_trees(parent_trees)
1989
resolve(self, filenames, ignore_misses=True, recursive=True)
1982
resolve(self, filenames, ignore_misses=True)
1991
1984
if basis_tree is not None:
1992
1985
basis_tree.unlock()
2046
2039
"""Set the root id for this tree."""
2047
2040
# for compatability
2048
2041
if file_id is None:
2050
'WorkingTree.set_root_id with fileid=None')
2051
file_id = osutils.safe_file_id(file_id)
2042
symbol_versioning.warn(symbol_versioning.zero_twelve
2043
% 'WorkingTree.set_root_id with fileid=None',
2048
file_id = osutils.safe_file_id(file_id)
2052
2049
self._set_root_id(file_id)
2054
2051
def _set_root_id(self, file_id):
2158
2155
to_tree = self.branch.basis_tree()
2159
2156
if basis.inventory.root is None:
2160
self.set_root_id(to_tree.get_root_id())
2157
self.set_root_id(to_tree.inventory.root.file_id)
2162
2159
result += merge.merge_inner(
2305
2302
current_inv = None
2306
2303
inv_finished = True
2307
2304
while not inv_finished or not disk_finished:
2309
((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
2310
cur_disk_dir_content) = current_disk
2312
((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
2313
cur_disk_dir_content) = ((None, None), None)
2314
2305
if not disk_finished:
2315
2306
# strip out .bzr dirs
2316
if (cur_disk_dir_path_from_top[top_strip_len:] == '' and
2317
len(cur_disk_dir_content) > 0):
2318
# osutils.walkdirs can be made nicer -
2307
if current_disk[0][1][top_strip_len:] == '':
2308
# osutils.walkdirs can be made nicer -
2319
2309
# yield the path-from-prefix rather than the pathjoined
2321
bzrdir_loc = bisect_left(cur_disk_dir_content,
2323
if cur_disk_dir_content[bzrdir_loc][0] == '.bzr':
2311
bzrdir_loc = bisect_left(current_disk[1], ('.bzr', '.bzr'))
2312
if current_disk[1][bzrdir_loc][0] == '.bzr':
2324
2313
# we dont yield the contents of, or, .bzr itself.
2325
del cur_disk_dir_content[bzrdir_loc]
2314
del current_disk[1][bzrdir_loc]
2326
2315
if inv_finished:
2327
2316
# everything is unknown
2330
2319
# everything is missing
2333
direction = cmp(current_inv[0][0], cur_disk_dir_relpath)
2322
direction = cmp(current_inv[0][0], current_disk[0][0])
2334
2323
if direction > 0:
2335
2324
# disk is before inventory - unknown
2336
2325
dirblock = [(relpath, basename, kind, stat, None, None) for
2337
relpath, basename, kind, stat, top_path in
2338
cur_disk_dir_content]
2339
yield (cur_disk_dir_relpath, None), dirblock
2326
relpath, basename, kind, stat, top_path in current_disk[1]]
2327
yield (current_disk[0][0], None), dirblock
2341
2329
current_disk = disk_iterator.next()
2342
2330
except StopIteration:
2344
2332
elif direction < 0:
2345
2333
# inventory is before disk - missing.
2346
2334
dirblock = [(relpath, basename, 'unknown', None, fileid, kind)
2347
for relpath, basename, dkind, stat, fileid, kind in
2335
for relpath, basename, dkind, stat, fileid, kind in
2348
2336
current_inv[1]]
2349
2337
yield (current_inv[0][0], current_inv[0][1]), dirblock
2356
2344
# merge the inventory and disk data together
2358
2346
for relpath, subiterator in itertools.groupby(sorted(
2359
current_inv[1] + cur_disk_dir_content,
2360
key=operator.itemgetter(0)), operator.itemgetter(1)):
2347
current_inv[1] + current_disk[1], key=operator.itemgetter(0)), operator.itemgetter(1)):
2361
2348
path_elements = list(subiterator)
2362
2349
if len(path_elements) == 2:
2363
2350
inv_row, disk_row = path_elements
2417
2404
# FIXME: stash the node in pending
2418
2405
entry = inv[top_id]
2419
if entry.kind == 'directory':
2420
for name, child in entry.sorted_children():
2421
dirblock.append((relroot + name, name, child.kind, None,
2422
child.file_id, child.kind
2406
for name, child in entry.sorted_children():
2407
dirblock.append((relroot + name, name, child.kind, None,
2408
child.file_id, child.kind
2424
2410
yield (currentdir[0], entry.file_id), dirblock
2425
2411
# push the user specified dirs from dirblock
2426
2412
for dir in reversed(dirblock):
2459
2445
self.set_conflicts(un_resolved)
2460
2446
return un_resolved, resolved
2464
tree_basis = self.basis_tree()
2465
tree_basis.lock_read()
2467
repo_basis = self.branch.repository.revision_tree(
2468
self.last_revision())
2469
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2470
raise errors.BzrCheckError(
2471
"Mismatched basis inventory content.")
2476
2448
def _validate(self):
2477
2449
"""Validate internal structures.
2488
def _get_rules_searcher(self, default_searcher):
2489
"""See Tree._get_rules_searcher."""
2490
if self._rules_searcher is None:
2491
self._rules_searcher = super(WorkingTree,
2492
self)._get_rules_searcher(default_searcher)
2493
return self._rules_searcher
2496
2460
class WorkingTree2(WorkingTree):
2497
2461
"""This is the Format 2 working tree.
2557
2521
def _last_revision(self):
2558
2522
"""See Mutable.last_revision."""
2560
return self._transport.get_bytes('last-revision')
2524
return self._control_files.get('last-revision').read()
2561
2525
except errors.NoSuchFile:
2562
2526
return _mod_revision.NULL_REVISION
2565
2529
"""See WorkingTree._change_last_revision."""
2566
2530
if revision_id is None or revision_id == NULL_REVISION:
2568
self._transport.delete('last-revision')
2532
self._control_files._transport.delete('last-revision')
2569
2533
except errors.NoSuchFile:
2573
self._transport.put_bytes('last-revision', revision_id,
2574
mode=self._control_files._file_mode)
2537
self._control_files.put_bytes('last-revision', revision_id)
2577
2540
@needs_tree_write_lock
2620
2583
return path[:-len(suffix)]
2586
@deprecated_function(zero_eight)
2587
def is_control_file(filename):
2588
"""See WorkingTree.is_control_filename(filename)."""
2589
## FIXME: better check
2590
filename = normpath(filename)
2591
while filename != '':
2592
head, tail = os.path.split(filename)
2593
## mutter('check %r for control file' % ((head, tail),))
2596
if filename == head:
2623
2602
class WorkingTreeFormat(object):
2624
2603
"""An encapsulation of the initialization and open routines for a format.
2658
2637
except errors.NoSuchFile:
2659
2638
raise errors.NoWorkingTree(base=transport.base)
2660
2639
except KeyError:
2661
raise errors.UnknownFormatError(format=format_string,
2662
kind="working tree")
2640
raise errors.UnknownFormatError(format=format_string)
2664
2642
def __eq__(self, other):
2665
2643
return self.__class__ is other.__class__
2714
2693
"""See WorkingTreeFormat.get_format_description()."""
2715
2694
return "Working tree format 2"
2717
def _stub_initialize_on_transport(self, transport, file_mode):
2718
"""Workaround: create control files for a remote working tree.
2696
def stub_initialize_remote(self, control_files):
2697
"""As a special workaround create critical control files for a remote working tree
2720
2699
This ensures that it can later be updated and dealt with locally,
2721
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2700
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2722
2701
no working tree. (See bug #43064).
2724
2703
sio = StringIO()
2725
2704
inv = Inventory()
2726
2705
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2728
transport.put_file('inventory', sio, file_mode)
2729
transport.put_bytes('pending-merges', '', file_mode)
2731
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2732
accelerator_tree=None, hardlink=False):
2707
control_files.put('inventory', sio)
2709
control_files.put_bytes('pending-merges', '')
2712
def initialize(self, a_bzrdir, revision_id=None):
2733
2713
"""See WorkingTreeFormat.initialize()."""
2734
2714
if not isinstance(a_bzrdir.transport, LocalTransport):
2735
2715
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2736
if from_branch is not None:
2737
branch = from_branch
2739
branch = a_bzrdir.open_branch()
2716
branch = a_bzrdir.open_branch()
2740
2717
if revision_id is None:
2741
2718
revision_id = _mod_revision.ensure_null(branch.last_revision())
2742
2719
branch.lock_write()
2753
2730
_bzrdir=a_bzrdir)
2754
2731
basis_tree = branch.repository.revision_tree(revision_id)
2755
2732
if basis_tree.inventory.root is not None:
2756
wt.set_root_id(basis_tree.get_root_id())
2733
wt.set_root_id(basis_tree.inventory.root.file_id)
2757
2734
# set the parent list and cache the basis tree.
2758
2735
if _mod_revision.is_null(revision_id):
2759
2736
parent_trees = []
2821
2798
return LockableFiles(transport, self._lock_file_name,
2822
2799
self._lock_class)
2824
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2825
accelerator_tree=None, hardlink=False):
2801
def initialize(self, a_bzrdir, revision_id=None):
2826
2802
"""See WorkingTreeFormat.initialize().
2828
:param revision_id: if supplied, create a working tree at a different
2829
revision than the branch is at.
2830
:param accelerator_tree: A tree which can be used for retrieving file
2831
contents more quickly than the revision tree, i.e. a workingtree.
2832
The revision tree will be used for cases where accelerator_tree's
2833
content is different.
2834
:param hardlink: If true, hard-link files from accelerator_tree,
2804
revision_id allows creating a working tree at a different
2805
revision than the branch is at.
2837
2807
if not isinstance(a_bzrdir.transport, LocalTransport):
2838
2808
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2840
2810
control_files = self._open_control_files(a_bzrdir)
2841
2811
control_files.create_lock()
2842
2812
control_files.lock_write()
2843
transport.put_bytes('format', self.get_format_string(),
2844
mode=control_files._file_mode)
2845
if from_branch is not None:
2846
branch = from_branch
2848
branch = a_bzrdir.open_branch()
2813
control_files.put_utf8('format', self.get_format_string())
2814
branch = a_bzrdir.open_branch()
2849
2815
if revision_id is None:
2850
2816
revision_id = _mod_revision.ensure_null(branch.last_revision())
2851
2817
# WorkingTree3 can handle an inventory which has a unique root id.
2866
2832
basis_tree = branch.repository.revision_tree(revision_id)
2867
2833
# only set an explicit root id if there is one to set.
2868
2834
if basis_tree.inventory.root is not None:
2869
wt.set_root_id(basis_tree.get_root_id())
2835
wt.set_root_id(basis_tree.inventory.root.file_id)
2870
2836
if revision_id == NULL_REVISION:
2871
2837
wt.set_parent_trees([])