295
296
def abspath(self, filename):
296
297
return pathjoin(self.basedir, filename)
299
def basis_tree(self):
300
"""Return RevisionTree for the current last revision."""
301
revision_id = self.last_revision()
302
if revision_id is not None:
304
xml = self.read_basis_inventory(revision_id)
305
inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
306
return bzrlib.tree.RevisionTree(self.branch.repository, inv,
310
return self.branch.repository.revision_tree(revision_id)
299
313
def create(branch, directory):
318
332
except OSError, e:
319
333
if e.errno != errno.EEXIST:
321
inv = branch.repository.revision_tree(branch.last_revision()).inventory
335
revision_tree = branch.repository.revision_tree(branch.last_revision())
336
inv = revision_tree.inventory
322
337
wt = WorkingTree(directory, branch, inv)
323
338
wt._write_inventory(inv)
339
wt.set_root_id(revision_tree.inventory.root.file_id)
324
340
if branch.last_revision() is not None:
325
341
wt.set_last_revision(branch.last_revision())
326
342
wt.set_pending_merges([])
359
375
## XXX: badly named; this is not in the store at all
360
376
return self.abspath(self.id2path(file_id))
379
def clone(self, to_directory, revision=None):
380
"""Copy this working tree to a new directory.
382
Currently this will make a new standalone branch at to_directory,
383
but it is planned to change this to use the same branch style that this
384
current tree uses (standalone if standalone, repository if repository)
385
- so that this really is a clone. FIXME RBC 20060127 do this.
386
FIXME MORE RBC 20060127 failed to reach consensus on this in #bzr.
388
If you want a standalone branch, please use branch.clone(to_directory)
389
followed by WorkingTree.create(cloned_branch, to_directory) which is
390
the supported api to produce that.
393
If not None, the cloned tree will have its last revision set to
394
revision, and if a branch is being copied it will be informed
395
of the revision to result in.
397
to_directory -- The destination directory: Must not exist.
399
to_directory = safe_unicode(to_directory)
400
os.mkdir(to_directory)
401
# FIXME here is where the decision to clone the branch should happen.
403
revision = self.last_revision()
404
cloned_branch = self.branch.clone(to_directory, revision)
405
return WorkingTree.create(cloned_branch, to_directory)
362
407
@needs_write_lock
363
408
def commit(self, *args, **kwargs):
364
409
from bzrlib.commit import Commit
455
500
kind = file_kind(fullpath)
502
if e.errno == errno.ENOENT:
503
raise NoSuchFile(fullpath)
457
504
# maybe something better?
458
505
raise BzrError('cannot add: not a regular file, symlink or directory: %s' % quotefn(f))
753
800
other_revision = None
754
801
repository = self.branch.repository
755
802
merge_inner(self.branch,
756
self.branch.basis_tree(),
757
804
repository.revision_tree(other_revision),
759
806
self.set_last_revision(self.branch.last_revision())
855
902
def kind(self, file_id):
856
903
return file_kind(self.id2abspath(file_id))
905
def last_revision(self):
906
"""Return the last revision id of this working tree.
908
In early branch formats this was == the branch last_revision,
909
but that cannot be relied upon - for working tree operations,
910
always use tree.last_revision().
912
return self.branch.last_revision()
858
914
def lock_read(self):
859
915
"""See Branch.lock_read, and WorkingTree.unlock."""
860
916
return self.branch.lock_read()
870
926
if old_revision is not None:
872
928
path = self._basis_inventory_name(old_revision)
873
path = self.branch.control_files._escape(path)
874
self.branch.control_files._transport.delete(path)
929
path = self._control_files._escape(path)
930
self._control_files._transport.delete(path)
875
931
except NoSuchFile:
933
if new_revision is None:
934
self.branch.set_revision_history([])
936
# current format is locked in with the branch
937
revision_history = self.branch.revision_history()
939
position = revision_history.index(new_revision)
941
raise errors.NoSuchRevision(self.branch, new_revision)
942
self.branch.set_revision_history(revision_history[:position + 1])
878
944
xml = self.branch.repository.get_inventory_xml(new_revision)
879
945
path = self._basis_inventory_name(new_revision)
880
self.branch.control_files.put_utf8(path, xml)
946
self._control_files.put_utf8(path, xml)
881
947
except WeaveRevisionNotPresent:
884
950
def read_basis_inventory(self, revision_id):
885
951
"""Read the cached basis inventory."""
886
952
path = self._basis_inventory_name(revision_id)
887
return self.branch.control_files.get_utf8(path).read()
953
return self._control_files.get_utf8(path).read()
890
956
def read_working_inventory(self):
891
957
"""Read the working inventory."""
892
958
# ElementTree does its own conversion from UTF-8, so open in
894
return bzrlib.xml5.serializer_v5.read_inventory(
960
result = bzrlib.xml5.serializer_v5.read_inventory(
895
961
self._control_files.get('inventory'))
962
self._set_inventory(result)
897
965
@needs_write_lock
898
966
def remove(self, files, verbose=False):
939
1007
def revert(self, filenames, old_tree=None, backups=True):
940
1008
from bzrlib.merge import merge_inner
941
1009
if old_tree is None:
942
old_tree = self.branch.basis_tree()
1010
old_tree = self.basis_tree()
943
1011
merge_inner(self.branch, old_tree,
944
1012
self, ignore_zero=True,
945
1013
backup_files=backups,
981
1049
inv._byid[inv.root.file_id] = inv.root
983
1051
entry = inv[fid]
984
if entry.parent_id in (None, orig_root_id):
1052
if entry.parent_id == orig_root_id:
985
1053
entry.parent_id = inv.root.file_id
986
1054
self._write_inventory(inv)
999
1067
# of a nasty hack; probably it's better to have a transaction object,
1000
1068
# which can do some finalization when it's either successfully or
1001
1069
# unsuccessfully completed. (Denys's original patch did that.)
1002
if self._hashcache.needs_write and self.branch.control_files._lock_count==1:
1070
if self._hashcache.needs_write and self._control_files._lock_count==1:
1003
1071
self._hashcache.write()
1004
1072
return self.branch.unlock()