123
121
def has_filename(self, filename):
124
122
"""True if the tree has given filename."""
125
raise NotImplementedError(self.has_filename)
123
raise NotImplementedError()
127
125
def has_id(self, file_id):
126
file_id = osutils.safe_file_id(file_id)
128
127
return self.inventory.has_id(file_id)
130
129
__contains__ = has_id
132
131
def has_or_had_id(self, file_id):
132
file_id = osutils.safe_file_id(file_id)
133
133
if file_id == self.inventory.root.file_id:
135
135
return self.inventory.has_id(file_id)
185
186
raise NotImplementedError("Tree subclass %s must implement kind"
186
187
% self.__class__.__name__)
188
def path_content_summary(self, path):
189
"""Get a summary of the information about path.
191
:param path: A relative path within the tree.
192
:return: A tuple containing kind, size, exec, sha1-or-link.
193
Kind is always present (see tree.kind()).
194
size is present if kind is file, None otherwise.
195
exec is None unless kind is file and the platform supports the 'x'
197
sha1-or-link is the link target if kind is symlink, or the sha1 if
198
it can be obtained without reading the file.
200
raise NotImplementedError(self.path_content_summary)
202
189
def get_reference_revision(self, file_id, path=None):
203
190
raise NotImplementedError("Tree subclass %s must implement "
204
191
"get_reference_revision"
221
208
def _get_inventory(self):
222
209
return self._inventory
224
def get_file(self, file_id, path=None):
225
"""Return a file object for the file file_id in the tree.
227
If both file_id and path are defined, it is implementation defined as
228
to which one is used.
211
def get_file(self, file_id):
212
"""Return a file object for the file file_id in the tree."""
230
213
raise NotImplementedError(self.get_file)
232
215
def get_file_mtime(self, file_id, path=None):
239
222
raise NotImplementedError(self.get_file_mtime)
241
224
def get_file_by_path(self, path):
242
return self.get_file(self._inventory.path2id(path), path)
244
def iter_files_bytes(self, desired_files):
245
"""Iterate through file contents.
247
Files will not necessarily be returned in the order they occur in
248
desired_files. No specific order is guaranteed.
250
Yields pairs of identifier, bytes_iterator. identifier is an opaque
251
value supplied by the caller as part of desired_files. It should
252
uniquely identify the file version in the caller's context. (Examples:
253
an index number or a TreeTransform trans_id.)
255
bytes_iterator is an iterable of bytestrings for the file. The
256
kind of iterable and length of the bytestrings are unspecified, but for
257
this implementation, it is a tuple containing a single bytestring with
258
the complete text of the file.
260
:param desired_files: a list of (file_id, identifier) pairs
262
for file_id, identifier in desired_files:
263
# We wrap the string in a tuple so that we can return an iterable
264
# of bytestrings. (Technically, a bytestring is also an iterable
265
# of bytestrings, but iterating through each character is not
267
cur_file = (self.get_file_text(file_id),)
268
yield identifier, cur_file
225
return self.get_file(self._inventory.path2id(path))
270
227
def get_symlink_target(self, file_id):
271
228
"""Get the target for a given file_id.
278
235
raise NotImplementedError(self.get_symlink_target)
280
def get_root_id(self):
281
"""Return the file_id for the root of this tree."""
282
raise NotImplementedError(self.get_root_id)
284
237
def annotate_iter(self, file_id):
285
"""Return an iterator of revision_id, line tuples.
238
"""Return an iterator of revision_id, line tuples
287
240
For working trees (and mutable trees in general), the special
288
241
revision_id 'current:' will be used for lines that are new in this
292
245
raise NotImplementedError(self.annotate_iter)
294
def plan_file_merge(self, file_id, other, base=None):
295
"""Generate a merge plan based on annotations.
297
If the file contains uncommitted changes in this tree, they will be
298
attributed to the 'current:' pseudo-revision. If the file contains
299
uncommitted changes in the other tree, they will be assigned to the
300
'other:' pseudo-revision.
302
from bzrlib import merge, versionedfile
303
vf = versionedfile._PlanMergeVersionedFile(file_id)
304
last_revision_a = self._get_file_revision(file_id, vf, 'this:')
305
last_revision_b = other._get_file_revision(file_id, vf, 'other:')
307
last_revision_base = None
309
last_revision_base = base._get_file_revision(file_id, vf, 'base:')
310
return vf.plan_merge(last_revision_a, last_revision_b,
313
def _get_file_revision(self, file_id, vf, tree_revision):
314
def file_revision(revision_tree):
315
revision_tree.lock_read()
317
return revision_tree.inventory[file_id].revision
319
revision_tree.unlock()
321
def iter_parent_trees():
322
for revision_id in self.get_parent_ids():
324
yield self.revision_tree(revision_id)
326
yield self.repository.revision_tree(revision_id)
328
if getattr(self, '_get_weave', None) is None:
329
last_revision = tree_revision
330
parent_revisions = [file_revision(t) for t in iter_parent_trees()]
331
vf.add_lines(last_revision, parent_revisions,
332
self.get_file(file_id).readlines())
333
repo = self.branch.repository
334
transaction = repo.get_transaction()
335
base_vf = repo.weave_store.get_weave(file_id, transaction)
337
last_revision = file_revision(self)
338
base_vf = self._get_weave(file_id)
339
vf.fallback_versionedfiles.append(base_vf)
342
247
inventory = property(_get_inventory,
343
248
doc="Inventory of this Tree")
369
274
def paths2ids(self, paths, trees=[], require_versioned=True):
370
275
"""Return all the ids that can be reached by walking from paths.
372
Each path is looked up in this tree and any extras provided in
277
Each path is looked up in each this tree and any extras provided in
373
278
trees, and this is repeated recursively: the children in an extra tree
374
279
of a directory that has been renamed under a provided path in this tree
375
are all returned, even if none exist under a provided path in this
280
are all returned, even if none exist until a provided path in this
376
281
tree, and vice versa.
378
283
:param paths: An iterable of paths to start converting to ids from.
451
357
- lstat is the stat data *if* the file was statted.
452
358
- path_from_tree_root is the path from the root of the tree.
453
- file_id is the file_id if the entry is versioned.
359
- file_id is the file_id is the entry is versioned.
454
360
- versioned_kind is the kind of the file as last recorded in the
455
361
versioning system. If 'unknown' the file is not versioned.
456
362
One of 'kind' and 'versioned_kind' must not be 'unknown'.
490
397
def __contains__(self, file_id):
398
file_id = osutils.safe_file_id(file_id)
491
399
return (file_id in self._inventory)
493
401
def get_file_sha1(self, file_id, path=None, stat_value=None):
639
547
Its instances have methods like 'compare' and contain references to the
640
548
source and target trees these operations are to be carried out on.
642
Clients of bzrlib should not need to use InterTree directly, rather they
550
clients of bzrlib should not need to use InterTree directly, rather they
643
551
should use the convenience methods on Tree such as 'Tree.compare()' which
644
552
will pass through to InterTree as appropriate.
686
594
return delta._compare_trees(self.source, self.target, want_unchanged,
687
595
specific_files, include_root, extra_trees=extra_trees,
688
require_versioned=require_versioned,
689
596
want_unversioned=want_unversioned)
691
598
def _iter_changes(self, include_unchanged=False,
722
629
lookup_trees = [self.source]
724
631
lookup_trees.extend(extra_trees)
725
if specific_files == []:
726
specific_file_ids = []
728
specific_file_ids = self.target.paths2ids(specific_files,
729
lookup_trees, require_versioned=require_versioned)
632
specific_file_ids = self.target.paths2ids(specific_files,
633
lookup_trees, require_versioned=require_versioned)
730
634
if want_unversioned:
731
all_unversioned = sorted([(p.split('/'), p) for p in
733
if specific_files is None or
635
all_unversioned = sorted([(p.split('/'), p) for p in self.target.extras()
636
if not specific_files or
734
637
osutils.is_inside_any(specific_files, p)])
735
638
all_unversioned = deque(all_unversioned)