~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: John Arbash Meinel
  • Date: 2007-06-28 23:18:09 UTC
  • mfrom: (2562 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2566.
  • Revision ID: john@arbash-meinel.com-20070628231809-pqbt7puoqj8bl07b
[merge] bzr.dev 2562

Show diffs side-by-side

added added

removed removed

Lines of Context:
413
413
 
414
414
        file_abspath = self.abspath(path)
415
415
        state = self.current_dirstate()
 
416
        if stat_value is None:
 
417
            try:
 
418
                stat_value = os.lstat(file_abspath)
 
419
            except OSError, e:
 
420
                if e.errno == errno.ENOENT:
 
421
                    return None
 
422
                else:
 
423
                    raise
416
424
        link_or_sha1 = state.update_entry(entry, file_abspath,
417
425
                                          stat_value=stat_value)
418
426
        if entry[1][0][0] == 'f':
464
472
 
465
473
    @needs_read_lock
466
474
    def id2path(self, file_id):
 
475
        "Convert a file-id to a path."
467
476
        file_id = osutils.safe_file_id(file_id)
468
477
        state = self.current_dirstate()
469
478
        entry = self._get_entry(file_id=file_id)
473
482
        return path_utf8.decode('utf8')
474
483
 
475
484
    if not osutils.supports_executable():
476
 
        @needs_read_lock
477
485
        def is_executable(self, file_id, path=None):
 
486
            """Test if a file is executable or not.
 
487
 
 
488
            Note: The caller is expected to take a read-lock before calling this.
 
489
            """
478
490
            file_id = osutils.safe_file_id(file_id)
479
491
            entry = self._get_entry(file_id=file_id, path=path)
480
492
            if entry == (None, None):
481
493
                return False
482
494
            return entry[1][0][3]
483
495
    else:
484
 
        @needs_read_lock
485
496
        def is_executable(self, file_id, path=None):
 
497
            """Test if a file is executable or not.
 
498
 
 
499
            Note: The caller is expected to take a read-lock before calling this.
 
500
            """
486
501
            if not path:
487
502
                file_id = osutils.safe_file_id(file_id)
488
503
                path = self.id2path(file_id)
522
537
                # path is missing on disk.
523
538
                continue
524
539
 
525
 
    @needs_read_lock
526
540
    def kind(self, file_id):
527
541
        """Return the kind of a file.
528
542
 
529
543
        This is always the actual kind that's on disk, regardless of what it
530
544
        was added as.
 
545
 
 
546
        Note: The caller is expected to take a read-lock before calling this.
531
547
        """
532
548
        relpath = self.id2path(file_id)
533
549
        assert relpath != None, \
1052
1068
            except (errors.NoSuchRevision, errors.RevisionNotPresent):
1053
1069
                revtree = None
1054
1070
            trees.append((revision_id, revtree))
1055
 
        self.current_dirstate()._validate()
1056
1071
        self.set_parent_trees(trees,
1057
1072
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
1058
 
        self.current_dirstate()._validate()
1059
1073
 
1060
1074
    @needs_tree_write_lock
1061
1075
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
1066
1080
            parent tree - i.e. a ghost.
1067
1081
        """
1068
1082
        dirstate = self.current_dirstate()
1069
 
        dirstate._validate()
1070
1083
        if len(parents_list) > 0:
1071
1084
            if not allow_leftmost_as_ghost and parents_list[0][1] is None:
1072
1085
                raise errors.GhostRevisionUnusableHere(parents_list[0][0])
1082
1095
                real_trees.append((rev_id,
1083
1096
                    self.branch.repository.revision_tree(None)))
1084
1097
                ghosts.append(rev_id)
1085
 
        dirstate._validate()
1086
1098
        dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1087
 
        dirstate._validate()
1088
1099
        self._make_dirty(reset_inventory=False)
1089
 
        dirstate._validate()
1090
1100
 
1091
1101
    def _set_root_id(self, file_id):
1092
1102
        """See WorkingTree.set_root_id."""
1275
1285
                         _control_files=control_files)
1276
1286
        wt._new_tree()
1277
1287
        wt.lock_tree_write()
1278
 
        wt.current_dirstate()._validate()
1279
1288
        try:
1280
1289
            if revision_id in (None, NULL_REVISION):
1281
1290
                if branch.repository.supports_rich_root():
1283
1292
                else:
1284
1293
                    wt._set_root_id(ROOT_ID)
1285
1294
                wt.flush()
1286
 
                wt.current_dirstate()._validate()
1287
1295
            wt.set_last_revision(revision_id)
1288
1296
            wt.flush()
1289
1297
            basis = wt.basis_tree()
1666
1674
            output. An unversioned file is defined as one with (False, False)
1667
1675
            for the versioned pair.
1668
1676
        """
1669
 
        utf8_decode_or_none = cache_utf8._utf8_decode_with_None
 
1677
        utf8_decode = cache_utf8._utf8_decode
1670
1678
        _minikind_to_kind = dirstate.DirState._minikind_to_kind
1671
1679
        # NB: show_status depends on being able to pass in non-versioned files
1672
1680
        # and report them as unknown
1800
1808
        NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1801
1809
        # Using a list so that we can access the values and change them in
1802
1810
        # nested scope. Each one is [path, file_id, entry]
1803
 
        last_source_parent = [None, None, None]
1804
 
        last_target_parent = [None, None, None]
 
1811
        last_source_parent = [None, None]
 
1812
        last_target_parent = [None, None]
1805
1813
 
1806
1814
        use_filesystem_for_exec = (sys.platform != 'win32')
1807
1815
 
 
1816
        # Just a sentry, so that _process_entry can say that this
 
1817
        # record is handled, but isn't interesting to process (unchanged)
 
1818
        uninteresting = object()
 
1819
 
 
1820
 
 
1821
        old_dirname_to_file_id = {}
 
1822
        new_dirname_to_file_id = {}
 
1823
        # TODO: jam 20070516 - Avoid the _get_entry lookup overhead by
 
1824
        #       keeping a cache of directories that we have seen.
 
1825
 
1808
1826
        def _process_entry(entry, path_info):
1809
1827
            """Compare an entry and real disk to generate delta information.
1810
1828
 
1814
1832
                Basename is returned as a utf8 string because we expect this
1815
1833
                tuple will be ignored, and don't want to take the time to
1816
1834
                decode.
 
1835
            :return: None if these don't match
 
1836
                     A tuple of information about the change, or
 
1837
                     the object 'uninteresting' if these match, but are
 
1838
                     basically identical.
1817
1839
            """
1818
1840
            if source_index is None:
1819
1841
                source_details = NULL_PARENT_DETAILS
1830
1852
                target_minikind = target_details[0]
1831
1853
            else:
1832
1854
                link_or_sha1 = None
 
1855
            file_id = entry[0][2]
1833
1856
            source_minikind = source_details[0]
1834
1857
            if source_minikind in 'fdltr' and target_minikind in 'fdlt':
1835
1858
                # claimed content in both: diff
1857
1880
                else:
1858
1881
                    old_dirname = entry[0][0]
1859
1882
                    old_basename = entry[0][1]
1860
 
                    old_path = path = pathjoin(old_dirname, old_basename)
 
1883
                    old_path = path = None
1861
1884
                if path_info is None:
1862
1885
                    # the file is missing on disk, show as removed.
1863
1886
                    content_change = True
1867
1890
                    # source and target are both versioned and disk file is present.
1868
1891
                    target_kind = path_info[2]
1869
1892
                    if target_kind == 'directory':
 
1893
                        if path is None:
 
1894
                            old_path = path = pathjoin(old_dirname, old_basename)
 
1895
                        new_dirname_to_file_id[path] = file_id
1870
1896
                        if source_minikind != 'd':
1871
1897
                            content_change = True
1872
1898
                        else:
1901
1927
                        target_exec = False
1902
1928
                    else:
1903
1929
                        raise Exception, "unknown kind %s" % path_info[2]
 
1930
                if source_minikind == 'd':
 
1931
                    if path is None:
 
1932
                        old_path = path = pathjoin(old_dirname, old_basename)
 
1933
                    old_dirname_to_file_id[old_path] = file_id
1904
1934
                # parent id is the entry for the path in the target tree
1905
1935
                if old_dirname == last_source_parent[0]:
1906
1936
                    source_parent_id = last_source_parent[1]
1907
1937
                else:
1908
 
                    source_parent_entry = state._get_entry(source_index,
1909
 
                                                           path_utf8=old_dirname)
1910
 
                    source_parent_id = source_parent_entry[0][2]
 
1938
                    try:
 
1939
                        source_parent_id = old_dirname_to_file_id[old_dirname]
 
1940
                    except KeyError:
 
1941
                        source_parent_entry = state._get_entry(source_index,
 
1942
                                                               path_utf8=old_dirname)
 
1943
                        source_parent_id = source_parent_entry[0][2]
1911
1944
                    if source_parent_id == entry[0][2]:
1912
1945
                        # This is the root, so the parent is None
1913
1946
                        source_parent_id = None
1914
1947
                    else:
1915
1948
                        last_source_parent[0] = old_dirname
1916
1949
                        last_source_parent[1] = source_parent_id
1917
 
                        last_source_parent[2] = source_parent_entry
1918
1950
                new_dirname = entry[0][0]
1919
1951
                if new_dirname == last_target_parent[0]:
1920
1952
                    target_parent_id = last_target_parent[1]
1921
1953
                else:
1922
 
                    # TODO: We don't always need to do the lookup, because the
1923
 
                    #       parent entry will be the same as the source entry.
1924
 
                    target_parent_entry = state._get_entry(target_index,
1925
 
                                                           path_utf8=new_dirname)
1926
 
                    assert target_parent_entry != (None, None), (
1927
 
                        "Could not find target parent in wt: %s\nparent of: %s"
1928
 
                        % (new_dirname, entry))
1929
 
                    target_parent_id = target_parent_entry[0][2]
 
1954
                    try:
 
1955
                        target_parent_id = new_dirname_to_file_id[new_dirname]
 
1956
                    except KeyError:
 
1957
                        # TODO: We don't always need to do the lookup, because the
 
1958
                        #       parent entry will be the same as the source entry.
 
1959
                        target_parent_entry = state._get_entry(target_index,
 
1960
                                                               path_utf8=new_dirname)
 
1961
                        assert target_parent_entry != (None, None), (
 
1962
                            "Could not find target parent in wt: %s\nparent of: %s"
 
1963
                            % (new_dirname, entry))
 
1964
                        target_parent_id = target_parent_entry[0][2]
1930
1965
                    if target_parent_id == entry[0][2]:
1931
1966
                        # This is the root, so the parent is None
1932
1967
                        target_parent_id = None
1933
1968
                    else:
1934
1969
                        last_target_parent[0] = new_dirname
1935
1970
                        last_target_parent[1] = target_parent_id
1936
 
                        last_target_parent[2] = target_parent_entry
1937
1971
 
1938
1972
                source_exec = source_details[3]
1939
 
                return ((entry[0][2], (old_path, path), content_change,
1940
 
                        (True, True),
1941
 
                        (source_parent_id, target_parent_id),
1942
 
                        (old_basename, entry[0][1]),
1943
 
                        (_minikind_to_kind[source_minikind], target_kind),
1944
 
                        (source_exec, target_exec)),)
 
1973
                if (include_unchanged
 
1974
                    or content_change
 
1975
                    or source_parent_id != target_parent_id
 
1976
                    or old_basename != entry[0][1]
 
1977
                    or source_exec != target_exec
 
1978
                    ):
 
1979
                    if old_path is None:
 
1980
                        old_path = path = pathjoin(old_dirname, old_basename)
 
1981
                        old_path_u = utf8_decode(old_path)[0]
 
1982
                        path_u = old_path_u
 
1983
                    else:
 
1984
                        old_path_u = utf8_decode(old_path)[0]
 
1985
                        if old_path == path:
 
1986
                            path_u = old_path_u
 
1987
                        else:
 
1988
                            path_u = utf8_decode(path)[0]
 
1989
                    source_kind = _minikind_to_kind[source_minikind]
 
1990
                    return (entry[0][2],
 
1991
                           (old_path_u, path_u),
 
1992
                           content_change,
 
1993
                           (True, True),
 
1994
                           (source_parent_id, target_parent_id),
 
1995
                           (utf8_decode(old_basename)[0], utf8_decode(entry[0][1])[0]),
 
1996
                           (source_kind, target_kind),
 
1997
                           (source_exec, target_exec))
 
1998
                else:
 
1999
                    return uninteresting
1945
2000
            elif source_minikind in 'a' and target_minikind in 'fdlt':
1946
2001
                # looks like a new file
1947
2002
                if path_info is not None:
1960
2015
                            and stat.S_IEXEC & path_info[3].st_mode)
1961
2016
                    else:
1962
2017
                        target_exec = target_details[3]
1963
 
                    return ((entry[0][2], (None, path), True,
1964
 
                            (False, True),
1965
 
                            (None, parent_id),
1966
 
                            (None, entry[0][1]),
1967
 
                            (None, path_info[2]),
1968
 
                            (None, target_exec)),)
 
2018
                    return (entry[0][2],
 
2019
                           (None, utf8_decode(path)[0]),
 
2020
                           True,
 
2021
                           (False, True),
 
2022
                           (None, parent_id),
 
2023
                           (None, utf8_decode(entry[0][1])[0]),
 
2024
                           (None, path_info[2]),
 
2025
                           (None, target_exec))
1969
2026
                else:
1970
2027
                    # but its not on disk: we deliberately treat this as just
1971
2028
                    # never-present. (Why ?! - RBC 20070224)
1980
2037
                parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
1981
2038
                if parent_id == entry[0][2]:
1982
2039
                    parent_id = None
1983
 
                return ((entry[0][2], (old_path, None), True,
1984
 
                        (True, False),
1985
 
                        (parent_id, None),
1986
 
                        (entry[0][1], None),
1987
 
                        (_minikind_to_kind[source_minikind], None),
1988
 
                        (source_details[3], None)),)
 
2040
                return (entry[0][2],
 
2041
                       (utf8_decode(old_path)[0], None),
 
2042
                       True,
 
2043
                       (True, False),
 
2044
                       (parent_id, None),
 
2045
                       (utf8_decode(entry[0][1])[0], None),
 
2046
                       (_minikind_to_kind[source_minikind], None),
 
2047
                       (source_details[3], None))
1989
2048
            elif source_minikind in 'fdlt' and target_minikind in 'r':
1990
2049
                # a rename; could be a true rename, or a rename inherited from
1991
2050
                # a renamed parent. TODO: handle this efficiently. Its not
2003
2062
                    "source_minikind=%r, target_minikind=%r"
2004
2063
                    % (source_minikind, target_minikind))
2005
2064
                ## import pdb;pdb.set_trace()
2006
 
            return ()
 
2065
            return None
2007
2066
 
2008
2067
        while search_specific_files:
2009
2068
            # TODO: the pending list should be lexically sorted?  the
2039
2098
                continue
2040
2099
            path_handled = False
2041
2100
            for entry in root_entries:
2042
 
                for result in _process_entry(entry, root_dir_info):
2043
 
                    # this check should probably be outside the loop: one
2044
 
                    # 'iterate two trees' api, and then _iter_changes filters
2045
 
                    # unchanged pairs. - RBC 20070226
 
2101
                result = _process_entry(entry, root_dir_info)
 
2102
                if result is not None:
2046
2103
                    path_handled = True
2047
 
                    if (include_unchanged
2048
 
                        or result[2]                    # content change
2049
 
                        or result[3][0] != result[3][1] # versioned status
2050
 
                        or result[4][0] != result[4][1] # parent id
2051
 
                        or result[5][0] != result[5][1] # name
2052
 
                        or result[6][0] != result[6][1] # kind
2053
 
                        or result[7][0] != result[7][1] # executable
2054
 
                        ):
2055
 
                        yield (result[0],
2056
 
                               (utf8_decode_or_none(result[1][0]),
2057
 
                                utf8_decode_or_none(result[1][1])),
2058
 
                               result[2],
2059
 
                               result[3],
2060
 
                               result[4],
2061
 
                               (utf8_decode_or_none(result[5][0]),
2062
 
                                utf8_decode_or_none(result[5][1])),
2063
 
                               result[6],
2064
 
                               result[7],
2065
 
                              )
 
2104
                    if result is not uninteresting:
 
2105
                        yield result
2066
2106
            if want_unversioned and not path_handled and root_dir_info:
2067
2107
                new_executable = bool(
2068
2108
                    stat.S_ISREG(root_dir_info[3].st_mode)
2122
2162
                   current_block is not None):
2123
2163
                if (current_dir_info and current_block
2124
2164
                    and current_dir_info[0][0] != current_block[0]):
2125
 
                    if current_dir_info[0][0] < current_block[0] :
 
2165
                    if current_dir_info[0][0].split('/') < current_block[0].split('/'):
2126
2166
                        # filesystem data refers to paths not covered by the dirblock.
2127
2167
                        # this has two possibilities:
2128
2168
                        # A) it is versioned but empty, so there is no block for it
2132
2172
                        # new unknown files or directories.
2133
2173
                        # if (B) then we should ignore it, because we don't
2134
2174
                        # recurse into unknown directories.
2135
 
                        if want_unversioned:
2136
 
                            path_index = 0
2137
 
                            while path_index < len(current_dir_info[1]):
2138
 
                                    current_path_info = current_dir_info[1][path_index]
 
2175
                        path_index = 0
 
2176
                        while path_index < len(current_dir_info[1]):
 
2177
                                current_path_info = current_dir_info[1][path_index]
 
2178
                                if want_unversioned:
2139
2179
                                    if current_path_info[2] == 'directory':
2140
2180
                                        if self.target._directory_is_tree_reference(
2141
2181
                                            current_path_info[0].decode('utf8')):
2145
2185
                                        stat.S_ISREG(current_path_info[3].st_mode)
2146
2186
                                        and stat.S_IEXEC & current_path_info[3].st_mode)
2147
2187
                                    yield (None,
2148
 
                                        (None, utf8_decode_or_none(current_path_info[0])),
 
2188
                                        (None, utf8_decode(current_path_info[0])[0]),
2149
2189
                                        True,
2150
2190
                                        (False, False),
2151
2191
                                        (None, None),
2152
 
                                        (None, utf8_decode_or_none(current_path_info[1])),
 
2192
                                        (None, utf8_decode(current_path_info[1])[0]),
2153
2193
                                        (None, current_path_info[2]),
2154
2194
                                        (None, new_executable))
2155
 
                                    # dont descend into this unversioned path if it is
2156
 
                                    # a dir
2157
 
                                    if current_path_info[2] in ('directory',
2158
 
                                                                'tree-reference'):
2159
 
                                        del current_dir_info[1][path_index]
2160
 
                                        path_index -= 1
2161
 
                                    path_index += 1
 
2195
                                # dont descend into this unversioned path if it is
 
2196
                                # a dir
 
2197
                                if current_path_info[2] in ('directory',
 
2198
                                                            'tree-reference'):
 
2199
                                    del current_dir_info[1][path_index]
 
2200
                                    path_index -= 1
 
2201
                                path_index += 1
2162
2202
 
2163
2203
                        # This dir info has been handled, go to the next
2164
2204
                        try:
2176
2216
                        for current_entry in current_block[1]:
2177
2217
                            # entry referring to file not present on disk.
2178
2218
                            # advance the entry only, after processing.
2179
 
                            for result in _process_entry(current_entry, None):
2180
 
                                # this check should probably be outside the loop: one
2181
 
                                # 'iterate two trees' api, and then _iter_changes filters
2182
 
                                # unchanged pairs. - RBC 20070226
2183
 
                                if (include_unchanged
2184
 
                                    or result[2]                    # content change
2185
 
                                    or result[3][0] != result[3][1] # versioned status
2186
 
                                    or result[4][0] != result[4][1] # parent id
2187
 
                                    or result[5][0] != result[5][1] # name
2188
 
                                    or result[6][0] != result[6][1] # kind
2189
 
                                    or result[7][0] != result[7][1] # executable
2190
 
                                    ):
2191
 
                                    yield (result[0],
2192
 
                                           (utf8_decode_or_none(result[1][0]),
2193
 
                                            utf8_decode_or_none(result[1][1])),
2194
 
                                           result[2],
2195
 
                                           result[3],
2196
 
                                           result[4],
2197
 
                                           (utf8_decode_or_none(result[5][0]),
2198
 
                                            utf8_decode_or_none(result[5][1])),
2199
 
                                           result[6],
2200
 
                                           result[7],
2201
 
                                          )
 
2219
                            result = _process_entry(current_entry, None)
 
2220
                            if result is not None:
 
2221
                                if result is not uninteresting:
 
2222
                                    yield result
2202
2223
                        block_index +=1
2203
2224
                        if (block_index < len(state._dirblocks) and
2204
2225
                            osutils.is_inside(current_root,
2233
2254
                        pass
2234
2255
                    elif current_path_info is None:
2235
2256
                        # no path is fine: the per entry code will handle it.
2236
 
                        for result in _process_entry(current_entry, current_path_info):
2237
 
                            # this check should probably be outside the loop: one
2238
 
                            # 'iterate two trees' api, and then _iter_changes filters
2239
 
                            # unchanged pairs. - RBC 20070226
2240
 
                            if (include_unchanged
2241
 
                                or result[2]                    # content change
2242
 
                                or result[3][0] != result[3][1] # versioned status
2243
 
                                or result[4][0] != result[4][1] # parent id
2244
 
                                or result[5][0] != result[5][1] # name
2245
 
                                or result[6][0] != result[6][1] # kind
2246
 
                                or result[7][0] != result[7][1] # executable
2247
 
                                ):
2248
 
                                yield (result[0],
2249
 
                                       (utf8_decode_or_none(result[1][0]),
2250
 
                                        utf8_decode_or_none(result[1][1])),
2251
 
                                       result[2],
2252
 
                                       result[3],
2253
 
                                       result[4],
2254
 
                                       (utf8_decode_or_none(result[5][0]),
2255
 
                                        utf8_decode_or_none(result[5][1])),
2256
 
                                       result[6],
2257
 
                                       result[7],
2258
 
                                      )
2259
 
                    elif current_entry[0][1] != current_path_info[1]:
2260
 
                        if current_path_info[1] < current_entry[0][1]:
 
2257
                        result = _process_entry(current_entry, current_path_info)
 
2258
                        if result is not None:
 
2259
                            if result is not uninteresting:
 
2260
                                yield result
 
2261
                    elif (current_entry[0][1] != current_path_info[1]
 
2262
                          or current_entry[1][target_index][0] in 'ar'):
 
2263
                        # The current path on disk doesn't match the dirblock
 
2264
                        # record. Either the dirblock is marked as absent, or
 
2265
                        # the file on disk is not present at all in the
 
2266
                        # dirblock. Either way, report about the dirblock
 
2267
                        # entry, and let other code handle the filesystem one.
 
2268
                        if current_path_info[1].split('/') < current_entry[0][1].split('/'):
2261
2269
                            # extra file on disk: pass for now, but only
2262
2270
                            # increment the path, not the entry
2263
2271
                            advance_entry = False
2264
2272
                        else:
2265
2273
                            # entry referring to file not present on disk.
2266
2274
                            # advance the entry only, after processing.
2267
 
                            for result in _process_entry(current_entry, None):
2268
 
                                # this check should probably be outside the loop: one
2269
 
                                # 'iterate two trees' api, and then _iter_changes filters
2270
 
                                # unchanged pairs. - RBC 20070226
2271
 
                                path_handled = True
2272
 
                                if (include_unchanged
2273
 
                                    or result[2]                    # content change
2274
 
                                    or result[3][0] != result[3][1] # versioned status
2275
 
                                    or result[4][0] != result[4][1] # parent id
2276
 
                                    or result[5][0] != result[5][1] # name
2277
 
                                    or result[6][0] != result[6][1] # kind
2278
 
                                    or result[7][0] != result[7][1] # executable
2279
 
                                    ):
2280
 
                                    yield (result[0],
2281
 
                                           (utf8_decode_or_none(result[1][0]),
2282
 
                                            utf8_decode_or_none(result[1][1])),
2283
 
                                           result[2],
2284
 
                                           result[3],
2285
 
                                           result[4],
2286
 
                                           (utf8_decode_or_none(result[5][0]),
2287
 
                                            utf8_decode_or_none(result[5][1])),
2288
 
                                           result[6],
2289
 
                                           result[7],
2290
 
                                          )
 
2275
                            result = _process_entry(current_entry, None)
 
2276
                            if result is not None:
 
2277
                                if result is not uninteresting:
 
2278
                                    yield result
2291
2279
                            advance_path = False
2292
2280
                    else:
2293
 
                        for result in _process_entry(current_entry, current_path_info):
2294
 
                            # this check should probably be outside the loop: one
2295
 
                            # 'iterate two trees' api, and then _iter_changes filters
2296
 
                            # unchanged pairs. - RBC 20070226
2297
 
                            if current_entry[1][target_index][0] == 'a':
2298
 
                                advance_path = False
2299
 
                                path_handled = False
2300
 
                            else:
2301
 
                                path_handled = True
2302
 
                            if (include_unchanged
2303
 
                                or result[2]                    # content change
2304
 
                                or result[3][0] != result[3][1] # versioned status
2305
 
                                or result[4][0] != result[4][1] # parent id
2306
 
                                or result[5][0] != result[5][1] # name
2307
 
                                or result[6][0] != result[6][1] # kind
2308
 
                                or result[7][0] != result[7][1] # executable
2309
 
                                ):
2310
 
                                yield (result[0],
2311
 
                                       (utf8_decode_or_none(result[1][0]),
2312
 
                                        utf8_decode_or_none(result[1][1])),
2313
 
                                       result[2],
2314
 
                                       result[3],
2315
 
                                       result[4],
2316
 
                                       (utf8_decode_or_none(result[5][0]),
2317
 
                                        utf8_decode_or_none(result[5][1])),
2318
 
                                       result[6],
2319
 
                                       result[7],
2320
 
                                      )
 
2281
                        result = _process_entry(current_entry, current_path_info)
 
2282
                        if result is not None:
 
2283
                            path_handled = True
 
2284
                            if result is not uninteresting:
 
2285
                                yield result
2321
2286
                    if advance_entry and current_entry is not None:
2322
2287
                        entry_index += 1
2323
2288
                        if entry_index < len(current_block[1]):
2334
2299
                                    stat.S_ISREG(current_path_info[3].st_mode)
2335
2300
                                    and stat.S_IEXEC & current_path_info[3].st_mode)
2336
2301
                                yield (None,
2337
 
                                    (None, utf8_decode_or_none(current_path_info[0])),
 
2302
                                    (None, utf8_decode(current_path_info[0])[0]),
2338
2303
                                    True,
2339
2304
                                    (False, False),
2340
2305
                                    (None, None),
2341
 
                                    (None, utf8_decode_or_none(current_path_info[1])),
 
2306
                                    (None, utf8_decode(current_path_info[1])[0]),
2342
2307
                                    (None, current_path_info[2]),
2343
2308
                                    (None, new_executable))
2344
2309
                            # dont descend into this unversioned path if it is