35
35
from bzrlib.decorators import needs_read_lock
36
from bzrlib.errors import BzrError, BzrCheckError
36
from bzrlib.errors import BzrError, BzrCheckError, NoSuchId
37
37
from bzrlib import errors
38
38
from bzrlib.inventory import Inventory, InventoryFile
39
39
from bzrlib.inter import InterObject
62
62
Trees can be compared, etc, regardless of whether they are working
63
63
trees or versioned trees.
66
66
def changes_from(self, other, want_unchanged=False, specific_files=None,
67
67
extra_trees=None, require_versioned=False, include_root=False,
68
68
want_unversioned=False):
82
82
a PathsNotVersionedError will be thrown.
83
83
:param want_unversioned: Scan for unversioned paths.
85
The comparison will be performed by an InterTree object looked up on
85
The comparison will be performed by an InterTree object looked up on
88
88
# Martin observes that Tree.changes_from returns a TreeDelta and this
107
107
intertree = InterTree.get(from_tree, self)
108
108
return intertree.iter_changes(include_unchanged, specific_files, pb,
109
109
extra_trees, require_versioned, want_unversioned=want_unversioned)
111
111
def conflicts(self):
112
112
"""Get a list of the conflicts in the tree.
122
122
def get_parent_ids(self):
123
"""Get the parent ids for this tree.
123
"""Get the parent ids for this tree.
125
125
:return: a list of parent ids. [] is returned to indicate
126
126
a tree with no parents.
127
127
:raises: BzrError if the parents are not known.
129
129
raise NotImplementedError(self.get_parent_ids)
131
131
def has_filename(self, filename):
132
132
"""True if the tree has given filename."""
133
133
raise NotImplementedError(self.has_filename)
225
225
def path_content_summary(self, path):
226
226
"""Get a summary of the information about path.
228
228
:param path: A relative path within the tree.
229
229
:return: A tuple containing kind, size, exec, sha1-or-link.
230
230
Kind is always present (see tree.kind()).
258
258
def _get_inventory(self):
259
259
return self._inventory
261
261
def get_file(self, file_id, path=None):
262
262
"""Return a file object for the file file_id in the tree.
264
264
If both file_id and path are defined, it is implementation defined as
265
265
to which one is used.
348
348
raise NotImplementedError(self.get_symlink_target)
350
def get_canonical_inventory_paths(self, paths):
351
"""Like get_canonical_inventory_path() but works on multiple items.
353
:param paths: A sequence of paths relative to the root of the tree.
354
:return: A list of paths, with each item the corresponding input path
355
adjusted to account for existing elements that match case
358
return list(self._yield_canonical_inventory_paths(paths))
360
def get_canonical_inventory_path(self, path):
361
"""Returns the first inventory item that case-insensitively matches path.
363
If a path matches exactly, it is returned. If no path matches exactly
364
but more than one path matches case-insensitively, it is implementation
365
defined which is returned.
367
If no path matches case-insensitively, the input path is returned, but
368
with as many path entries that do exist changed to their canonical
371
If you need to resolve many names from the same tree, you should
372
use get_canonical_inventory_paths() to avoid O(N) behaviour.
374
:param path: A paths relative to the root of the tree.
375
:return: The input path adjusted to account for existing elements
376
that match case insensitively.
378
return self._yield_canonical_inventory_paths([path]).next()
380
def _yield_canonical_inventory_paths(self, paths):
382
# First, if the path as specified exists exactly, just use it.
383
if self.path2id(path) is not None:
387
cur_id = self.get_root_id()
389
bit_iter = iter(path.split("/"))
392
for child in self.iter_children(cur_id):
394
child_base = os.path.basename(self.id2path(child))
395
if child_base.lower() == lelt:
397
cur_path = osutils.pathjoin(cur_path, child_base)
400
# before a change is committed we can see this error...
403
# got to the end of this directory and no entries matched.
404
# Return what matched so far, plus the rest as specified.
405
cur_path = osutils.pathjoin(cur_path, elt, *list(bit_iter))
350
410
def get_root_id(self):
351
411
"""Return the file_id for the root of this tree."""
352
412
raise NotImplementedError(self.get_root_id)
443
503
def _check_retrieved(self, ie, f):
444
504
if not __debug__:
446
506
fp = fingerprint_file(f)
449
509
if ie.text_size is not None:
450
510
if ie.text_size != fp['size']:
451
511
raise BzrError("mismatched size for file %r in %r" % (ie.file_id, self._store),
467
527
def paths2ids(self, paths, trees=[], require_versioned=True):
468
528
"""Return all the ids that can be reached by walking from paths.
470
530
Each path is looked up in this tree and any extras provided in
471
531
trees, and this is repeated recursively: the children in an extra tree
472
532
of a directory that has been renamed under a provided path in this tree
503
563
The intention of this method is to allow access to possibly cached
504
564
tree data. Implementors of this method should raise NoSuchRevision if
505
the tree is not locally available, even if they could obtain the
506
tree via a repository or some other means. Callers are responsible
565
the tree is not locally available, even if they could obtain the
566
tree via a repository or some other means. Callers are responsible
507
567
for finding the ultimate source for a revision tree.
509
569
:param revision_id: The revision_id of the requested tree.
528
588
:return: set of paths.
530
590
# NB: we specifically *don't* call self.has_filename, because for
531
# WorkingTrees that can indicate files that exist on disk but that
591
# WorkingTrees that can indicate files that exist on disk but that
532
592
# are not versioned.
533
593
pred = self.inventory.has_filename
534
594
return set((p for p in paths if not pred(p)))
539
599
This yields all the data about the contents of a directory at a time.
540
600
After each directory has been yielded, if the caller has mutated the
541
601
list to exclude some directories, they are then not descended into.
543
603
The data yielded is of the form:
544
604
((directory-relpath, directory-path-from-root, directory-fileid),
545
[(relpath, basename, kind, lstat, path_from_tree_root, file_id,
605
[(relpath, basename, kind, lstat, path_from_tree_root, file_id,
546
606
versioned_kind), ...]),
547
607
- directory-relpath is the containing dirs relpath from prefix
548
608
- directory-path-from-root is the containing dirs path from /
555
615
- lstat is the stat data *if* the file was statted.
556
616
- path_from_tree_root is the path from the root of the tree.
557
617
- file_id is the file_id if the entry is versioned.
558
- versioned_kind is the kind of the file as last recorded in the
618
- versioned_kind is the kind of the file as last recorded in the
559
619
versioning system. If 'unknown' the file is not versioned.
560
620
One of 'kind' and 'versioned_kind' must not be 'unknown'.
572
632
def _content_filter_stack(self, path=None, file_id=None):
573
633
"""The stack of content filters for a path if filtering is supported.
575
635
Readers will be applied in first-to-last order.
576
636
Writers will be applied in last-to-first order.
577
637
Either the path or the file-id needs to be provided.
730
790
def find_ids_across_trees(filenames, trees, require_versioned=True):
731
791
"""Find the ids corresponding to specified filenames.
733
793
All matches in all trees will be used, and all children of matched
734
794
directories will be used.
750
810
def _find_ids_across_trees(filenames, trees, require_versioned):
751
811
"""Find the ids corresponding to specified filenames.
753
813
All matches in all trees will be used, but subdirectories are not scanned.
755
815
:param filenames: The filenames to find file_ids for
777
837
def _find_children_across_trees(specified_ids, trees):
778
838
"""Return a set including specified ids and their children.
780
840
All matches in all trees will be used.
782
842
:param trees: The trees to find file_ids within
783
:return: a set containing all specified ids and their children
843
:return: a set containing all specified ids and their children
785
845
interesting_ids = set(specified_ids)
786
846
pending = interesting_ids
910
970
specific_file_ids=specific_file_ids))
911
971
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
913
# the unversioned path lookup only occurs on real trees - where there
973
# the unversioned path lookup only occurs on real trees - where there
914
974
# can be extras. So the fake_entry is solely used to look up
915
975
# executable it values when execute is not supported.
916
976
fake_entry = InventoryFile('unused', 'unused', 'unused')
960
1020
elif from_kind == 'tree-reference':
961
1021
if (self.source.get_reference_revision(file_id, from_path)
962
1022
!= self.target.get_reference_revision(file_id, to_path)):
963
changed_content = True
1023
changed_content = True
964
1024
parent = (from_parent, to_entry.parent_id)
965
1025
name = (from_name, to_entry.name)
966
1026
executable = (from_executable, to_executable)
967
1027
if pb is not None:
968
1028
pb.update('comparing files', entry_count, num_entries)
969
1029
if (changed_content is not False or versioned[0] != versioned[1]
970
or parent[0] != parent[1] or name[0] != name[1] or
1030
or parent[0] != parent[1] or name[0] != name[1] or
971
1031
executable[0] != executable[1] or include_unchanged):
972
1032
yield (file_id, (from_path, to_path), changed_content,
973
1033
versioned, parent, name, kind, executable)
1143
1203
def _walk_master_tree(self):
1144
1204
"""First pass, walk all trees in lock-step.
1146
1206
When we are done, all nodes in the master_tree will have been
1147
1207
processed. _other_walkers, _other_entries, and _others_extra will be
1148
1208
set on 'self' for future processing.