/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2009-03-22 00:24:37 UTC
  • mfrom: (4180 +trunk)
  • mto: (3920.2.35 dpush)
  • mto: This revision was merged to the branch mainline in revision 4281.
  • Revision ID: jelmer@samba.org-20090322002437-0vlyqnz29isqeozo
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,
102
103
    splitpath,
103
104
    supports_executable,
104
105
    )
 
106
from bzrlib.filters import filtered_input_file
105
107
from bzrlib.trace import mutter, note
106
108
from bzrlib.transport.local import LocalTransport
107
109
from bzrlib.progress import DummyProgress, ProgressPhase
123
125
class TreeEntry(object):
124
126
    """An entry that implements the minimum interface used by commands.
125
127
 
126
 
    This needs further inspection, it may be better to have 
 
128
    This needs further inspection, it may be better to have
127
129
    InventoryEntries without ids - though that seems wrong. For now,
128
130
    this is a parallel hierarchy to InventoryEntry, and needs to become
129
131
    one of several things: decorates to that hierarchy, children of, or
132
134
    no InventoryEntry available - i.e. for unversioned objects.
133
135
    Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
134
136
    """
135
 
 
 
137
 
136
138
    def __eq__(self, other):
137
139
        # yes, this us ugly, TODO: best practice __eq__ style.
138
140
        return (isinstance(other, TreeEntry)
139
141
                and other.__class__ == self.__class__)
140
 
 
 
142
 
141
143
    def kind_character(self):
142
144
        return "???"
143
145
 
185
187
    not listed in the Inventory and vice versa.
186
188
    """
187
189
 
 
190
    # override this to set the strategy for storing views
 
191
    def _make_views(self):
 
192
        return views.DisabledViews(self)
 
193
 
188
194
    def __init__(self, basedir='.',
189
195
                 branch=DEPRECATED_PARAMETER,
190
196
                 _inventory=None,
225
231
        wt_trans = self.bzrdir.get_workingtree_transport(None)
226
232
        cache_filename = wt_trans.local_abspath('stat-cache')
227
233
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
228
 
            self.bzrdir._get_file_mode())
 
234
            self.bzrdir._get_file_mode(),
 
235
            self._content_filter_stack_provider())
229
236
        hc = self._hashcache
230
237
        hc.read()
231
238
        # is this scan needed ? it makes things kinda slow.
247
254
            self._set_inventory(_inventory, dirty=False)
248
255
        self._detect_case_handling()
249
256
        self._rules_searcher = None
 
257
        self.views = self._make_views()
250
258
 
251
259
    def _detect_case_handling(self):
252
260
        wt_trans = self.bzrdir.get_workingtree_transport(None)
288
296
        return self._format.supports_content_filtering()
289
297
 
290
298
    def supports_views(self):
291
 
        return self._format.supports_views()
 
299
        return self.views.supports_views()
292
300
 
293
301
    def _set_inventory(self, inv, dirty):
294
302
        """Set the internal cached inventory.
383
391
 
384
392
    def basis_tree(self):
385
393
        """Return RevisionTree for the current last revision.
386
 
        
 
394
 
387
395
        If the left most parent is a ghost then the returned tree will be an
388
 
        empty tree - one obtained by calling 
 
396
        empty tree - one obtained by calling
389
397
        repository.revision_tree(NULL_REVISION).
390
398
        """
391
399
        try:
420
428
 
421
429
    def relpath(self, path):
422
430
        """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 
 
431
 
 
432
        The path may be absolute or relative. If its a relative path it is
425
433
        interpreted relative to the python current working directory.
426
434
        """
427
435
        return osutils.relpath(self.basedir, path)
429
437
    def has_filename(self, filename):
430
438
        return osutils.lexists(self.abspath(filename))
431
439
 
432
 
    def get_file(self, file_id, path=None):
433
 
        return self.get_file_with_stat(file_id, path)[0]
 
440
    def get_file(self, file_id, path=None, filtered=True):
 
441
        return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
434
442
 
435
 
    def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
 
443
    def get_file_with_stat(self, file_id, path=None, filtered=True,
 
444
        _fstat=os.fstat):
436
445
        """See MutableTree.get_file_with_stat."""
437
446
        if path is None:
438
447
            path = self.id2path(file_id)
439
 
        file_obj = self.get_file_byname(path)
440
 
        return (file_obj, _fstat(file_obj.fileno()))
441
 
 
442
 
    def get_file_byname(self, filename):
443
 
        return file(self.abspath(filename), 'rb')
444
 
 
445
 
    def get_file_lines(self, file_id, path=None):
 
448
        file_obj = self.get_file_byname(path, filtered=False)
 
449
        stat_value = _fstat(file_obj.fileno())
 
450
        if self.supports_content_filtering() and filtered:
 
451
            filters = self._content_filter_stack(path)
 
452
            file_obj = filtered_input_file(file_obj, filters)
 
453
        return (file_obj, stat_value)
 
454
 
 
455
    def get_file_text(self, file_id, path=None, filtered=True):
 
456
        return self.get_file(file_id, path=path, filtered=filtered).read()
 
457
 
 
458
    def get_file_byname(self, filename, filtered=True):
 
459
        path = self.abspath(filename)
 
460
        f = file(path, 'rb')
 
461
        if self.supports_content_filtering() and filtered:
 
462
            filters = self._content_filter_stack(filename)
 
463
            return filtered_input_file(f, filters)
 
464
        else:
 
465
            return f
 
466
 
 
467
    def get_file_lines(self, file_id, path=None, filtered=True):
446
468
        """See Tree.get_file_lines()"""
447
 
        file = self.get_file(file_id, path)
 
469
        file = self.get_file(file_id, path, filtered=filtered)
448
470
        try:
449
471
            return file.readlines()
450
472
        finally:
496
518
 
497
519
    def get_parent_ids(self):
498
520
        """See Tree.get_parent_ids.
499
 
        
 
521
 
500
522
        This implementation reads the pending merges list and last_revision
501
523
        value and uses that to decide what the parents list should be.
502
524
        """
519
541
    def get_root_id(self):
520
542
        """Return the id of this trees root"""
521
543
        return self._inventory.root.file_id
522
 
        
 
544
 
523
545
    def _get_store_filename(self, file_id):
524
546
        ## XXX: badly named; this is not in the store at all
525
547
        return self.abspath(self.id2path(file_id))
527
549
    @needs_read_lock
528
550
    def clone(self, to_bzrdir, revision_id=None):
529
551
        """Duplicate this working tree into to_bzr, including all state.
530
 
        
 
552
 
531
553
        Specifically modified files are kept as modified, but
532
554
        ignored and unknown files are discarded.
533
555
 
534
556
        If you want to make a new line of development, see bzrdir.sprout()
535
557
 
536
558
        revision
537
 
            If not None, the cloned tree will have its last revision set to 
 
559
            If not None, the cloned tree will have its last revision set to
538
560
            revision, and and difference between the source trees last revision
539
561
            and this one merged in.
540
562
        """
623
645
        """See MutableTree._add."""
624
646
        # TODO: Re-adding a file that is removed in the working copy
625
647
        # should probably put it back with the previous ID.
626
 
        # the read and write working inventory should not occur in this 
 
648
        # the read and write working inventory should not occur in this
627
649
        # function - they should be part of lock_write and unlock.
628
650
        inv = self.inventory
629
651
        for f, file_id, kind in zip(files, ids, kinds):
723
745
                kind = 'tree-reference'
724
746
            return kind, None, None, None
725
747
        elif kind == 'symlink':
726
 
            return ('symlink', None, None, os.readlink(abspath))
 
748
            return ('symlink', None, None,
 
749
                    os.readlink(abspath.encode(osutils._fs_enc)
 
750
                                ).decode(osutils._fs_enc))
727
751
        else:
728
752
            return (kind, None, None, None)
729
753
 
748
772
        """Check that all merged revisions are proper 'heads'.
749
773
 
750
774
        This will always return the first revision_id, and any merged revisions
751
 
        which are 
 
775
        which are
752
776
        """
753
777
        if len(revision_ids) == 0:
754
778
            return revision_ids
766
790
    @needs_tree_write_lock
767
791
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
768
792
        """Set the parent ids to revision_ids.
769
 
        
 
793
 
770
794
        See also set_parent_trees. This api will try to retrieve the tree data
771
795
        for each element of revision_ids from the trees repository. If you have
772
796
        tree data already available, it is more efficient to use
905
929
    def merge_modified(self):
906
930
        """Return a dictionary of files modified by a merge.
907
931
 
908
 
        The list is initialized by WorkingTree.set_merge_modified, which is 
 
932
        The list is initialized by WorkingTree.set_merge_modified, which is
909
933
        typically called after we make some automatic updates to the tree
910
934
        because of a merge.
911
935
 
945
969
        return file_id
946
970
 
947
971
    def get_symlink_target(self, file_id):
948
 
        return os.readlink(self.id2abspath(file_id))
 
972
        return os.readlink(self.id2abspath(file_id).encode(osutils._fs_enc))
949
973
 
950
974
    @needs_write_lock
951
975
    def subsume(self, other_tree):
1001
1025
        return False
1002
1026
 
1003
1027
    def _directory_may_be_tree_reference(self, relpath):
1004
 
        # as a special case, if a directory contains control files then 
 
1028
        # as a special case, if a directory contains control files then
1005
1029
        # it's a tree reference, except that the root of the tree is not
1006
1030
        return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1007
1031
        # TODO: We could ask all the control formats whether they
1018
1042
    @needs_tree_write_lock
1019
1043
    def extract(self, file_id, format=None):
1020
1044
        """Extract a subtree from this tree.
1021
 
        
 
1045
 
1022
1046
        A new branch will be created, relative to the path for this tree.
1023
1047
        """
1024
1048
        self.flush()
1029
1053
                transport = transport.clone(name)
1030
1054
                transport.ensure_base()
1031
1055
            return transport
1032
 
            
 
1056
 
1033
1057
        sub_path = self.id2path(file_id)
1034
1058
        branch_transport = mkdirs(sub_path)
1035
1059
        if format is None:
1117
1141
        # directory file_id, relative path, absolute path, reverse sorted children
1118
1142
        children = os.listdir(self.basedir)
1119
1143
        children.sort()
1120
 
        # jam 20060527 The kernel sized tree seems equivalent whether we 
 
1144
        # jam 20060527 The kernel sized tree seems equivalent whether we
1121
1145
        # use a deque and popleft to keep them sorted, or if we use a plain
1122
1146
        # list and just reverse() them.
1123
1147
        children = collections.deque(children)
1143
1167
 
1144
1168
                # absolute path
1145
1169
                fap = from_dir_abspath + '/' + f
1146
 
                
 
1170
 
1147
1171
                f_ie = inv.get_child(from_dir_id, f)
1148
1172
                if f_ie:
1149
1173
                    c = 'V'
1181
1205
                    except KeyError:
1182
1206
                        yield fp[1:], c, fk, None, TreeEntry()
1183
1207
                    continue
1184
 
                
 
1208
 
1185
1209
                if fk != 'directory':
1186
1210
                    continue
1187
1211
 
1204
1228
        to_dir must exist in the inventory.
1205
1229
 
1206
1230
        If to_dir exists and is a directory, the files are moved into
1207
 
        it, keeping their old names.  
 
1231
        it, keeping their old names.
1208
1232
 
1209
1233
        Note that to_dir is only the last component of the new name;
1210
1234
        this doesn't change the directory.
1487
1511
        These are files in the working directory that are not versioned or
1488
1512
        control files or ignored.
1489
1513
        """
1490
 
        # force the extras method to be fully executed before returning, to 
 
1514
        # force the extras method to be fully executed before returning, to
1491
1515
        # prevent race conditions with the lock
1492
1516
        return iter(
1493
1517
            [subp for subp in self.extras() if not self.is_ignored(subp)])
1508
1532
            else:
1509
1533
                raise errors.NoSuchId(self, file_id)
1510
1534
        if len(file_ids):
1511
 
            # in the future this should just set a dirty bit to wait for the 
 
1535
            # in the future this should just set a dirty bit to wait for the
1512
1536
            # final unlock. However, until all methods of workingtree start
1513
 
            # with the current in -memory inventory rather than triggering 
 
1537
            # with the current in -memory inventory rather than triggering
1514
1538
            # a read, it is more complex - we need to teach read_inventory
1515
1539
            # to know when to read, and when to not read first... and possibly
1516
1540
            # to save first when the in memory one may be corrupted.
1517
1541
            # so for now, we just only write it if it is indeed dirty.
1518
1542
            # - RBC 20060907
1519
1543
            self._write_inventory(self._inventory)
1520
 
    
 
1544
 
1521
1545
    def _iter_conflicts(self):
1522
1546
        conflicted = set()
1523
1547
        for info in self.list_files():
1566
1590
                # reuse the revisiontree we merged against to set the new
1567
1591
                # tree data.
1568
1592
                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 
 
1593
                # we have to pull the merge trees out again, because
 
1594
                # merge_inner has set the ids. - this corner is not yet
1571
1595
                # layered well enough to prevent double handling.
1572
1596
                # XXX TODO: Fix the double handling: telling the tree about
1573
1597
                # the already known parent data is wasteful.
1627
1651
                            fl.append(subf_norm)
1628
1652
                    else:
1629
1653
                        fl.append(subf)
1630
 
            
 
1654
 
1631
1655
            fl.sort()
1632
1656
            for subf in fl:
1633
1657
                subp = pathjoin(path, subf)
1784
1808
 
1785
1809
    def _change_last_revision(self, new_revision):
1786
1810
        """Template method part of set_last_revision to perform the change.
1787
 
        
 
1811
 
1788
1812
        This is used to allow WorkingTree3 instances to not affect branch
1789
1813
        when their last revision is set.
1790
1814
        """
1816
1840
        # as commit already has that ready-to-use [while the format is the
1817
1841
        # same, that is].
1818
1842
        try:
1819
 
            # this double handles the inventory - unpack and repack - 
 
1843
            # this double handles the inventory - unpack and repack -
1820
1844
            # but is easier to understand. We can/should put a conditional
1821
1845
            # in here based on whether the inventory is in the latest format
1822
1846
            # - perhaps we should repack all inventories on a repository
1823
1847
            # upgrade ?
1824
1848
            # the fast path is to copy the raw xml from the repository. If the
1825
 
            # xml contains 'revision_id="', then we assume the right 
 
1849
            # xml contains 'revision_id="', then we assume the right
1826
1850
            # revision_id is set. We must check for this full string, because a
1827
1851
            # root node id can legitimately look like 'revision_id' but cannot
1828
1852
            # contain a '"'.
1829
1853
            xml = self.branch.repository.get_inventory_xml(new_revision)
1830
1854
            firstline = xml.split('\n', 1)[0]
1831
 
            if (not 'revision_id="' in firstline or 
 
1855
            if (not 'revision_id="' in firstline or
1832
1856
                'format="7"' not in firstline):
1833
1857
                inv = self.branch.repository.deserialise_inventory(
1834
1858
                    new_revision, xml)
1841
1865
        """Read the cached basis inventory."""
1842
1866
        path = self._basis_inventory_name()
1843
1867
        return self._transport.get_bytes(path)
1844
 
        
 
1868
 
1845
1869
    @needs_read_lock
1846
1870
    def read_working_inventory(self):
1847
1871
        """Read the working inventory.
1848
 
        
 
1872
 
1849
1873
        :raises errors.InventoryModified: read_working_inventory will fail
1850
1874
            when the current in memory inventory has been modified.
1851
1875
        """
1852
 
        # conceptually this should be an implementation detail of the tree. 
 
1876
        # conceptually this should be an implementation detail of the tree.
1853
1877
        # XXX: Deprecate this.
1854
1878
        # ElementTree does its own conversion from UTF-8, so open in
1855
1879
        # binary.
2052
2076
            name = os.path.basename(path)
2053
2077
            if name == "":
2054
2078
                continue
2055
 
            # fixme, there should be a factory function inv,add_?? 
 
2079
            # fixme, there should be a factory function inv,add_??
2056
2080
            if kind == 'directory':
2057
2081
                inv.add(InventoryDirectory(file_id, name, parent))
2058
2082
            elif kind == 'file':
2066
2090
    @needs_tree_write_lock
2067
2091
    def set_root_id(self, file_id):
2068
2092
        """Set the root id for this tree."""
2069
 
        # for compatability 
 
2093
        # for compatability
2070
2094
        if file_id is None:
2071
2095
            raise ValueError(
2072
2096
                'WorkingTree.set_root_id with fileid=None')
2076
2100
    def _set_root_id(self, file_id):
2077
2101
        """Set the root id for this tree, in a format specific manner.
2078
2102
 
2079
 
        :param file_id: The file id to assign to the root. It must not be 
 
2103
        :param file_id: The file id to assign to the root. It must not be
2080
2104
            present in the current inventory or an error will occur. It must
2081
2105
            not be None, but rather a valid file id.
2082
2106
        """
2101
2125
 
2102
2126
    def unlock(self):
2103
2127
        """See Branch.unlock.
2104
 
        
 
2128
 
2105
2129
        WorkingTree locking just uses the Branch locking facilities.
2106
2130
        This is current because all working trees have an embedded branch
2107
2131
        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 
 
2132
        between multiple working trees, i.e. via shared storage, then we
2109
2133
        would probably want to lock both the local tree, and the branch.
2110
2134
        """
2111
2135
        raise NotImplementedError(self.unlock)
2163
2187
        # cant set that until we update the working trees last revision to be
2164
2188
        # one from the new branch, because it will just get absorbed by the
2165
2189
        # parent de-duplication logic.
2166
 
        # 
 
2190
        #
2167
2191
        # We MUST save it even if an error occurs, because otherwise the users
2168
2192
        # local work is unreferenced and will appear to have been lost.
2169
 
        # 
 
2193
        #
2170
2194
        result = 0
2171
2195
        try:
2172
2196
            last_rev = self.get_parent_ids()[0]
2524
2548
class WorkingTree2(WorkingTree):
2525
2549
    """This is the Format 2 working tree.
2526
2550
 
2527
 
    This was the first weave based working tree. 
 
2551
    This was the first weave based working tree.
2528
2552
     - uses os locks for locking.
2529
2553
     - uses the branch last-revision.
2530
2554
    """
2563
2587
            if self._inventory_is_modified:
2564
2588
                self.flush()
2565
2589
            self._write_hashcache_if_dirty()
2566
 
                    
 
2590
 
2567
2591
        # reverse order of locking.
2568
2592
        try:
2569
2593
            return self._control_files.unlock()
2604
2628
 
2605
2629
    @needs_tree_write_lock
2606
2630
    def set_conflicts(self, conflicts):
2607
 
        self._put_rio('conflicts', conflicts.to_stanzas(), 
 
2631
        self._put_rio('conflicts', conflicts.to_stanzas(),
2608
2632
                      CONFLICT_HEADER_1)
2609
2633
 
2610
2634
    @needs_tree_write_lock
2659
2683
     * a format string,
2660
2684
     * an open routine.
2661
2685
 
2662
 
    Formats are placed in an dict by their format string for reference 
 
2686
    Formats are placed in an dict by their format string for reference
2663
2687
    during workingtree opening. Its not required that these be instances, they
2664
 
    can be classes themselves with class methods - it simply depends on 
 
2688
    can be classes themselves with class methods - it simply depends on
2665
2689
    whether state is needed for a given format or not.
2666
2690
 
2667
2691
    Once a format is deprecated, just deprecate the initialize and open
2668
 
    methods on the format class. Do not deprecate the object, as the 
 
2692
    methods on the format class. Do not deprecate the object, as the
2669
2693
    object will be created every time regardless.
2670
2694
    """
2671
2695
 
2715
2739
        """Is this format supported?
2716
2740
 
2717
2741
        Supported formats can be initialized and opened.
2718
 
        Unsupported formats may not support initialization or committing or 
 
2742
        Unsupported formats may not support initialization or committing or
2719
2743
        some other features depending on the reason for not being supported.
2720
2744
        """
2721
2745
        return True
2742
2766
 
2743
2767
 
2744
2768
class WorkingTreeFormat2(WorkingTreeFormat):
2745
 
    """The second working tree format. 
 
2769
    """The second working tree format.
2746
2770
 
2747
2771
    This format modified the hash cache from the format 1 hash cache.
2748
2772
    """
2834
2858
        - is new in bzr 0.8
2835
2859
        - uses a LockDir to guard access for writes.
2836
2860
    """
2837
 
    
 
2861
 
2838
2862
    upgrade_recommended = True
2839
2863
 
2840
2864
    def get_format_string(self):
2857
2881
 
2858
2882
    def _open_control_files(self, a_bzrdir):
2859
2883
        transport = a_bzrdir.get_workingtree_transport(None)
2860
 
        return LockableFiles(transport, self._lock_file_name, 
 
2884
        return LockableFiles(transport, self._lock_file_name,
2861
2885
                             self._lock_class)
2862
2886
 
2863
2887
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2864
2888
                   accelerator_tree=None, hardlink=False):
2865
2889
        """See WorkingTreeFormat.initialize().
2866
 
        
 
2890
 
2867
2891
        :param revision_id: if supplied, create a working tree at a different
2868
2892
            revision than the branch is at.
2869
2893
        :param accelerator_tree: A tree which can be used for retrieving file
2940
2964
 
2941
2965
    def _open(self, a_bzrdir, control_files):
2942
2966
        """Open the tree itself.
2943
 
        
 
2967
 
2944
2968
        :param a_bzrdir: the dir for the tree.
2945
2969
        :param control_files: the control files for the tree.
2946
2970
        """