~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Martin Pool
  • Date: 2005-05-05 02:46:54 UTC
  • Revision ID: mbp@sourcefrog.net-20050505024654-eeb9582a23927c28
Better error for incorrect commands

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
from sets import Set
21
21
import os.path, os, fnmatch
22
22
 
 
23
from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
 
24
     joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
 
25
import errno
 
26
from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE
 
27
 
23
28
from inventory import Inventory
24
29
from trace import mutter, note
25
 
from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
26
 
     joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
27
30
from errors import bailout
28
31
import branch
29
 
from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE
30
32
 
31
33
import bzrlib
32
34
 
76
78
        fp = fingerprint_file(f)
77
79
        f.seek(0)
78
80
        
79
 
        if ie.text_size is not None:
 
81
        if ie.text_size != None:
80
82
            if ie.text_size != fp['size']:
81
83
                bailout("mismatched size for file %r in %r" % (ie.file_id, self._store),
82
84
                        ["inventory expects %d bytes" % ie.text_size,
90
92
                     "store is probably damaged/corrupt"])
91
93
 
92
94
 
93
 
    def export(self, dest):
 
95
    def print_file(self, fileid):
 
96
        """Print file with id `fileid` to stdout."""
 
97
        import sys
 
98
        pumpfile(self.get_file(fileid), sys.stdout)
 
99
        
 
100
        
 
101
    def export(self, dest):        
94
102
        """Export this tree to a new directory.
95
103
 
96
104
        `dest` should not exist, and will be created holding the
97
105
        contents of this tree.
98
106
 
99
 
        :todo: To handle subdirectories we need to create the
 
107
        TODO: To handle subdirectories we need to create the
100
108
               directories first.
101
109
 
102
110
        :note: If the export fails, the destination directory will be
113
121
            elif kind == 'file':
114
122
                pumpfile(self.get_file(ie.file_id), file(fullpath, 'wb'))
115
123
            else:
116
 
                bailout("don't know how to export {%s} of kind %r", fid, kind)
 
124
                bailout("don't know how to export {%s} of kind %r" % (fid, kind))
117
125
            mutter("  export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
118
126
 
119
127
 
149
157
        return file(self.abspath(filename), 'rb')
150
158
 
151
159
    def _get_store_filename(self, file_id):
 
160
        ## XXX: badly named; this isn't in the store at all
152
161
        return self.abspath(self.id2path(file_id))
153
162
 
154
163
    def has_id(self, file_id):
186
195
        """
187
196
        inv = self.inventory
188
197
 
189
 
        def descend(from_dir, from_dir_id, dp):
 
198
        def descend(from_dir_relpath, from_dir_id, dp):
190
199
            ls = os.listdir(dp)
191
200
            ls.sort()
192
201
            for f in ls:
197
206
                    continue
198
207
 
199
208
                # path within tree
200
 
                fp = appendpath(from_dir, f)
 
209
                fp = appendpath(from_dir_relpath, f)
201
210
 
202
211
                # absolute path
203
212
                fap = appendpath(dp, f)
229
238
                for ff in descend(fp, f_ie.file_id, fap):
230
239
                    yield ff
231
240
 
232
 
        for f in descend('', None, self.basedir):
 
241
        for f in descend('', inv.root.file_id, self.basedir):
233
242
            yield f
234
243
            
235
244
 
268
277
            for subf in fl:
269
278
                subp = appendpath(path, subf)
270
279
                yield subp
271
 
                
 
280
 
272
281
 
273
282
    def ignored_files(self):
274
283
        """Yield list of PATH, IGNORE_PATTERN"""
295
304
 
296
305
 
297
306
    def is_ignored(self, filename):
298
 
        """Check whether the filename matches an ignore pattern.
 
307
        r"""Check whether the filename matches an ignore pattern.
299
308
 
300
 
        Patterns containing '/' need to match the whole path; others
301
 
        match against only the last component.
 
309
        Patterns containing '/' or '\' need to match the whole path;
 
310
        others match against only the last component.
302
311
 
303
312
        If the file is ignored, returns the pattern which caused it to
304
313
        be ignored, otherwise None.  So this can simply be used as a
305
314
        boolean if desired."""
306
315
 
307
 
        ## TODO: Use '**' to match directories, and other extended globbing stuff from cvs/rsync.
 
316
        # TODO: Use '**' to match directories, and other extended
 
317
        # globbing stuff from cvs/rsync.
 
318
 
 
319
        # XXX: fnmatch is actually not quite what we want: it's only
 
320
        # approximately the same as real Unix fnmatch, and doesn't
 
321
        # treat dotfiles correctly and allows * to match /.
 
322
        # Eventually it should be replaced with something more
 
323
        # accurate.
308
324
        
309
325
        for pat in self.get_ignore_list():
310
 
            if '/' in pat:
311
 
                # as a special case, you can put ./ at the start of a pattern;
312
 
                # this is good to match in the top-level only;
313
 
                if pat[:2] == './':
 
326
            if '/' in pat or '\\' in pat:
 
327
                
 
328
                # as a special case, you can put ./ at the start of a
 
329
                # pattern; this is good to match in the top-level
 
330
                # only;
 
331
                
 
332
                if (pat[:2] == './') or (pat[:2] == '.\\'):
314
333
                    newpat = pat[2:]
315
334
                else:
316
335
                    newpat = pat
330
349
 
331
350
    File text can be retrieved from the text store.
332
351
 
333
 
    :todo: Some kind of `__repr__` method, but a good one
 
352
    TODO: Some kind of `__repr__` method, but a good one
334
353
           probably means knowing the branch and revision number,
335
354
           or at least passing a description to the constructor.
336
355
    """
430
449
 
431
450
    
432
451
 
 
452
def find_renames(old_inv, new_inv):
 
453
    for file_id in old_inv:
 
454
        if file_id not in new_inv:
 
455
            continue
 
456
        old_name = old_inv.id2path(file_id)
 
457
        new_name = new_inv.id2path(file_id)
 
458
        if old_name != new_name:
 
459
            yield (old_name, new_name)
 
460