~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Martin Pool
  • Date: 2005-05-11 08:11:37 UTC
  • Revision ID: mbp@sourcefrog.net-20050511081137-b4a639321fbe37bb
- change 'file_list' to more explanatory 'specific_files'

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
# TODO: Don't allow WorkingTrees to be constructed for remote branches.
18
 
 
19
 
# FIXME: I don't know if writing out the cache from the destructor is really a
20
 
# good idea, because destructors are considered poor taste in Python, and
21
 
# it's not predictable when it will be written out.
22
17
 
23
18
import os
24
 
import fnmatch
25
 
        
 
19
    
26
20
import bzrlib.tree
27
 
from bzrlib.osutils import appendpath, file_kind, isdir, splitpath
28
 
from bzrlib.errors import BzrCheckError
29
 
from bzrlib.trace import mutter
 
21
from errors import BzrCheckError
 
22
from trace import mutter
 
23
 
30
24
 
31
25
class WorkingTree(bzrlib.tree.Tree):
32
26
    """Working copy tree.
37
31
    It is possible for a `WorkingTree` to have a filename which is
38
32
    not listed in the Inventory and vice versa.
39
33
    """
 
34
    _statcache = None
 
35
    
40
36
    def __init__(self, basedir, inv):
41
 
        from bzrlib.hashcache import HashCache
42
 
        from bzrlib.trace import note, mutter
43
 
 
44
37
        self._inventory = inv
45
38
        self.basedir = basedir
46
39
        self.path2id = inv.path2id
47
40
 
48
 
        # update the whole cache up front and write to disk if anything changed;
49
 
        # in the future we might want to do this more selectively
50
 
        hc = self._hashcache = HashCache(basedir)
51
 
        hc.read()
52
 
        hc.scan()
53
 
 
54
 
        if hc.needs_write:
55
 
            mutter("write hc")
56
 
            hc.write()
57
 
            
58
 
            
59
 
    def __del__(self):
60
 
        if self._hashcache.needs_write:
61
 
            self._hashcache.write()
62
 
 
63
 
 
64
41
    def __iter__(self):
65
42
        """Iterate through file_ids for this tree.
66
43
 
67
44
        file_ids are in a WorkingTree if they are in the working inventory
68
45
        and the working file exists.
69
46
        """
 
47
        self._update_statcache()
70
48
        inv = self._inventory
71
 
        for path, ie in inv.iter_entries():
72
 
            if os.path.exists(self.abspath(path)):
73
 
                yield ie.file_id
 
49
        for file_id in self._inventory:
 
50
            # TODO: This is slightly redundant; we should be able to just
 
51
            # check the statcache but it only includes regular files.
 
52
            # only include files which still exist on disk
 
53
            ie = inv[file_id]
 
54
            if ie.kind == 'file':
 
55
                if ((file_id in self._statcache)
 
56
                    or (os.path.exists(self.abspath(inv.id2path(file_id))))):
 
57
                    yield file_id
 
58
 
74
59
 
75
60
 
76
61
    def __repr__(self):
77
62
        return "<%s of %s>" % (self.__class__.__name__,
78
 
                               getattr(self, 'basedir', None))
79
 
 
80
 
 
 
63
                               self.basedir)
81
64
 
82
65
    def abspath(self, filename):
83
66
        return os.path.join(self.basedir, filename)
98
81
                
99
82
    def has_id(self, file_id):
100
83
        # files that have been deleted are excluded
101
 
        inv = self._inventory
102
 
        if not inv.has_id(file_id):
 
84
        if not self.inventory.has_id(file_id):
103
85
            return False
104
 
        path = inv.id2path(file_id)
105
 
        return os.path.exists(self.abspath(path))
 
86
        self._update_statcache()
 
87
        if file_id in self._statcache:
 
88
            return True
 
89
        return os.path.exists(self.abspath(self.id2path(file_id)))
106
90
 
107
91
 
108
92
    __contains__ = has_id
109
93
    
110
94
 
 
95
    def _update_statcache(self):
 
96
        import statcache
 
97
        if not self._statcache:
 
98
            self._statcache = statcache.update_cache(self.basedir, self.inventory)
 
99
 
111
100
    def get_file_size(self, file_id):
112
 
        # is this still called?
113
 
        raise NotImplementedError()
 
101
        import os, stat
 
102
        return os.stat(self._get_store_filename(file_id))[stat.ST_SIZE]
114
103
 
115
104
 
116
105
    def get_file_sha1(self, file_id):
117
 
        path = self._inventory.id2path(file_id)
118
 
        return self._hashcache.get_sha1(path)
 
106
        import statcache
 
107
        self._update_statcache()
 
108
        return self._statcache[file_id][statcache.SC_SHA1]
119
109
 
120
110
 
121
111
    def file_class(self, filename):
137
127
 
138
128
        Skips the control directory.
139
129
        """
140
 
        inv = self._inventory
 
130
        from osutils import appendpath, file_kind
 
131
        import os
 
132
 
 
133
        inv = self.inventory
141
134
 
142
135
        def descend(from_dir_relpath, from_dir_id, dp):
143
136
            ls = os.listdir(dp)
204
197
        Currently returned depth-first, sorted by name within directories.
205
198
        """
206
199
        ## TODO: Work from given directory downwards
 
200
        from osutils import isdir, appendpath
 
201
        
207
202
        for path, dir_entry in self.inventory.directories():
208
203
            mutter("search for unknowns in %r" % path)
209
204
            dirabs = self.abspath(path)
266
261
        # Eventually it should be replaced with something more
267
262
        # accurate.
268
263
        
 
264
        import fnmatch
 
265
        from osutils import splitpath
 
266
        
269
267
        for pat in self.get_ignore_list():
270
268
            if '/' in pat or '\\' in pat:
271
269
                
285
283
        else:
286
284
            return None
287
285
        
 
286
 
 
287
        
 
288
        
 
289