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