13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
"""WorkingTree object and friends.
19
19
A WorkingTree represents the editable working copy of a branch.
20
Operations which represent the WorkingTree are also done here,
21
such as renaming or adding files. The WorkingTree has an inventory
22
which is updated by these operations. A commit produces a
20
Operations which represent the WorkingTree are also done here,
21
such as renaming or adding files. The WorkingTree has an inventory
22
which is updated by these operations. A commit produces a
23
23
new revision based on the workingtree and its inventory.
25
25
At the moment every WorkingTree has its own branch. Remote
59
57
conflicts as _mod_conflicts,
68
66
revision as _mod_revision,
80
75
import bzrlib.branch
81
76
from bzrlib.transport import get_transport
83
from bzrlib.workingtree_4 import WorkingTreeFormat4
77
from bzrlib.workingtree_4 import (
86
84
from bzrlib import symbol_versioning
87
85
from bzrlib.decorators import needs_read_lock, needs_write_lock
88
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
89
from bzrlib.lockable_files import LockableFiles, TransportLock
86
from bzrlib.lockable_files import LockableFiles
90
87
from bzrlib.lockdir import LockDir
91
88
import bzrlib.mutabletree
92
89
from bzrlib.mutabletree import needs_tree_write_lock
90
from bzrlib import osutils
93
91
from bzrlib.osutils import (
103
99
supports_executable,
101
from bzrlib.filters import filtered_input_file
105
102
from bzrlib.trace import mutter, note
106
103
from bzrlib.transport.local import LocalTransport
107
104
from bzrlib.progress import DummyProgress, ProgressPhase
108
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
105
from bzrlib.revision import CURRENT_REVISION
109
106
from bzrlib.rio import RioReader, rio_file, Stanza
110
from bzrlib.symbol_versioning import (deprecated_passed,
113
DEPRECATED_PARAMETER,
107
from bzrlib.symbol_versioning import (
109
DEPRECATED_PARAMETER,
120
113
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
123
116
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()
144
119
class TreeEntry(object):
145
120
"""An entry that implements the minimum interface used by commands.
147
This needs further inspection, it may be better to have
122
This needs further inspection, it may be better to have
148
123
InventoryEntries without ids - though that seems wrong. For now,
149
124
this is a parallel hierarchy to InventoryEntry, and needs to become
150
125
one of several things: decorates to that hierarchy, children of, or
237
214
self._control_files = self.branch.control_files
239
216
# assume all other formats have their own control files.
240
assert isinstance(_control_files, LockableFiles), \
241
"_control_files must be a LockableFiles, not %r" \
243
217
self._control_files = _control_files
218
self._transport = self._control_files._transport
244
219
# update the whole cache up front and write to disk if anything changed;
245
220
# in the future we might want to do this more selectively
246
221
# two possible ways offer themselves : in self._unlock, write the cache
270
246
# the Format factory and creation methods that are
271
247
# permitted to do this.
272
248
self._set_inventory(_inventory, dirty=False)
249
self._detect_case_handling()
250
self._rules_searcher = None
251
self.views = self._make_views()
253
def _detect_case_handling(self):
254
wt_trans = self.bzrdir.get_workingtree_transport(None)
256
wt_trans.stat("FoRMaT")
257
except errors.NoSuchFile:
258
self.case_sensitive = True
260
self.case_sensitive = False
262
self._setup_directory_is_tree_reference()
274
264
branch = property(
275
265
fget=lambda self: self._branch,
290
280
self._control_files.break_lock()
291
281
self.branch.break_lock()
283
def _get_check_refs(self):
284
"""Return the references needed to perform a check of this tree.
286
The default implementation returns no refs, and is only suitable for
287
trees that have no local caching and can commit on ghosts at any time.
289
:seealso: bzrlib.check for details about check_refs.
293
293
def requires_rich_root(self):
294
294
return self._format.requires_rich_root
296
296
def supports_tree_reference(self):
299
def supports_content_filtering(self):
300
return self._format.supports_content_filtering()
302
def supports_views(self):
303
return self.views.supports_views()
299
305
def _set_inventory(self, inv, dirty):
300
306
"""Set the internal cached inventory.
348
353
return WorkingTree.open(path, _unsupported=True)
356
def find_trees(location):
357
def list_current(transport):
358
return [d for d in transport.list_dir('') if d != '.bzr']
359
def evaluate(bzrdir):
361
tree = bzrdir.open_workingtree()
362
except errors.NoWorkingTree:
366
transport = get_transport(location)
367
iterator = bzrdir.BzrDir.find_bzrdirs(transport, evaluate=evaluate,
368
list_current=list_current)
369
return [t for t in iterator if t is not None]
350
371
# should be deprecated - this is slow and in any case treating them as a
351
372
# container is (we now know) bad style -- mbp 20070302
352
373
## @deprecated_method(zero_fifteen)
390
417
# at this point ?
392
419
return self.branch.repository.revision_tree(revision_id)
393
except errors.RevisionNotPresent:
420
except (errors.RevisionNotPresent, errors.NoSuchRevision):
394
421
# the basis tree *may* be a ghost or a low level error may have
395
# occured. If the revision is present, its a problem, if its not
422
# occurred. If the revision is present, its a problem, if its not
397
424
if self.branch.repository.has_revision(revision_id):
399
426
# the basis tree is a ghost so return an empty tree.
400
return self.branch.repository.revision_tree(None)
427
return self.branch.repository.revision_tree(
428
_mod_revision.NULL_REVISION)
402
430
def _cleanup(self):
403
431
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)
443
433
def relpath(self, path):
444
434
"""Return the local path portion from a given path.
446
The path may be absolute or relative. If its a relative path it is
436
The path may be absolute or relative. If its a relative path it is
447
437
interpreted relative to the python current working directory.
449
439
return osutils.relpath(self.basedir, path)
451
441
def has_filename(self, filename):
452
442
return osutils.lexists(self.abspath(filename))
454
def get_file(self, file_id, path=None):
444
def get_file(self, file_id, path=None, filtered=True):
445
return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
447
def get_file_with_stat(self, file_id, path=None, filtered=True,
449
"""See Tree.get_file_with_stat."""
456
file_id = osutils.safe_file_id(file_id)
457
451
path = self.id2path(file_id)
458
return self.get_file_byname(path)
460
def get_file_text(self, file_id):
461
file_id = osutils.safe_file_id(file_id)
462
return self.get_file(file_id).read()
464
def get_file_byname(self, filename):
465
return file(self.abspath(filename), 'rb')
452
file_obj = self.get_file_byname(path, filtered=False)
453
stat_value = _fstat(file_obj.fileno())
454
if filtered and self.supports_content_filtering():
455
filters = self._content_filter_stack(path)
456
file_obj = filtered_input_file(file_obj, filters)
457
return (file_obj, stat_value)
459
def get_file_text(self, file_id, path=None, filtered=True):
460
return self.get_file(file_id, path=path, filtered=filtered).read()
462
def get_file_byname(self, filename, filtered=True):
463
path = self.abspath(filename)
465
if filtered and self.supports_content_filtering():
466
filters = self._content_filter_stack(filename)
467
return filtered_input_file(f, filters)
471
def get_file_lines(self, file_id, path=None, filtered=True):
472
"""See Tree.get_file_lines()"""
473
file = self.get_file(file_id, path, filtered=filtered)
475
return file.readlines()
468
480
def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
475
487
incorrectly attributed to CURRENT_REVISION (but after committing, the
476
488
attribution will be correct).
478
file_id = osutils.safe_file_id(file_id)
479
basis = self.basis_tree()
482
changes = self._iter_changes(basis, True, [self.id2path(file_id)],
483
require_versioned=True).next()
484
changed_content, kind = changes[2], changes[6]
485
if not changed_content:
486
return basis.annotate_iter(file_id)
490
if kind[0] != 'file':
493
old_lines = list(basis.annotate_iter(file_id))
495
for tree in self.branch.repository.revision_trees(
496
self.get_parent_ids()[1:]):
497
if file_id not in tree:
499
old.append(list(tree.annotate_iter(file_id)))
500
return annotate.reannotate(old, self.get_file(file_id).readlines(),
490
maybe_file_parent_keys = []
491
for parent_id in self.get_parent_ids():
493
parent_tree = self.revision_tree(parent_id)
494
except errors.NoSuchRevisionInTree:
495
parent_tree = self.branch.repository.revision_tree(parent_id)
496
parent_tree.lock_read()
498
if file_id not in parent_tree:
500
ie = parent_tree.inventory[file_id]
501
if ie.kind != 'file':
502
# Note: this is slightly unnecessary, because symlinks and
503
# directories have a "text" which is the empty text, and we
504
# know that won't mess up annotations. But it seems cleaner
506
parent_text_key = (file_id, ie.revision)
507
if parent_text_key not in maybe_file_parent_keys:
508
maybe_file_parent_keys.append(parent_text_key)
511
graph = _mod_graph.Graph(self.branch.repository.texts)
512
heads = graph.heads(maybe_file_parent_keys)
513
file_parent_keys = []
514
for key in maybe_file_parent_keys:
516
file_parent_keys.append(key)
518
# Now we have the parents of this content
519
annotator = self.branch.repository.texts.get_annotator()
520
text = self.get_file(file_id).read()
521
this_key =(file_id, default_revision)
522
annotator.add_special_text(this_key, file_parent_keys, text)
523
annotations = [(key[-1], line)
524
for key, line in annotator.annotate_flat(this_key)]
505
527
def _get_ancestors(self, default_revision):
506
528
ancestors = set([default_revision])
534
556
def get_root_id(self):
535
557
"""Return the id of this trees root"""
536
558
return self._inventory.root.file_id
538
560
def _get_store_filename(self, file_id):
539
561
## XXX: badly named; this is not in the store at all
540
file_id = osutils.safe_file_id(file_id)
541
562
return self.abspath(self.id2path(file_id))
544
565
def clone(self, to_bzrdir, revision_id=None):
545
566
"""Duplicate this working tree into to_bzr, including all state.
547
568
Specifically modified files are kept as modified, but
548
569
ignored and unknown files are discarded.
550
571
If you want to make a new line of development, see bzrdir.sprout()
553
If not None, the cloned tree will have its last revision set to
554
revision, and and difference between the source trees last revision
574
If not None, the cloned tree will have its last revision set to
575
revision, and difference between the source trees last revision
555
576
and this one merged in.
557
578
# assumes the target bzr dir format is compatible.
558
result = self._format.initialize(to_bzrdir)
579
result = to_bzrdir.create_workingtree()
559
580
self.copy_content_into(result, revision_id)
593
611
__contains__ = has_id
595
613
def get_file_size(self, file_id):
596
file_id = osutils.safe_file_id(file_id)
597
return os.path.getsize(self.id2abspath(file_id))
614
"""See Tree.get_file_size"""
615
# XXX: this returns the on-disk size; it should probably return the
618
return os.path.getsize(self.id2abspath(file_id))
620
if e.errno != errno.ENOENT:
600
626
def get_file_sha1(self, file_id, path=None, stat_value=None):
601
file_id = osutils.safe_file_id(file_id)
603
628
path = self._inventory.id2path(file_id)
604
629
return self._hashcache.get_sha1(path, stat_value)
606
631
def get_file_mtime(self, file_id, path=None):
607
file_id = osutils.safe_file_id(file_id)
609
633
path = self.inventory.id2path(file_id)
610
634
return os.lstat(self.abspath(path)).st_mtime
636
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
637
file_id = self.path2id(path)
639
# For unversioned files on win32, we just assume they are not
642
return self._inventory[file_id].executable
644
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
645
mode = stat_result.st_mode
646
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
612
648
if not supports_executable():
613
649
def is_executable(self, file_id, path=None):
614
file_id = osutils.safe_file_id(file_id)
615
650
return self._inventory[file_id].executable
652
_is_executable_from_path_and_stat = \
653
_is_executable_from_path_and_stat_from_basis
617
655
def is_executable(self, file_id, path=None):
619
file_id = osutils.safe_file_id(file_id)
620
657
path = self.id2path(file_id)
621
658
mode = os.lstat(self.abspath(path)).st_mode
622
659
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
661
_is_executable_from_path_and_stat = \
662
_is_executable_from_path_and_stat_from_stat
624
664
@needs_tree_write_lock
625
665
def _add(self, files, ids, kinds):
626
666
"""See MutableTree._add."""
627
667
# TODO: Re-adding a file that is removed in the working copy
628
668
# should probably put it back with the previous ID.
629
# the read and write working inventory should not occur in this
669
# the read and write working inventory should not occur in this
630
670
# function - they should be part of lock_write and unlock.
631
671
inv = self.inventory
632
672
for f, file_id, kind in zip(files, ids, kinds):
633
assert kind is not None
634
673
if file_id is None:
635
674
inv.add_path(f, kind=kind)
637
file_id = osutils.safe_file_id(file_id)
638
676
inv.add_path(f, kind=kind, file_id=file_id)
639
677
self._inventory_is_modified = True
703
741
self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
705
@deprecated_method(zero_eleven)
707
def pending_merges(self):
708
"""Return a list of pending merges.
710
These are revisions that have been merged into the working
711
directory but not yet committed.
713
As of 0.11 this is deprecated. Please see WorkingTree.get_parent_ids()
714
instead - which is available on all tree objects.
716
return self.get_parent_ids()[1:]
743
def path_content_summary(self, path, _lstat=os.lstat,
744
_mapper=osutils.file_kind_from_stat_mode):
745
"""See Tree.path_content_summary."""
746
abspath = self.abspath(path)
748
stat_result = _lstat(abspath)
750
if getattr(e, 'errno', None) == errno.ENOENT:
752
return ('missing', None, None, None)
753
# propagate other errors
755
kind = _mapper(stat_result.st_mode)
757
return self._file_content_summary(path, stat_result)
758
elif kind == 'directory':
759
# perhaps it looks like a plain directory, but it's really a
761
if self._directory_is_tree_reference(path):
762
kind = 'tree-reference'
763
return kind, None, None, None
764
elif kind == 'symlink':
765
target = osutils.readlink(abspath)
766
return ('symlink', None, None, target)
768
return (kind, None, None, None)
770
def _file_content_summary(self, path, stat_result):
771
size = stat_result.st_size
772
executable = self._is_executable_from_path_and_stat(path, stat_result)
773
# try for a stat cache lookup
774
return ('file', size, executable, self._sha_from_stat(
718
777
def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
719
778
"""Common ghost checking functionality from set_parent_*.
730
789
def _set_merges_from_parent_ids(self, parent_ids):
731
790
merges = parent_ids[1:]
732
self._control_files.put_bytes('pending-merges', '\n'.join(merges))
791
self._transport.put_bytes('pending-merges', '\n'.join(merges),
792
mode=self.bzrdir._get_file_mode())
794
def _filter_parent_ids_by_ancestry(self, revision_ids):
795
"""Check that all merged revisions are proper 'heads'.
797
This will always return the first revision_id, and any merged revisions
800
if len(revision_ids) == 0:
802
graph = self.branch.repository.get_graph()
803
heads = graph.heads(revision_ids)
804
new_revision_ids = revision_ids[:1]
805
for revision_id in revision_ids[1:]:
806
if revision_id in heads and revision_id not in new_revision_ids:
807
new_revision_ids.append(revision_id)
808
if new_revision_ids != revision_ids:
809
trace.mutter('requested to set revision_ids = %s,'
810
' but filtered to %s', revision_ids, new_revision_ids)
811
return new_revision_ids
734
813
@needs_tree_write_lock
735
814
def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
736
815
"""Set the parent ids to revision_ids.
738
817
See also set_parent_trees. This api will try to retrieve the tree data
739
818
for each element of revision_ids from the trees repository. If you have
740
819
tree data already available, it is more efficient to use
744
823
:param revision_ids: The revision_ids to set as the parent ids of this
745
824
working tree. Any of these may be ghosts.
747
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
748
826
self._check_parents_for_ghosts(revision_ids,
749
827
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
750
828
for revision_id in revision_ids:
751
829
_mod_revision.check_not_reserved_id(revision_id)
831
revision_ids = self._filter_parent_ids_by_ancestry(revision_ids)
753
833
if len(revision_ids) > 0:
754
834
self.set_last_revision(revision_ids[0])
760
840
@needs_tree_write_lock
761
841
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
762
842
"""See MutableTree.set_parent_trees."""
763
parent_ids = [osutils.safe_revision_id(rev) for (rev, tree) in parents_list]
843
parent_ids = [rev for (rev, tree) in parents_list]
764
844
for revision_id in parent_ids:
765
845
_mod_revision.check_not_reserved_id(revision_id)
767
847
self._check_parents_for_ghosts(parent_ids,
768
848
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
850
parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
770
852
if len(parent_ids) == 0:
771
853
leftmost_parent_id = _mod_revision.NULL_REVISION
772
854
leftmost_parent_tree = None
799
881
yield Stanza(file_id=file_id.decode('utf8'), hash=hash)
800
882
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
884
def _sha_from_stat(self, path, stat_result):
885
"""Get a sha digest from the tree's stat cache.
887
The default implementation assumes no stat cache is present.
889
:param path: The path.
890
:param stat_result: The stat result being looked up.
802
894
def _put_rio(self, filename, stanzas, header):
803
895
self._must_be_locked()
804
896
my_file = rio_file(stanzas, header)
805
self._control_files.put(filename, my_file)
897
self._transport.put_file(filename, my_file,
898
mode=self.bzrdir._get_file_mode())
807
900
@needs_write_lock # because merge pulls data into the branch.
808
901
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
902
merge_type=None, force=False):
810
903
"""Merge from a branch into this working tree.
812
905
:param branch: The branch to merge from.
816
909
branch.last_revision().
818
911
from bzrlib.merge import Merger, Merge3Merger
819
pb = bzrlib.ui.ui_factory.nested_progress_bar()
912
pb = ui.ui_factory.nested_progress_bar()
821
914
merger = Merger(self.branch, this_tree=self, pb=pb)
822
915
merger.pp = ProgressPhase("Merge phase", 5, pb)
823
916
merger.pp.next_phase()
824
# check that there are no
826
merger.check_basis(check_clean=True, require_commits=False)
917
# check that there are no local alterations
918
if not force and self.has_changes():
919
raise errors.UncommittedChanges(self)
827
920
if to_revision is None:
828
921
to_revision = _mod_revision.ensure_null(branch.last_revision())
830
to_revision = osutils.safe_revision_id(to_revision)
831
922
merger.other_rev_id = to_revision
832
923
if _mod_revision.is_null(merger.other_rev_id):
833
924
raise errors.NoCommits(branch)
869
960
still in the working inventory and have that text hash.
872
hashfile = self._control_files.get('merge-hashes')
963
hashfile = self._transport.get('merge-hashes')
873
964
except errors.NoSuchFile:
877
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
969
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
970
raise errors.MergeModifiedFormatError()
971
except StopIteration:
878
972
raise errors.MergeModifiedFormatError()
879
except StopIteration:
880
raise errors.MergeModifiedFormatError()
881
for s in RioReader(hashfile):
882
# RioReader reads in Unicode, so convert file_ids back to utf8
883
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
884
if file_id not in self.inventory:
886
text_hash = s.get("hash")
887
if text_hash == self.get_file_sha1(file_id):
888
merge_hashes[file_id] = text_hash
973
for s in RioReader(hashfile):
974
# RioReader reads in Unicode, so convert file_ids back to utf8
975
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
976
if file_id not in self.inventory:
978
text_hash = s.get("hash")
979
if text_hash == self.get_file_sha1(file_id):
980
merge_hashes[file_id] = text_hash
891
985
@needs_write_lock
892
986
def mkdir(self, path, file_id=None):
943
1038
other_tree.unlock()
944
1039
other_tree.bzrdir.retire_bzrdir()
1041
def _setup_directory_is_tree_reference(self):
1042
if self._branch.repository._format.supports_tree_reference:
1043
self._directory_is_tree_reference = \
1044
self._directory_may_be_tree_reference
1046
self._directory_is_tree_reference = \
1047
self._directory_is_never_tree_reference
1049
def _directory_is_never_tree_reference(self, relpath):
1052
def _directory_may_be_tree_reference(self, relpath):
1053
# as a special case, if a directory contains control files then
1054
# it's a tree reference, except that the root of the tree is not
1055
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1056
# TODO: We could ask all the control formats whether they
1057
# recognize this directory, but at the moment there's no cheap api
1058
# to do that. Since we probably can only nest bzr checkouts and
1059
# they always use this name it's ok for now. -- mbp 20060306
1061
# FIXME: There is an unhandled case here of a subdirectory
1062
# containing .bzr but not a branch; that will probably blow up
1063
# when you try to commit it. It might happen if there is a
1064
# checkout in a subdirectory. This can be avoided by not adding
946
1067
@needs_tree_write_lock
947
1068
def extract(self, file_id, format=None):
948
1069
"""Extract a subtree from this tree.
950
1071
A new branch will be created, relative to the path for this tree.
957
1078
transport = transport.clone(name)
958
1079
transport.ensure_base()
959
1080
return transport
961
1082
sub_path = self.id2path(file_id)
962
1083
branch_transport = mkdirs(sub_path)
963
1084
if format is None:
964
format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
1085
format = self.bzrdir.cloning_metadir()
965
1086
branch_transport.ensure_base()
966
1087
branch_bzrdir = format.initialize_on_transport(branch_transport)
968
1089
repo = branch_bzrdir.find_repository()
969
1090
except errors.NoRepositoryPresent:
970
1091
repo = branch_bzrdir.create_repository()
971
assert repo.supports_rich_root()
973
if not repo.supports_rich_root():
974
raise errors.RootNotRich()
1092
if not repo.supports_rich_root():
1093
raise errors.RootNotRich()
975
1094
new_branch = branch_bzrdir.create_branch()
976
1095
new_branch.pull(self.branch)
977
1096
for parent_id in self.get_parent_ids():
982
1101
branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
984
1103
tree_bzrdir = branch_bzrdir
985
wt = tree_bzrdir.create_workingtree(NULL_REVISION)
1104
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
986
1105
wt.set_parent_ids(self.get_parent_ids())
987
1106
my_inv = self.inventory
988
child_inv = Inventory(root_id=None)
1107
child_inv = inventory.Inventory(root_id=None)
989
1108
new_root = my_inv[file_id]
990
1109
my_inv.remove_recursive_id(file_id)
991
1110
new_root.parent_id = None
1008
1128
sio = StringIO()
1009
1129
self._serialize(self._inventory, sio)
1011
self._control_files.put('inventory', sio)
1131
self._transport.put_file('inventory', sio,
1132
mode=self.bzrdir._get_file_mode())
1012
1133
self._inventory_is_modified = False
1014
1135
def _kind(self, relpath):
1015
1136
return osutils.file_kind(self.abspath(relpath))
1017
def list_files(self, include_root=False):
1018
"""Recursively list all files as (path, class, kind, id, entry).
1138
def list_files(self, include_root=False, from_dir=None, recursive=True):
1139
"""List all files as (path, class, kind, id, entry).
1020
1141
Lists, but does not descend into unversioned directories.
1022
1142
This does not include files that have been deleted in this
1143
tree. Skips the control directory.
1025
Skips the control directory.
1145
:param include_root: if True, do not return an entry for the root
1146
:param from_dir: start from this directory or None for the root
1147
:param recursive: whether to recurse into subdirectories or not
1027
1149
# list_files is an iterator, so @needs_read_lock doesn't work properly
1028
1150
# with it. So callers should be careful to always read_lock the tree.
1043
1165
fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1045
1167
# directory file_id, relative path, absolute path, reverse sorted children
1046
children = os.listdir(self.basedir)
1168
if from_dir is not None:
1169
from_dir_id = inv.path2id(from_dir)
1170
if from_dir_id is None:
1171
# Directory not versioned
1173
from_dir_abspath = pathjoin(self.basedir, from_dir)
1175
from_dir_id = inv.root.file_id
1176
from_dir_abspath = self.basedir
1177
children = os.listdir(from_dir_abspath)
1047
1178
children.sort()
1048
# jam 20060527 The kernel sized tree seems equivalent whether we
1179
# jam 20060527 The kernel sized tree seems equivalent whether we
1049
1180
# use a deque and popleft to keep them sorted, or if we use a plain
1050
1181
# list and just reverse() them.
1051
1182
children = collections.deque(children)
1052
stack = [(inv.root.file_id, u'', self.basedir, children)]
1183
stack = [(from_dir_id, u'', from_dir_abspath, children)]
1054
1185
from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1109
1240
except KeyError:
1110
1241
yield fp[1:], c, fk, None, TreeEntry()
1113
1244
if fk != 'directory':
1116
# But do this child first
1117
new_children = os.listdir(fap)
1119
new_children = collections.deque(new_children)
1120
stack.append((f_ie.file_id, fp, fap, new_children))
1121
# Break out of inner loop,
1122
# so that we start outer loop with child
1247
# But do this child first if recursing down
1249
new_children = os.listdir(fap)
1251
new_children = collections.deque(new_children)
1252
stack.append((f_ie.file_id, fp, fap, new_children))
1253
# Break out of inner loop,
1254
# so that we start outer loop with child
1125
1257
# if we finished all children, pop it off the stack
1357
1494
from_tail = splitpath(from_rel)[-1]
1358
1495
from_id = inv.path2id(from_rel)
1359
1496
if from_id is None:
1360
raise errors.BzrRenameFailedError(from_rel,to_rel,
1361
errors.NotVersionedError(path=str(from_rel)))
1362
from_entry = inv[from_id]
1497
# if file is missing in the inventory maybe it's in the basis_tree
1498
basis_tree = self.branch.basis_tree()
1499
from_id = basis_tree.path2id(from_rel)
1501
raise errors.BzrRenameFailedError(from_rel,to_rel,
1502
errors.NotVersionedError(path=str(from_rel)))
1503
# put entry back in the inventory so we can rename it
1504
from_entry = basis_tree.inventory[from_id].copy()
1507
from_entry = inv[from_id]
1363
1508
from_parent_id = from_entry.parent_id
1364
1509
to_dir, to_tail = os.path.split(to_rel)
1365
1510
to_dir_id = inv.path2id(to_dir)
1427
1572
:raises: NoSuchId if any fileid is not currently versioned.
1429
1574
for file_id in file_ids:
1430
file_id = osutils.safe_file_id(file_id)
1575
if file_id not in self._inventory:
1576
raise errors.NoSuchId(self, file_id)
1577
for file_id in file_ids:
1431
1578
if self._inventory.has_id(file_id):
1432
1579
self._inventory.remove_recursive_id(file_id)
1434
raise errors.NoSuchId(self, file_id)
1435
1580
if len(file_ids):
1436
# in the future this should just set a dirty bit to wait for the
1581
# in the future this should just set a dirty bit to wait for the
1437
1582
# final unlock. However, until all methods of workingtree start
1438
# with the current in -memory inventory rather than triggering
1583
# with the current in -memory inventory rather than triggering
1439
1584
# a read, it is more complex - we need to teach read_inventory
1440
1585
# to know when to read, and when to not read first... and possibly
1441
1586
# to save first when the in memory one may be corrupted.
1442
1587
# so for now, we just only write it if it is indeed dirty.
1443
1588
# - RBC 20060907
1444
1589
self._write_inventory(self._inventory)
1446
@deprecated_method(zero_eight)
1447
def iter_conflicts(self):
1448
"""List all files in the tree that have text or content conflicts.
1449
DEPRECATED. Use conflicts instead."""
1450
return self._iter_conflicts()
1452
1591
def _iter_conflicts(self):
1453
1592
conflicted = set()
1463
1602
@needs_write_lock
1464
1603
def pull(self, source, overwrite=False, stop_revision=None,
1465
change_reporter=None):
1466
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1604
change_reporter=None, possible_transports=None, local=False):
1605
top_pb = ui.ui_factory.nested_progress_bar()
1467
1606
source.lock_read()
1469
1608
pp = ProgressPhase("Pull phase", 2, top_pb)
1470
1609
pp.next_phase()
1471
1610
old_revision_info = self.branch.last_revision_info()
1472
1611
basis_tree = self.basis_tree()
1473
count = self.branch.pull(source, overwrite, stop_revision)
1612
count = self.branch.pull(source, overwrite, stop_revision,
1613
possible_transports=possible_transports,
1474
1615
new_revision_info = self.branch.last_revision_info()
1475
1616
if new_revision_info != old_revision_info:
1476
1617
pp.next_phase()
1477
1618
repository = self.branch.repository
1478
pb = bzrlib.ui.ui_factory.nested_progress_bar()
1619
pb = ui.ui_factory.nested_progress_bar()
1479
1620
basis_tree.lock_read()
1481
1622
new_basis_tree = self.branch.basis_tree()
1496
1638
# reuse the revisiontree we merged against to set the new
1498
1640
parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1499
# we have to pull the merge trees out again, because
1500
# merge_inner has set the ids. - this corner is not yet
1641
# we have to pull the merge trees out again, because
1642
# merge_inner has set the ids. - this corner is not yet
1501
1643
# layered well enough to prevent double handling.
1502
1644
# XXX TODO: Fix the double handling: telling the tree about
1503
1645
# the already known parent data is wasteful.
1544
1685
for subf in os.listdir(dirabs):
1686
if self.bzrdir.is_control_filename(subf):
1547
1688
if subf not in dir_entry.children:
1548
subf_norm, can_access = osutils.normalized_filename(subf)
1691
can_access) = osutils.normalized_filename(subf)
1692
except UnicodeDecodeError:
1693
path_os_enc = path.encode(osutils._fs_enc)
1694
relpath = path_os_enc + '/' + subf
1695
raise errors.BadFilenameEncoding(relpath,
1549
1697
if subf_norm != subf and can_access:
1550
1698
if subf_norm not in dir_entry.children:
1551
1699
fl.append(subf_norm)
1553
1701
fl.append(subf)
1556
1704
for subf in fl:
1557
1705
subp = pathjoin(path, subf)
1594
1742
r"""Check whether the filename matches an ignore pattern.
1596
1744
Patterns containing '/' or '\' need to match the whole path;
1597
others match against only the last component.
1745
others match against only the last component. Patterns starting
1746
with '!' are ignore exceptions. Exceptions take precedence
1747
over regular patterns and cause the filename to not be ignored.
1599
1749
If the file is ignored, returns the pattern which caused it to
1600
1750
be ignored, otherwise None. So this can simply be used as a
1601
1751
boolean if desired."""
1602
1752
if getattr(self, '_ignoreglobster', None) is None:
1603
self._ignoreglobster = globbing.Globster(self.get_ignore_list())
1753
self._ignoreglobster = globbing.ExceptionGlobster(self.get_ignore_list())
1604
1754
return self._ignoreglobster.match(filename)
1606
1756
def kind(self, file_id):
1607
1757
return file_kind(self.id2abspath(file_id))
1759
def stored_kind(self, file_id):
1760
"""See Tree.stored_kind"""
1761
return self.inventory[file_id].kind
1609
1763
def _comparison_data(self, entry, path):
1610
1764
abspath = self.abspath(path)
1693
1847
def _reset_data(self):
1694
1848
"""Reset transient data that cannot be revalidated."""
1695
1849
self._inventory_is_modified = False
1696
result = self._deserialize(self._control_files.get('inventory'))
1850
f = self._transport.get('inventory')
1852
result = self._deserialize(f)
1697
1855
self._set_inventory(result, dirty=False)
1699
1857
@needs_tree_write_lock
1700
1858
def set_last_revision(self, new_revision):
1701
1859
"""Change the last revision in the working tree."""
1702
new_revision = osutils.safe_revision_id(new_revision)
1703
1860
if self._change_last_revision(new_revision):
1704
1861
self._cache_basis_inventory(new_revision)
1706
1863
def _change_last_revision(self, new_revision):
1707
1864
"""Template method part of set_last_revision to perform the change.
1709
1866
This is used to allow WorkingTree3 instances to not affect branch
1710
1867
when their last revision is set.
1722
1879
def _write_basis_inventory(self, xml):
1723
1880
"""Write the basis inventory XML to the basis-inventory file"""
1724
assert isinstance(xml, str), 'serialised xml must be bytestring.'
1725
1881
path = self._basis_inventory_name()
1726
1882
sio = StringIO(xml)
1727
self._control_files.put(path, sio)
1883
self._transport.put_file(path, sio,
1884
mode=self.bzrdir._get_file_mode())
1729
1886
def _create_basis_xml_from_inventory(self, revision_id, inventory):
1730
1887
"""Create the text that will be saved in basis-inventory"""
1731
# TODO: jam 20070209 This should be redundant, as the revision_id
1732
# as all callers should have already converted the revision_id to
1734
inventory.revision_id = osutils.safe_revision_id(revision_id)
1888
inventory.revision_id = revision_id
1735
1889
return xml7.serializer_v7.write_inventory_to_string(inventory)
1737
1891
def _cache_basis_inventory(self, new_revision):
1740
1894
# as commit already has that ready-to-use [while the format is the
1741
1895
# same, that is].
1743
# this double handles the inventory - unpack and repack -
1897
# this double handles the inventory - unpack and repack -
1744
1898
# but is easier to understand. We can/should put a conditional
1745
1899
# in here based on whether the inventory is in the latest format
1746
1900
# - perhaps we should repack all inventories on a repository
1748
1902
# the fast path is to copy the raw xml from the repository. If the
1749
# xml contains 'revision_id="', then we assume the right
1903
# xml contains 'revision_id="', then we assume the right
1750
1904
# revision_id is set. We must check for this full string, because a
1751
1905
# root node id can legitimately look like 'revision_id' but cannot
1752
1906
# contain a '"'.
1753
1907
xml = self.branch.repository.get_inventory_xml(new_revision)
1754
1908
firstline = xml.split('\n', 1)[0]
1755
if (not 'revision_id="' in firstline or
1909
if (not 'revision_id="' in firstline or
1756
1910
'format="7"' not in firstline):
1757
inv = self.branch.repository.deserialise_inventory(
1911
inv = self.branch.repository._serializer.read_inventory_from_string(
1759
1913
xml = self._create_basis_xml_from_inventory(new_revision, inv)
1760
1914
self._write_basis_inventory(xml)
1761
1915
except (errors.NoSuchRevision, errors.RevisionNotPresent):
1764
1918
def read_basis_inventory(self):
1765
1919
"""Read the cached basis inventory."""
1766
1920
path = self._basis_inventory_name()
1767
return self._control_files.get(path).read()
1921
return self._transport.get_bytes(path)
1769
1923
@needs_read_lock
1770
1924
def read_working_inventory(self):
1771
1925
"""Read the working inventory.
1773
1927
:raises errors.InventoryModified: read_working_inventory will fail
1774
1928
when the current in memory inventory has been modified.
1776
# conceptually this should be an implementation detail of the tree.
1930
# conceptually this should be an implementation detail of the tree.
1777
1931
# XXX: Deprecate this.
1778
1932
# ElementTree does its own conversion from UTF-8, so open in
1780
1934
if self._inventory_is_modified:
1781
1935
raise errors.InventoryModified(self)
1782
result = self._deserialize(self._control_files.get('inventory'))
1936
f = self._transport.get('inventory')
1938
result = self._deserialize(f)
1783
1941
self._set_inventory(result, dirty=False)
1793
1951
:force: Delete files and directories, even if they are changed and
1794
1952
even if the directories are not empty.
1796
## TODO: Normalize names
1798
1954
if isinstance(files, basestring):
1799
1955
files = [files]
1803
1959
new_files=set()
1804
unknown_files_in_directory=set()
1960
unknown_nested_files=set()
1962
to_file = sys.stdout
1806
1964
def recurse_directory_to_add_files(directory):
1807
# recurse directory and add all files
1965
# Recurse directory and add all files
1808
1966
# so we can check if they have changed.
1809
1967
for parent_info, file_infos in\
1810
osutils.walkdirs(self.abspath(directory),
1812
for relpath, basename, kind, lstat, abspath in file_infos:
1814
if self.path2id(relpath): #is it versioned?
1815
new_files.add(relpath)
1817
unknown_files_in_directory.add(
1818
(relpath, None, kind))
1968
self.walkdirs(directory):
1969
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1970
# Is it versioned or ignored?
1971
if self.path2id(relpath) or self.is_ignored(relpath):
1972
# Add nested content for deletion.
1973
new_files.add(relpath)
1975
# Files which are not versioned and not ignored
1976
# should be treated as unknown.
1977
unknown_nested_files.add((relpath, None, kind))
1820
1979
for filename in files:
1821
1980
# Get file name into canonical form.
1823
1982
filename = self.relpath(abspath)
1824
1983
if len(filename) > 0:
1825
1984
new_files.add(filename)
1826
if osutils.isdir(abspath):
1827
recurse_directory_to_add_files(filename)
1828
files = [f for f in new_files]
1985
recurse_directory_to_add_files(filename)
1987
files = list(new_files)
1830
1989
if len(files) == 0:
1831
1990
return # nothing to do
1833
1992
# Sort needed to first handle directory content before the directory
1834
1993
files.sort(reverse=True)
1995
# Bail out if we are going to delete files we shouldn't
1835
1996
if not keep_files and not force:
1836
has_changed_files = len(unknown_files_in_directory) > 0
1997
has_changed_files = len(unknown_nested_files) > 0
1837
1998
if not has_changed_files:
1838
1999
for (file_id, path, content_change, versioned, parent_id, name,
1839
kind, executable) in self._iter_changes(self.basis_tree(),
2000
kind, executable) in self.iter_changes(self.basis_tree(),
1840
2001
include_unchanged=True, require_versioned=False,
1841
2002
want_unversioned=True, specific_files=files):
1842
# check if it's unknown OR changed but not deleted:
1843
if (versioned == (False, False)
1844
or (content_change and kind[1] != None)):
2003
if versioned == (False, False):
2004
# The record is unknown ...
2005
if not self.is_ignored(path[1]):
2006
# ... but not ignored
2007
has_changed_files = True
2009
elif content_change and (kind[1] is not None):
2010
# Versioned and changed, but not deleted
1845
2011
has_changed_files = True
1848
2014
if has_changed_files:
1849
# make delta to show ALL applicable changes in error message.
2015
# Make delta show ALL applicable changes in error message.
1850
2016
tree_delta = self.changes_from(self.basis_tree(),
2017
require_versioned=False, want_unversioned=True,
1851
2018
specific_files=files)
1852
for unknown_file in unknown_files_in_directory:
1853
tree_delta.unversioned.extend((unknown_file,))
2019
for unknown_file in unknown_nested_files:
2020
if unknown_file not in tree_delta.unversioned:
2021
tree_delta.unversioned.extend((unknown_file,))
1854
2022
raise errors.BzrRemoveChangedFilesError(tree_delta)
1856
# do this before any modifications
2024
# Build inv_delta and delete files where applicable,
2025
# do this before any modifications to inventory.
1857
2026
for f in files:
1858
2027
fid = self.path2id(f)
1861
message="%s is not versioned." % (f,)
2030
message = "%s is not versioned." % (f,)
1864
2033
# having removed it, it must be either ignored or unknown
1866
2035
new_status = 'I'
1868
2037
new_status = '?'
1869
textui.show_status(new_status, self.kind(fid), f,
2038
# XXX: Really should be a more abstract reporter interface
2039
kind_ch = osutils.kind_marker(self.kind(fid))
2040
to_file.write(new_status + ' ' + f + kind_ch + '\n')
1872
2042
inv_delta.append((f, None, fid, None))
1873
message="removed %s" % (f,)
2043
message = "removed %s" % (f,)
1875
2045
if not keep_files:
1876
2046
abs_path = self.abspath(f)
1877
2047
if osutils.lexists(abs_path):
1878
2048
if (osutils.isdir(abs_path) and
1879
2049
len(os.listdir(abs_path)) > 0):
1880
message="%s is not empty directory "\
1881
"and won't be deleted." % (f,)
2051
osutils.rmtree(abs_path)
2053
message = "%s is not an empty directory "\
2054
"and won't be deleted." % (f,)
1883
2056
osutils.delete_any(abs_path)
1884
message="deleted %s" % (f,)
2057
message = "deleted %s" % (f,)
1885
2058
elif message is not None:
1886
# only care if we haven't done anything yet.
1887
message="%s does not exist." % (f,)
2059
# Only care if we haven't done anything yet.
2060
message = "%s does not exist." % (f,)
1889
# print only one message (if any) per file.
2062
# Print only one message (if any) per file.
1890
2063
if message is not None:
1892
2065
self.apply_inventory_delta(inv_delta)
1894
2067
@needs_tree_write_lock
1895
def revert(self, filenames, old_tree=None, backups=True,
2068
def revert(self, filenames=None, old_tree=None, backups=True,
1896
2069
pb=DummyProgress(), report_changes=False):
1897
2070
from bzrlib.conflicts import resolve
2073
symbol_versioning.warn('Using [] to revert all files is deprecated'
2074
' as of bzr 0.91. Please use None (the default) instead.',
2075
DeprecationWarning, stacklevel=2)
1898
2076
if old_tree is None:
1899
old_tree = self.basis_tree()
1900
conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1902
if not len(filenames):
1903
self.set_parent_ids(self.get_parent_ids()[:1])
2077
basis_tree = self.basis_tree()
2078
basis_tree.lock_read()
2079
old_tree = basis_tree
1906
resolve(self, filenames, ignore_misses=True)
2083
conflicts = transform.revert(self, old_tree, filenames, backups, pb,
2085
if filenames is None and len(self.get_parent_ids()) > 1:
2087
last_revision = self.last_revision()
2088
if last_revision != _mod_revision.NULL_REVISION:
2089
if basis_tree is None:
2090
basis_tree = self.basis_tree()
2091
basis_tree.lock_read()
2092
parent_trees.append((last_revision, basis_tree))
2093
self.set_parent_trees(parent_trees)
2096
resolve(self, filenames, ignore_misses=True, recursive=True)
2098
if basis_tree is not None:
1907
2100
return conflicts
1909
2102
def revision_tree(self, revision_id):
1958
2150
@needs_tree_write_lock
1959
2151
def set_root_id(self, file_id):
1960
2152
"""Set the root id for this tree."""
1962
2154
if file_id is None:
1963
symbol_versioning.warn(symbol_versioning.zero_twelve
1964
% 'WorkingTree.set_root_id with fileid=None',
1969
file_id = osutils.safe_file_id(file_id)
2156
'WorkingTree.set_root_id with fileid=None')
2157
file_id = osutils.safe_file_id(file_id)
1970
2158
self._set_root_id(file_id)
1972
2160
def _set_root_id(self, file_id):
1973
2161
"""Set the root id for this tree, in a format specific manner.
1975
:param file_id: The file id to assign to the root. It must not be
2163
:param file_id: The file id to assign to the root. It must not be
1976
2164
present in the current inventory or an error will occur. It must
1977
2165
not be None, but rather a valid file id.
1998
2186
def unlock(self):
1999
2187
"""See Branch.unlock.
2001
2189
WorkingTree locking just uses the Branch locking facilities.
2002
2190
This is current because all working trees have an embedded branch
2003
2191
within them. IF in the future, we were to make branch data shareable
2004
between multiple working trees, i.e. via shared storage, then we
2192
between multiple working trees, i.e. via shared storage, then we
2005
2193
would probably want to lock both the local tree, and the branch.
2007
2195
raise NotImplementedError(self.unlock)
2009
def update(self, change_reporter=None):
2199
def update(self, change_reporter=None, possible_transports=None,
2200
revision=None, old_tip=_marker):
2010
2201
"""Update a working tree along its branch.
2012
2203
This will update the branch if its bound too, which means we have
2030
2221
- Merge current state -> basis tree of the master w.r.t. the old tree
2032
2223
- Do a 'normal' merge of the old branch basis if it is relevant.
2225
:param revision: The target revision to update to. Must be in the
2227
:param old_tip: If branch.update() has already been run, the value it
2228
returned (old tip of the branch or None). _marker is used
2034
if self.branch.get_master_branch() is not None:
2231
if self.branch.get_bound_location() is not None:
2035
2232
self.lock_write()
2036
update_branch = True
2233
update_branch = (old_tip is self._marker)
2038
2235
self.lock_tree_write()
2039
2236
update_branch = False
2041
2238
if update_branch:
2042
old_tip = self.branch.update()
2239
old_tip = self.branch.update(possible_transports)
2045
return self._update_tree(old_tip, change_reporter)
2241
if old_tip is self._marker:
2243
return self._update_tree(old_tip, change_reporter, revision)
2049
2247
@needs_tree_write_lock
2050
def _update_tree(self, old_tip=None, change_reporter=None):
2248
def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2051
2249
"""Update a tree to the master branch.
2053
2251
:param old_tip: if supplied, the previous tip revision the branch,
2059
2257
# cant set that until we update the working trees last revision to be
2060
2258
# one from the new branch, because it will just get absorbed by the
2061
2259
# parent de-duplication logic.
2063
2261
# We MUST save it even if an error occurs, because otherwise the users
2064
2262
# local work is unreferenced and will appear to have been lost.
2068
2266
last_rev = self.get_parent_ids()[0]
2069
2267
except IndexError:
2070
2268
last_rev = _mod_revision.NULL_REVISION
2071
if last_rev != _mod_revision.ensure_null(self.branch.last_revision()):
2072
# merge tree state up to new branch tip.
2269
if revision is None:
2270
revision = self.branch.last_revision()
2272
if revision not in self.branch.revision_history():
2273
raise errors.NoSuchRevision(self.branch, revision)
2274
if last_rev != _mod_revision.ensure_null(revision):
2275
# merge tree state up to specified revision.
2073
2276
basis = self.basis_tree()
2074
2277
basis.lock_read()
2076
to_tree = self.branch.basis_tree()
2077
if basis.inventory.root is None:
2078
self.set_root_id(to_tree.inventory.root.file_id)
2279
to_tree = self.branch.repository.revision_tree(revision)
2280
to_root_id = to_tree.get_root_id()
2281
if (basis.inventory.root is None
2282
or basis.inventory.root.file_id != to_root_id):
2283
self.set_root_id(to_root_id)
2080
2285
result += merge.merge_inner(
2084
2289
this_tree=self,
2085
2290
change_reporter=change_reporter)
2291
self.set_last_revision(revision)
2088
2294
# TODO - dedup parents list with things merged by pull ?
2089
2295
# reuse the tree we've updated to to set the basis:
2090
parent_trees = [(self.branch.last_revision(), to_tree)]
2296
parent_trees = [(revision, to_tree)]
2091
2297
merges = self.get_parent_ids()[1:]
2092
2298
# Ideally we ask the tree for the trees here, that way the working
2093
# tree can decide whether to give us teh entire tree or give us a
2299
# tree can decide whether to give us the entire tree or give us a
2094
2300
# lazy initialised tree. dirstate for instance will have the trees
2095
2301
# in ram already, whereas a last-revision + basis-inventory tree
2096
2302
# will not, but also does not need them when setting parents.
2223
2428
current_inv = None
2224
2429
inv_finished = True
2225
2430
while not inv_finished or not disk_finished:
2432
((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
2433
cur_disk_dir_content) = current_disk
2435
((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
2436
cur_disk_dir_content) = ((None, None), None)
2226
2437
if not disk_finished:
2227
2438
# strip out .bzr dirs
2228
if current_disk[0][1][top_strip_len:] == '':
2229
# osutils.walkdirs can be made nicer -
2439
if (cur_disk_dir_path_from_top[top_strip_len:] == '' and
2440
len(cur_disk_dir_content) > 0):
2441
# osutils.walkdirs can be made nicer -
2230
2442
# yield the path-from-prefix rather than the pathjoined
2232
bzrdir_loc = bisect_left(current_disk[1], ('.bzr', '.bzr'))
2233
if current_disk[1][bzrdir_loc][0] == '.bzr':
2444
bzrdir_loc = bisect_left(cur_disk_dir_content,
2446
if (bzrdir_loc < len(cur_disk_dir_content)
2447
and self.bzrdir.is_control_filename(
2448
cur_disk_dir_content[bzrdir_loc][0])):
2234
2449
# we dont yield the contents of, or, .bzr itself.
2235
del current_disk[1][bzrdir_loc]
2450
del cur_disk_dir_content[bzrdir_loc]
2236
2451
if inv_finished:
2237
2452
# everything is unknown
2240
2455
# everything is missing
2243
direction = cmp(current_inv[0][0], current_disk[0][0])
2458
direction = cmp(current_inv[0][0], cur_disk_dir_relpath)
2244
2459
if direction > 0:
2245
2460
# disk is before inventory - unknown
2246
2461
dirblock = [(relpath, basename, kind, stat, None, None) for
2247
relpath, basename, kind, stat, top_path in current_disk[1]]
2248
yield (current_disk[0][0], None), dirblock
2462
relpath, basename, kind, stat, top_path in
2463
cur_disk_dir_content]
2464
yield (cur_disk_dir_relpath, None), dirblock
2250
2466
current_disk = disk_iterator.next()
2251
2467
except StopIteration:
2253
2469
elif direction < 0:
2254
2470
# inventory is before disk - missing.
2255
2471
dirblock = [(relpath, basename, 'unknown', None, fileid, kind)
2256
for relpath, basename, dkind, stat, fileid, kind in
2472
for relpath, basename, dkind, stat, fileid, kind in
2257
2473
current_inv[1]]
2258
2474
yield (current_inv[0][0], current_inv[0][1]), dirblock
2265
2481
# merge the inventory and disk data together
2267
2483
for relpath, subiterator in itertools.groupby(sorted(
2268
current_inv[1] + current_disk[1], key=operator.itemgetter(0)), operator.itemgetter(1)):
2484
current_inv[1] + cur_disk_dir_content,
2485
key=operator.itemgetter(0)), operator.itemgetter(1)):
2269
2486
path_elements = list(subiterator)
2270
2487
if len(path_elements) == 2:
2271
2488
inv_row, disk_row = path_elements
2325
2542
# FIXME: stash the node in pending
2326
2543
entry = inv[top_id]
2327
for name, child in entry.sorted_children():
2328
dirblock.append((relroot + name, name, child.kind, None,
2329
child.file_id, child.kind
2544
if entry.kind == 'directory':
2545
for name, child in entry.sorted_children():
2546
dirblock.append((relroot + name, name, child.kind, None,
2547
child.file_id, child.kind
2331
2549
yield (currentdir[0], entry.file_id), dirblock
2332
2550
# push the user specified dirs from dirblock
2333
2551
for dir in reversed(dirblock):
2366
2584
self.set_conflicts(un_resolved)
2367
2585
return un_resolved, resolved
2588
def _check(self, references):
2589
"""Check the tree for consistency.
2591
:param references: A dict with keys matching the items returned by
2592
self._get_check_refs(), and values from looking those keys up in
2595
tree_basis = self.basis_tree()
2596
tree_basis.lock_read()
2598
repo_basis = references[('trees', self.last_revision())]
2599
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2600
raise errors.BzrCheckError(
2601
"Mismatched basis inventory content.")
2369
2606
def _validate(self):
2370
2607
"""Validate internal structures.
2617
def _get_rules_searcher(self, default_searcher):
2618
"""See Tree._get_rules_searcher."""
2619
if self._rules_searcher is None:
2620
self._rules_searcher = super(WorkingTree,
2621
self)._get_rules_searcher(default_searcher)
2622
return self._rules_searcher
2624
def get_shelf_manager(self):
2625
"""Return the ShelfManager for this WorkingTree."""
2626
from bzrlib.shelf import ShelfManager
2627
return ShelfManager(self, self._transport)
2381
2630
class WorkingTree2(WorkingTree):
2382
2631
"""This is the Format 2 working tree.
2384
This was the first weave based working tree.
2633
This was the first weave based working tree.
2385
2634
- uses os locks for locking.
2386
2635
- uses the branch last-revision.
2442
2695
def _last_revision(self):
2443
2696
"""See Mutable.last_revision."""
2445
return osutils.safe_revision_id(
2446
self._control_files.get('last-revision').read())
2698
return self._transport.get_bytes('last-revision')
2447
2699
except errors.NoSuchFile:
2448
2700
return _mod_revision.NULL_REVISION
2450
2702
def _change_last_revision(self, revision_id):
2451
2703
"""See WorkingTree._change_last_revision."""
2452
if revision_id is None or revision_id == NULL_REVISION:
2704
if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2454
self._control_files._transport.delete('last-revision')
2706
self._transport.delete('last-revision')
2455
2707
except errors.NoSuchFile:
2459
self._control_files.put_bytes('last-revision', revision_id)
2711
self._transport.put_bytes('last-revision', revision_id,
2712
mode=self.bzrdir._get_file_mode())
2715
def _get_check_refs(self):
2716
"""Return the references needed to perform a check of this tree."""
2717
return [('trees', self.last_revision())]
2462
2719
@needs_tree_write_lock
2463
2720
def set_conflicts(self, conflicts):
2464
self._put_rio('conflicts', conflicts.to_stanzas(),
2721
self._put_rio('conflicts', conflicts.to_stanzas(),
2465
2722
CONFLICT_HEADER_1)
2467
2724
@needs_tree_write_lock
2474
2731
@needs_read_lock
2475
2732
def conflicts(self):
2477
confile = self._control_files.get('conflicts')
2734
confile = self._transport.get('conflicts')
2478
2735
except errors.NoSuchFile:
2479
2736
return _mod_conflicts.ConflictList()
2481
if confile.next() != CONFLICT_HEADER_1 + '\n':
2739
if confile.next() != CONFLICT_HEADER_1 + '\n':
2740
raise errors.ConflictFormatError()
2741
except StopIteration:
2482
2742
raise errors.ConflictFormatError()
2483
except StopIteration:
2484
raise errors.ConflictFormatError()
2485
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2743
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2487
2747
def unlock(self):
2488
2748
# do non-implementation specific cleanup
2505
2765
return path[:-len(suffix)]
2508
@deprecated_function(zero_eight)
2509
def is_control_file(filename):
2510
"""See WorkingTree.is_control_filename(filename)."""
2511
## FIXME: better check
2512
filename = normpath(filename)
2513
while filename != '':
2514
head, tail = os.path.split(filename)
2515
## mutter('check %r for control file' % ((head, tail),))
2518
if filename == head:
2524
2768
class WorkingTreeFormat(object):
2525
2769
"""An encapsulation of the initialization and open routines for a format.
2529
2773
* a format string,
2530
2774
* an open routine.
2532
Formats are placed in an dict by their format string for reference
2776
Formats are placed in an dict by their format string for reference
2533
2777
during workingtree opening. Its not required that these be instances, they
2534
can be classes themselves with class methods - it simply depends on
2778
can be classes themselves with class methods - it simply depends on
2535
2779
whether state is needed for a given format or not.
2537
2781
Once a format is deprecated, just deprecate the initialize and open
2538
methods on the format class. Do not deprecate the object, as the
2782
methods on the format class. Do not deprecate the object, as the
2539
2783
object will be created every time regardless.
2554
2798
"""Return the format for the working tree object in a_bzrdir."""
2556
2800
transport = a_bzrdir.get_workingtree_transport(None)
2557
format_string = transport.get("format").read()
2801
format_string = transport.get_bytes("format")
2558
2802
return klass._formats[format_string]
2559
2803
except errors.NoSuchFile:
2560
2804
raise errors.NoWorkingTree(base=transport.base)
2561
2805
except KeyError:
2562
raise errors.UnknownFormatError(format=format_string)
2806
raise errors.UnknownFormatError(format=format_string,
2807
kind="working tree")
2564
2809
def __eq__(self, other):
2565
2810
return self.__class__ is other.__class__
2584
2829
"""Is this format supported?
2586
2831
Supported formats can be initialized and opened.
2587
Unsupported formats may not support initialization or committing or
2832
Unsupported formats may not support initialization or committing or
2588
2833
some other features depending on the reason for not being supported.
2837
def supports_content_filtering(self):
2838
"""True if this format supports content filtering."""
2841
def supports_views(self):
2842
"""True if this format supports stored views."""
2593
2846
def register_format(klass, format):
2594
2847
klass._formats[format.get_format_string()] = format
2615
2867
"""See WorkingTreeFormat.get_format_description()."""
2616
2868
return "Working tree format 2"
2618
def stub_initialize_remote(self, control_files):
2619
"""As a special workaround create critical control files for a remote working tree
2870
def _stub_initialize_on_transport(self, transport, file_mode):
2871
"""Workaround: create control files for a remote working tree.
2621
2873
This ensures that it can later be updated and dealt with locally,
2622
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2874
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2623
2875
no working tree. (See bug #43064).
2625
2877
sio = StringIO()
2627
xml5.serializer_v5.write_inventory(inv, sio)
2878
inv = inventory.Inventory()
2879
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2629
control_files.put('inventory', sio)
2631
control_files.put_bytes('pending-merges', '')
2634
def initialize(self, a_bzrdir, revision_id=None):
2881
transport.put_file('inventory', sio, file_mode)
2882
transport.put_bytes('pending-merges', '', file_mode)
2884
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2885
accelerator_tree=None, hardlink=False):
2635
2886
"""See WorkingTreeFormat.initialize()."""
2636
2887
if not isinstance(a_bzrdir.transport, LocalTransport):
2637
2888
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2638
branch = a_bzrdir.open_branch()
2889
if from_branch is not None:
2890
branch = from_branch
2892
branch = a_bzrdir.open_branch()
2639
2893
if revision_id is None:
2640
2894
revision_id = _mod_revision.ensure_null(branch.last_revision())
2642
revision_id = osutils.safe_revision_id(revision_id)
2643
2895
branch.lock_write()
2645
2897
branch.generate_revision_history(revision_id)
2647
2899
branch.unlock()
2900
inv = inventory.Inventory()
2649
2901
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2720
2972
def _open_control_files(self, a_bzrdir):
2721
2973
transport = a_bzrdir.get_workingtree_transport(None)
2722
return LockableFiles(transport, self._lock_file_name,
2974
return LockableFiles(transport, self._lock_file_name,
2723
2975
self._lock_class)
2725
def initialize(self, a_bzrdir, revision_id=None):
2977
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2978
accelerator_tree=None, hardlink=False):
2726
2979
"""See WorkingTreeFormat.initialize().
2728
revision_id allows creating a working tree at a different
2729
revision than the branch is at.
2981
:param revision_id: if supplied, create a working tree at a different
2982
revision than the branch is at.
2983
:param accelerator_tree: A tree which can be used for retrieving file
2984
contents more quickly than the revision tree, i.e. a workingtree.
2985
The revision tree will be used for cases where accelerator_tree's
2986
content is different.
2987
:param hardlink: If true, hard-link files from accelerator_tree,
2731
2990
if not isinstance(a_bzrdir.transport, LocalTransport):
2732
2991
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2734
2993
control_files = self._open_control_files(a_bzrdir)
2735
2994
control_files.create_lock()
2736
2995
control_files.lock_write()
2737
control_files.put_utf8('format', self.get_format_string())
2738
branch = a_bzrdir.open_branch()
2996
transport.put_bytes('format', self.get_format_string(),
2997
mode=a_bzrdir._get_file_mode())
2998
if from_branch is not None:
2999
branch = from_branch
3001
branch = a_bzrdir.open_branch()
2739
3002
if revision_id is None:
2740
3003
revision_id = _mod_revision.ensure_null(branch.last_revision())
2742
revision_id = osutils.safe_revision_id(revision_id)
2743
3004
# WorkingTree3 can handle an inventory which has a unique root id.
2744
3005
# as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
2745
3006
# those trees. And because there isn't a format bump inbetween, we