~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2009-02-23 20:55:58 UTC
  • mfrom: (4034 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4053.
  • Revision ID: jelmer@samba.org-20090223205558-1cx2k4w1zgs8r5qa
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""WorkingTree object and friends.
18
18
 
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.
24
24
 
25
25
At the moment every WorkingTree has its own branch.  Remote
72
72
    transform,
73
73
    ui,
74
74
    urlutils,
 
75
    views,
75
76
    xml5,
76
77
    xml6,
77
78
    xml7,
123
124
class TreeEntry(object):
124
125
    """An entry that implements the minimum interface used by commands.
125
126
 
126
 
    This needs further inspection, it may be better to have 
 
127
    This needs further inspection, it may be better to have
127
128
    InventoryEntries without ids - though that seems wrong. For now,
128
129
    this is a parallel hierarchy to InventoryEntry, and needs to become
129
130
    one of several things: decorates to that hierarchy, children of, or
132
133
    no InventoryEntry available - i.e. for unversioned objects.
133
134
    Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
134
135
    """
135
 
 
 
136
 
136
137
    def __eq__(self, other):
137
138
        # yes, this us ugly, TODO: best practice __eq__ style.
138
139
        return (isinstance(other, TreeEntry)
139
140
                and other.__class__ == self.__class__)
140
 
 
 
141
 
141
142
    def kind_character(self):
142
143
        return "???"
143
144
 
185
186
    not listed in the Inventory and vice versa.
186
187
    """
187
188
 
 
189
    # override this to set the strategy for storing views
 
190
    def _make_views(self):
 
191
        return views.DisabledViews(self)
 
192
 
188
193
    def __init__(self, basedir='.',
189
194
                 branch=DEPRECATED_PARAMETER,
190
195
                 _inventory=None,
247
252
            self._set_inventory(_inventory, dirty=False)
248
253
        self._detect_case_handling()
249
254
        self._rules_searcher = None
 
255
        self.views = self._make_views()
250
256
 
251
257
    def _detect_case_handling(self):
252
258
        wt_trans = self.bzrdir.get_workingtree_transport(None)
288
294
        return self._format.supports_content_filtering()
289
295
 
290
296
    def supports_views(self):
291
 
        return self._format.supports_views()
 
297
        return self.views.supports_views()
292
298
 
293
299
    def _set_inventory(self, inv, dirty):
294
300
        """Set the internal cached inventory.
383
389
 
384
390
    def basis_tree(self):
385
391
        """Return RevisionTree for the current last revision.
386
 
        
 
392
 
387
393
        If the left most parent is a ghost then the returned tree will be an
388
 
        empty tree - one obtained by calling 
 
394
        empty tree - one obtained by calling
389
395
        repository.revision_tree(NULL_REVISION).
390
396
        """
391
397
        try:
420
426
 
421
427
    def relpath(self, path):
422
428
        """Return the local path portion from a given path.
423
 
        
424
 
        The path may be absolute or relative. If its a relative path it is 
 
429
 
 
430
        The path may be absolute or relative. If its a relative path it is
425
431
        interpreted relative to the python current working directory.
426
432
        """
427
433
        return osutils.relpath(self.basedir, path)
496
502
 
497
503
    def get_parent_ids(self):
498
504
        """See Tree.get_parent_ids.
499
 
        
 
505
 
500
506
        This implementation reads the pending merges list and last_revision
501
507
        value and uses that to decide what the parents list should be.
502
508
        """
519
525
    def get_root_id(self):
520
526
        """Return the id of this trees root"""
521
527
        return self._inventory.root.file_id
522
 
        
 
528
 
523
529
    def _get_store_filename(self, file_id):
524
530
        ## XXX: badly named; this is not in the store at all
525
531
        return self.abspath(self.id2path(file_id))
527
533
    @needs_read_lock
528
534
    def clone(self, to_bzrdir, revision_id=None):
529
535
        """Duplicate this working tree into to_bzr, including all state.
530
 
        
 
536
 
531
537
        Specifically modified files are kept as modified, but
532
538
        ignored and unknown files are discarded.
533
539
 
534
540
        If you want to make a new line of development, see bzrdir.sprout()
535
541
 
536
542
        revision
537
 
            If not None, the cloned tree will have its last revision set to 
 
543
            If not None, the cloned tree will have its last revision set to
538
544
            revision, and and difference between the source trees last revision
539
545
            and this one merged in.
540
546
        """
623
629
        """See MutableTree._add."""
624
630
        # TODO: Re-adding a file that is removed in the working copy
625
631
        # should probably put it back with the previous ID.
626
 
        # the read and write working inventory should not occur in this 
 
632
        # the read and write working inventory should not occur in this
627
633
        # function - they should be part of lock_write and unlock.
628
634
        inv = self.inventory
629
635
        for f, file_id, kind in zip(files, ids, kinds):
748
754
        """Check that all merged revisions are proper 'heads'.
749
755
 
750
756
        This will always return the first revision_id, and any merged revisions
751
 
        which are 
 
757
        which are
752
758
        """
753
759
        if len(revision_ids) == 0:
754
760
            return revision_ids
766
772
    @needs_tree_write_lock
767
773
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
768
774
        """Set the parent ids to revision_ids.
769
 
        
 
775
 
770
776
        See also set_parent_trees. This api will try to retrieve the tree data
771
777
        for each element of revision_ids from the trees repository. If you have
772
778
        tree data already available, it is more efficient to use
905
911
    def merge_modified(self):
906
912
        """Return a dictionary of files modified by a merge.
907
913
 
908
 
        The list is initialized by WorkingTree.set_merge_modified, which is 
 
914
        The list is initialized by WorkingTree.set_merge_modified, which is
909
915
        typically called after we make some automatic updates to the tree
910
916
        because of a merge.
911
917
 
1001
1007
        return False
1002
1008
 
1003
1009
    def _directory_may_be_tree_reference(self, relpath):
1004
 
        # as a special case, if a directory contains control files then 
 
1010
        # as a special case, if a directory contains control files then
1005
1011
        # it's a tree reference, except that the root of the tree is not
1006
1012
        return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1007
1013
        # TODO: We could ask all the control formats whether they
1018
1024
    @needs_tree_write_lock
1019
1025
    def extract(self, file_id, format=None):
1020
1026
        """Extract a subtree from this tree.
1021
 
        
 
1027
 
1022
1028
        A new branch will be created, relative to the path for this tree.
1023
1029
        """
1024
1030
        self.flush()
1029
1035
                transport = transport.clone(name)
1030
1036
                transport.ensure_base()
1031
1037
            return transport
1032
 
            
 
1038
 
1033
1039
        sub_path = self.id2path(file_id)
1034
1040
        branch_transport = mkdirs(sub_path)
1035
1041
        if format is None:
1117
1123
        # directory file_id, relative path, absolute path, reverse sorted children
1118
1124
        children = os.listdir(self.basedir)
1119
1125
        children.sort()
1120
 
        # jam 20060527 The kernel sized tree seems equivalent whether we 
 
1126
        # jam 20060527 The kernel sized tree seems equivalent whether we
1121
1127
        # use a deque and popleft to keep them sorted, or if we use a plain
1122
1128
        # list and just reverse() them.
1123
1129
        children = collections.deque(children)
1143
1149
 
1144
1150
                # absolute path
1145
1151
                fap = from_dir_abspath + '/' + f
1146
 
                
 
1152
 
1147
1153
                f_ie = inv.get_child(from_dir_id, f)
1148
1154
                if f_ie:
1149
1155
                    c = 'V'
1181
1187
                    except KeyError:
1182
1188
                        yield fp[1:], c, fk, None, TreeEntry()
1183
1189
                    continue
1184
 
                
 
1190
 
1185
1191
                if fk != 'directory':
1186
1192
                    continue
1187
1193
 
1204
1210
        to_dir must exist in the inventory.
1205
1211
 
1206
1212
        If to_dir exists and is a directory, the files are moved into
1207
 
        it, keeping their old names.  
 
1213
        it, keeping their old names.
1208
1214
 
1209
1215
        Note that to_dir is only the last component of the new name;
1210
1216
        this doesn't change the directory.
1487
1493
        These are files in the working directory that are not versioned or
1488
1494
        control files or ignored.
1489
1495
        """
1490
 
        # force the extras method to be fully executed before returning, to 
 
1496
        # force the extras method to be fully executed before returning, to
1491
1497
        # prevent race conditions with the lock
1492
1498
        return iter(
1493
1499
            [subp for subp in self.extras() if not self.is_ignored(subp)])
1508
1514
            else:
1509
1515
                raise errors.NoSuchId(self, file_id)
1510
1516
        if len(file_ids):
1511
 
            # in the future this should just set a dirty bit to wait for the 
 
1517
            # in the future this should just set a dirty bit to wait for the
1512
1518
            # final unlock. However, until all methods of workingtree start
1513
 
            # with the current in -memory inventory rather than triggering 
 
1519
            # with the current in -memory inventory rather than triggering
1514
1520
            # a read, it is more complex - we need to teach read_inventory
1515
1521
            # to know when to read, and when to not read first... and possibly
1516
1522
            # to save first when the in memory one may be corrupted.
1517
1523
            # so for now, we just only write it if it is indeed dirty.
1518
1524
            # - RBC 20060907
1519
1525
            self._write_inventory(self._inventory)
1520
 
    
 
1526
 
1521
1527
    def _iter_conflicts(self):
1522
1528
        conflicted = set()
1523
1529
        for info in self.list_files():
1566
1572
                # reuse the revisiontree we merged against to set the new
1567
1573
                # tree data.
1568
1574
                parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1569
 
                # we have to pull the merge trees out again, because 
1570
 
                # merge_inner has set the ids. - this corner is not yet 
 
1575
                # we have to pull the merge trees out again, because
 
1576
                # merge_inner has set the ids. - this corner is not yet
1571
1577
                # layered well enough to prevent double handling.
1572
1578
                # XXX TODO: Fix the double handling: telling the tree about
1573
1579
                # the already known parent data is wasteful.
1627
1633
                            fl.append(subf_norm)
1628
1634
                    else:
1629
1635
                        fl.append(subf)
1630
 
            
 
1636
 
1631
1637
            fl.sort()
1632
1638
            for subf in fl:
1633
1639
                subp = pathjoin(path, subf)
1784
1790
 
1785
1791
    def _change_last_revision(self, new_revision):
1786
1792
        """Template method part of set_last_revision to perform the change.
1787
 
        
 
1793
 
1788
1794
        This is used to allow WorkingTree3 instances to not affect branch
1789
1795
        when their last revision is set.
1790
1796
        """
1816
1822
        # as commit already has that ready-to-use [while the format is the
1817
1823
        # same, that is].
1818
1824
        try:
1819
 
            # this double handles the inventory - unpack and repack - 
 
1825
            # this double handles the inventory - unpack and repack -
1820
1826
            # but is easier to understand. We can/should put a conditional
1821
1827
            # in here based on whether the inventory is in the latest format
1822
1828
            # - perhaps we should repack all inventories on a repository
1823
1829
            # upgrade ?
1824
1830
            # the fast path is to copy the raw xml from the repository. If the
1825
 
            # xml contains 'revision_id="', then we assume the right 
 
1831
            # xml contains 'revision_id="', then we assume the right
1826
1832
            # revision_id is set. We must check for this full string, because a
1827
1833
            # root node id can legitimately look like 'revision_id' but cannot
1828
1834
            # contain a '"'.
1829
1835
            xml = self.branch.repository.get_inventory_xml(new_revision)
1830
1836
            firstline = xml.split('\n', 1)[0]
1831
 
            if (not 'revision_id="' in firstline or 
 
1837
            if (not 'revision_id="' in firstline or
1832
1838
                'format="7"' not in firstline):
1833
1839
                inv = self.branch.repository.deserialise_inventory(
1834
1840
                    new_revision, xml)
1841
1847
        """Read the cached basis inventory."""
1842
1848
        path = self._basis_inventory_name()
1843
1849
        return self._transport.get_bytes(path)
1844
 
        
 
1850
 
1845
1851
    @needs_read_lock
1846
1852
    def read_working_inventory(self):
1847
1853
        """Read the working inventory.
1848
 
        
 
1854
 
1849
1855
        :raises errors.InventoryModified: read_working_inventory will fail
1850
1856
            when the current in memory inventory has been modified.
1851
1857
        """
1852
 
        # conceptually this should be an implementation detail of the tree. 
 
1858
        # conceptually this should be an implementation detail of the tree.
1853
1859
        # XXX: Deprecate this.
1854
1860
        # ElementTree does its own conversion from UTF-8, so open in
1855
1861
        # binary.
2052
2058
            name = os.path.basename(path)
2053
2059
            if name == "":
2054
2060
                continue
2055
 
            # fixme, there should be a factory function inv,add_?? 
 
2061
            # fixme, there should be a factory function inv,add_??
2056
2062
            if kind == 'directory':
2057
2063
                inv.add(InventoryDirectory(file_id, name, parent))
2058
2064
            elif kind == 'file':
2066
2072
    @needs_tree_write_lock
2067
2073
    def set_root_id(self, file_id):
2068
2074
        """Set the root id for this tree."""
2069
 
        # for compatability 
 
2075
        # for compatability
2070
2076
        if file_id is None:
2071
2077
            raise ValueError(
2072
2078
                'WorkingTree.set_root_id with fileid=None')
2076
2082
    def _set_root_id(self, file_id):
2077
2083
        """Set the root id for this tree, in a format specific manner.
2078
2084
 
2079
 
        :param file_id: The file id to assign to the root. It must not be 
 
2085
        :param file_id: The file id to assign to the root. It must not be
2080
2086
            present in the current inventory or an error will occur. It must
2081
2087
            not be None, but rather a valid file id.
2082
2088
        """
2101
2107
 
2102
2108
    def unlock(self):
2103
2109
        """See Branch.unlock.
2104
 
        
 
2110
 
2105
2111
        WorkingTree locking just uses the Branch locking facilities.
2106
2112
        This is current because all working trees have an embedded branch
2107
2113
        within them. IF in the future, we were to make branch data shareable
2108
 
        between multiple working trees, i.e. via shared storage, then we 
 
2114
        between multiple working trees, i.e. via shared storage, then we
2109
2115
        would probably want to lock both the local tree, and the branch.
2110
2116
        """
2111
2117
        raise NotImplementedError(self.unlock)
2163
2169
        # cant set that until we update the working trees last revision to be
2164
2170
        # one from the new branch, because it will just get absorbed by the
2165
2171
        # parent de-duplication logic.
2166
 
        # 
 
2172
        #
2167
2173
        # We MUST save it even if an error occurs, because otherwise the users
2168
2174
        # local work is unreferenced and will appear to have been lost.
2169
 
        # 
 
2175
        #
2170
2176
        result = 0
2171
2177
        try:
2172
2178
            last_rev = self.get_parent_ids()[0]
2524
2530
class WorkingTree2(WorkingTree):
2525
2531
    """This is the Format 2 working tree.
2526
2532
 
2527
 
    This was the first weave based working tree. 
 
2533
    This was the first weave based working tree.
2528
2534
     - uses os locks for locking.
2529
2535
     - uses the branch last-revision.
2530
2536
    """
2563
2569
            if self._inventory_is_modified:
2564
2570
                self.flush()
2565
2571
            self._write_hashcache_if_dirty()
2566
 
                    
 
2572
 
2567
2573
        # reverse order of locking.
2568
2574
        try:
2569
2575
            return self._control_files.unlock()
2604
2610
 
2605
2611
    @needs_tree_write_lock
2606
2612
    def set_conflicts(self, conflicts):
2607
 
        self._put_rio('conflicts', conflicts.to_stanzas(), 
 
2613
        self._put_rio('conflicts', conflicts.to_stanzas(),
2608
2614
                      CONFLICT_HEADER_1)
2609
2615
 
2610
2616
    @needs_tree_write_lock
2659
2665
     * a format string,
2660
2666
     * an open routine.
2661
2667
 
2662
 
    Formats are placed in an dict by their format string for reference 
 
2668
    Formats are placed in an dict by their format string for reference
2663
2669
    during workingtree opening. Its not required that these be instances, they
2664
 
    can be classes themselves with class methods - it simply depends on 
 
2670
    can be classes themselves with class methods - it simply depends on
2665
2671
    whether state is needed for a given format or not.
2666
2672
 
2667
2673
    Once a format is deprecated, just deprecate the initialize and open
2668
 
    methods on the format class. Do not deprecate the object, as the 
 
2674
    methods on the format class. Do not deprecate the object, as the
2669
2675
    object will be created every time regardless.
2670
2676
    """
2671
2677
 
2715
2721
        """Is this format supported?
2716
2722
 
2717
2723
        Supported formats can be initialized and opened.
2718
 
        Unsupported formats may not support initialization or committing or 
 
2724
        Unsupported formats may not support initialization or committing or
2719
2725
        some other features depending on the reason for not being supported.
2720
2726
        """
2721
2727
        return True
2742
2748
 
2743
2749
 
2744
2750
class WorkingTreeFormat2(WorkingTreeFormat):
2745
 
    """The second working tree format. 
 
2751
    """The second working tree format.
2746
2752
 
2747
2753
    This format modified the hash cache from the format 1 hash cache.
2748
2754
    """
2834
2840
        - is new in bzr 0.8
2835
2841
        - uses a LockDir to guard access for writes.
2836
2842
    """
2837
 
    
 
2843
 
2838
2844
    upgrade_recommended = True
2839
2845
 
2840
2846
    def get_format_string(self):
2857
2863
 
2858
2864
    def _open_control_files(self, a_bzrdir):
2859
2865
        transport = a_bzrdir.get_workingtree_transport(None)
2860
 
        return LockableFiles(transport, self._lock_file_name, 
 
2866
        return LockableFiles(transport, self._lock_file_name,
2861
2867
                             self._lock_class)
2862
2868
 
2863
2869
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2864
2870
                   accelerator_tree=None, hardlink=False):
2865
2871
        """See WorkingTreeFormat.initialize().
2866
 
        
 
2872
 
2867
2873
        :param revision_id: if supplied, create a working tree at a different
2868
2874
            revision than the branch is at.
2869
2875
        :param accelerator_tree: A tree which can be used for retrieving file
2940
2946
 
2941
2947
    def _open(self, a_bzrdir, control_files):
2942
2948
        """Open the tree itself.
2943
 
        
 
2949
 
2944
2950
        :param a_bzrdir: the dir for the tree.
2945
2951
        :param control_files: the control files for the tree.
2946
2952
        """