/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 breezy/git/tree.py

Support Git rename tracking.

Merged from https://code.launchpad.net/~jelmer/brz/renames/+merge/381006

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
    parse_submodules,
29
29
    ConfigFile as GitConfigFile,
30
30
    )
31
 
from dulwich.diff_tree import tree_changes
 
31
from dulwich.diff_tree import tree_changes, RenameDetector
32
32
from dulwich.errors import NotTreeError
33
33
from dulwich.index import (
34
34
    blob_from_path_and_stat,
737
737
        target_extras = set()
738
738
    ret = delta.TreeDelta()
739
739
    added = []
740
 
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
 
740
    for (change_type, old, new) in changes:
 
741
        (oldpath, oldmode, oldsha) = old
 
742
        (newpath, newmode, newsha) = new
741
743
        if newpath == b'' and not include_root:
742
744
            continue
743
745
        if oldpath is not None:
809
811
            fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
810
812
            (oldversioned, newversioned),
811
813
            (oldparent, newparent), (oldname, newname),
812
 
            (oldkind, newkind), (oldexe, newexe))
 
814
            (oldkind, newkind), (oldexe, newexe),
 
815
            copied=(change_type == 'copy'))
813
816
        if oldpath is None:
814
817
            added.append((newpath, newkind))
815
818
        elif newpath is None or newmode == 0:
816
819
            ret.removed.append(change)
817
820
        elif oldpath != newpath:
818
 
            ret.renamed.append(change)
 
821
            if change_type == 'copy':
 
822
                ret.copied.append(change)
 
823
            else:
 
824
                ret.renamed.append(change)
819
825
        elif mode_kind(oldmode) != mode_kind(newmode):
820
826
            ret.kind_changed.append(change)
821
827
        elif oldsha != newsha or oldmode != newmode:
863
869
    """
864
870
    if target_extras is None:
865
871
        target_extras = set()
866
 
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
 
872
    for (change_type, old, new) in changes:
 
873
        (oldpath, oldmode, oldsha) = old
 
874
        (newpath, newmode, newsha) = new
867
875
        if oldpath is not None:
868
876
            oldpath_decoded = oldpath.decode('utf-8')
869
877
        else:
934
942
            fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
935
943
            (oldversioned, newversioned),
936
944
            (oldparent, newparent), (oldname, newname),
937
 
            (oldkind, newkind), (oldexe, newexe))
 
945
            (oldkind, newkind), (oldexe, newexe),
 
946
            copied=(change_type == 'copy'))
938
947
 
939
948
 
940
949
class InterGitTrees(_mod_tree.InterTree):
997
1006
        paths = set(paths)
998
1007
        ret = {}
999
1008
        changes = self._iter_git_changes(specific_files=paths)[0]
1000
 
        for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
 
1009
        for (change_type, old, new) in changes:
 
1010
            oldpath = old[0]
 
1011
            newpath = new[0]
1001
1012
            if oldpath in paths:
1002
1013
                ret[oldpath] = newpath
1003
1014
        for path in paths:
1015
1026
        paths = set(paths)
1016
1027
        ret = {}
1017
1028
        changes = self._iter_git_changes(specific_files=paths)[0]
1018
 
        for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
 
1029
        for (change_type, old, new) in changes:
 
1030
            oldpath = old[0]
 
1031
            newpath = new[0]
1019
1032
            if newpath in paths:
1020
1033
                ret[newpath] = oldpath
1021
1034
        for path in paths:
1060
1073
                    self.target._repository._git.object_store])
1061
1074
        else:
1062
1075
            store = self.source._repository._git.object_store
1063
 
        return store.tree_changes(
1064
 
            self.source.tree, self.target.tree, want_unchanged=want_unchanged,
1065
 
            include_trees=True, change_type_same=True), set()
 
1076
        rename_detector = RenameDetector(store)
 
1077
        return tree_changes(
 
1078
            store, self.source.tree, self.target.tree, want_unchanged=want_unchanged,
 
1079
            include_trees=True, change_type_same=True, rename_detector=rename_detector), set()
1066
1080
 
1067
1081
 
1068
1082
_mod_tree.InterTree.register_optimiser(InterGitRevisionTrees)
1601
1615
    def __init__(self, source, target):
1602
1616
        super(InterIndexGitTree, self).__init__(source, target)
1603
1617
        self._index = target.index
 
1618
        if self.source.store == self.target.store:
 
1619
            self.store = self.source.store
 
1620
        else:
 
1621
            self.store = OverlayObjectStore(
 
1622
                [self.source.store, self.target.store])
 
1623
        self.rename_detector = RenameDetector(self.store)
1604
1624
 
1605
1625
    @classmethod
1606
1626
    def is_compatible(cls, source, target):
1622
1642
            return changes_between_git_tree_and_working_copy(
1623
1643
                self.source.store, self.source.tree,
1624
1644
                self.target, want_unchanged=want_unchanged,
1625
 
                want_unversioned=want_unversioned)
 
1645
                want_unversioned=want_unversioned,
 
1646
                rename_detector=self.rename_detector)
1626
1647
 
1627
1648
 
1628
1649
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
1629
1650
 
1630
1651
 
1631
 
def changes_between_git_tree_and_working_copy(store, from_tree_sha, target,
 
1652
def changes_between_git_tree_and_working_copy(source_store, from_tree_sha, target,
1632
1653
                                              want_unchanged=False,
1633
 
                                              want_unversioned=False):
 
1654
                                              want_unversioned=False,
 
1655
                                              rename_detector=None):
1634
1656
    """Determine the changes between a git tree and a working tree with index.
1635
1657
 
1636
1658
    """
1657
1679
                    blobs[path] = (index_entry.sha, index_entry.mode)
1658
1680
                else:
1659
1681
                    dirified.append((path, Tree().id, stat.S_IFDIR))
1660
 
                    store.add_object(Tree())
 
1682
                    target.store.add_object(Tree())
1661
1683
            else:
1662
1684
                mode = live_entry.mode
1663
1685
                if not trust_executable:
1665
1687
                        mode |= 0o111
1666
1688
                    else:
1667
1689
                        mode &= ~0o111
 
1690
                if live_entry.sha != index_entry.sha:
 
1691
                    rp = path.decode('utf-8')
 
1692
                    if stat.S_ISREG(live_entry.mode):
 
1693
                        blob = Blob()
 
1694
                        with target.get_file(rp) as f:
 
1695
                            blob.data = f.read()
 
1696
                    elif stat.S_ISLNK(live_entry.mode):
 
1697
                        blob = Blob()
 
1698
                        blob.data = target.get_symlink_target(rp).encode(osutils._fs_enc)
 
1699
                    else:
 
1700
                        blob = None
 
1701
                    if blob is not None:
 
1702
                        target.store.add_object(blob)
1668
1703
                blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
1669
1704
    if want_unversioned:
1670
1705
        for e in target.extras():
1681
1716
                    target.abspath(e).encode(osutils._fs_enc), st)
1682
1717
            else:
1683
1718
                continue
1684
 
            store.add_object(blob)
 
1719
            target.store.add_object(blob)
1685
1720
            np = np.encode('utf-8')
1686
1721
            blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1687
1722
            extras.add(np)
1688
1723
    to_tree_sha = commit_tree(
1689
 
        store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
1690
 
    return store.tree_changes(
1691
 
        from_tree_sha, to_tree_sha, include_trees=True,
 
1724
        target.store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
 
1725
    store = OverlayObjectStore([source_store, target.store])
 
1726
    return tree_changes(
 
1727
        store, from_tree_sha, to_tree_sha, include_trees=True,
 
1728
        rename_detector=rename_detector,
1692
1729
        want_unchanged=want_unchanged, change_type_same=True), extras