~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-29 02:31:34 UTC
  • Revision ID: mbp@sourcefrog.net-20050329023134-2d1eb96c55831937
check size and sha1 of files retrieved from the tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/env python
2
 
# -*- coding: UTF-8 -*-
 
1
# Copyright (C) 2005 Canonical Ltd
3
2
 
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
24
23
from inventory import Inventory
25
24
from trace import mutter, note
26
25
from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
27
 
     joinpath, splitpath, appendpath, isdir, isfile, file_kind
 
26
     joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
28
27
from errors import bailout
29
28
import branch
30
29
from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE
74
73
                         doc="Inventory of this Tree")
75
74
 
76
75
    def _check_retrieved(self, ie, f):
77
 
        # TODO: Test this check by damaging the store?
 
76
        fp = fingerprint_file(f)
 
77
        f.seek(0)
 
78
        
78
79
        if ie.text_size is not None:
79
 
            fs = filesize(f)
80
 
            if fs != ie.text_size:
 
80
            if ie.text_size != fp['size']:
81
81
                bailout("mismatched size for file %r in %r" % (ie.file_id, self._store),
82
82
                        ["inventory expects %d bytes" % ie.text_size,
83
 
                         "file is actually %d bytes" % fs,
 
83
                         "file is actually %d bytes" % fp['size'],
84
84
                         "store is probably damaged/corrupt"])
85
85
 
86
 
        f_hash = sha_file(f)
87
 
        f.seek(0)
88
 
        if ie.text_sha1 != f_hash:
 
86
        if ie.text_sha1 != fp['sha1']:
89
87
            bailout("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store),
90
88
                    ["inventory expects %s" % ie.text_sha1,
91
 
                     "file is actually %s" % f_hash,
 
89
                     "file is actually %s" % fp['sha1'],
92
90
                     "store is probably damaged/corrupt"])
93
91
 
94
92
 
138
136
        return "<%s of %s>" % (self.__class__.__name__,
139
137
                               self.basedir)
140
138
 
141
 
    def _rel(self, filename):
 
139
    def abspath(self, filename):
142
140
        return os.path.join(self.basedir, filename)
143
141
 
144
142
    def has_filename(self, filename):
145
 
        return os.path.exists(self._rel(filename))
 
143
        return os.path.exists(self.abspath(filename))
146
144
 
147
145
    def get_file(self, file_id):
148
146
        return self.get_file_byname(self.id2path(file_id))
149
147
 
150
148
    def get_file_byname(self, filename):
151
 
        return file(self._rel(filename), 'rb')
 
149
        return file(self.abspath(filename), 'rb')
152
150
 
153
151
    def _get_store_filename(self, file_id):
154
 
        return self._rel(self.id2path(file_id))
 
152
        return self.abspath(self.id2path(file_id))
155
153
 
156
154
    def has_id(self, file_id):
157
155
        # files that have been deleted are excluded
158
156
        if not self.inventory.has_id(file_id):
159
157
            return False
160
 
        return os.access(self._rel(self.inventory.id2path(file_id)), os.F_OK)
 
158
        return os.access(self.abspath(self.inventory.id2path(file_id)), os.F_OK)
161
159
 
162
160
    def get_file_size(self, file_id):
163
161
        return os.stat(self._get_store_filename(file_id))[ST_SIZE]
177
175
 
178
176
 
179
177
    def file_kind(self, filename):
180
 
        if isfile(self._rel(filename)):
 
178
        if isfile(self.abspath(filename)):
181
179
            return 'file'
182
 
        elif isdir(self._rel(filename)):
 
180
        elif isdir(self.abspath(filename)):
183
181
            return 'directory'
184
182
        else:
185
183
            return 'unknown'
263
261
 
264
262
 
265
263
    def get_ignore_list(self):
266
 
        """Return list of ignore patterns."""
 
264
        """Return list of ignore patterns.
 
265
 
 
266
        Cached in the Tree object after the first call.
 
267
        """
 
268
        if hasattr(self, '_ignorelist'):
 
269
            return self._ignorelist
 
270
 
 
271
        l = bzrlib.DEFAULT_IGNORE[:]
267
272
        if self.has_filename(bzrlib.IGNORE_FILENAME):
268
273
            f = self.get_file_byname(bzrlib.IGNORE_FILENAME)
269
 
            return [line.rstrip("\n\r") for line in f.readlines()]
270
 
        else:
271
 
            return bzrlib.DEFAULT_IGNORE
 
274
            l.extend([line.rstrip("\n\r") for line in f.readlines()])
 
275
        self._ignorelist = l
 
276
        return l
272
277
 
273
278
 
274
279
    def is_ignored(self, filename):
276
281
 
277
282
        Patterns containing '/' need to match the whole path; others
278
283
        match against only the last component."""
279
 
        ## TODO: Take them from a file, not hardcoded
280
284
        ## TODO: Use extended zsh-style globs maybe?
281
285
        ## TODO: Use '**' to match directories?
282
286
        for pat in self.get_ignore_list():
310
314
        ie = self._inventory[file_id]
311
315
        f = self._store[ie.text_id]
312
316
        mutter("  get fileid{%s} from %r" % (file_id, self))
313
 
        fs = filesize(f)
314
 
        if ie.text_size is None:
315
 
            note("warning: no text size recorded on %r" % ie)
316
317
        self._check_retrieved(ie, f)
317
318
        return f
318
319