/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.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
20
from __future__ import absolute_import
21
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
22
from dulwich.object_store import tree_lookup_path
23
import stat
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
24
import posixpath
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
25
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
26
from ... import (
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
27
    delta,
28
    errors,
0.264.10 by Jelmer Vernooij
Yield inventory entries.
29
    osutils,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
30
    revisiontree,
31
    tree,
32
    )
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
33
from ...revision import NULL_REVISION
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
34
from ...bzr import (
35
    inventory,
36
    )
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
37
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
38
from .mapping import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
39
    mode_is_executable,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
40
    mode_kind,
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
41
    GitFileIdMap,
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
42
    default_mapping,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
43
    )
44
45
46
class GitRevisionTree(revisiontree.RevisionTree):
0.200.959 by Jelmer Vernooij
Improve docstrings.
47
    """Revision tree implementation based on Git objects."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
48
49
    def __init__(self, repository, revision_id):
50
        self._revision_id = revision_id
51
        self._repository = repository
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
52
        self.store = repository._git.object_store
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
53
        assert isinstance(revision_id, str)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
54
        self.commit_id, self.mapping = repository.lookup_bzr_revision_id(revision_id)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
55
        if revision_id == NULL_REVISION:
56
            self.tree = None
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
57
            self.mapping = default_mapping
58
            self._fileid_map = GitFileIdMap(
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
59
                {},
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
60
                default_mapping)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
61
        else:
62
            try:
63
                commit = self.store[self.commit_id]
64
            except KeyError, r:
65
                raise errors.NoSuchRevision(repository, revision_id)
66
            self.tree = commit.tree
67
            self._fileid_map = self.mapping.get_fileid_map(self.store.__getitem__, self.tree)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
68
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
69
    def get_file_revision(self, path, file_id=None):
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
70
        change_scanner = self._repository._file_change_scanner
71
        (path, commit_id) = change_scanner.find_last_change_revision(path,
72
            self.commit_id)
73
        return self._repository.lookup_foreign_revision_id(commit_id, self.mapping)
74
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
75
    def get_file_mtime(self, path, file_id=None):
76
        revid = self.get_file_revision(path, file_id)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
77
        try:
78
            rev = self._repository.get_revision(revid)
79
        except errors.NoSuchRevision:
80
            raise errors.FileTimestampUnavailable(path)
81
        return rev.timestamp
82
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
83
    def id2path(self, file_id):
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
84
        try:
85
            return self._fileid_map.lookup_path(file_id)
86
        except ValueError:
0.200.1714 by Jelmer Vernooij
Fix NoSuchId raising.
87
            raise errors.NoSuchId(self, file_id)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
88
89
    def path2id(self, path):
0.200.1328 by Jelmer Vernooij
More test fixes.
90
        if self.mapping.is_special_file(path):
91
            return None
92
        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.
93
0.200.1569 by Jelmer Vernooij
Implement GitRevisionTree.all_file_ids().
94
    def all_file_ids(self):
95
        return set(self._fileid_map.all_file_ids())
96
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
97
    def all_versioned_paths(self):
98
        ret = set()
99
        todo = set([('', self.tree)])
100
        while todo:
101
            (path, tree_id) = todo.pop()
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
102
            if tree_id is None:
103
                continue
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
104
            tree = self.store[tree_id]
105
            for name, mode, hexsha in tree.iteritems():
106
                subpath = posixpath.join(path, name)
107
                if stat.S_ISDIR(mode):
108
                    todo.add((subpath, hexsha))
109
                else:
110
                    ret.add(subpath)
111
        return ret
112
0.200.1204 by Jelmer Vernooij
Implement GitRevisionTree.get_root_id().
113
    def get_root_id(self):
114
        return self.path2id("")
115
0.200.1208 by Jelmer Vernooij
Add GitWorkingTree.has_id and GitWorkingTree.has_or_had_id.
116
    def has_or_had_id(self, file_id):
117
        return self.has_id(file_id)
118
119
    def has_id(self, file_id):
120
        try:
121
            path = self.id2path(file_id)
122
        except errors.NoSuchId:
123
            return False
124
        return self.has_filename(path)
125
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
126
    def is_executable(self, path, file_id=None):
0.200.1615 by Jelmer Vernooij
Implement GitRevisionTree.is_executable.:
127
        try:
128
            (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree,
129
                path)
130
        except KeyError:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
131
            raise errors.NoSuchId(self, path)
0.200.1615 by Jelmer Vernooij
Implement GitRevisionTree.is_executable.:
132
        if mode is None:
133
            # the tree root is a directory
134
            return False
135
        return mode_is_executable(mode)
136
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
137
    def kind(self, path, file_id=None):
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
138
        if self.tree is None:
0.287.5 by Jelmer Vernooij
Fix root handling.
139
            raise errors.NoSuchFile(path)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
140
        try:
141
            (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree,
142
                path)
143
        except KeyError:
0.287.5 by Jelmer Vernooij
Fix root handling.
144
            raise errors.NoSuchFile(path)
0.200.1253 by Jelmer Vernooij
Fix Tree.kind(TREE_ROOT).
145
        if mode is None:
146
            # the tree root is a directory
147
            return "directory"
0.200.1241 by Jelmer Vernooij
Implement GitRevisionTree.kind.
148
        return mode_kind(mode)
149
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
150
    def has_filename(self, path):
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
151
        if self.tree is None:
152
            return False
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
153
        try:
154
            tree_lookup_path(self.store.__getitem__, self.tree,
155
                path.encode("utf-8"))
156
        except KeyError:
157
            return False
158
        else:
159
            return True
160
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
161
    def list_files(self, include_root=False, from_dir=None, recursive=True):
162
        if from_dir is None:
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
163
            from_dir = u""
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
164
        if self.tree is None:
165
            return
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
166
        (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree,
167
            from_dir.encode("utf-8"))
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
168
        if mode is None: # Root
0.264.10 by Jelmer Vernooij
Yield inventory entries.
169
            root_ie = self._get_dir_ie("", None)
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
170
        else:
0.264.10 by Jelmer Vernooij
Yield inventory entries.
171
            parent_path = posixpath.dirname(from_dir.encode("utf-8"))
0.200.1328 by Jelmer Vernooij
More test fixes.
172
            parent_id = self._fileid_map.lookup_file_id(parent_path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
173
            if mode_kind(mode) == 'directory':
174
                root_ie = self._get_dir_ie(from_dir.encode("utf-8"), parent_id)
175
            else:
176
                root_ie = self._get_file_ie(from_dir.encode("utf-8"),
177
                    posixpath.basename(from_dir), mode, hexsha)
178
        if from_dir != "" or include_root:
179
            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.
180
        todo = set()
0.264.10 by Jelmer Vernooij
Yield inventory entries.
181
        if root_ie.kind == 'directory':
182
            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.
183
        while todo:
0.264.10 by Jelmer Vernooij
Yield inventory entries.
184
            (path, hexsha, parent_id) = todo.pop()
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
185
            tree = self.store[hexsha]
186
            for name, mode, hexsha in tree.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
187
                if self.mapping.is_special_file(name):
188
                    continue
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
189
                child_path = posixpath.join(path, name)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
190
                if stat.S_ISDIR(mode):
191
                    ie = self._get_dir_ie(child_path, parent_id)
192
                    if recursive:
193
                        todo.add((child_path, hexsha, ie.file_id))
194
                else:
195
                    ie = self._get_file_ie(child_path, name, mode, hexsha, parent_id)
196
                yield child_path, "V", ie.kind, ie.file_id, ie
197
198
    def _get_file_ie(self, path, name, mode, hexsha, parent_id):
199
        kind = mode_kind(mode)
0.200.1328 by Jelmer Vernooij
More test fixes.
200
        file_id = self._fileid_map.lookup_file_id(path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
201
        ie = inventory.entry_factory[kind](file_id, name.decode("utf-8"), parent_id)
202
        if kind == 'symlink':
203
            ie.symlink_target = self.store[hexsha].data
0.200.1401 by Jelmer Vernooij
Cope with submodules in working trees.
204
        elif kind == 'tree-reference':
205
            ie.reference_revision = self.mapping.revision_id_foreign_to_bzr(hexsha)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
206
        else:
207
            data = self.store[hexsha].data
208
            ie.text_sha1 = osutils.sha_string(data)
209
            ie.text_size = len(data)
210
            ie.executable = mode_is_executable(mode)
211
        return ie
212
213
    def _get_dir_ie(self, path, parent_id):
0.200.1328 by Jelmer Vernooij
More test fixes.
214
        file_id = self._fileid_map.lookup_file_id(path)
0.287.6 by Jelmer Vernooij
Fix some more tests.
215
        ie = inventory.InventoryDirectory(file_id,
0.264.10 by Jelmer Vernooij
Yield inventory entries.
216
            posixpath.basename(path).decode("utf-8"), parent_id)
0.287.6 by Jelmer Vernooij
Fix some more tests.
217
        ie.revision = self.get_file_revision(path)
218
        return ie
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
219
0.200.1744 by Jelmer Vernooij
Implement GitRevisionTree.iter_children.
220
    def iter_children(self, file_id):
221
        path = self._fileid_map.lookup_path(file_id)
222
        mode, tree_sha = tree_lookup_path(self.store.__getitem__, self.tree, path)
223
        if stat.S_ISDIR(mode):
224
            for name, mode, hexsha  in self.store[tree_sha].iteritems():
225
                yield self._fileid_map.lookup_file_id(posixpath.join(path, name))
226
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
227
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
228
        if self.tree is None:
229
            return
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
230
        # FIXME: Support yield parents
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
231
        if specific_file_ids is not None:
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
232
            specific_paths = [self.id2path(file_id) for file_id in specific_file_ids]
233
            if specific_paths in ([u""], []):
234
                specific_paths = None
235
            else:
236
                specific_paths = set(specific_paths)
237
        else:
238
            specific_paths = None
0.264.10 by Jelmer Vernooij
Yield inventory entries.
239
        todo = set([("", self.tree, None)])
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
240
        while todo:
0.264.10 by Jelmer Vernooij
Yield inventory entries.
241
            path, tree_sha, parent_id = todo.pop()
242
            ie = self._get_dir_ie(path, parent_id)
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
243
            if specific_paths is None or path in specific_paths:
0.200.1715 by Jelmer Vernooij
Fix some more tests.
244
                yield path.decode("utf-8"), ie
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
245
            tree = self.store[tree_sha]
246
            for name, mode, hexsha  in tree.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
247
                if self.mapping.is_special_file(name):
248
                    continue
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
249
                child_path = posixpath.join(path, name)
250
                if stat.S_ISDIR(mode):
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
251
                    if (specific_paths is None or
252
                        any(filter(lambda p: p.startswith(child_path), specific_paths))):
253
                        todo.add((child_path, hexsha, ie.file_id))
254
                elif specific_paths is None or child_path in specific_paths:
0.200.1715 by Jelmer Vernooij
Fix some more tests.
255
                    yield (child_path.decode("utf-8"),
0.200.1307 by Jelmer Vernooij
Formatting fixes, specify path to a couple more functions.
256
                            self._get_file_ie(child_path, name, mode, hexsha,
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
257
                           ie.file_id))
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
258
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
259
    def get_revision_id(self):
0.200.959 by Jelmer Vernooij
Improve docstrings.
260
        """See RevisionTree.get_revision_id."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
261
        return self._revision_id
262
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
263
    def get_file_sha1(self, path, file_id=None, stat_value=None):
0.287.6 by Jelmer Vernooij
Fix some more tests.
264
        if self.tree is None:
265
            raise errors.NoSuchFile(path)
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
266
        return osutils.sha_string(self.get_file_text(path, file_id))
0.200.1255 by Jelmer Vernooij
Implement GitRevisionTree.get_file_sha1.
267
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
268
    def get_file_verifier(self, path, file_id=None, stat_value=None):
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
269
        (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree,
270
            path)
271
        return ("GIT", hexsha)
272
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
273
    def get_file_text(self, path, file_id=None):
0.200.959 by Jelmer Vernooij
Improve docstrings.
274
        """See RevisionTree.get_file_text."""
0.287.5 by Jelmer Vernooij
Fix root handling.
275
        if self.tree is None:
276
            raise errors.NoSuchFile(path)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
277
        (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree, path)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
278
        if stat.S_ISREG(mode):
279
            return self.store[hexsha].data
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
280
        else:
0.200.664 by Jelmer Vernooij
Support submodules during fetch.
281
            return ""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
282
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
283
    def get_symlink_target(self, path, file_id=None):
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
284
        """See RevisionTree.get_symlink_target."""
0.200.1701 by Jelmer Vernooij
Fix a few tests.
285
        (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree, path.encode('utf-8'))
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
286
        if stat.S_ISLNK(mode):
0.200.1701 by Jelmer Vernooij
Fix a few tests.
287
            return self.store[hexsha].data.decode('utf-8')
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
288
        else:
289
            return None
290
0.264.10 by Jelmer Vernooij
Yield inventory entries.
291
    def _comparison_data(self, entry, path):
292
        if entry is None:
293
            return None, False, None
294
        return entry.kind, entry.executable, None
295
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
296
    def path_content_summary(self, path):
297
        """See Tree.path_content_summary."""
298
        try:
299
            (mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree, path)
300
        except KeyError:
301
            return ('missing', None, None, None)
302
        kind = mode_kind(mode)
303
        if kind == 'file':
304
            executable = mode_is_executable(mode)
305
            contents = self.store[hexsha].data
306
            return (kind, len(contents), executable, osutils.sha_string(contents))
307
        elif kind == 'symlink':
308
            return (kind, None, None, self.store[hexsha].data)
309
        else:
310
            return (kind, None, None, None)
311
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
312
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
313
def tree_delta_from_git_changes(changes, mapping,
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
314
        (old_fileid_map, new_fileid_map), specific_files=None,
0.287.5 by Jelmer Vernooij
Fix root handling.
315
        require_versioned=False, include_root=False):
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
316
    """Create a TreeDelta from two git trees.
0.200.959 by Jelmer Vernooij
Improve docstrings.
317
318
    source and target are iterators over tuples with:
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
319
        (filename, sha, mode)
320
    """
321
    ret = delta.TreeDelta()
322
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
0.287.5 by Jelmer Vernooij
Fix root handling.
323
        if newpath == u'' and not include_root:
324
            continue
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
325
        if not (specific_files is None or
0.287.5 by Jelmer Vernooij
Fix root handling.
326
                (oldpath is not None and osutils.is_inside_or_parent_of_any(specific_files, oldpath)) or
327
                (newpath is not None and osutils.is_inside_or_parent_of_any(specific_files, newpath))):
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
328
            continue
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
329
        if mapping.is_special_file(oldpath):
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
330
            oldpath = None
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
331
        if mapping.is_special_file(newpath):
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
332
            newpath = None
333
        if oldpath is None and newpath is None:
334
            continue
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
335
        if oldpath is None:
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
336
            file_id = new_fileid_map.lookup_file_id(newpath)
337
            ret.added.append((newpath.decode('utf-8'), file_id, mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
338
        elif newpath is None:
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
339
            file_id = old_fileid_map.lookup_file_id(oldpath)
340
            ret.removed.append((oldpath.decode('utf-8'), file_id, mode_kind(oldmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
341
        elif oldpath != newpath:
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
342
            file_id = old_fileid_map.lookup_file_id(oldpath)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
343
            ret.renamed.append(
344
                (oldpath.decode('utf-8'), newpath.decode('utf-8'), file_id,
345
                mode_kind(newmode), (oldsha != newsha),
346
                (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
347
        elif mode_kind(oldmode) != mode_kind(newmode):
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
348
            file_id = new_fileid_map.lookup_file_id(newpath)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
349
            ret.kind_changed.append(
350
                (newpath.decode('utf-8'), file_id, mode_kind(oldmode),
351
                mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
352
        elif oldsha != newsha or oldmode != newmode:
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
353
            if stat.S_ISDIR(oldmode) and stat.S_ISDIR(newmode):
354
                continue
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
355
            file_id = new_fileid_map.lookup_file_id(newpath)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
356
            ret.modified.append(
357
                (newpath.decode('utf-8'), file_id, mode_kind(newmode),
358
                (oldsha != newsha), (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
359
        else:
0.200.1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
360
            file_id = new_fileid_map.lookup_file_id(newpath)
361
            ret.unchanged.append((newpath.decode('utf-8'), file_id, mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
362
    return ret
363
364
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
365
def changes_from_git_changes(changes, mapping, specific_files=None,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
366
                                require_versioned=False):
367
    """Create a iter_changes-like generator from a git stream.
0.200.959 by Jelmer Vernooij
Improve docstrings.
368
369
    source and target are iterators over tuples with:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
370
        (filename, sha, mode)
371
    """
372
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
373
        if not (specific_files is None or
0.287.5 by Jelmer Vernooij
Fix root handling.
374
                (oldpath is not None and osutils.is_inside_or_parent_of_any(specific_files, oldpath)) or
375
                (newpath is not None and osutils.is_inside_or_parent_of_any(specific_files, newpath))):
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
376
            continue
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
377
        path = (oldpath, newpath)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
378
        if oldpath is not None and mapping.is_special_file(oldpath):
379
            continue
380
        if newpath is not None and mapping.is_special_file(newpath):
0.200.1328 by Jelmer Vernooij
More test fixes.
381
            continue
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
382
        if oldpath is None:
383
            fileid = mapping.generate_file_id(newpath)
384
            oldexe = None
385
            oldkind = None
386
            oldname = None
387
            oldparent = None
388
        else:
0.200.1345 by Jelmer Vernooij
paths should be unicode when yielded by iter_changes.
389
            oldpath = oldpath.decode("utf-8")
0.200.1576 by Jelmer Vernooij
Merge a bunch of fixes from store-roundtrip-info.
390
            assert oldmode is not None
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
391
            oldexe = mode_is_executable(oldmode)
392
            oldkind = mode_kind(oldmode)
393
            try:
394
                (oldparentpath, oldname) = oldpath.rsplit("/", 1)
395
            except ValueError:
396
                oldparent = None
397
                oldname = oldpath
398
            else:
399
                oldparent = mapping.generate_file_id(oldparentpath)
400
            fileid = mapping.generate_file_id(oldpath)
401
        if newpath is None:
402
            newexe = None
403
            newkind = None
404
            newname = None
405
            newparent = None
406
        else:
0.200.1345 by Jelmer Vernooij
paths should be unicode when yielded by iter_changes.
407
            newpath = newpath.decode("utf-8")
0.200.1576 by Jelmer Vernooij
Merge a bunch of fixes from store-roundtrip-info.
408
            if newmode is not None:
409
                newexe = mode_is_executable(newmode)
410
                newkind = mode_kind(newmode)
411
            else:
412
                newexe = False
413
                newkind = None
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
414
            try:
415
                newparentpath, newname = newpath.rsplit("/", 1)
416
            except ValueError:
417
                newparent = None
418
                newname = newpath
419
            else:
420
                newparent = mapping.generate_file_id(newparentpath)
0.200.959 by Jelmer Vernooij
Improve docstrings.
421
        yield (fileid, (oldpath, newpath), (oldsha != newsha),
422
             (oldpath is not None, newpath is not None),
423
             (oldparent, newparent), (oldname, newname),
424
             (oldkind, newkind), (oldexe, newexe))
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
425
426
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
427
class InterGitTrees(tree.InterTree):
428
    """InterTree that works between two git trees."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
429
0.200.659 by Jelmer Vernooij
Prevent tests using InterGitRevisionTrees.
430
    _matching_from_tree_format = None
431
    _matching_to_tree_format = None
432
    _test_mutable_trees_to_test_trees = None
433
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
434
    @classmethod
435
    def is_compatible(cls, source, target):
0.200.959 by Jelmer Vernooij
Improve docstrings.
436
        return (isinstance(source, GitRevisionTree) and
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
437
                isinstance(target, GitRevisionTree))
438
439
    def compare(self, want_unchanged=False, specific_files=None,
440
                extra_trees=None, require_versioned=False, include_root=False,
441
                want_unversioned=False):
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
442
        changes = self._iter_git_changes(want_unchanged=want_unchanged)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
443
        source_fileid_map = self.source._fileid_map
444
        target_fileid_map = self.target._fileid_map
0.200.959 by Jelmer Vernooij
Improve docstrings.
445
        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.
446
            (source_fileid_map, target_fileid_map),
0.287.5 by Jelmer Vernooij
Fix root handling.
447
            specific_files=specific_files, include_root=include_root)
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
448
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
449
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
450
                     pb=None, extra_trees=[], require_versioned=True,
451
                     want_unversioned=False):
452
        changes = self._iter_git_changes(want_unchanged=include_unchanged)
0.200.959 by Jelmer Vernooij
Improve docstrings.
453
        return changes_from_git_changes(changes, self.target.mapping,
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
454
            specific_files=specific_files)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
455
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
456
    def _iter_git_changes(self, want_unchanged=False):
457
        raise NotImplementedError(self._iter_git_changes)
458
459
460
class InterGitRevisionTrees(InterGitTrees):
461
    """InterTree that works between two git revision trees."""
462
463
    _matching_from_tree_format = None
464
    _matching_to_tree_format = None
465
    _test_mutable_trees_to_test_trees = None
466
467
    @classmethod
468
    def is_compatible(cls, source, target):
469
        return (isinstance(source, GitRevisionTree) and
470
                isinstance(target, GitRevisionTree))
471
472
    def _iter_git_changes(self, want_unchanged=False):
473
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
474
            raise AssertionError
475
        return self.source._repository._git.object_store.tree_changes(
476
            self.source.tree, self.target.tree, want_unchanged=want_unchanged,
477
            include_trees=True)
478
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
479
480
tree.InterTree.register_optimiser(InterGitRevisionTrees)