~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: INADA Naoki
  • Date: 2011-05-05 09:15:34 UTC
  • mto: (5830.3.3 i18n-msgfmt)
  • mto: This revision was merged to the branch mainline in revision 5873.
  • Revision ID: songofacandy@gmail.com-20110505091534-7sv835xpofwrmpt4
Add update-pot command to Makefile and tools/bzrgettext script that
extracts help text from bzr commands.

Show diffs side-by-side

added added

removed removed

Lines of Context:
230
230
        """True if filename is the name of a control file in this tree.
231
231
 
232
232
        :param filename: A filename within the tree. This is a relative path
233
 
            from the root of this tree.
 
233
        from the root of this tree.
234
234
 
235
235
        This is true IF and ONLY IF the filename is part of the meta data
236
236
        that bzr controls in this tree. I.E. a random .bzr directory placed
268
268
        self._control_files.break_lock()
269
269
        self.branch.break_lock()
270
270
 
 
271
    def _get_check_refs(self):
 
272
        """Return the references needed to perform a check of this tree.
 
273
        
 
274
        The default implementation returns no refs, and is only suitable for
 
275
        trees that have no local caching and can commit on ghosts at any time.
 
276
 
 
277
        :seealso: bzrlib.check for details about check_refs.
 
278
        """
 
279
        return []
 
280
 
271
281
    def requires_rich_root(self):
272
282
        return self._format.requires_rich_root
273
283
 
496
506
        finally:
497
507
            file.close()
498
508
 
 
509
    def _get_ancestors(self, default_revision):
 
510
        ancestors = set([default_revision])
 
511
        for parent_id in self.get_parent_ids():
 
512
            ancestors.update(self.branch.repository.get_ancestry(
 
513
                             parent_id, topo_sorted=False))
 
514
        return ancestors
 
515
 
499
516
    def get_parent_ids(self):
500
517
        """See Tree.get_parent_ids.
501
518
 
555
572
    def id2abspath(self, file_id):
556
573
        return self.abspath(self.id2path(file_id))
557
574
 
558
 
    def _check_for_tree_references(self, iterator):
559
 
        """See if directories have become tree-references."""
560
 
        blocked_parent_ids = set()
561
 
        for path, ie in iterator:
562
 
            if ie.parent_id in blocked_parent_ids:
563
 
                # This entry was pruned because one of its parents became a
564
 
                # TreeReference. If this is a directory, mark it as blocked.
565
 
                if ie.kind == 'directory':
566
 
                    blocked_parent_ids.add(ie.file_id)
567
 
                continue
568
 
            if ie.kind == 'directory' and self._directory_is_tree_reference(path):
569
 
                # This InventoryDirectory needs to be a TreeReference
570
 
                ie = inventory.TreeReference(ie.file_id, ie.name, ie.parent_id)
571
 
                blocked_parent_ids.add(ie.file_id)
572
 
            yield path, ie
573
 
 
574
 
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
575
 
        """See Tree.iter_entries_by_dir()"""
576
 
        # The only trick here is that if we supports_tree_reference then we
577
 
        # need to detect if a directory becomes a tree-reference.
578
 
        iterator = super(WorkingTree, self).iter_entries_by_dir(
579
 
                specific_file_ids=specific_file_ids,
580
 
                yield_parents=yield_parents)
581
 
        if not self.supports_tree_reference():
582
 
            return iterator
583
 
        else:
584
 
            return self._check_for_tree_references(iterator)
585
 
 
586
575
    def get_file_size(self, file_id):
587
576
        """See Tree.get_file_size"""
588
577
        # XXX: this returns the on-disk size; it should probably return the
595
584
            else:
596
585
                return None
597
586
 
 
587
    def get_file_sha1(self, file_id, path=None, stat_value=None):
 
588
        # FIXME: Shouldn't this be in Tree?
 
589
        raise NotImplementedError(self.get_file_sha1)
 
590
 
598
591
    @needs_tree_write_lock
599
592
    def _gather_kinds(self, files, kinds):
600
593
        """See MutableTree._gather_kinds."""
615
608
        and setting the list to its value plus revision_id.
616
609
 
617
610
        :param revision_id: The revision id to add to the parent list. It may
618
 
            be a ghost revision as long as its not the first parent to be
619
 
            added, or the allow_leftmost_as_ghost parameter is set True.
 
611
        be a ghost revision as long as its not the first parent to be added,
 
612
        or the allow_leftmost_as_ghost parameter is set True.
620
613
        :param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
621
614
        """
622
615
        parents = self.get_parent_ids() + [revision_id]
852
845
        self.add(path, file_id, 'directory')
853
846
        return file_id
854
847
 
855
 
    def get_symlink_target(self, file_id, path=None):
856
 
        if path is not None:
857
 
            abspath = self.abspath(path)
858
 
        else:
859
 
            abspath = self.id2abspath(file_id)
 
848
    def get_symlink_target(self, file_id):
 
849
        abspath = self.id2abspath(file_id)
860
850
        target = osutils.readlink(abspath)
861
851
        return target
862
852
 
962
952
        file and change the file_id. That is the normal mode. Second, it can
963
953
        only change the file_id without touching any physical file.
964
954
 
965
 
        rename_one uses the second mode if 'after == True' and 'to_rel' is
966
 
        either not versioned or newly added, and present in the working tree.
 
955
        rename_one uses the second mode if 'after == True' and 'to_rel' is not
 
956
        versioned but present in the working tree.
967
957
 
968
958
        rename_one uses the second mode if 'after == False' and 'from_rel' is
969
959
        versioned but no longer in the working tree, and 'to_rel' is not
1014
1004
            new_revision_info = self.branch.last_revision_info()
1015
1005
            if new_revision_info != old_revision_info:
1016
1006
                repository = self.branch.repository
1017
 
                if repository._format.fast_deltas:
1018
 
                    parent_ids = self.get_parent_ids()
1019
 
                    if parent_ids:
1020
 
                        basis_id = parent_ids[0]
1021
 
                        basis_tree = repository.revision_tree(basis_id)
1022
1007
                basis_tree.lock_read()
1023
1008
                try:
1024
1009
                    new_basis_tree = self.branch.basis_tree()
1243
1228
        if _mod_revision.is_null(new_revision):
1244
1229
            self.branch.set_last_revision_info(0, new_revision)
1245
1230
            return False
1246
 
        _mod_revision.check_not_reserved_id(new_revision)
1247
1231
        try:
1248
1232
            self.branch.generate_revision_history(new_revision)
1249
1233
        except errors.NoSuchRevision:
1374
1358
    def revert(self, filenames=None, old_tree=None, backups=True,
1375
1359
               pb=None, report_changes=False):
1376
1360
        from bzrlib.conflicts import resolve
 
1361
        if filenames == []:
 
1362
            filenames = None
 
1363
            symbol_versioning.warn('Using [] to revert all files is deprecated'
 
1364
                ' as of bzr 0.91.  Please use None (the default) instead.',
 
1365
                DeprecationWarning, stacklevel=2)
1377
1366
        if old_tree is None:
1378
1367
            basis_tree = self.basis_tree()
1379
1368
            basis_tree.lock_read()
1462
1451
        - Restore the wt.basis->wt.state changes.
1463
1452
 
1464
1453
        There isn't a single operation at the moment to do that, so we:
1465
 
 
1466
1454
        - Merge current state -> basis tree of the master w.r.t. the old tree
1467
1455
          basis.
1468
1456
        - Do a 'normal' merge of the old branch basis if it is relevant.
1723
1711
    def _walkdirs(self, prefix=""):
1724
1712
        """Walk the directories of this tree.
1725
1713
 
1726
 
        :param prefix: is used as the directrory to start with.
1727
 
        :returns: a generator which yields items in the form::
1728
 
 
1729
 
            ((curren_directory_path, fileid),
1730
 
             [(file1_path, file1_name, file1_kind, None, file1_id,
1731
 
               file1_kind), ... ])
 
1714
           :prefix: is used as the directrory to start with.
 
1715
           returns a generator which yields items in the form:
 
1716
                ((curren_directory_path, fileid),
 
1717
                 [(file1_path, file1_name, file1_kind, None, file1_id,
 
1718
                   file1_kind), ... ])
1732
1719
        """
1733
1720
        raise NotImplementedError(self._walkdirs)
1734
1721
 
1740
1727
        are considered 'resolved', because bzr always puts conflict markers
1741
1728
        into files that have text conflicts.  The corresponding .THIS .BASE and
1742
1729
        .OTHER files are deleted, as per 'resolve'.
1743
 
 
1744
1730
        :return: a tuple of ConflictLists: (un_resolved, resolved).
1745
1731
        """
1746
1732
        un_resolved = _mod_conflicts.ConflictList()
1765
1751
        self.set_conflicts(un_resolved)
1766
1752
        return un_resolved, resolved
1767
1753
 
 
1754
    @needs_read_lock
 
1755
    def _check(self, references):
 
1756
        """Check the tree for consistency.
 
1757
 
 
1758
        :param references: A dict with keys matching the items returned by
 
1759
            self._get_check_refs(), and values from looking those keys up in
 
1760
            the repository.
 
1761
        """
 
1762
        tree_basis = self.basis_tree()
 
1763
        tree_basis.lock_read()
 
1764
        try:
 
1765
            repo_basis = references[('trees', self.last_revision())]
 
1766
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
 
1767
                raise errors.BzrCheckError(
 
1768
                    "Mismatched basis inventory content.")
 
1769
            self._validate()
 
1770
        finally:
 
1771
            tree_basis.unlock()
 
1772
 
1768
1773
    def _validate(self):
1769
1774
        """Validate internal structures.
1770
1775
 
1776
1781
        """
1777
1782
        return
1778
1783
 
 
1784
    @needs_read_lock
1779
1785
    def check_state(self):
1780
1786
        """Check that the working state is/isn't valid."""
1781
 
        raise NotImplementedError(self.check_state)
 
1787
        check_refs = self._get_check_refs()
 
1788
        refs = {}
 
1789
        for ref in check_refs:
 
1790
            kind, value = ref
 
1791
            if kind == 'trees':
 
1792
                refs[ref] = self.branch.repository.revision_tree(value)
 
1793
        self._check(refs)
1782
1794
 
1783
1795
    def reset_state(self, revision_ids=None):
1784
1796
        """Reset the state of the working tree.
2073
2085
            return True
2074
2086
        return self.inventory.has_id(file_id)
2075
2087
 
2076
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
 
2088
    __contains__ = has_id
 
2089
 
 
2090
    # should be deprecated - this is slow and in any case treating them as a
 
2091
    # container is (we now know) bad style -- mbp 20070302
 
2092
    ## @deprecated_method(zero_fifteen)
2077
2093
    def __iter__(self):
2078
2094
        """Iterate through file_ids for this tree.
2079
2095
 
2091
2107
        if self._change_last_revision(new_revision):
2092
2108
            self._cache_basis_inventory(new_revision)
2093
2109
 
2094
 
    def _get_check_refs(self):
2095
 
        """Return the references needed to perform a check of this tree.
2096
 
        
2097
 
        The default implementation returns no refs, and is only suitable for
2098
 
        trees that have no local caching and can commit on ghosts at any time.
2099
 
 
2100
 
        :seealso: bzrlib.check for details about check_refs.
2101
 
        """
2102
 
        return []
2103
 
 
2104
 
    @needs_read_lock
2105
 
    def _check(self, references):
2106
 
        """Check the tree for consistency.
2107
 
 
2108
 
        :param references: A dict with keys matching the items returned by
2109
 
            self._get_check_refs(), and values from looking those keys up in
2110
 
            the repository.
2111
 
        """
2112
 
        tree_basis = self.basis_tree()
2113
 
        tree_basis.lock_read()
2114
 
        try:
2115
 
            repo_basis = references[('trees', self.last_revision())]
2116
 
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2117
 
                raise errors.BzrCheckError(
2118
 
                    "Mismatched basis inventory content.")
2119
 
            self._validate()
2120
 
        finally:
2121
 
            tree_basis.unlock()
2122
 
 
2123
 
    @needs_read_lock
2124
 
    def check_state(self):
2125
 
        """Check that the working state is/isn't valid."""
2126
 
        check_refs = self._get_check_refs()
2127
 
        refs = {}
2128
 
        for ref in check_refs:
2129
 
            kind, value = ref
2130
 
            if kind == 'trees':
2131
 
                refs[ref] = self.branch.repository.revision_tree(value)
2132
 
        self._check(refs)
2133
 
 
2134
2110
    @needs_tree_write_lock
2135
2111
    def reset_state(self, revision_ids=None):
2136
2112
        """Reset the state of the working tree.
2254
2230
                parent_tree = self.branch.repository.revision_tree(parent_id)
2255
2231
            parent_tree.lock_read()
2256
2232
            try:
2257
 
                if not parent_tree.has_id(file_id):
 
2233
                if file_id not in parent_tree:
2258
2234
                    continue
2259
2235
                ie = parent_tree.inventory[file_id]
2260
2236
                if ie.kind != 'file':
2308
2284
            for s in _mod_rio.RioReader(hashfile):
2309
2285
                # RioReader reads in Unicode, so convert file_ids back to utf8
2310
2286
                file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2311
 
                if not self.inventory.has_id(file_id):
 
2287
                if file_id not in self.inventory:
2312
2288
                    continue
2313
2289
                text_hash = s.get("hash")
2314
2290
                if text_hash == self.get_file_sha1(file_id):
2555
2531
        inventory. The second mode only updates the inventory without
2556
2532
        touching the file on the filesystem.
2557
2533
 
2558
 
        move uses the second mode if 'after == True' and the target is
2559
 
        either not versioned or newly added, and present in the working tree.
 
2534
        move uses the second mode if 'after == True' and the target is not
 
2535
        versioned but present in the working tree.
2560
2536
 
2561
2537
        move uses the second mode if 'after == False' and the source is
2562
2538
        versioned but no longer in the working tree, and the target is not
2709
2685
 
2710
2686
    class _RenameEntry(object):
2711
2687
        def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2712
 
                     to_rel, to_tail, to_parent_id, only_change_inv=False,
2713
 
                     change_id=False):
 
2688
                     to_rel, to_tail, to_parent_id, only_change_inv=False):
2714
2689
            self.from_rel = from_rel
2715
2690
            self.from_id = from_id
2716
2691
            self.from_tail = from_tail
2718
2693
            self.to_rel = to_rel
2719
2694
            self.to_tail = to_tail
2720
2695
            self.to_parent_id = to_parent_id
2721
 
            self.change_id = change_id
2722
2696
            self.only_change_inv = only_change_inv
2723
2697
 
2724
2698
    def _determine_mv_mode(self, rename_entries, after=False):
2736
2710
            to_rel = rename_entry.to_rel
2737
2711
            to_id = inv.path2id(to_rel)
2738
2712
            only_change_inv = False
2739
 
            change_id = False
2740
2713
 
2741
2714
            # check the inventory for source and destination
2742
2715
            if from_id is None:
2743
2716
                raise errors.BzrMoveFailedError(from_rel,to_rel,
2744
2717
                    errors.NotVersionedError(path=from_rel))
2745
2718
            if to_id is not None:
2746
 
                allowed = False
2747
 
                # allow it with --after but only if dest is newly added
2748
 
                if after:
2749
 
                    basis = self.basis_tree()
2750
 
                    basis.lock_read()
2751
 
                    try:
2752
 
                        if not basis.has_id(to_id):
2753
 
                            rename_entry.change_id = True
2754
 
                            allowed = True
2755
 
                    finally:
2756
 
                        basis.unlock()
2757
 
                if not allowed:
2758
 
                    raise errors.BzrMoveFailedError(from_rel,to_rel,
2759
 
                        errors.AlreadyVersionedError(path=to_rel))
 
2719
                raise errors.BzrMoveFailedError(from_rel,to_rel,
 
2720
                    errors.AlreadyVersionedError(path=to_rel))
2760
2721
 
2761
2722
            # try to determine the mode for rename (only change inv or change
2762
2723
            # inv and file system)
2833
2794
            except OSError, e:
2834
2795
                raise errors.BzrMoveFailedError(entry.from_rel,
2835
2796
                    entry.to_rel, e[1])
2836
 
        if entry.change_id:
2837
 
            to_id = inv.path2id(entry.to_rel)
2838
 
            inv.remove_recursive_id(to_id)
2839
2797
        inv.rename(entry.from_id, entry.to_parent_id, entry.to_tail)
2840
2798
 
2841
2799
    @needs_tree_write_lock
2849
2807
        :raises: NoSuchId if any fileid is not currently versioned.
2850
2808
        """
2851
2809
        for file_id in file_ids:
2852
 
            if not self._inventory.has_id(file_id):
 
2810
            if file_id not in self._inventory:
2853
2811
                raise errors.NoSuchId(self, file_id)
2854
2812
        for file_id in file_ids:
2855
2813
            if self._inventory.has_id(file_id):
2914
2872
    def _walkdirs(self, prefix=""):
2915
2873
        """Walk the directories of this tree.
2916
2874
 
2917
 
        :param prefix: is used as the directrory to start with.
2918
 
        :returns: a generator which yields items in the form::
2919
 
 
2920
 
            ((curren_directory_path, fileid),
2921
 
             [(file1_path, file1_name, file1_kind, None, file1_id,
2922
 
               file1_kind), ... ])
 
2875
           :prefix: is used as the directrory to start with.
 
2876
           returns a generator which yields items in the form:
 
2877
                ((curren_directory_path, fileid),
 
2878
                 [(file1_path, file1_name, file1_kind, None, file1_id,
 
2879
                   file1_kind), ... ])
2923
2880
        """
2924
2881
        _directory = 'directory'
2925
2882
        # get the root in the inventory
3010
2967
    missing_parent_conflicts = False
3011
2968
    """If this format supports missing parent conflicts."""
3012
2969
 
3013
 
    supports_versioned_directories = None
3014
 
 
3015
2970
    @classmethod
3016
2971
    def find_format_string(klass, a_bzrdir):
3017
2972
        """Return format name for the working tree object in a_bzrdir."""