~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-23 23:52:10 UTC
  • Revision ID: mbp@sourcefrog.net-20050323235210-5464746b93c39ed0
more notes on darcs

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from inventory import Inventory
24
24
from trace import mutter, note
25
25
from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
26
 
     joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
 
26
     joinpath, splitpath, appendpath, isdir, isfile, file_kind
27
27
from errors import bailout
28
28
import branch
29
29
from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE
73
73
                         doc="Inventory of this Tree")
74
74
 
75
75
    def _check_retrieved(self, ie, f):
76
 
        fp = fingerprint_file(f)
77
 
        f.seek(0)
78
 
        
 
76
        # TODO: Test this check by damaging the store?
79
77
        if ie.text_size is not None:
80
 
            if ie.text_size != fp['size']:
 
78
            fs = filesize(f)
 
79
            if fs != ie.text_size:
81
80
                bailout("mismatched size for file %r in %r" % (ie.file_id, self._store),
82
81
                        ["inventory expects %d bytes" % ie.text_size,
83
 
                         "file is actually %d bytes" % fp['size'],
 
82
                         "file is actually %d bytes" % fs,
84
83
                         "store is probably damaged/corrupt"])
85
84
 
86
 
        if ie.text_sha1 != fp['sha1']:
 
85
        f_hash = sha_file(f)
 
86
        f.seek(0)
 
87
        if ie.text_sha1 != f_hash:
87
88
            bailout("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store),
88
89
                    ["inventory expects %s" % ie.text_sha1,
89
 
                     "file is actually %s" % fp['sha1'],
 
90
                     "file is actually %s" % f_hash,
90
91
                     "store is probably damaged/corrupt"])
91
92
 
92
93
 
174
175
            return '?'
175
176
 
176
177
 
 
178
    def file_kind(self, filename):
 
179
        if isfile(self.abspath(filename)):
 
180
            return 'file'
 
181
        elif isdir(self.abspath(filename)):
 
182
            return 'directory'
 
183
        else:
 
184
            return 'unknown'
 
185
 
 
186
 
177
187
    def list_files(self):
178
188
        """Recursively list all files as (path, class, kind, id).
179
189
 
190
200
            ls = os.listdir(dp)
191
201
            ls.sort()
192
202
            for f in ls:
193
 
                ## TODO: If we find a subdirectory with its own .bzr
194
 
                ## directory, then that is a separate tree and we
195
 
                ## should exclude it.
196
203
                if bzrlib.BZRDIR == f:
197
204
                    continue
198
205
 
234
241
            
235
242
 
236
243
 
237
 
    def unknowns(self):
238
 
        """Yield all unknown files in this WorkingTree.
 
244
    def unknowns(self, path='', dir_id=None):
 
245
        """Yield names of unknown files in this WorkingTree.
239
246
 
240
247
        If there are any unknown directories then only the directory is
241
248
        returned, not all its children.  But if there are unknown files
243
250
 
244
251
        Currently returned depth-first, sorted by name within directories.
245
252
        """
246
 
        ## TODO: Work from given directory downwards
247
 
        
248
 
        for path, dir_entry in self.inventory.directories():
249
 
            mutter("search for unknowns in %r" % path)
250
 
            dirabs = self.abspath(path)
251
 
            if not isdir(dirabs):
252
 
                # e.g. directory deleted
253
 
                continue
254
 
 
255
 
            fl = []
256
 
            for subf in os.listdir(dirabs):
257
 
                if (subf != '.bzr'
258
 
                    and (subf not in dir_entry.children)):
259
 
                    fl.append(subf)
260
 
            
261
 
            fl.sort()
262
 
            for subf in fl:
263
 
                subp = appendpath(path, subf)
264
 
                if self.is_ignored(subp):
265
 
                    continue
266
 
                yield subp
 
253
        for fpath, fclass, fkind, fid in self.list_files():
 
254
            if fclass == '?':
 
255
                yield fpath
267
256
                
268
257
 
269
258
    def ignored_files(self):
273
262
 
274
263
 
275
264
    def get_ignore_list(self):
276
 
        """Return list of ignore patterns.
277
 
 
278
 
        Cached in the Tree object after the first call.
279
 
        """
280
 
        if hasattr(self, '_ignorelist'):
281
 
            return self._ignorelist
282
 
 
283
 
        l = bzrlib.DEFAULT_IGNORE[:]
 
265
        """Return list of ignore patterns."""
284
266
        if self.has_filename(bzrlib.IGNORE_FILENAME):
285
267
            f = self.get_file_byname(bzrlib.IGNORE_FILENAME)
286
 
            l.extend([line.rstrip("\n\r") for line in f.readlines()])
287
 
        self._ignorelist = l
288
 
        return l
 
268
            return [line.rstrip("\n\r") for line in f.readlines()]
 
269
        else:
 
270
            return bzrlib.DEFAULT_IGNORE
289
271
 
290
272
 
291
273
    def is_ignored(self, filename):
292
274
        """Check whether the filename matches an ignore pattern.
293
275
 
294
276
        Patterns containing '/' need to match the whole path; others
295
 
        match against only the last component.
296
 
 
297
 
        If the file is ignored, returns the pattern which caused it to
298
 
        be ignored, otherwise None.  So this can simply be used as a
299
 
        boolean if desired."""
300
 
 
301
 
        ## TODO: Use '**' to match directories, and other extended globbing stuff from cvs/rsync.
302
 
        
 
277
        match against only the last component."""
 
278
        ## TODO: Take them from a file, not hardcoded
 
279
        ## TODO: Use extended zsh-style globs maybe?
 
280
        ## TODO: Use '**' to match directories?
303
281
        for pat in self.get_ignore_list():
304
282
            if '/' in pat:
305
283
                if fnmatch.fnmatchcase(filename, pat):
306
 
                    return pat
 
284
                    return True
307
285
            else:
308
286
                if fnmatch.fnmatchcase(splitpath(filename)[-1], pat):
309
 
                    return pat
310
 
        return None
 
287
                    return True
 
288
        return False
311
289
        
312
290
 
313
291
        
331
309
        ie = self._inventory[file_id]
332
310
        f = self._store[ie.text_id]
333
311
        mutter("  get fileid{%s} from %r" % (file_id, self))
 
312
        fs = filesize(f)
 
313
        if ie.text_size is None:
 
314
            note("warning: no text size recorded on %r" % ie)
334
315
        self._check_retrieved(ie, f)
335
316
        return f
336
317