/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
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
20
from dulwich.object_store import tree_lookup_path
21
import stat
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
22
import posixpath
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
23
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
24
from bzrlib import (
25
    delta,
26
    errors,
27
    revisiontree,
28
    tree,
29
    )
30
31
from bzrlib.plugins.git.mapping import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
32
    mode_is_executable,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
33
    mode_kind,
34
    )
35
36
37
class GitRevisionTree(revisiontree.RevisionTree):
0.200.959 by Jelmer Vernooij
Improve docstrings.
38
    """Revision tree implementation based on Git objects."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
39
40
    def __init__(self, repository, revision_id):
41
        self._revision_id = revision_id
42
        self._repository = repository
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
43
        self.store = repository._git.object_store
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
44
        assert isinstance(revision_id, str)
0.200.650 by Jelmer Vernooij
Use standard names for lookup functions.
45
        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.
46
        try:
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
47
            commit = self.store[git_id]
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
48
        except KeyError, r:
49
            raise errors.NoSuchRevision(repository, revision_id)
50
        self.tree = commit.tree
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
51
        self.fileid_map = self.mapping.get_fileid_map(self.store.__getitem__, self.tree)
52
53
    def id2path(self, file_id):
54
        return self.fileid_map.lookup_path(file_id)
55
56
    def path2id(self, path):
57
        return self.fileid_map.lookup_file_id(path.encode('utf-8'))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
58
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
59
    def list_files(self, include_root=False, from_dir=None, recursive=True):
60
        # FIXME: Yield ie's
61
        if from_dir is None:
62
            from_dir = ""
63
        (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree, from_dir)
64
        root_kind = mode_kind(mode)
65
        if include_root:
66
            yield from_dir, "V", root_kind, self.path2id(from_dir), None
67
        todo = set()
68
        if root_kind == 'directory':
69
            todo.add((from_dir, hexsha))
70
        while todo:
71
            (path, hexsha) = todo.pop()
72
            tree = self.store[hexsha]
73
            for name, mode, hexsha in tree.iteritems():
74
                child_path = posixpath.join(path, name)
75
                kind = mode_kind(mode)
76
                yield child_path, "V", kind, self.path2id(path), None
77
                if recursive and kind == 'directory':
78
                    todo.add((child_path, hexsha))
79
80
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
81
        # FIXME: Support specific_file_ids
82
        #FIXME: yield actual inventory entries
83
        if specific_file_ids is not None:
84
            raise NotImplementedError(self.iter_entries_by_dir)
85
        todo = set([("", self.tree)])
86
        while todo:
87
            path, tree_sha = todo.pop()
88
            yield path, None
89
            tree = self.store[tree_sha]
90
            for name, mode, hexsha  in tree.iteritems():
91
                child_path = posixpath.join(path, name)
92
                if stat.S_ISDIR(mode):
93
                    todo.add((child_path, hexsha))
94
                else:
95
                    yield child_path, None
96
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
97
    def get_revision_id(self):
0.200.959 by Jelmer Vernooij
Improve docstrings.
98
        """See RevisionTree.get_revision_id."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
99
        return self._revision_id
100
101
    def get_file_text(self, file_id, path=None):
0.200.959 by Jelmer Vernooij
Improve docstrings.
102
        """See RevisionTree.get_file_text."""
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
103
        if path is None:
104
            path = self.id2path(file_id)
105
        (mode, hexsha)= tree_lookup_path(self.store.__getitem__, self.tree, path)
106
        if stat.S_ISREG(mode):
107
            return self.store[hexsha].data
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
108
        else:
0.200.664 by Jelmer Vernooij
Support submodules during fetch.
109
            return ""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
110
111
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
112
def tree_delta_from_git_changes(changes, mapping,
113
        (old_fileid_map, new_fileid_map), specific_file=None,
114
        require_versioned=False):
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
115
    """Create a TreeDelta from two git trees.
0.200.959 by Jelmer Vernooij
Improve docstrings.
116
117
    source and target are iterators over tuples with:
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
118
        (filename, sha, mode)
119
    """
120
    ret = delta.TreeDelta()
121
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
122
        if mapping.is_control_file(oldpath):
123
            oldpath = None
124
        if mapping.is_control_file(newpath):
125
            newpath = None
126
        if oldpath is None and newpath is None:
127
            continue
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
128
        if oldpath is None:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
129
            ret.added.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
130
        elif newpath is None:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
131
            ret.removed.append((oldpath, old_fileid_map.lookup_file_id(oldpath.encode("utf-8")), mode_kind(oldmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
132
        elif oldpath != newpath:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
133
            ret.renamed.append((oldpath, newpath, old_fileid_map.lookup_file_id(oldpath.encode("utf-8")), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
134
        elif mode_kind(oldmode) != mode_kind(newmode):
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
135
            ret.kind_changed.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(oldmode), mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
136
        elif oldsha != newsha or oldmode != newmode:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
137
            ret.modified.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
138
        else:
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
139
            ret.unchanged.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
140
    return ret
141
142
0.200.959 by Jelmer Vernooij
Improve docstrings.
143
def changes_from_git_changes(changes, mapping, specific_file=None,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
144
                                require_versioned=False):
145
    """Create a iter_changes-like generator from a git stream.
0.200.959 by Jelmer Vernooij
Improve docstrings.
146
147
    source and target are iterators over tuples with:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
148
        (filename, sha, mode)
149
    """
150
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
151
        path = (oldpath, newpath)
152
        if oldpath is None:
153
            fileid = mapping.generate_file_id(newpath)
154
            oldexe = None
155
            oldkind = None
156
            oldname = None
157
            oldparent = None
158
        else:
159
            oldexe = mode_is_executable(oldmode)
160
            oldkind = mode_kind(oldmode)
161
            try:
162
                (oldparentpath, oldname) = oldpath.rsplit("/", 1)
163
            except ValueError:
164
                oldparent = None
165
                oldname = oldpath
166
            else:
167
                oldparent = mapping.generate_file_id(oldparentpath)
168
            fileid = mapping.generate_file_id(oldpath)
169
        if newpath is None:
170
            newexe = None
171
            newkind = None
172
            newname = None
173
            newparent = None
174
        else:
175
            newexe = mode_is_executable(newmode)
176
            newkind = mode_kind(newmode)
177
            try:
178
                newparentpath, newname = newpath.rsplit("/", 1)
179
            except ValueError:
180
                newparent = None
181
                newname = newpath
182
            else:
183
                newparent = mapping.generate_file_id(newparentpath)
0.200.959 by Jelmer Vernooij
Improve docstrings.
184
        yield (fileid, (oldpath, newpath), (oldsha != newsha),
185
             (oldpath is not None, newpath is not None),
186
             (oldparent, newparent), (oldname, newname),
187
             (oldkind, newkind), (oldexe, newexe))
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
188
189
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
190
class InterGitRevisionTrees(tree.InterTree):
191
    """InterTree that works between two git revision trees."""
192
0.200.659 by Jelmer Vernooij
Prevent tests using InterGitRevisionTrees.
193
    _matching_from_tree_format = None
194
    _matching_to_tree_format = None
195
    _test_mutable_trees_to_test_trees = None
196
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
197
    @classmethod
198
    def is_compatible(cls, source, target):
0.200.959 by Jelmer Vernooij
Improve docstrings.
199
        return (isinstance(source, GitRevisionTree) and
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
200
                isinstance(target, GitRevisionTree))
201
202
    def compare(self, want_unchanged=False, specific_files=None,
203
                extra_trees=None, require_versioned=False, include_root=False,
204
                want_unversioned=False):
205
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
206
            raise AssertionError
207
        changes = self.source._repository._git.object_store.tree_changes(
208
            self.source.tree, self.target.tree, want_unchanged=want_unchanged)
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
209
        source_fileid_map = self.source.mapping.get_fileid_map(
210
            self.source._repository._git.object_store.__getitem__,
211
            self.source.tree)
212
        target_fileid_map = self.target.mapping.get_fileid_map(
213
            self.target._repository._git.object_store.__getitem__,
214
            self.target.tree)
0.200.959 by Jelmer Vernooij
Improve docstrings.
215
        return tree_delta_from_git_changes(changes, self.target.mapping,
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
216
            (source_fileid_map, target_fileid_map),
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
217
            specific_file=specific_files)
218
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
219
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.200.959 by Jelmer Vernooij
Improve docstrings.
220
        pb=None, extra_trees=[], require_versioned=True,
221
        want_unversioned=False):
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
222
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
223
            raise AssertionError
224
        changes = self.source._repository._git.object_store.tree_changes(
0.200.959 by Jelmer Vernooij
Improve docstrings.
225
            self.source.tree, self.target.tree,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
226
            want_unchanged=include_unchanged)
0.200.959 by Jelmer Vernooij
Improve docstrings.
227
        return changes_from_git_changes(changes, self.target.mapping,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
228
            specific_file=specific_files)
229
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
230
231
tree.InterTree.register_optimiser(InterGitRevisionTrees)