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