50
50
from bzrlib.atomicfile import AtomicFile
51
51
from bzrlib.branch import (Branch,
57
from bzrlib.decorators import needs_read_lock, needs_write_lock
56
58
from bzrlib.errors import (BzrCheckError,
59
61
WeaveRevisionNotPresent,
62
65
from bzrlib.inventory import InventoryEntry
66
from bzrlib.lockable_files import LockableFiles
63
67
from bzrlib.osutils import (appendpath,
181
186
not listed in the Inventory and vice versa.
184
def __init__(self, basedir='.', branch=None, _inventory=None):
189
def __init__(self, basedir='.', branch=None, _inventory=None, _control_files=None):
185
190
"""Construct a WorkingTree for basedir.
187
192
If the branch is not supplied, it is opened automatically.
194
199
assert isinstance(basedir, basestring), \
195
200
"base directory %r is not a string" % basedir
196
201
basedir = safe_unicode(basedir)
202
mutter("openeing working tree %r", basedir)
197
203
if branch is None:
198
204
branch = Branch.open(basedir)
199
205
assert isinstance(branch, Branch), \
200
206
"branch %r is not a Branch" % branch
201
207
self.branch = branch
202
208
self.basedir = realpath(basedir)
209
# if branch is at our basedir and is a format 6 or less
210
if (isinstance(self.branch._branch_format,
211
(BzrBranchFormat4, BzrBranchFormat5, BzrBranchFormat6))
212
# might be able to share control object
213
and self.branch.base.split('/')[-2] == self.basedir.split('/')[-1]):
214
self._control_files = self.branch.control_files
215
elif _control_files is not None:
216
assert False, "not done yet"
217
# self._control_files = _control_files
219
self._control_files = LockableFiles(
220
get_transport(self.basedir).clone(bzrlib.BZRDIR), 'branch-lock')
204
222
# update the whole cache up front and write to disk if anything changed;
205
223
# in the future we might want to do this more selectively
300
318
except OSError, e:
301
319
if e.errno != errno.EEXIST:
303
inv = branch.revision_tree(branch.last_revision()).inventory
321
inv = branch.repository.revision_tree(branch.last_revision()).inventory
304
322
wt = WorkingTree(directory, branch, inv)
305
323
wt._write_inventory(inv)
306
324
if branch.last_revision() is not None:
481
500
p.append(l.rstrip('\n'))
484
def _abs_controlfilename(self, name):
485
"""return the path for the controlfile name in the workingtree."""
486
return pathjoin(self.basedir, '.bzr', name)
488
def _controlfile(self, name, encoding='utf-8'):
489
"""Get a control file for the checkout.
491
FIXME RBC 20060123 when storage comes in this should be a lockable
495
return codecs.open(self._abs_controlfilename(name), encoding=encoding)
497
503
@needs_write_lock
498
504
def set_pending_merges(self, rev_list):
500
sio.write('\n'.join(rev_list).encode('utf-8'))
502
f = AtomicFile(self._abs_controlfilename('pending-merges'))
505
self._control_files.put_utf8('pending-merges', '\n'.join(rev_list))
509
507
def get_symlink_target(self, file_id):
510
508
return os.readlink(self.id2abspath(file_id))
753
751
other_revision = old_revision_history[-1]
755
753
other_revision = None
754
repository = self.branch.repository
756
755
merge_inner(self.branch,
757
756
self.branch.basis_tree(),
758
self.branch.revision_tree(other_revision),
757
repository.revision_tree(other_revision),
760
759
self.set_last_revision(self.branch.last_revision())
868
867
return 'basis-inventory.%s' % revision_id
870
869
def set_last_revision(self, new_revision, old_revision=None):
870
if old_revision is not None:
873
872
path = self._basis_inventory_name(old_revision)
874
path = self.branch._rel_controlfilename(path)
875
self.branch._transport.delete(path)
873
path = self.branch.control_files._escape(path)
874
self.branch.control_files._transport.delete(path)
879
xml = self.branch.get_inventory_xml(new_revision)
878
xml = self.branch.repository.get_inventory_xml(new_revision)
880
879
path = self._basis_inventory_name(new_revision)
881
self.branch.put_controlfile(path, xml)
880
self.branch.control_files.put_utf8(path, xml)
882
881
except WeaveRevisionNotPresent:
885
884
def read_basis_inventory(self, revision_id):
886
885
"""Read the cached basis inventory."""
887
886
path = self._basis_inventory_name(revision_id)
888
return self.branch.controlfile(path, 'r').read()
887
return self.branch.control_files.get_utf8(path).read()
891
890
def read_working_inventory(self):
893
892
# ElementTree does its own conversion from UTF-8, so open in
895
894
return bzrlib.xml5.serializer_v5.read_inventory(
896
self._controlfile('inventory', encoding=None))
895
self._control_files.get('inventory'))
898
897
@needs_write_lock
899
898
def remove(self, files, verbose=False):
995
994
between multiple working trees, i.e. via shared storage, then we
996
995
would probably want to lock both the local tree, and the branch.
998
if self._hashcache.needs_write and self.branch._lock_count==1:
997
# FIXME: We want to write out the hashcache only when the last lock on
998
# this working copy is released. Peeking at the lock count is a bit
999
# of a nasty hack; probably it's better to have a transaction object,
1000
# which can do some finalization when it's either successfully or
1001
# unsuccessfully completed. (Denys's original patch did that.)
1002
if self._hashcache.needs_write and self.branch.control_files._lock_count==1:
999
1003
self._hashcache.write()
1000
1004
return self.branch.unlock()
1005
1009
sio = StringIO()
1006
1010
bzrlib.xml5.serializer_v5.write_inventory(inv, sio)
1008
f = AtomicFile(self._abs_controlfilename('inventory'))
1012
self._control_files.put('inventory', sio)
1014
1013
self._set_inventory(inv)
1015
1014
mutter('wrote working inventory')