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