/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
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
16
17
18
"""Git Trees."""
19
20
from bzrlib import (
21
    delta,
22
    errors,
23
    revisiontree,
24
    tree,
25
    )
26
27
from bzrlib.plugins.git.inventory import (
28
    GitInventory,
29
    )
30
from bzrlib.plugins.git.mapping import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
31
    mode_is_executable,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
32
    mode_kind,
33
    )
34
35
36
class GitRevisionTree(revisiontree.RevisionTree):
37
38
    def __init__(self, repository, revision_id):
39
        self._revision_id = revision_id
40
        self._repository = repository
41
        store = repository._git.object_store
42
        assert isinstance(revision_id, str)
0.200.650 by Jelmer Vernooij
Use standard names for lookup functions.
43
        git_id, self.mapping = repository.lookup_bzr_revision_id(revision_id)
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
44
        try:
45
            commit = store[git_id]
46
        except KeyError, r:
47
            raise errors.NoSuchRevision(repository, revision_id)
48
        self.tree = commit.tree
49
        self._inventory = GitInventory(self.tree, self.mapping, store, 
50
                                       revision_id)
51
52
    def get_revision_id(self):
53
        return self._revision_id
54
55
    def get_file_text(self, file_id, path=None):
56
        if path is not None:
57
            entry = self._inventory._get_ie(path)
58
        else:
59
            entry = self._inventory[file_id]
0.200.664 by Jelmer Vernooij
Support submodules during fetch.
60
        if entry.kind in ('directory', 'tree-reference'):
61
            return ""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
62
        return entry.object.data
63
64
65
def tree_delta_from_git_changes(changes, mapping, specific_file=None, 
66
                                require_versioned=False):
67
    """Create a TreeDelta from two git trees.
68
    
69
    source and target are iterators over tuples with: 
70
        (filename, sha, mode)
71
    """
72
    ret = delta.TreeDelta()
73
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
74
        if oldpath is None:
75
            ret.added.append((newpath, mapping.generate_file_id(newpath), mode_kind(newmode)))
76
        elif newpath is None:
77
            ret.removed.append((oldpath, mapping.generate_file_id(oldpath), mode_kind(oldmode)))
78
        elif oldpath != newpath:
79
            ret.renamed.append((oldpath, newpath, mapping.generate_file_id(oldpath), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
80
        elif mode_kind(oldmode) != mode_kind(newmode):
81
            ret.kind_changed.append((newpath, mapping.generate_file_id(newpath), mode_kind(oldmode), mode_kind(newmode)))
82
        elif oldsha != newsha or oldmode != newmode:
83
            ret.modified.append((newpath, mapping.generate_file_id(newpath), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
84
        else:
85
            ret.unchanged.append((newpath, mapping.generate_file_id(newpath), mode_kind(newmode)))
86
    return ret
87
88
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
89
def changes_from_git_changes(changes, mapping, specific_file=None, 
90
                                require_versioned=False):
91
    """Create a iter_changes-like generator from a git stream.
92
    
93
    source and target are iterators over tuples with: 
94
        (filename, sha, mode)
95
    """
96
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
97
        path = (oldpath, newpath)
98
        if oldpath is None:
99
            fileid = mapping.generate_file_id(newpath)
100
            oldexe = None
101
            oldkind = None
102
            oldname = None
103
            oldparent = None
104
        else:
105
            oldexe = mode_is_executable(oldmode)
106
            oldkind = mode_kind(oldmode)
107
            try:
108
                (oldparentpath, oldname) = oldpath.rsplit("/", 1)
109
            except ValueError:
110
                oldparent = None
111
                oldname = oldpath
112
            else:
113
                oldparent = mapping.generate_file_id(oldparentpath)
114
            fileid = mapping.generate_file_id(oldpath)
115
        if newpath is None:
116
            newexe = None
117
            newkind = None
118
            newname = None
119
            newparent = None
120
        else:
121
            newexe = mode_is_executable(newmode)
122
            newkind = mode_kind(newmode)
123
            try:
124
                newparentpath, newname = newpath.rsplit("/", 1)
125
            except ValueError:
126
                newparent = None
127
                newname = newpath
128
            else:
129
                newparent = mapping.generate_file_id(newparentpath)
130
        yield fileid, (oldpath, newpath), (oldsha != newsha), (oldpath is not None, newpath is not None), (oldparent, newparent), (oldname, newname), (oldkind, newkind), (oldexe, newexe)
131
132
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
133
class InterGitRevisionTrees(tree.InterTree):
134
    """InterTree that works between two git revision trees."""
135
0.200.659 by Jelmer Vernooij
Prevent tests using InterGitRevisionTrees.
136
    _matching_from_tree_format = None
137
    _matching_to_tree_format = None
138
    _test_mutable_trees_to_test_trees = None
139
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
140
    @classmethod
141
    def is_compatible(cls, source, target):
142
        return (isinstance(source, GitRevisionTree) and 
143
                isinstance(target, GitRevisionTree))
144
145
    def compare(self, want_unchanged=False, specific_files=None,
146
                extra_trees=None, require_versioned=False, include_root=False,
147
                want_unversioned=False):
148
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
149
            raise AssertionError
150
        changes = self.source._repository._git.object_store.tree_changes(
151
            self.source.tree, self.target.tree, want_unchanged=want_unchanged)
152
        return tree_delta_from_git_changes(changes, self.target.mapping, 
153
            specific_file=specific_files)
154
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
155
    def iter_changes(self, include_unchanged=False, specific_files=None,
156
        pb=None, extra_trees=[], require_versioned=True, want_unversioned=False):
157
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
158
            raise AssertionError
159
        changes = self.source._repository._git.object_store.tree_changes(
160
            self.source.tree, self.target.tree, 
161
            want_unchanged=include_unchanged)
162
        return changes_from_git_changes(changes, self.target.mapping, 
163
            specific_file=specific_files)
164
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
165
166
tree.InterTree.register_optimiser(InterGitRevisionTrees)