/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/dirstate.py

MergeĀ upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""DirState objects record the state of a directory and its bzr metadata.
18
18
 
82
82
'a' is an absent entry: In that tree the id is not present at this path.
83
83
'd' is a directory entry: This path in this tree is a directory with the
84
84
    current file id. There is no fingerprint for directories.
85
 
'f' is a file entry: As for directory, but its a file. The fingerprint is a
86
 
    sha1 value.
 
85
'f' is a file entry: As for directory, but it's a file. The fingerprint is the
 
86
    sha1 value of the file's canonical form, i.e. after any read filters have
 
87
    been applied to the convenience form stored in the working tree.
87
88
'l' is a symlink entry: As for directory, but a symlink. The fingerprint is the
88
89
    link target.
89
90
't' is a reference to a nested subtree; the fingerprint is the referenced
262
263
        # return '%X.%X' % (int(st.st_mtime), st.st_mode)
263
264
 
264
265
 
 
266
class SHA1Provider(object):
 
267
    """An interface for getting sha1s of a file."""
 
268
 
 
269
    def sha1(self, abspath):
 
270
        """Return the sha1 of a file given its absolute path."""
 
271
        raise NotImplementedError(self.sha1)
 
272
 
 
273
    def stat_and_sha1(self, abspath):
 
274
        """Return the stat and sha1 of a file given its absolute path.
 
275
        
 
276
        Note: the stat should be the stat of the physical file
 
277
        while the sha may be the sha of its canonical content.
 
278
        """
 
279
        raise NotImplementedError(self.stat_and_sha1)
 
280
 
 
281
 
 
282
class DefaultSHA1Provider(SHA1Provider):
 
283
    """A SHA1Provider that reads directly from the filesystem."""
 
284
 
 
285
    def sha1(self, abspath):
 
286
        """Return the sha1 of a file given its absolute path."""
 
287
        return osutils.sha_file_by_name(abspath)
 
288
 
 
289
    def stat_and_sha1(self, abspath):
 
290
        """Return the stat and sha1 of a file given its absolute path."""
 
291
        file_obj = file(abspath, 'rb')
 
292
        try:
 
293
            statvalue = os.fstat(file_obj.fileno())
 
294
            sha1 = osutils.sha_file(file_obj)
 
295
        finally:
 
296
            file_obj.close()
 
297
        return statvalue, sha1
 
298
 
 
299
 
265
300
class DirState(object):
266
301
    """Record directory and metadata state for fast access.
267
302
 
320
355
    HEADER_FORMAT_2 = '#bazaar dirstate flat format 2\n'
321
356
    HEADER_FORMAT_3 = '#bazaar dirstate flat format 3\n'
322
357
 
323
 
    def __init__(self, path):
 
358
    def __init__(self, path, sha1_provider):
324
359
        """Create a  DirState object.
325
360
 
326
361
        :param path: The path at which the dirstate file on disk should live.
 
362
        :param sha1_provider: an object meeting the SHA1Provider interface.
327
363
        """
328
364
        # _header_state and _dirblock_state represent the current state
329
365
        # of the dirstate metadata and the per-row data respectiely.
355
391
        self._cutoff_time = None
356
392
        self._split_path_cache = {}
357
393
        self._bisect_page_size = DirState.BISECT_PAGE_SIZE
 
394
        self._sha1_provider = sha1_provider
358
395
        if 'hashcache' in debug.debug_flags:
359
396
            self._sha1_file = self._sha1_file_and_mutter
360
397
        else:
361
 
            self._sha1_file = osutils.sha_file_by_name
 
398
            self._sha1_file = self._sha1_provider.sha1
362
399
        # These two attributes provide a simple cache for lookups into the
363
400
        # dirstate in-memory vectors. By probing respectively for the last
364
401
        # block, and for the next entry, we save nearly 2 bisections per path
380
417
        :param kind: The kind of the path, as a string like 'file',
381
418
            'directory', etc.
382
419
        :param stat: The output of os.lstat for the path.
383
 
        :param fingerprint: The sha value of the file,
 
420
        :param fingerprint: The sha value of the file's canonical form (i.e.
 
421
            after any read filters have been applied),
384
422
            or the target of a symlink,
385
423
            or the referenced revision id for tree-references,
386
424
            or '' for directories.
1194
1232
        return entry_index, present
1195
1233
 
1196
1234
    @staticmethod
1197
 
    def from_tree(tree, dir_state_filename):
 
1235
    def from_tree(tree, dir_state_filename, sha1_provider=None):
1198
1236
        """Create a dirstate from a bzr Tree.
1199
1237
 
1200
1238
        :param tree: The tree which should provide parent information and
1201
1239
            inventory ids.
 
1240
        :param sha1_provider: an object meeting the SHA1Provider interface.
 
1241
            If None, a DefaultSHA1Provider is used.
1202
1242
        :return: a DirState object which is currently locked for writing.
1203
1243
            (it was locked by DirState.initialize)
1204
1244
        """
1205
 
        result = DirState.initialize(dir_state_filename)
 
1245
        result = DirState.initialize(dir_state_filename,
 
1246
            sha1_provider=sha1_provider)
1206
1247
        try:
1207
1248
            tree.lock_read()
1208
1249
            try:
1569
1610
        # when -Dhashcache is turned on, this is monkey-patched in to log
1570
1611
        # file reads
1571
1612
        trace.mutter("dirstate sha1 " + abspath)
1572
 
        return osutils.sha_file_by_name(abspath)
 
1613
        return self._sha1_provider.sha1(abspath)
1573
1614
 
1574
1615
    def _is_executable(self, mode, old_executable):
1575
1616
        """Is this file executable?"""
1829
1870
            return None, None
1830
1871
 
1831
1872
    @classmethod
1832
 
    def initialize(cls, path):
 
1873
    def initialize(cls, path, sha1_provider=None):
1833
1874
        """Create a new dirstate on path.
1834
1875
 
1835
1876
        The new dirstate will be an empty tree - that is it has no parents,
1836
1877
        and only a root node - which has id ROOT_ID.
1837
1878
 
1838
1879
        :param path: The name of the file for the dirstate.
 
1880
        :param sha1_provider: an object meeting the SHA1Provider interface.
 
1881
            If None, a DefaultSHA1Provider is used.
1839
1882
        :return: A write-locked DirState object.
1840
1883
        """
1841
1884
        # This constructs a new DirState object on a path, sets the _state_file
1843
1886
        # stock empty dirstate information - a root with ROOT_ID, no children,
1844
1887
        # and no parents. Finally it calls save() to ensure that this data will
1845
1888
        # persist.
1846
 
        result = cls(path)
 
1889
        if sha1_provider is None:
 
1890
            sha1_provider = DefaultSHA1Provider()
 
1891
        result = cls(path, sha1_provider)
1847
1892
        # root dir and root dir contents with no children.
1848
1893
        empty_tree_dirblocks = [('', []), ('', [])]
1849
1894
        # a new root directory, with a NULLSTAT.
1982
2027
        return len(self._parents) - len(self._ghosts)
1983
2028
 
1984
2029
    @staticmethod
1985
 
    def on_file(path):
 
2030
    def on_file(path, sha1_provider=None):
1986
2031
        """Construct a DirState on the file at path path.
1987
2032
 
 
2033
        :param path: The path at which the dirstate file on disk should live.
 
2034
        :param sha1_provider: an object meeting the SHA1Provider interface.
 
2035
            If None, a DefaultSHA1Provider is used.
1988
2036
        :return: An unlocked DirState object, associated with the given path.
1989
2037
        """
1990
 
        result = DirState(path)
 
2038
        if sha1_provider is None:
 
2039
            sha1_provider = DefaultSHA1Provider()
 
2040
        result = DirState(path, sha1_provider)
1991
2041
        return result
1992
2042
 
1993
2043
    def _read_dirblocks_if_needed(self):
2482
2532
        :param minikind: The type for the entry ('f' == 'file', 'd' ==
2483
2533
                'directory'), etc.
2484
2534
        :param executable: Should the executable bit be set?
2485
 
        :param fingerprint: Simple fingerprint for new entry: sha1 for files,
2486
 
            referenced revision id for subtrees, etc.
 
2535
        :param fingerprint: Simple fingerprint for new entry: canonical-form
 
2536
            sha1 for files, referenced revision id for subtrees, etc.
2487
2537
        :param packed_stat: Packed stat value for new entry.
2488
2538
        :param size: Size information for new entry
2489
2539
        :param path_utf8: key[0] + '/' + key[1], just passed in to avoid doing
2845
2895
            and stat_value.st_ctime < state._cutoff_time
2846
2896
            and len(entry[1]) > 1
2847
2897
            and entry[1][1][0] != 'a'):
2848
 
                # Could check for size changes for further optimised
2849
 
                # avoidance of sha1's. However the most prominent case of
2850
 
                # over-shaing is during initial add, which this catches.
 
2898
            # Could check for size changes for further optimised
 
2899
            # avoidance of sha1's. However the most prominent case of
 
2900
            # over-shaing is during initial add, which this catches.
 
2901
            # Besides, if content filtering happens, size and sha
 
2902
            # are calculated at the same time, so checking just the size
 
2903
            # gains nothing w.r.t. performance.
2851
2904
            link_or_sha1 = state._sha1_file(abspath)
2852
2905
            entry[1][0] = ('f', link_or_sha1, stat_value.st_size,
2853
2906
                           executable, packed_stat)
3006
3059
                        if target_details[2] == source_details[2]:
3007
3060
                            if link_or_sha1 is None:
3008
3061
                                # Stat cache miss:
3009
 
                                file_obj = file(path_info[4], 'rb')
3010
 
                                try:
3011
 
                                    statvalue = os.fstat(file_obj.fileno())
3012
 
                                    link_or_sha1 = osutils.sha_file(file_obj)
3013
 
                                finally:
3014
 
                                    file_obj.close()
 
3062
                                statvalue, link_or_sha1 = \
 
3063
                                    self.state._sha1_provider.stat_and_sha1(
 
3064
                                    path_info[4])
3015
3065
                                self.state._observed_sha1(entry, link_or_sha1,
3016
3066
                                    statvalue)
3017
3067
                            content_change = (link_or_sha1 != source_details[1])