~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

fix NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
from bzrlib import (
26
26
    delta,
27
27
    osutils,
28
 
    revision as _mod_revision,
29
 
    conflicts as _mod_conflicts,
30
28
    symbol_versioning,
31
29
    )
32
30
from bzrlib.decorators import needs_read_lock
105
103
 
106
104
        Each conflict is an instance of bzrlib.conflicts.Conflict.
107
105
        """
108
 
        return _mod_conflicts.ConflictList()
 
106
        return []
109
107
 
110
108
    def extras(self):
111
109
        """For trees that can have unversioned files, return all such paths."""
122
120
    
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()
126
124
 
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)
129
128
 
130
129
    __contains__ = has_id
131
130
 
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:
134
134
            return True
135
135
        return self.inventory.has_id(file_id)
150
150
 
151
151
        :raises NoSuchId:
152
152
        """
 
153
        file_id = osutils.safe_file_id(file_id)
153
154
        return self.inventory.id2path(file_id)
154
155
 
155
156
    def is_control_filename(self, filename):
185
186
        raise NotImplementedError("Tree subclass %s must implement kind"
186
187
            % self.__class__.__name__)
187
188
 
188
 
    def path_content_summary(self, path):
189
 
        """Get a summary of the information about path.
190
 
        
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'
196
 
                bit.
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.
199
 
        """
200
 
        raise NotImplementedError(self.path_content_summary)
201
 
 
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
223
210
    
224
 
    def get_file(self, file_id, path=None):
225
 
        """Return a file object for the file file_id in the tree.
226
 
        
227
 
        If both file_id and path are defined, it is implementation defined as
228
 
        to which one is used.
229
 
        """
 
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)
231
214
 
232
215
    def get_file_mtime(self, file_id, path=None):
239
222
        raise NotImplementedError(self.get_file_mtime)
240
223
 
241
224
    def get_file_by_path(self, path):
242
 
        return self.get_file(self._inventory.path2id(path), path)
243
 
 
244
 
    def iter_files_bytes(self, desired_files):
245
 
        """Iterate through file contents.
246
 
 
247
 
        Files will not necessarily be returned in the order they occur in
248
 
        desired_files.  No specific order is guaranteed.
249
 
 
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.)
254
 
 
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.
259
 
 
260
 
        :param desired_files: a list of (file_id, identifier) pairs
261
 
        """
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
266
 
            # performant.)
267
 
            cur_file = (self.get_file_text(file_id),)
268
 
            yield identifier, cur_file
 
225
        return self.get_file(self._inventory.path2id(path))
269
226
 
270
227
    def get_symlink_target(self, file_id):
271
228
        """Get the target for a given file_id.
277
234
        """
278
235
        raise NotImplementedError(self.get_symlink_target)
279
236
 
280
 
    def get_root_id(self):
281
 
        """Return the file_id for the root of this tree."""
282
 
        raise NotImplementedError(self.get_root_id)
283
 
 
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
286
239
 
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
291
244
        """
292
245
        raise NotImplementedError(self.annotate_iter)
293
246
 
294
 
    def plan_file_merge(self, file_id, other, base=None):
295
 
        """Generate a merge plan based on annotations.
296
 
 
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.
301
 
        """
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:')
306
 
        if base is None:
307
 
            last_revision_base = None
308
 
        else:
309
 
            last_revision_base = base._get_file_revision(file_id, vf, 'base:')
310
 
        return vf.plan_merge(last_revision_a, last_revision_b,
311
 
                             last_revision_base)
312
 
 
313
 
    def _get_file_revision(self, file_id, vf, tree_revision):
314
 
        def file_revision(revision_tree):
315
 
            revision_tree.lock_read()
316
 
            try:
317
 
                return revision_tree.inventory[file_id].revision
318
 
            finally:
319
 
                revision_tree.unlock()
320
 
 
321
 
        def iter_parent_trees():
322
 
            for revision_id in self.get_parent_ids():
323
 
                try:
324
 
                    yield self.revision_tree(revision_id)
325
 
                except:
326
 
                    yield self.repository.revision_tree(revision_id)
327
 
 
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)
336
 
        else:
337
 
            last_revision = file_revision(self)
338
 
            base_vf = self._get_weave(file_id)
339
 
        vf.fallback_versionedfiles.append(base_vf)
340
 
        return last_revision
341
 
 
342
247
    inventory = property(_get_inventory,
343
248
                         doc="Inventory of this Tree")
344
249
 
369
274
    def paths2ids(self, paths, trees=[], require_versioned=True):
370
275
        """Return all the ids that can be reached by walking from paths.
371
276
        
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.
377
282
 
378
283
        :param paths: An iterable of paths to start converting to ids from.
387
292
 
388
293
    def print_file(self, file_id):
389
294
        """Print file with id `file_id` to stdout."""
 
295
        file_id = osutils.safe_file_id(file_id)
390
296
        import sys
391
297
        sys.stdout.write(self.get_file_text(file_id))
392
298
 
450
356
           versioned_kind.
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'.
481
387
        return False
482
388
 
483
389
    def kind(self, file_id):
 
390
        file_id = osutils.safe_file_id(file_id)
484
391
        assert self._inventory[file_id].kind == "directory"
485
392
        return "directory"
486
393
 
488
395
        return iter([])
489
396
    
490
397
    def __contains__(self, file_id):
 
398
        file_id = osutils.safe_file_id(file_id)
491
399
        return (file_id in self._inventory)
492
400
 
493
401
    def get_file_sha1(self, file_id, path=None, stat_value=None):
588
496
    :param trees: The trees to find file_ids within
589
497
    :param require_versioned: if true, all specified filenames must occur in
590
498
        at least one tree.
591
 
    :return: a set of file ids for the specified filenames
 
499
    :return: a set of (path, file ids) for the specified filenames
592
500
    """
593
501
    not_versioned = []
594
502
    interesting_ids = set()
607
515
 
608
516
 
609
517
def _find_children_across_trees(specified_ids, trees):
610
 
    """Return a set including specified ids and their children.
 
518
    """Return a set including specified ids and their children
611
519
    
612
520
    All matches in all trees will be used.
613
521
 
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.
641
549
 
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.
645
553
    """
685
593
            return result
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)
690
597
 
691
598
    def _iter_changes(self, include_unchanged=False,
722
629
        lookup_trees = [self.source]
723
630
        if extra_trees:
724
631
             lookup_trees.extend(extra_trees)
725
 
        if specific_files == []:
726
 
            specific_file_ids = []
727
 
        else:
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
732
 
                                     self.target.extras()
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)
736
639
        else: