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
87
87
from bzrlib import symbol_versioning
88
88
from bzrlib.decorators import needs_read_lock, needs_write_lock
89
89
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
90
from bzrlib.lockable_files import LockableFiles, TransportLock
90
from bzrlib.lockable_files import LockableFiles
91
91
from bzrlib.lockdir import LockDir
92
92
import bzrlib.mutabletree
93
93
from bzrlib.mutabletree import needs_tree_write_lock
316
path = os.path.getcwdu()
316
path = osutils.getcwd()
317
317
control = bzrdir.BzrDir.open(path, _unsupported)
318
318
return control.open_workingtree(_unsupported)
321
321
def open_containing(path=None):
322
322
"""Open an existing working tree which has its root about path.
324
324
This probes for a working tree at path and searches upwards from there.
326
326
Basically we keep looking up until we find the control directory or
389
389
"""Return RevisionTree for the current last revision.
391
391
If the left most parent is a ghost then the returned tree will be an
392
empty tree - one obtained by calling repository.revision_tree(None).
392
empty tree - one obtained by calling
393
repository.revision_tree(NULL_REVISION).
395
396
revision_id = self.get_parent_ids()[0]
397
398
# no parents, return an empty revision tree.
398
399
# in the future this should return the tree for
399
400
# 'empty:' - the implicit root empty tree.
400
return self.branch.repository.revision_tree(None)
401
return self.branch.repository.revision_tree(
402
_mod_revision.NULL_REVISION)
402
404
return self.revision_tree(revision_id)
403
405
except errors.NoSuchRevision:
414
416
if self.branch.repository.has_revision(revision_id):
416
418
# the basis tree is a ghost so return an empty tree.
417
return self.branch.repository.revision_tree(None)
419
return self.branch.repository.revision_tree(
420
_mod_revision.NULL_REVISION)
419
422
def _cleanup(self):
420
423
self._flush_ignore_list_cache()
431
434
return osutils.lexists(self.abspath(filename))
433
436
def get_file(self, file_id, path=None):
437
return self.get_file_with_stat(file_id, path)[0]
439
def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
440
"""See MutableTree.get_file_with_stat."""
435
442
path = self.id2path(file_id)
436
return self.get_file_byname(path)
438
def get_file_text(self, file_id):
439
return self.get_file(file_id).read()
443
file_obj = self.get_file_byname(path)
444
return (file_obj, _fstat(file_obj.fileno()))
441
446
def get_file_byname(self, filename):
442
447
return file(self.abspath(filename), 'rb')
449
def get_file_lines(self, file_id, path=None):
450
"""See Tree.get_file_lines()"""
451
file = self.get_file(file_id, path)
453
return file.readlines()
445
458
def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
446
459
"""See Tree.annotate_iter
530
543
and this one merged in.
532
545
# assumes the target bzr dir format is compatible.
533
result = self._format.initialize(to_bzrdir)
546
result = to_bzrdir.create_workingtree()
534
547
self.copy_content_into(result, revision_id)
907
920
hashfile = self._transport.get('merge-hashes')
908
921
except errors.NoSuchFile:
912
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
926
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
927
raise errors.MergeModifiedFormatError()
928
except StopIteration:
913
929
raise errors.MergeModifiedFormatError()
914
except StopIteration:
915
raise errors.MergeModifiedFormatError()
916
for s in RioReader(hashfile):
917
# RioReader reads in Unicode, so convert file_ids back to utf8
918
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
919
if file_id not in self.inventory:
921
text_hash = s.get("hash")
922
if text_hash == self.get_file_sha1(file_id):
923
merge_hashes[file_id] = text_hash
930
for s in RioReader(hashfile):
931
# RioReader reads in Unicode, so convert file_ids back to utf8
932
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
933
if file_id not in self.inventory:
935
text_hash = s.get("hash")
936
if text_hash == self.get_file_sha1(file_id):
937
merge_hashes[file_id] = text_hash
926
942
@needs_write_lock
927
943
def mkdir(self, path, file_id=None):
1326
1342
only_change_inv = True
1327
1343
elif self.has_filename(from_rel) and not self.has_filename(to_rel):
1328
1344
only_change_inv = False
1329
elif (sys.platform == 'win32'
1330
and from_rel.lower() == to_rel.lower()
1331
and self.has_filename(from_rel)):
1345
elif (not self.case_sensitive
1346
and from_rel.lower() == to_rel.lower()
1347
and self.has_filename(from_rel)):
1332
1348
only_change_inv = False
1334
1350
# something is wrong, so lets determine what exactly
2331
2347
bzrdir_loc = bisect_left(cur_disk_dir_content,
2332
2348
('.bzr', '.bzr'))
2333
if cur_disk_dir_content[bzrdir_loc][0] == '.bzr':
2349
if (bzrdir_loc < len(cur_disk_dir_content)
2350
and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
2334
2351
# we dont yield the contents of, or, .bzr itself.
2335
2352
del cur_disk_dir_content[bzrdir_loc]
2336
2353
if inv_finished:
2502
2519
self)._get_rules_searcher(default_searcher)
2503
2520
return self._rules_searcher
2522
def get_shelf_manager(self):
2523
"""Return the ShelfManager for this WorkingTree."""
2524
from bzrlib.shelf import ShelfManager
2525
return ShelfManager(self, self._transport)
2506
2528
class WorkingTree2(WorkingTree):
2507
2529
"""This is the Format 2 working tree.
2603
2625
except errors.NoSuchFile:
2604
2626
return _mod_conflicts.ConflictList()
2606
if confile.next() != CONFLICT_HEADER_1 + '\n':
2629
if confile.next() != CONFLICT_HEADER_1 + '\n':
2630
raise errors.ConflictFormatError()
2631
except StopIteration:
2607
2632
raise errors.ConflictFormatError()
2608
except StopIteration:
2609
raise errors.ConflictFormatError()
2610
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2633
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2612
2637
def unlock(self):
2613
2638
# do non-implementation specific cleanup
2728
2753
"""See WorkingTreeFormat.get_format_description()."""
2729
2754
return "Working tree format 2"
2731
def _stub_initialize_remote(self, branch):
2732
"""As a special workaround create critical control files for a remote working tree.
2756
def _stub_initialize_on_transport(self, transport, file_mode):
2757
"""Workaround: create control files for a remote working tree.
2734
2759
This ensures that it can later be updated and dealt with locally,
2735
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2760
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2736
2761
no working tree. (See bug #43064).
2738
2763
sio = StringIO()
2739
2764
inv = Inventory()
2740
2765
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2742
branch._transport.put_file('inventory', sio,
2743
mode=branch.control_files._file_mode)
2744
branch._transport.put_bytes('pending-merges', '',
2745
mode=branch.control_files._file_mode)
2767
transport.put_file('inventory', sio, file_mode)
2768
transport.put_bytes('pending-merges', '', file_mode)
2748
2770
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2749
2771
accelerator_tree=None, hardlink=False):