/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_helpers_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2009-07-29 21:35:05 UTC
  • mfrom: (4576 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4577.
  • Revision ID: john@arbash-meinel.com-20090729213505-tkqsvy1zfpocu75w
Merge bzr.dev 4576 in prep for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
cdef extern from *:
55
55
    ctypedef unsigned long size_t
56
56
 
57
 
cdef extern from "_dirstate_helpers_c.h":
 
57
cdef extern from "_dirstate_helpers_pyx.h":
58
58
    ctypedef int intptr_t
59
59
 
60
60
 
237
237
    return 0
238
238
 
239
239
 
240
 
def cmp_by_dirs_c(path1, path2):
 
240
def cmp_by_dirs(path1, path2):
241
241
    """Compare two paths directory by directory.
242
242
 
243
243
    This is equivalent to doing::
266
266
                        PyString_Size(path2))
267
267
 
268
268
 
269
 
def _cmp_path_by_dirblock_c(path1, path2):
 
269
def _cmp_path_by_dirblock(path1, path2):
270
270
    """Compare two paths based on what directory they are in.
271
271
 
272
272
    This generates a sort order, such that all children of a directory are
288
288
    if not PyString_CheckExact(path2):
289
289
        raise TypeError("'path2' must be a plain string, not %s: %r"
290
290
                        % (type(path2), path2))
291
 
    return _cmp_path_by_dirblock(PyString_AsString(path1),
292
 
                                 PyString_Size(path1),
293
 
                                 PyString_AsString(path2),
294
 
                                 PyString_Size(path2))
295
 
 
296
 
 
297
 
cdef int _cmp_path_by_dirblock(char *path1, int path1_len,
298
 
                               char *path2, int path2_len):
 
291
    return _cmp_path_by_dirblock_intern(PyString_AsString(path1),
 
292
                                        PyString_Size(path1),
 
293
                                        PyString_AsString(path2),
 
294
                                        PyString_Size(path2))
 
295
 
 
296
 
 
297
cdef int _cmp_path_by_dirblock_intern(char *path1, int path1_len,
 
298
                                      char *path2, int path2_len):
299
299
    """Compare two paths by what directory they are in.
300
300
 
301
 
    see ``_cmp_path_by_dirblock_c`` for details.
 
301
    see ``_cmp_path_by_dirblock`` for details.
302
302
    """
303
303
    cdef char *dirname1
304
304
    cdef int dirname1_len
368
368
    return 1
369
369
 
370
370
 
371
 
def _bisect_path_left_c(paths, path):
 
371
def _bisect_path_left(paths, path):
372
372
    """Return the index where to insert path into paths.
373
373
 
374
374
    This uses a path-wise comparison so we get::
413
413
        cur = PyList_GetItem_object_void(paths, _mid)
414
414
        cur_cstr = PyString_AS_STRING_void(cur)
415
415
        cur_size = PyString_GET_SIZE_void(cur)
416
 
        if _cmp_path_by_dirblock(cur_cstr, cur_size, path_cstr, path_size) < 0:
 
416
        if _cmp_path_by_dirblock_intern(cur_cstr, cur_size,
 
417
                                        path_cstr, path_size) < 0:
417
418
            _lo = _mid + 1
418
419
        else:
419
420
            _hi = _mid
420
421
    return _lo
421
422
 
422
423
 
423
 
def _bisect_path_right_c(paths, path):
 
424
def _bisect_path_right(paths, path):
424
425
    """Return the index where to insert path into paths.
425
426
 
426
427
    This uses a path-wise comparison so we get::
465
466
        cur = PyList_GetItem_object_void(paths, _mid)
466
467
        cur_cstr = PyString_AS_STRING_void(cur)
467
468
        cur_size = PyString_GET_SIZE_void(cur)
468
 
        if _cmp_path_by_dirblock(path_cstr, path_size, cur_cstr, cur_size) < 0:
 
469
        if _cmp_path_by_dirblock_intern(path_cstr, path_size,
 
470
                                        cur_cstr, cur_size) < 0:
469
471
            _hi = _mid
470
472
        else:
471
473
            _lo = _mid + 1
472
474
    return _lo
473
475
 
474
476
 
475
 
def bisect_dirblock_c(dirblocks, dirname, lo=0, hi=None, cache=None):
 
477
def bisect_dirblock(dirblocks, dirname, lo=0, hi=None, cache=None):
476
478
    """Return the index where to insert dirname into the dirblocks.
477
479
 
478
480
    The return value idx is such that all directories blocks in dirblock[:idx]
744
746
        self.state._split_root_dirblock_into_contents()
745
747
 
746
748
 
747
 
def _read_dirblocks_c(state):
 
749
def _read_dirblocks(state):
748
750
    """Read in the dirblocks for the given DirState object.
749
751
 
750
752
    This is tightly bound to the DirState internal representation. It should be
963
965
 
964
966
    cdef object old_dirname_to_file_id # dict
965
967
    cdef object new_dirname_to_file_id # dict
966
 
    cdef readonly object uninteresting
967
968
    cdef object last_source_parent
968
969
    cdef object last_target_parent
969
970
    cdef object include_unchanged
1000
1001
        want_unversioned, tree):
1001
1002
        self.old_dirname_to_file_id = {}
1002
1003
        self.new_dirname_to_file_id = {}
1003
 
        # Just a sentry, so that _process_entry can say that this
1004
 
        # record is handled, but isn't interesting to process (unchanged)
1005
 
        self.uninteresting = object()
1006
1004
        # Using a list so that we can access the values and change them in
1007
1005
        # nested scope. Each one is [path, file_id, entry]
1008
1006
        self.last_source_parent = [None, None]
1053
1051
            Basename is returned as a utf8 string because we expect this
1054
1052
            tuple will be ignored, and don't want to take the time to
1055
1053
            decode.
1056
 
        :return: None if the these don't match
1057
 
                 A tuple of information about the change, or
1058
 
                 the object 'uninteresting' if these match, but are
1059
 
                 basically identical.
 
1054
        :return: (iter_changes_result, changed). If the entry has not been
 
1055
            handled then changed is None. Otherwise it is False if no content
 
1056
            or metadata changes have occured, and None if any content or
 
1057
            metadata change has occured. If self.include_unchanged is True then
 
1058
            if changed is not None, iter_changes_result will always be a result
 
1059
            tuple. Otherwise, iter_changes_result is None unless changed is
 
1060
            True.
1060
1061
        """
1061
1062
        cdef char target_minikind
1062
1063
        cdef char source_minikind
1140
1141
                    if source_minikind != c'f':
1141
1142
                        content_change = 1
1142
1143
                    else:
1143
 
                        # If the size is the same, check the sha:
1144
 
                        if target_details[2] == source_details[2]:
1145
 
                            if link_or_sha1 is None:
1146
 
                                # Stat cache miss:
1147
 
                                statvalue, link_or_sha1 = \
1148
 
                                    self.state._sha1_provider.stat_and_sha1(
1149
 
                                    path_info[4])
1150
 
                                self.state._observed_sha1(entry, link_or_sha1,
1151
 
                                    statvalue)
1152
 
                            content_change = (link_or_sha1 != source_details[1])
1153
 
                        else:
1154
 
                            # Size changed, so must be different
1155
 
                            content_change = 1
 
1144
                        # Check the sha. We can't just rely on the size as
 
1145
                        # content filtering may mean differ sizes actually
 
1146
                        # map to the same content
 
1147
                        if link_or_sha1 is None:
 
1148
                            # Stat cache miss:
 
1149
                            statvalue, link_or_sha1 = \
 
1150
                                self.state._sha1_provider.stat_and_sha1(
 
1151
                                path_info[4])
 
1152
                            self.state._observed_sha1(entry, link_or_sha1,
 
1153
                                statvalue)
 
1154
                        content_change = (link_or_sha1 != source_details[1])
1156
1155
                    # Target details is updated at update_entry time
1157
1156
                    if self.use_filesystem_for_exec:
1158
1157
                        # We don't need S_ISREG here, because we are sure
1220
1219
                    self.last_target_parent[1] = target_parent_id
1221
1220
 
1222
1221
            source_exec = source_details[3]
1223
 
            if (self.include_unchanged
1224
 
                or content_change
 
1222
            changed = (content_change
1225
1223
                or source_parent_id != target_parent_id
1226
1224
                or old_basename != entry[0][1]
1227
1225
                or source_exec != target_exec
1228
 
                ):
 
1226
                )
 
1227
            if not changed and not self.include_unchanged:
 
1228
                return None, False
 
1229
            else:
1229
1230
                if old_path is None:
1230
1231
                    path = self.pathjoin(old_dirname, old_basename)
1231
1232
                    old_path = path
1245
1246
                       (source_parent_id, target_parent_id),
1246
1247
                       (self.utf8_decode(old_basename)[0], self.utf8_decode(entry[0][1])[0]),
1247
1248
                       (source_kind, target_kind),
1248
 
                       (source_exec, target_exec))
1249
 
            else:
1250
 
                return self.uninteresting
 
1249
                       (source_exec, target_exec)), changed
1251
1250
        elif source_minikind == c'a' and _versioned_minikind(target_minikind):
1252
1251
            # looks like a new file
1253
1252
            path = self.pathjoin(entry[0][0], entry[0][1])
1280
1279
                       (None, parent_id),
1281
1280
                       (None, self.utf8_decode(entry[0][1])[0]),
1282
1281
                       (None, path_info[2]),
1283
 
                       (None, target_exec))
 
1282
                       (None, target_exec)), True
1284
1283
            else:
1285
1284
                # Its a missing file, report it as such.
1286
1285
                return (entry[0][2],
1290
1289
                       (None, parent_id),
1291
1290
                       (None, self.utf8_decode(entry[0][1])[0]),
1292
1291
                       (None, None),
1293
 
                       (None, False))
 
1292
                       (None, False)), True
1294
1293
        elif _versioned_minikind(source_minikind) and target_minikind == c'a':
1295
1294
            # unversioned, possibly, or possibly not deleted: we dont care.
1296
1295
            # if its still on disk, *and* theres no other entry at this
1308
1307
                   (parent_id, None),
1309
1308
                   (self.utf8_decode(entry[0][1])[0], None),
1310
1309
                   (_minikind_to_kind(source_minikind), None),
1311
 
                   (source_details[3], None))
 
1310
                   (source_details[3], None)), True
1312
1311
        elif _versioned_minikind(source_minikind) and target_minikind == c'r':
1313
1312
            # a rename; could be a true rename, or a rename inherited from
1314
1313
            # a renamed parent. TODO: handle this efficiently. Its not
1327
1326
                "source_minikind=%r, target_minikind=%r"
1328
1327
                % (source_minikind, target_minikind))
1329
1328
            ## import pdb;pdb.set_trace()
1330
 
        return None
 
1329
        return None, None
1331
1330
 
1332
1331
    def __iter__(self):
1333
1332
        return self
1401
1400
        cdef char * current_dirname_c, * current_blockname_c
1402
1401
        cdef int advance_entry, advance_path
1403
1402
        cdef int path_handled
1404
 
        uninteresting = self.uninteresting
1405
1403
        searched_specific_files = self.searched_specific_files
1406
1404
        # Are we walking a root?
1407
1405
        while self.root_entries_pos < self.root_entries_len:
1408
1406
            entry = self.root_entries[self.root_entries_pos]
1409
1407
            self.root_entries_pos = self.root_entries_pos + 1
1410
 
            result = self._process_entry(entry, self.root_dir_info)
1411
 
            if result is not None and result is not self.uninteresting:
 
1408
            result, changed = self._process_entry(entry, self.root_dir_info)
 
1409
            if changed is not None and changed or self.include_unchanged:
1412
1410
                return result
1413
1411
        # Have we finished the prior root, or never started one ?
1414
1412
        if self.current_root is None:
1457
1455
            while self.root_entries_pos < self.root_entries_len:
1458
1456
                entry = self.root_entries[self.root_entries_pos]
1459
1457
                self.root_entries_pos = self.root_entries_pos + 1
1460
 
                result = self._process_entry(entry, self.root_dir_info)
1461
 
                if result is not None:
 
1458
                result, changed = self._process_entry(entry, self.root_dir_info)
 
1459
                if changed is not None:
1462
1460
                    path_handled = -1
1463
 
                    if result is not self.uninteresting:
 
1461
                    if changed or self.include_unchanged:
1464
1462
                        return result
1465
1463
            # handle unversioned specified paths:
1466
1464
            if self.want_unversioned and not path_handled and self.root_dir_info:
1606
1604
                        self.current_block_pos = self.current_block_pos + 1
1607
1605
                        # entry referring to file not present on disk.
1608
1606
                        # advance the entry only, after processing.
1609
 
                        result = self._process_entry(current_entry, None)
1610
 
                        if result is not None:
1611
 
                            if result is not self.uninteresting:
 
1607
                        result, changed = self._process_entry(current_entry, None)
 
1608
                        if changed is not None:
 
1609
                            if changed or self.include_unchanged:
1612
1610
                                return result
1613
1611
                    self.block_index = self.block_index + 1
1614
1612
                    self._update_current_block()
1675
1673
                    pass
1676
1674
                elif current_path_info is None:
1677
1675
                    # no path is fine: the per entry code will handle it.
1678
 
                    result = self._process_entry(current_entry, current_path_info)
1679
 
                    if result is not None:
1680
 
                        if result is self.uninteresting:
1681
 
                            result = None
 
1676
                    result, changed = self._process_entry(current_entry,
 
1677
                        current_path_info)
1682
1678
                else:
1683
1679
                    minikind = _minikind_from_string(
1684
1680
                        current_entry[1][self.target_index][0])
1699
1695
                        else:
1700
1696
                            # entry referring to file not present on disk.
1701
1697
                            # advance the entry only, after processing.
1702
 
                            result = self._process_entry(current_entry, None)
1703
 
                            if result is not None:
1704
 
                                if result is self.uninteresting:
1705
 
                                    result = None
 
1698
                            result, changed = self._process_entry(current_entry,
 
1699
                                None)
1706
1700
                            advance_path = 0
1707
1701
                    else:
1708
1702
                        # paths are the same,and the dirstate entry is not
1709
1703
                        # absent or renamed.
1710
 
                        result = self._process_entry(current_entry, current_path_info)
1711
 
                        if result is not None:
 
1704
                        result, changed = self._process_entry(current_entry,
 
1705
                            current_path_info)
 
1706
                        if changed is not None:
1712
1707
                            path_handled = -1
1713
 
                            if result is self.uninteresting:
1714
 
                                result = None
1715
1708
                # >- loop control starts here:
1716
1709
                # >- entry
1717
1710
                if advance_entry and current_entry is not None: