/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.358.2 by Jelmer Vernooij
Refresh copyright headers, add my email.
1
# Copyright (C) 2009-2018 Jelmer Vernooij <jelmer@jelmer.uk>
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
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
0.358.1 by Jelmer Vernooij
Fix FSF address.
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
16
17
18
"""Git Trees."""
19
0.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
20
from __future__ import absolute_import
21
7096.3.2 by Jelmer Vernooij
Fix some git tests.
22
from collections import deque
0.360.2 by Jelmer Vernooij
Fix test.
23
import errno
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
24
from io import BytesIO
25
import os
26
27
from dulwich.index import (
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
28
    blob_from_path_and_stat,
29
    cleanup_mode,
30
    commit_tree,
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
31
    index_entry_from_stat,
32
    )
0.200.1780 by Jelmer Vernooij
Fix cross-object-store tree comparison.
33
from dulwich.object_store import (
34
    tree_lookup_path,
35
    OverlayObjectStore,
36
    )
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
37
from dulwich.objects import (
38
    Blob,
39
    Tree,
0.372.1 by Jelmer Vernooij
Fix some missing id handling.
40
    ZERO_SHA,
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
41
    S_IFGITLINK,
0.429.7 by Jelmer Vernooij
Consistent file ids.
42
    S_ISGITLINK,
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
43
    )
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
44
import stat
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
45
import posixpath
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
46
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
47
from .. import (
0.429.26 by Jelmer Vernooij
Fix remaining test.
48
    controldir as _mod_controldir,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
49
    delta,
50
    errors,
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
51
    mutabletree,
0.264.10 by Jelmer Vernooij
Yield inventory entries.
52
    osutils,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
53
    revisiontree,
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
54
    trace,
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
55
    tree as _mod_tree,
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
56
    workingtree,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
57
    )
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
58
from ..revision import (
6973.2.1 by Jelmer Vernooij
Implement GitRevisionTree.annotate_iter.
59
    CURRENT_REVISION,
60
    NULL_REVISION,
61
    )
6986.2.2 by Jelmer Vernooij
Merge trunk.
62
from ..sixish import (
6973.9.1 by Jelmer Vernooij
More test fixes.
63
    text_type,
64
    viewitems,
65
    )
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
66
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
67
from .mapping import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
68
    mode_is_executable,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
69
    mode_kind,
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
70
    GitFileIdMap,
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
71
    default_mapping,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
72
    )
73
74
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
75
class GitTreeDirectory(_mod_tree.TreeDirectory):
76
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
77
    __slots__ = ['file_id', 'name', 'parent_id', 'children']
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
78
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
79
    def __init__(self, file_id, name, parent_id):
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
80
        self.file_id = file_id
81
        self.name = name
82
        self.parent_id = parent_id
83
        # TODO(jelmer)
84
        self.children = {}
85
86
    @property
87
    def kind(self):
88
        return 'directory'
89
90
    @property
91
    def executable(self):
92
        return False
93
94
    def copy(self):
95
        return self.__class__(
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
96
            self.file_id, self.name, self.parent_id)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
97
98
    def __repr__(self):
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
99
        return "%s(file_id=%r, name=%r, parent_id=%r)" % (
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
100
            self.__class__.__name__, self.file_id, self.name,
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
101
            self.parent_id)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
102
103
    def __eq__(self, other):
104
        return (self.kind == other.kind and
105
                self.file_id == other.file_id and
106
                self.name == other.name and
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
107
                self.parent_id == other.parent_id)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
108
109
110
class GitTreeFile(_mod_tree.TreeFile):
111
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
112
    __slots__ = ['file_id', 'name', 'parent_id', 'text_size', 'text_sha1',
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
113
                 'executable']
114
0.390.2 by Jelmer Vernooij
merge trunk
115
    def __init__(self, file_id, name, parent_id, text_size=None,
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
116
                 text_sha1=None, executable=None):
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
117
        self.file_id = file_id
118
        self.name = name
119
        self.parent_id = parent_id
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
120
        self.text_size = text_size
121
        self.text_sha1 = text_sha1
122
        self.executable = executable
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
123
124
    @property
125
    def kind(self):
126
        return 'file'
127
128
    def __eq__(self, other):
129
        return (self.kind == other.kind and
130
                self.file_id == other.file_id and
131
                self.name == other.name and
132
                self.parent_id == other.parent_id and
133
                self.text_sha1 == other.text_sha1 and
134
                self.text_size == other.text_size and
135
                self.executable == other.executable)
136
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
137
    def __repr__(self):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
138
        return ("%s(file_id=%r, name=%r, parent_id=%r, text_size=%r, "
139
                "text_sha1=%r, executable=%r)") % (
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
140
            type(self).__name__, self.file_id, self.name, self.parent_id,
0.390.2 by Jelmer Vernooij
merge trunk
141
            self.text_size, self.text_sha1, self.executable)
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
142
0.365.2 by Jelmer Vernooij
Add eq/copy.
143
    def copy(self):
144
        ret = self.__class__(
7143.15.2 by Jelmer Vernooij
Run autopep8.
145
            self.file_id, self.name, self.parent_id)
0.365.2 by Jelmer Vernooij
Add eq/copy.
146
        ret.text_sha1 = self.text_sha1
147
        ret.text_size = self.text_size
148
        ret.executable = self.executable
149
        return ret
150
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
151
152
class GitTreeSymlink(_mod_tree.TreeLink):
153
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
154
    __slots__ = ['file_id', 'name', 'parent_id', 'symlink_target']
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
155
0.390.1 by Jelmer Vernooij
Don't set .revision for returned TreeEntry objects; it's slow, and callers can call Tree.get_file_revision if they really care.
156
    def __init__(self, file_id, name, parent_id,
0.365.2 by Jelmer Vernooij
Add eq/copy.
157
                 symlink_target=None):
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
158
        self.file_id = file_id
159
        self.name = name
160
        self.parent_id = parent_id
0.365.2 by Jelmer Vernooij
Add eq/copy.
161
        self.symlink_target = symlink_target
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
162
163
    @property
164
    def kind(self):
165
        return 'symlink'
166
167
    @property
168
    def executable(self):
169
        return False
170
171
    @property
172
    def text_size(self):
173
        return None
174
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
175
    def __repr__(self):
0.390.2 by Jelmer Vernooij
merge trunk
176
        return "%s(file_id=%r, name=%r, parent_id=%r, symlink_target=%r)" % (
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
177
            type(self).__name__, self.file_id, self.name, self.parent_id,
0.390.2 by Jelmer Vernooij
merge trunk
178
            self.symlink_target)
0.389.2 by Jelmer Vernooij
Add repr implementation to GitTreeFile & GitTreeLink.
179
0.365.2 by Jelmer Vernooij
Add eq/copy.
180
    def __eq__(self, other):
181
        return (self.kind == other.kind and
182
                self.file_id == other.file_id and
183
                self.name == other.name and
184
                self.parent_id == other.parent_id and
185
                self.symlink_target == other.symlink_target)
186
187
    def copy(self):
188
        return self.__class__(
7143.15.2 by Jelmer Vernooij
Run autopep8.
189
            self.file_id, self.name, self.parent_id,
190
            self.symlink_target)
0.365.2 by Jelmer Vernooij
Add eq/copy.
191
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
192
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
193
class GitTreeSubmodule(_mod_tree.TreeLink):
194
0.429.12 by Jelmer Vernooij
Remove revision.
195
    __slots__ = ['file_id', 'name', 'parent_id', 'reference_revision']
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
196
0.429.12 by Jelmer Vernooij
Remove revision.
197
    def __init__(self, file_id, name, parent_id, reference_revision=None):
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
198
        self.file_id = file_id
199
        self.name = name
200
        self.parent_id = parent_id
201
        self.reference_revision = reference_revision
202
203
    @property
204
    def kind(self):
205
        return 'tree-reference'
206
207
    def __repr__(self):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
208
        return ("%s(file_id=%r, name=%r, parent_id=%r, "
209
                "reference_revision=%r)") % (
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
210
            type(self).__name__, self.file_id, self.name, self.parent_id,
0.429.12 by Jelmer Vernooij
Remove revision.
211
            self.reference_revision)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
212
213
    def __eq__(self, other):
214
        return (self.kind == other.kind and
215
                self.file_id == other.file_id and
216
                self.name == other.name and
217
                self.parent_id == other.parent_id and
218
                self.reference_revision == other.reference_revision)
219
220
    def copy(self):
221
        return self.__class__(
7143.15.2 by Jelmer Vernooij
Run autopep8.
222
            self.file_id, self.name, self.parent_id,
223
            self.reference_revision)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
224
225
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
226
entry_factory = {
227
    'directory': GitTreeDirectory,
228
    'file': GitTreeFile,
229
    'symlink': GitTreeSymlink,
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
230
    'tree-reference': GitTreeSubmodule,
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
231
    }
232
233
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
234
def ensure_normalized_path(path):
235
    """Check whether path is normalized.
236
237
    :raises InvalidNormalization: When path is not normalized, and cannot be
238
        accessed on this platform by the normalized path.
239
    :return: The NFC normalised version of path.
240
    """
241
    norm_path, can_access = osutils.normalized_filename(path)
242
    if norm_path != path:
243
        if can_access:
244
            return norm_path
245
        else:
246
            raise errors.InvalidNormalization(path)
247
    return path
248
249
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
250
class GitRevisionTree(revisiontree.RevisionTree):
0.200.959 by Jelmer Vernooij
Improve docstrings.
251
    """Revision tree implementation based on Git objects."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
252
253
    def __init__(self, repository, revision_id):
254
        self._revision_id = revision_id
255
        self._repository = repository
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
256
        self.store = repository._git.object_store
6964.2.3 by Jelmer Vernooij
Review comments.
257
        if not isinstance(revision_id, bytes):
0.361.1 by Jelmer Vernooij
Don't use assert.
258
            raise TypeError(revision_id)
7143.15.2 by Jelmer Vernooij
Run autopep8.
259
        self.commit_id, self.mapping = repository.lookup_bzr_revision_id(
260
            revision_id)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
261
        if revision_id == NULL_REVISION:
262
            self.tree = None
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
263
            self.mapping = default_mapping
264
            self._fileid_map = GitFileIdMap(
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
265
                {},
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
266
                default_mapping)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
267
        else:
268
            try:
269
                commit = self.store[self.commit_id]
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
270
            except KeyError:
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
271
                raise errors.NoSuchRevision(repository, revision_id)
272
            self.tree = commit.tree
7143.15.2 by Jelmer Vernooij
Run autopep8.
273
            self._fileid_map = self.mapping.get_fileid_map(
274
                self.store.__getitem__, self.tree)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
275
0.429.26 by Jelmer Vernooij
Fix remaining test.
276
    def _get_nested_repository(self, path):
277
        nested_repo_transport = self._repository.user_transport.clone(path)
7143.15.2 by Jelmer Vernooij
Run autopep8.
278
        nested_controldir = _mod_controldir.ControlDir.open_from_transport(
279
            nested_repo_transport)
0.429.26 by Jelmer Vernooij
Fix remaining test.
280
        return nested_controldir.find_repository()
281
0.349.1 by Jelmer Vernooij
Support supports_rename_tracking method.
282
    def supports_rename_tracking(self):
283
        return False
284
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
285
    def get_file_revision(self, path):
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
286
        change_scanner = self._repository._file_change_scanner
0.372.1 by Jelmer Vernooij
Fix some missing id handling.
287
        if self.commit_id == ZERO_SHA:
288
            return NULL_REVISION
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
289
        (unused_path, commit_id) = change_scanner.find_last_change_revision(
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
290
            path.encode('utf-8'), self.commit_id)
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
291
        return self._repository.lookup_foreign_revision_id(
292
            commit_id, self.mapping)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
293
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
294
    def get_file_mtime(self, path):
6965.1.1 by Jelmer Vernooij
Add basic support for horizoned history.
295
        try:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
296
            revid = self.get_file_revision(path)
6965.1.1 by Jelmer Vernooij
Add basic support for horizoned history.
297
        except KeyError:
7096.3.2 by Jelmer Vernooij
Fix some git tests.
298
            raise errors.NoSuchFile(path)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
299
        try:
300
            rev = self._repository.get_revision(revid)
301
        except errors.NoSuchRevision:
6965.1.1 by Jelmer Vernooij
Add basic support for horizoned history.
302
            raise _mod_tree.FileTimestampUnavailable(path)
0.200.1283 by Jelmer Vernooij
Provide Repository.get_file_graph() and Tree.get_file_revision().
303
        return rev.timestamp
304
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
305
    def id2path(self, file_id):
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
306
        try:
0.329.1 by Jelmer Vernooij
Check that path actually exists in Tree.id2path.
307
            path = self._fileid_map.lookup_path(file_id)
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
308
        except ValueError:
0.200.1714 by Jelmer Vernooij
Fix NoSuchId raising.
309
            raise errors.NoSuchId(self, file_id)
0.372.1 by Jelmer Vernooij
Fix some missing id handling.
310
        if self.is_versioned(path):
0.329.1 by Jelmer Vernooij
Check that path actually exists in Tree.id2path.
311
            return path
312
        raise errors.NoSuchId(self, file_id)
313
314
    def is_versioned(self, path):
315
        return self.has_filename(path)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
316
317
    def path2id(self, path):
0.200.1328 by Jelmer Vernooij
More test fixes.
318
        if self.mapping.is_special_file(path):
319
            return None
7096.3.6 by Jelmer Vernooij
Fix tests, on python 2 at least.
320
        if not self.is_versioned(path):
321
            return None
7018.3.2 by Jelmer Vernooij
Fix some git tests.
322
        return self._fileid_map.lookup_file_id(osutils.safe_unicode(path))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
323
0.200.1569 by Jelmer Vernooij
Implement GitRevisionTree.all_file_ids().
324
    def all_file_ids(self):
7170.3.1 by Jelmer Vernooij
Make Tree.all_file_ids optional.
325
        raise errors.UnsupportedOperation(self.all_file_ids, self)
0.200.1569 by Jelmer Vernooij
Implement GitRevisionTree.all_file_ids().
326
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
327
    def all_versioned_paths(self):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
328
        ret = {u''}
7045.2.17 by Jelmer Vernooij
Some more.
329
        todo = [(self.store, b'', self.tree)]
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
330
        while todo:
0.400.1 by Jelmer Vernooij
Track store in Tree.all_versioned_paths.
331
            (store, path, tree_id) = todo.pop()
0.287.2 by Jelmer Vernooij
Support empty trees in GitRevisionTree.
332
            if tree_id is None:
333
                continue
0.400.1 by Jelmer Vernooij
Track store in Tree.all_versioned_paths.
334
            tree = store[tree_id]
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
335
            for name, mode, hexsha in tree.items():
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
336
                subpath = posixpath.join(path, name)
7096.3.2 by Jelmer Vernooij
Fix some git tests.
337
                ret.add(subpath.decode('utf-8'))
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
338
                if stat.S_ISDIR(mode):
7045.2.17 by Jelmer Vernooij
Some more.
339
                    todo.append((store, subpath, hexsha))
0.200.1724 by Jelmer Vernooij
Add GitRevisionTree.all_versioned_paths implementation.
340
        return ret
341
0.200.1204 by Jelmer Vernooij
Implement GitRevisionTree.get_root_id().
342
    def get_root_id(self):
0.378.1 by Jelmer Vernooij
Return None from Tree.get_root_id() when encountering an empty tree.
343
        if self.tree is None:
344
            return None
0.200.1204 by Jelmer Vernooij
Implement GitRevisionTree.get_root_id().
345
        return self.path2id("")
346
0.200.1208 by Jelmer Vernooij
Add GitWorkingTree.has_id and GitWorkingTree.has_or_had_id.
347
    def has_or_had_id(self, file_id):
0.372.1 by Jelmer Vernooij
Fix some missing id handling.
348
        try:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
349
            self.id2path(file_id)
0.372.1 by Jelmer Vernooij
Fix some missing id handling.
350
        except errors.NoSuchId:
351
            return False
352
        return True
0.200.1208 by Jelmer Vernooij
Add GitWorkingTree.has_id and GitWorkingTree.has_or_had_id.
353
354
    def has_id(self, file_id):
355
        try:
356
            path = self.id2path(file_id)
357
        except errors.NoSuchId:
358
            return False
359
        return self.has_filename(path)
360
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
361
    def _lookup_path(self, path):
362
        if self.tree is None:
363
            raise errors.NoSuchFile(path)
364
        try:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
365
            (mode, hexsha) = tree_lookup_path(
366
                self.store.__getitem__, self.tree, path.encode('utf-8'))
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
367
        except KeyError:
368
            raise errors.NoSuchFile(self, path)
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
369
        else:
370
            return (self.store, mode, hexsha)
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
371
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
372
    def is_executable(self, path):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
373
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1615 by Jelmer Vernooij
Implement GitRevisionTree.is_executable.:
374
        if mode is None:
375
            # the tree root is a directory
376
            return False
377
        return mode_is_executable(mode)
378
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
379
    def kind(self, path):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
380
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1253 by Jelmer Vernooij
Fix Tree.kind(TREE_ROOT).
381
        if mode is None:
382
            # the tree root is a directory
383
            return "directory"
0.200.1241 by Jelmer Vernooij
Implement GitRevisionTree.kind.
384
        return mode_kind(mode)
385
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
386
    def has_filename(self, path):
387
        try:
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
388
            self._lookup_path(path)
389
        except errors.NoSuchFile:
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
390
            return False
391
        else:
392
            return True
393
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
394
    def list_files(self, include_root=False, from_dir=None, recursive=True):
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
395
        if self.tree is None:
396
            return
7143.17.1 by Jelmer Vernooij
Fix grep in git working trees.
397
        if from_dir is None or from_dir == '.':
0.200.1197 by Jelmer Vernooij
Implement GitRevisionTree.has_filename.
398
            from_dir = u""
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
399
        (store, mode, hexsha) = self._lookup_path(from_dir)
7143.15.2 by Jelmer Vernooij
Run autopep8.
400
        if mode is None:  # Root
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
401
            root_ie = self._get_dir_ie(b"", None)
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
402
        else:
7096.3.2 by Jelmer Vernooij
Fix some git tests.
403
            parent_path = posixpath.dirname(from_dir)
0.200.1328 by Jelmer Vernooij
More test fixes.
404
            parent_id = self._fileid_map.lookup_file_id(parent_path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
405
            if mode_kind(mode) == 'directory':
406
                root_ie = self._get_dir_ie(from_dir.encode("utf-8"), parent_id)
407
            else:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
408
                root_ie = self._get_file_ie(
409
                    store, from_dir.encode("utf-8"),
410
                    posixpath.basename(from_dir), mode, hexsha)
7096.3.2 by Jelmer Vernooij
Fix some git tests.
411
        if include_root:
0.264.10 by Jelmer Vernooij
Yield inventory entries.
412
            yield (from_dir, "V", root_ie.kind, root_ie.file_id, root_ie)
7018.3.7 by Jelmer Vernooij
Fix remaining git tests.
413
        todo = []
0.264.10 by Jelmer Vernooij
Yield inventory entries.
414
        if root_ie.kind == 'directory':
7143.15.2 by Jelmer Vernooij
Run autopep8.
415
            todo.append((store, from_dir.encode("utf-8"),
416
                         b"", hexsha, root_ie.file_id))
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
417
        while todo:
7096.3.2 by Jelmer Vernooij
Fix some git tests.
418
            (store, path, relpath, hexsha, parent_id) = todo.pop()
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
419
            tree = store[hexsha]
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
420
            for name, mode, hexsha in tree.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
421
                if self.mapping.is_special_file(name):
422
                    continue
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
423
                child_path = posixpath.join(path, name)
7096.3.2 by Jelmer Vernooij
Fix some git tests.
424
                child_relpath = posixpath.join(relpath, name)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
425
                if stat.S_ISDIR(mode):
426
                    ie = self._get_dir_ie(child_path, parent_id)
427
                    if recursive:
7143.15.2 by Jelmer Vernooij
Run autopep8.
428
                        todo.append(
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
429
                            (store, child_path, child_relpath, hexsha,
430
                             ie.file_id))
0.264.10 by Jelmer Vernooij
Yield inventory entries.
431
                else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
432
                    ie = self._get_file_ie(
433
                        store, child_path, name, mode, hexsha, parent_id)
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
434
                yield (child_relpath.decode('utf-8'), "V", ie.kind, ie.file_id,
435
                       ie)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
436
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
437
    def _get_file_ie(self, store, path, name, mode, hexsha, parent_id):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
438
        if not isinstance(path, bytes):
0.361.1 by Jelmer Vernooij
Don't use assert.
439
            raise TypeError(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
440
        if not isinstance(name, bytes):
0.361.1 by Jelmer Vernooij
Don't use assert.
441
            raise TypeError(name)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
442
        kind = mode_kind(mode)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
443
        path = path.decode('utf-8')
444
        name = name.decode("utf-8")
0.200.1328 by Jelmer Vernooij
More test fixes.
445
        file_id = self._fileid_map.lookup_file_id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
446
        ie = entry_factory[kind](file_id, name, parent_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
447
        if kind == 'symlink':
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
448
            ie.symlink_target = store[hexsha].data.decode('utf-8')
0.200.1401 by Jelmer Vernooij
Cope with submodules in working trees.
449
        elif kind == 'tree-reference':
7143.15.2 by Jelmer Vernooij
Run autopep8.
450
            ie.reference_revision = self.mapping.revision_id_foreign_to_bzr(
451
                hexsha)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
452
        else:
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
453
            data = store[hexsha].data
0.264.10 by Jelmer Vernooij
Yield inventory entries.
454
            ie.text_sha1 = osutils.sha_string(data)
455
            ie.text_size = len(data)
456
            ie.executable = mode_is_executable(mode)
457
        return ie
458
459
    def _get_dir_ie(self, path, parent_id):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
460
        path = path.decode('utf-8')
0.200.1328 by Jelmer Vernooij
More test fixes.
461
        file_id = self._fileid_map.lookup_file_id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
462
        return GitTreeDirectory(file_id, posixpath.basename(path), parent_id)
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
463
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
464
    def iter_child_entries(self, path, file_id=None):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
465
        (store, mode, tree_sha) = self._lookup_path(path)
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
466
7096.3.1 by Jelmer Vernooij
Run tests against GitRevisionTree.
467
        if mode is not None and not stat.S_ISDIR(mode):
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
468
            return
469
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
470
        encoded_path = path.encode('utf-8')
471
        file_id = self.path2id(path)
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
472
        tree = store[tree_sha]
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
473
        for name, mode, hexsha in tree.iteritems():
474
            if self.mapping.is_special_file(name):
475
                continue
476
            child_path = posixpath.join(encoded_path, name)
477
            if stat.S_ISDIR(mode):
478
                yield self._get_dir_ie(child_path, file_id)
479
            else:
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
480
                yield self._get_file_ie(store, child_path, name, mode, hexsha,
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
481
                                        file_id)
482
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
483
    def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
484
        if self.tree is None:
485
            return
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
486
        if yield_parents:
487
            # TODO(jelmer): Support yield parents
488
            raise NotImplementedError
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
489
        if specific_files is not None:
490
            if specific_files in ([""], []):
491
                specific_files = None
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
492
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
493
                specific_files = set([p.encode('utf-8')
494
                                      for p in specific_files])
7096.3.2 by Jelmer Vernooij
Fix some git tests.
495
        todo = deque([(self.store, b"", self.tree, self.get_root_id())])
496
        if specific_files is None or u"" in specific_files:
7096.3.7 by Jelmer Vernooij
Fix tests on python 3.
497
            yield u"", self._get_dir_ie(b"", None)
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
498
        while todo:
7096.3.2 by Jelmer Vernooij
Fix some git tests.
499
            store, path, tree_sha, parent_id = todo.popleft()
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
500
            tree = store[tree_sha]
7096.3.2 by Jelmer Vernooij
Fix some git tests.
501
            extradirs = []
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
502
            for name, mode, hexsha in tree.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
503
                if self.mapping.is_special_file(name):
504
                    continue
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
505
                child_path = posixpath.join(path, name)
7096.3.2 by Jelmer Vernooij
Fix some git tests.
506
                child_path_decoded = child_path.decode('utf-8')
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
507
                if stat.S_ISDIR(mode):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
508
                    if (specific_files is None or
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
509
                            any([p for p in specific_files if p.startswith(
510
                                child_path)])):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
511
                        extradirs.append(
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
512
                            (store, child_path, hexsha,
513
                             self.path2id(child_path_decoded)))
7096.3.2 by Jelmer Vernooij
Fix some git tests.
514
                if specific_files is None or child_path in specific_files:
515
                    if stat.S_ISDIR(mode):
516
                        yield (child_path_decoded,
517
                               self._get_dir_ie(child_path, parent_id))
518
                    else:
519
                        yield (child_path_decoded,
520
                               self._get_file_ie(store, child_path, name, mode,
7143.15.2 by Jelmer Vernooij
Run autopep8.
521
                                                 hexsha, parent_id))
7096.3.2 by Jelmer Vernooij
Fix some git tests.
522
            todo.extendleft(reversed(extradirs))
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
523
7096.3.5 by Jelmer Vernooij
Fix GitRevisionTree.iter_references.
524
    def iter_references(self):
525
        if self.supports_tree_reference():
526
            for path, entry in self.iter_entries_by_dir():
527
                if entry.kind == 'tree-reference':
528
                    yield path, self.mapping.generate_file_id(b'')
529
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
530
    def get_revision_id(self):
0.200.959 by Jelmer Vernooij
Improve docstrings.
531
        """See RevisionTree.get_revision_id."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
532
        return self._revision_id
533
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
534
    def get_file_sha1(self, path, stat_value=None):
0.287.6 by Jelmer Vernooij
Fix some more tests.
535
        if self.tree is None:
536
            raise errors.NoSuchFile(path)
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
537
        return osutils.sha_string(self.get_file_text(path))
0.200.1255 by Jelmer Vernooij
Implement GitRevisionTree.get_file_sha1.
538
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
539
    def get_file_verifier(self, path, stat_value=None):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
540
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
541
        return ("GIT", hexsha)
542
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
543
    def get_file_size(self, path):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
544
        (store, mode, hexsha) = self._lookup_path(path)
545
        if stat.S_ISREG(mode):
546
            return len(store[hexsha].data)
547
        return None
548
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
549
    def get_file_text(self, path):
0.200.959 by Jelmer Vernooij
Improve docstrings.
550
        """See RevisionTree.get_file_text."""
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
551
        (store, mode, hexsha) = self._lookup_path(path)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
552
        if stat.S_ISREG(mode):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
553
            return store[hexsha].data
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
554
        else:
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
555
            return b""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
556
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
557
    def get_symlink_target(self, path):
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
558
        """See RevisionTree.get_symlink_target."""
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
559
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
560
        if stat.S_ISLNK(mode):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
561
            return store[hexsha].data.decode('utf-8')
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
562
        else:
563
            return None
564
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
565
    def get_reference_revision(self, path):
0.429.17 by Jelmer Vernooij
Fix some more tests.
566
        """See RevisionTree.get_symlink_target."""
0.429.25 by Jelmer Vernooij
Merge trunk.
567
        (store, mode, hexsha) = self._lookup_path(path)
0.429.17 by Jelmer Vernooij
Fix some more tests.
568
        if S_ISGITLINK(mode):
0.429.26 by Jelmer Vernooij
Fix remaining test.
569
            nested_repo = self._get_nested_repository(path)
570
            return nested_repo.lookup_foreign_revision_id(hexsha)
0.429.17 by Jelmer Vernooij
Fix some more tests.
571
        else:
572
            return None
573
0.264.10 by Jelmer Vernooij
Yield inventory entries.
574
    def _comparison_data(self, entry, path):
575
        if entry is None:
576
            return None, False, None
577
        return entry.kind, entry.executable, None
578
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
579
    def path_content_summary(self, path):
580
        """See Tree.path_content_summary."""
581
        try:
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
582
            (store, mode, hexsha) = self._lookup_path(path)
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
583
        except errors.NoSuchFile:
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
584
            return ('missing', None, None, None)
585
        kind = mode_kind(mode)
586
        if kind == 'file':
587
            executable = mode_is_executable(mode)
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
588
            contents = store[hexsha].data
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
589
            return (kind, len(contents), executable,
590
                    osutils.sha_string(contents))
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
591
        elif kind == 'symlink':
7096.3.2 by Jelmer Vernooij
Fix some git tests.
592
            return (kind, None, None, store[hexsha].data.decode('utf-8'))
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
593
        elif kind == 'tree-reference':
0.429.26 by Jelmer Vernooij
Fix remaining test.
594
            nested_repo = self._get_nested_repository(path)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
595
            return (kind, None, None,
0.429.26 by Jelmer Vernooij
Fix remaining test.
596
                    nested_repo.lookup_foreign_revision_id(hexsha))
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
597
        else:
598
            return (kind, None, None, None)
599
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
600
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
601
                                        require_versioned=True):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
602
        if paths is None:
603
            return None
604
        if require_versioned:
605
            trees = [self] + (trees if trees is not None else [])
606
            unversioned = set()
607
            for p in paths:
608
                for t in trees:
609
                    if t.is_versioned(p):
610
                        break
611
                else:
612
                    unversioned.add(p)
613
            if unversioned:
614
                raise errors.PathsNotVersionedError(unversioned)
615
        return filter(self.is_versioned, paths)
616
0.393.1 by Jelmer Vernooij
Avoid expensive bzr APIs in commit.
617
    def _iter_tree_contents(self, include_trees=False):
618
        if self.tree is None:
619
            return iter([])
620
        return self.store.iter_tree_contents(
7143.15.2 by Jelmer Vernooij
Run autopep8.
621
            self.tree, include_trees=include_trees)
0.393.1 by Jelmer Vernooij
Avoid expensive bzr APIs in commit.
622
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
623
    def annotate_iter(self, path, default_revision=CURRENT_REVISION):
6973.2.1 by Jelmer Vernooij
Implement GitRevisionTree.annotate_iter.
624
        """Return an iterator of revision_id, line tuples.
625
626
        For working trees (and mutable trees in general), the special
627
        revision_id 'current:' will be used for lines that are new in this
628
        tree, e.g. uncommitted changes.
629
        :param default_revision: For lines that don't match a basis, mark them
630
            with this revision id. Not all implementations will make use of
631
            this value.
632
        """
633
        with self.lock_read():
634
            # Now we have the parents of this content
635
            from breezy.annotate import Annotator
636
            from .annotate import AnnotateProvider
637
            annotator = Annotator(AnnotateProvider(
638
                self._repository._file_change_scanner))
639
            this_key = (path, self.get_file_revision(path))
640
            annotations = [(key[-1], line)
641
                           for key, line in annotator.annotate_flat(this_key)]
642
            return annotations
643
7096.3.2 by Jelmer Vernooij
Fix some git tests.
644
    def _get_rules_searcher(self, default_searcher):
645
        return default_searcher
646
7096.3.6 by Jelmer Vernooij
Fix tests, on python 2 at least.
647
    def walkdirs(self, prefix=u""):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
648
        (store, mode, hexsha) = self._lookup_path(prefix)
7143.15.2 by Jelmer Vernooij
Run autopep8.
649
        todo = deque(
650
            [(store, prefix.encode('utf-8'), hexsha, self.path2id(prefix))])
7096.3.2 by Jelmer Vernooij
Fix some git tests.
651
        while todo:
7096.3.4 by Jelmer Vernooij
Fix returned paths.
652
            store, path, tree_sha, parent_id = todo.popleft()
7096.3.2 by Jelmer Vernooij
Fix some git tests.
653
            path_decoded = path.decode('utf-8')
654
            tree = store[tree_sha]
655
            children = []
656
            for name, mode, hexsha in tree.iteritems():
657
                if self.mapping.is_special_file(name):
658
                    continue
659
                child_path = posixpath.join(path, name)
660
                file_id = self.path2id(child_path.decode('utf-8'))
661
                if stat.S_ISDIR(mode):
7096.3.4 by Jelmer Vernooij
Fix returned paths.
662
                    todo.append((store, child_path, hexsha, file_id))
7096.3.6 by Jelmer Vernooij
Fix tests, on python 2 at least.
663
                children.append(
664
                    (child_path.decode('utf-8'), name.decode('utf-8'),
665
                        mode_kind(mode), None,
666
                        file_id, mode_kind(mode)))
7096.3.4 by Jelmer Vernooij
Fix returned paths.
667
            yield (path_decoded, parent_id), children
7096.3.2 by Jelmer Vernooij
Fix some git tests.
668
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
669
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
670
def tree_delta_from_git_changes(changes, mapping,
7143.15.2 by Jelmer Vernooij
Run autopep8.
671
                                fileid_maps, specific_files=None,
672
                                require_versioned=False, include_root=False,
673
                                target_extras=None):
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
674
    """Create a TreeDelta from two git trees.
0.200.959 by Jelmer Vernooij
Improve docstrings.
675
676
    source and target are iterators over tuples with:
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
677
        (filename, sha, mode)
678
    """
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
679
    (old_fileid_map, new_fileid_map) = fileid_maps
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
680
    if target_extras is None:
681
        target_extras = set()
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
682
    ret = delta.TreeDelta()
683
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
684
        if newpath == b'' and not include_root:
0.287.5 by Jelmer Vernooij
Fix root handling.
685
            continue
7027.5.2 by Jelmer Vernooij
Fix some more git tests.
686
        if oldpath is None:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
687
            oldpath_decoded = None
7027.5.2 by Jelmer Vernooij
Fix some more git tests.
688
        else:
689
            oldpath_decoded = oldpath.decode('utf-8')
690
        if newpath is None:
691
            newpath_decoded = None
692
        else:
693
            newpath_decoded = newpath.decode('utf-8')
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
694
        if not (specific_files is None or
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
695
                (oldpath is not None and
696
                    osutils.is_inside_or_parent_of_any(
697
                        specific_files, oldpath_decoded)) or
698
                (newpath is not None and
699
                    osutils.is_inside_or_parent_of_any(
700
                        specific_files, newpath_decoded))):
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
701
            continue
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
702
        if mapping.is_special_file(oldpath):
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
703
            oldpath = None
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
704
        if mapping.is_special_file(newpath):
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
705
            newpath = None
706
        if oldpath is None and newpath is None:
707
            continue
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
708
        if oldpath is None:
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
709
            if newpath in target_extras:
710
                ret.unversioned.append(
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
711
                    (osutils.normalized_filename(newpath)[0], None,
712
                     mode_kind(newmode)))
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
713
            else:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
714
                file_id = new_fileid_map.lookup_file_id(newpath_decoded)
7143.15.2 by Jelmer Vernooij
Run autopep8.
715
                ret.added.append(
716
                    (newpath_decoded, file_id, mode_kind(newmode)))
6977.1.2 by Jelmer Vernooij
Deal with missing files properly in 'bzr st'.
717
        elif newpath is None or newmode == 0:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
718
            file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
719
            ret.removed.append((oldpath_decoded, file_id, mode_kind(oldmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
720
        elif oldpath != newpath:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
721
            file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
722
            ret.renamed.append(
7018.3.2 by Jelmer Vernooij
Fix some git tests.
723
                (oldpath_decoded, newpath.decode('utf-8'), file_id,
7143.15.2 by Jelmer Vernooij
Run autopep8.
724
                 mode_kind(newmode), (oldsha != newsha),
725
                 (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
726
        elif mode_kind(oldmode) != mode_kind(newmode):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
727
            file_id = new_fileid_map.lookup_file_id(newpath_decoded)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
728
            ret.kind_changed.append(
7018.3.2 by Jelmer Vernooij
Fix some git tests.
729
                (newpath_decoded, file_id, mode_kind(oldmode),
7143.15.2 by Jelmer Vernooij
Run autopep8.
730
                 mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
731
        elif oldsha != newsha or oldmode != newmode:
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
732
            if stat.S_ISDIR(oldmode) and stat.S_ISDIR(newmode):
733
                continue
7018.3.2 by Jelmer Vernooij
Fix some git tests.
734
            file_id = new_fileid_map.lookup_file_id(newpath_decoded)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
735
            ret.modified.append(
7067.13.12 by Jelmer Vernooij
Handle decoded paths.
736
                (newpath_decoded, file_id, mode_kind(newmode),
7143.15.2 by Jelmer Vernooij
Run autopep8.
737
                 (oldsha != newsha), (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
738
        else:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
739
            file_id = new_fileid_map.lookup_file_id(newpath_decoded)
7143.15.2 by Jelmer Vernooij
Run autopep8.
740
            ret.unchanged.append(
741
                (newpath_decoded, file_id, mode_kind(newmode)))
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
742
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
743
    return ret
744
745
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
746
def changes_from_git_changes(changes, mapping, specific_files=None,
747
                             include_unchanged=False, target_extras=None):
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
748
    """Create a iter_changes-like generator from a git stream.
0.200.959 by Jelmer Vernooij
Improve docstrings.
749
750
    source and target are iterators over tuples with:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
751
        (filename, sha, mode)
752
    """
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
753
    if target_extras is None:
754
        target_extras = set()
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
755
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
756
        if oldpath is not None:
757
            oldpath_decoded = oldpath.decode('utf-8')
758
        else:
759
            oldpath_decoded = None
760
        if newpath is not None:
761
            newpath_decoded = newpath.decode('utf-8')
762
        else:
763
            newpath_decoded = None
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
764
        if not (specific_files is None or
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
765
                (oldpath_decoded is not None and
766
                    osutils.is_inside_or_parent_of_any(
767
                        specific_files, oldpath_decoded)) or
768
                (newpath_decoded is not None and
769
                    osutils.is_inside_or_parent_of_any(
770
                        specific_files, newpath_decoded))):
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
771
            continue
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
772
        if oldpath is not None and mapping.is_special_file(oldpath):
773
            continue
774
        if newpath is not None and mapping.is_special_file(newpath):
0.200.1328 by Jelmer Vernooij
More test fixes.
775
            continue
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
776
        if oldpath_decoded is None:
777
            fileid = mapping.generate_file_id(newpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
778
            oldexe = None
779
            oldkind = None
780
            oldname = None
781
            oldparent = None
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
782
            oldversioned = False
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
783
        else:
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
784
            oldversioned = True
0.391.8 by Jelmer Vernooij
Allow missing items in old tree.
785
            if oldmode:
786
                oldexe = mode_is_executable(oldmode)
787
                oldkind = mode_kind(oldmode)
788
            else:
789
                oldexe = False
790
                oldkind = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
791
            if oldpath_decoded == u'':
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
792
                oldparent = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
793
                oldname = u''
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
794
            else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
795
                (oldparentpath, oldname) = osutils.split(oldpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
796
                oldparent = mapping.generate_file_id(oldparentpath)
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
797
            fileid = mapping.generate_file_id(oldpath_decoded)
798
        if newpath_decoded is None:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
799
            newexe = None
800
            newkind = None
801
            newname = None
802
            newparent = None
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
803
            newversioned = False
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
804
        else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
805
            newversioned = (newpath_decoded not in target_extras)
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
806
            if newmode:
0.200.1576 by Jelmer Vernooij
Merge a bunch of fixes from store-roundtrip-info.
807
                newexe = mode_is_executable(newmode)
808
                newkind = mode_kind(newmode)
809
            else:
810
                newexe = False
811
                newkind = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
812
            if newpath_decoded == u'':
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
813
                newparent = None
0.316.1 by Jelmer Vernooij
Fix iter_changes behaviour for trees in the tree root.
814
                newname = u''
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
815
            else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
816
                newparentpath, newname = osutils.split(newpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
817
                newparent = mapping.generate_file_id(newparentpath)
0.357.3 by Jelmer Vernooij
More remove fixes.
818
        if (not include_unchanged and
819
            oldkind == 'directory' and newkind == 'directory' and
7143.15.2 by Jelmer Vernooij
Run autopep8.
820
                oldpath_decoded == newpath_decoded):
0.357.3 by Jelmer Vernooij
More remove fixes.
821
            continue
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
822
        yield (fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
7143.15.2 by Jelmer Vernooij
Run autopep8.
823
               (oldversioned, newversioned),
824
               (oldparent, newparent), (oldname, newname),
825
               (oldkind, newkind), (oldexe, newexe))
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
826
827
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
828
class InterGitTrees(_mod_tree.InterTree):
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
829
    """InterTree that works between two git trees."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
830
0.200.659 by Jelmer Vernooij
Prevent tests using InterGitRevisionTrees.
831
    _matching_from_tree_format = None
832
    _matching_to_tree_format = None
833
    _test_mutable_trees_to_test_trees = None
834
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
835
    @classmethod
836
    def is_compatible(cls, source, target):
0.200.959 by Jelmer Vernooij
Improve docstrings.
837
        return (isinstance(source, GitRevisionTree) and
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
838
                isinstance(target, GitRevisionTree))
839
840
    def compare(self, want_unchanged=False, specific_files=None,
841
                extra_trees=None, require_versioned=False, include_root=False,
842
                want_unversioned=False):
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
843
        with self.lock_read():
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
844
            changes, target_extras = self._iter_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
845
                want_unchanged=want_unchanged,
846
                require_versioned=require_versioned,
847
                specific_files=specific_files,
848
                extra_trees=extra_trees,
849
                want_unversioned=want_unversioned)
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
850
            source_fileid_map = self.source._fileid_map
851
            target_fileid_map = self.target._fileid_map
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
852
            return tree_delta_from_git_changes(
853
                changes, self.target.mapping,
854
                (source_fileid_map, target_fileid_map),
855
                specific_files=specific_files,
856
                include_root=include_root, target_extras=target_extras)
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
857
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
858
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
859
                     pb=None, extra_trees=[], require_versioned=True,
860
                     want_unversioned=False):
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
861
        with self.lock_read():
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
862
            changes, target_extras = self._iter_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
863
                want_unchanged=include_unchanged,
864
                require_versioned=require_versioned,
865
                specific_files=specific_files,
866
                extra_trees=extra_trees,
867
                want_unversioned=want_unversioned)
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
868
            return changes_from_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
869
                changes, self.target.mapping,
870
                specific_files=specific_files,
871
                include_unchanged=include_unchanged,
872
                target_extras=target_extras)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
873
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
874
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
875
                          require_versioned=False, extra_trees=None,
876
                          want_unversioned=False):
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
877
        raise NotImplementedError(self._iter_git_changes)
878
879
880
class InterGitRevisionTrees(InterGitTrees):
881
    """InterTree that works between two git revision trees."""
882
883
    _matching_from_tree_format = None
884
    _matching_to_tree_format = None
885
    _test_mutable_trees_to_test_trees = None
886
887
    @classmethod
888
    def is_compatible(cls, source, target):
889
        return (isinstance(source, GitRevisionTree) and
890
                isinstance(target, GitRevisionTree))
891
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
892
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
893
                          require_versioned=True, extra_trees=None,
894
                          want_unversioned=False):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
895
        trees = [self.source]
896
        if extra_trees is not None:
897
            trees.extend(extra_trees)
898
        if specific_files is not None:
899
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
900
                specific_files, trees,
901
                require_versioned=require_versioned)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
902
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
903
        if (self.source._repository._git.object_store !=
904
                self.target._repository._git.object_store):
905
            store = OverlayObjectStore(
906
                [self.source._repository._git.object_store,
907
                    self.target._repository._git.object_store])
0.200.1780 by Jelmer Vernooij
Fix cross-object-store tree comparison.
908
        else:
909
            store = self.source._repository._git.object_store
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
910
        return store.tree_changes(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
911
            self.source.tree, self.target.tree, want_unchanged=want_unchanged,
0.391.2 by Jelmer Vernooij
Pass along target_missing.
912
            include_trees=True, change_type_same=True), set()
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
913
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
914
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
915
_mod_tree.InterTree.register_optimiser(InterGitRevisionTrees)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
916
917
918
class MutableGitIndexTree(mutabletree.MutableTree):
919
920
    def __init__(self):
921
        self._lock_mode = None
922
        self._lock_count = 0
923
        self._versioned_dirs = None
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
924
        self._index_dirty = False
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
925
926
    def is_versioned(self, path):
927
        with self.lock_read():
928
            path = path.rstrip('/').encode('utf-8')
0.429.1 by Jelmer Vernooij
Abstract away index access.
929
            (index, subpath) = self._lookup_index(path)
930
            return (subpath in index or self._has_dir(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
931
932
    def _has_dir(self, path):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
933
        if not isinstance(path, bytes):
934
            raise TypeError(path)
935
        if path == b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
936
            return True
937
        if self._versioned_dirs is None:
938
            self._load_dirs()
939
        return path in self._versioned_dirs
940
941
    def _load_dirs(self):
0.361.3 by Jelmer Vernooij
Merge trunk,
942
        if self._lock_mode is None:
943
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
944
        self._versioned_dirs = set()
0.429.1 by Jelmer Vernooij
Abstract away index access.
945
        # TODO(jelmer): Browse over all indexes
0.429.11 by Jelmer Vernooij
Merge trunk.
946
        for p, i in self._recurse_index_entries():
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
947
            self._ensure_versioned_dir(posixpath.dirname(p))
948
949
    def _ensure_versioned_dir(self, dirname):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
950
        if not isinstance(dirname, bytes):
951
            raise TypeError(dirname)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
952
        if dirname in self._versioned_dirs:
953
            return
7018.3.2 by Jelmer Vernooij
Fix some git tests.
954
        if dirname != b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
955
            self._ensure_versioned_dir(posixpath.dirname(dirname))
956
        self._versioned_dirs.add(dirname)
957
958
    def path2id(self, path):
959
        with self.lock_read():
960
            path = path.rstrip('/')
961
            if self.is_versioned(path.rstrip('/')):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
962
                return self._fileid_map.lookup_file_id(
963
                    osutils.safe_unicode(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
964
            return None
965
966
    def has_id(self, file_id):
967
        try:
968
            self.id2path(file_id)
969
        except errors.NoSuchId:
970
            return False
971
        else:
972
            return True
973
974
    def id2path(self, file_id):
975
        if file_id is None:
976
            return ''
0.361.3 by Jelmer Vernooij
Merge trunk,
977
        if type(file_id) is not bytes:
978
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
979
        with self.lock_read():
980
            try:
981
                path = self._fileid_map.lookup_path(file_id)
982
            except ValueError:
983
                raise errors.NoSuchId(self, file_id)
984
            if self.is_versioned(path):
985
                return path
986
            raise errors.NoSuchId(self, file_id)
987
988
    def _set_root_id(self, file_id):
989
        self._fileid_map.set_file_id("", file_id)
990
991
    def get_root_id(self):
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
992
        return self.path2id(u"")
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
993
994
    def _add(self, files, ids, kinds):
995
        for (path, file_id, kind) in zip(files, ids, kinds):
996
            if file_id is not None:
997
                raise workingtree.SettingFileIdUnsupported()
0.366.1 by Jelmer Vernooij
Fix normalized filename checking in add.
998
            path, can_access = osutils.normalized_filename(path)
999
            if not can_access:
1000
                raise errors.InvalidNormalization(path)
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1001
            self._index_add_entry(path, kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1002
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1003
    def _read_submodule_head(self, path):
1004
        raise NotImplementedError(self._read_submodule_head)
1005
0.429.1 by Jelmer Vernooij
Abstract away index access.
1006
    def _lookup_index(self, encoded_path):
1007
        if not isinstance(encoded_path, bytes):
1008
            raise TypeError(encoded_path)
0.429.11 by Jelmer Vernooij
Merge trunk.
1009
        # TODO(jelmer): Look in other indexes
0.429.1 by Jelmer Vernooij
Abstract away index access.
1010
        return self.index, encoded_path
1011
0.429.25 by Jelmer Vernooij
Merge trunk.
1012
    def _index_del_entry(self, index, path):
1013
        del index[path]
1014
        # TODO(jelmer): Keep track of dirty per index
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1015
        self._index_dirty = True
1016
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1017
    def _index_add_entry(self, path, kind, flags=0, reference_revision=None):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1018
        if kind == "directory":
1019
            # Git indexes don't contain directories
1020
            return
1021
        if kind == "file":
1022
            blob = Blob()
1023
            try:
1024
                file, stat_val = self.get_file_with_stat(path)
1025
            except (errors.NoSuchFile, IOError):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1026
                # TODO: Rather than come up with something here, use the old
1027
                # index
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1028
                file = BytesIO()
1029
                stat_val = os.stat_result(
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
1030
                    (stat.S_IFREG | 0o644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
7027.4.7 by Jelmer Vernooij
Fix some tests.
1031
            with file:
1032
                blob.set_raw_string(file.read())
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1033
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1034
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1035
                self.store.add_object(blob)
1036
            hexsha = blob.id
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1037
        elif kind == "symlink":
1038
            blob = Blob()
1039
            try:
1040
                stat_val = self._lstat(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1041
            except EnvironmentError:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1042
                # TODO: Rather than come up with something here, use the
1043
                # old index
1044
                stat_val = os.stat_result(
1045
                    (stat.S_IFLNK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1046
            blob.set_raw_string(
1047
                self.get_symlink_target(path).encode("utf-8"))
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1048
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1049
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1050
                self.store.add_object(blob)
1051
            hexsha = blob.id
1052
        elif kind == "tree-reference":
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1053
            if reference_revision is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1054
                hexsha = self.branch.lookup_bzr_revision_id(
1055
                    reference_revision)[0]
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1056
            else:
1057
                hexsha = self._read_submodule_head(path)
1058
                if hexsha is None:
1059
                    raise errors.NoCommits(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1060
            try:
1061
                stat_val = self._lstat(path)
1062
            except EnvironmentError:
1063
                stat_val = os.stat_result(
1064
                    (S_IFGITLINK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1065
            stat_val = os.stat_result((S_IFGITLINK, ) + stat_val[1:])
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1066
        else:
1067
            raise AssertionError("unknown kind '%s'" % kind)
1068
        # Add an entry to the index or update the existing entry
1069
        ensure_normalized_path(path)
1070
        encoded_path = path.encode("utf-8")
1071
        if b'\r' in encoded_path or b'\n' in encoded_path:
1072
            # TODO(jelmer): Why do we need to do this?
1073
            trace.mutter('ignoring path with invalid newline in it: %r', path)
1074
            return
0.429.1 by Jelmer Vernooij
Abstract away index access.
1075
        (index, index_path) = self._lookup_index(encoded_path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1076
        index[index_path] = index_entry_from_stat(stat_val, hexsha, flags)
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1077
        self._index_dirty = True
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1078
        if self._versioned_dirs is not None:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1079
            self._ensure_versioned_dir(index_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1080
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1081
    def _recurse_index_entries(self, index=None, basepath=b""):
0.429.7 by Jelmer Vernooij
Consistent file ids.
1082
        # Iterate over all index entries
1083
        with self.lock_read():
1084
            if index is None:
1085
                index = self.index
6973.12.3 by Jelmer Vernooij
Fixes.
1086
            for path, value in index.items():
0.429.7 by Jelmer Vernooij
Consistent file ids.
1087
                yield (posixpath.join(basepath, path), value)
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1088
                (ctime, mtime, dev, ino, mode, uid, gid, size, sha,
1089
                 flags) = value
0.429.10 by Jelmer Vernooij
use new read_submodule_head from dulwich.
1090
                if S_ISGITLINK(mode):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1091
                    pass  # TODO(jelmer): dive into submodule
0.429.7 by Jelmer Vernooij
Consistent file ids.
1092
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1093
    def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1094
        if yield_parents:
1095
            raise NotImplementedError(self.iter_entries_by_dir)
1096
        with self.lock_read():
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1097
            if specific_files is not None:
1098
                specific_files = set(specific_files)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1099
            else:
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1100
                specific_files = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1101
            root_ie = self._get_dir_ie(u"", None)
1102
            ret = {}
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1103
            if specific_files is None or u"" in specific_files:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1104
                ret[(u"", u"")] = root_ie
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1105
            dir_ids = {u"": root_ie.file_id}
0.429.7 by Jelmer Vernooij
Consistent file ids.
1106
            for path, value in self._recurse_index_entries():
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1107
                if self.mapping.is_special_file(path):
1108
                    continue
1109
                path = path.decode("utf-8")
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1110
                if specific_files is not None and path not in specific_files:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1111
                    continue
1112
                (parent, name) = posixpath.split(path)
1113
                try:
1114
                    file_ie = self._get_file_ie(name, path, value, None)
1115
                except errors.NoSuchFile:
1116
                    continue
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1117
                if yield_parents or specific_files is None:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1118
                    for (dir_path, dir_ie) in self._add_missing_parent_ids(
1119
                            parent, dir_ids):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1120
                        ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
0.429.12 by Jelmer Vernooij
Remove revision.
1121
                file_ie.parent_id = self.path2id(parent)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1122
                ret[(posixpath.dirname(path), path)] = file_ie
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1123
            return ((path, ie) for ((_, path), ie) in sorted(viewitems(ret)))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1124
0.429.7 by Jelmer Vernooij
Consistent file ids.
1125
    def iter_references(self):
1126
        # TODO(jelmer): Implement a more efficient version of this
1127
        for path, entry in self.iter_entries_by_dir():
1128
            if entry.kind == 'tree-reference':
0.429.20 by Jelmer Vernooij
Fix iter_references.
1129
                yield path, self.mapping.generate_file_id(b'')
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1130
1131
    def _get_dir_ie(self, path, parent_id):
1132
        file_id = self.path2id(path)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1133
        return GitTreeDirectory(file_id,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1134
                                posixpath.basename(path).strip("/"), parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1135
1136
    def _get_file_ie(self, name, path, value, parent_id):
6973.6.2 by Jelmer Vernooij
Fix more tests.
1137
        if not isinstance(name, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1138
            raise TypeError(name)
6973.6.2 by Jelmer Vernooij
Fix more tests.
1139
        if not isinstance(path, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1140
            raise TypeError(path)
1141
        if not isinstance(value, tuple) or len(value) != 10:
1142
            raise TypeError(value)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1143
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
1144
        file_id = self.path2id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1145
        if not isinstance(file_id, bytes):
1146
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1147
        kind = mode_kind(mode)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1148
        ie = entry_factory[kind](file_id, name, parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1149
        if kind == 'symlink':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1150
            ie.symlink_target = self.get_symlink_target(path)
0.429.7 by Jelmer Vernooij
Consistent file ids.
1151
        elif kind == 'tree-reference':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1152
            ie.reference_revision = self.get_reference_revision(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1153
        else:
1154
            try:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1155
                data = self.get_file_text(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1156
            except errors.NoSuchFile:
1157
                data = None
1158
            except IOError as e:
1159
                if e.errno != errno.ENOENT:
1160
                    raise
1161
                data = None
1162
            if data is None:
1163
                data = self.branch.repository._git.object_store[sha].data
1164
            ie.text_sha1 = osutils.sha_string(data)
1165
            ie.text_size = len(data)
1166
            ie.executable = bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
1167
        return ie
1168
1169
    def _add_missing_parent_ids(self, path, dir_ids):
1170
        if path in dir_ids:
1171
            return []
1172
        parent = posixpath.dirname(path).strip("/")
1173
        ret = self._add_missing_parent_ids(parent, dir_ids)
1174
        parent_id = dir_ids[parent]
1175
        ie = self._get_dir_ie(path, parent_id)
1176
        dir_ids[path] = ie.file_id
1177
        ret.append((path, ie))
1178
        return ret
1179
1180
    def _comparison_data(self, entry, path):
1181
        if entry is None:
1182
            return None, False, None
1183
        return entry.kind, entry.executable, None
1184
1185
    def _unversion_path(self, path):
0.361.3 by Jelmer Vernooij
Merge trunk,
1186
        if self._lock_mode is None:
1187
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1188
        encoded_path = path.encode("utf-8")
1189
        count = 0
0.429.1 by Jelmer Vernooij
Abstract away index access.
1190
        (index, subpath) = self._lookup_index(encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1191
        try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1192
            self._index_del_entry(index, encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1193
        except KeyError:
1194
            # A directory, perhaps?
0.429.1 by Jelmer Vernooij
Abstract away index access.
1195
            # TODO(jelmer): Deletes that involve submodules?
1196
            for p in list(index):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1197
                if p.startswith(subpath + b"/"):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1198
                    count += 1
0.429.25 by Jelmer Vernooij
Merge trunk.
1199
                    self._index_del_entry(index, p)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1200
        else:
1201
            count = 1
1202
        self._versioned_dirs = None
1203
        return count
1204
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1205
    def unversion(self, paths):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1206
        with self.lock_tree_write():
1207
            for path in paths:
1208
                if self._unversion_path(path) == 0:
1209
                    raise errors.NoSuchFile(path)
1210
            self._versioned_dirs = None
1211
            self.flush()
1212
1213
    def flush(self):
1214
        pass
1215
1216
    def update_basis_by_delta(self, revid, delta):
1217
        # TODO(jelmer): This shouldn't be called, it's inventory specific.
1218
        for (old_path, new_path, file_id, ie) in delta:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1219
            if old_path is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1220
                (index, old_subpath) = self._lookup_index(
1221
                    old_path.encode('utf-8'))
0.429.1 by Jelmer Vernooij
Abstract away index access.
1222
                if old_subpath in index:
0.429.25 by Jelmer Vernooij
Merge trunk.
1223
                    self._index_del_entry(index, old_subpath)
0.429.1 by Jelmer Vernooij
Abstract away index access.
1224
                    self._versioned_dirs = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1225
            if new_path is not None and ie.kind != 'directory':
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1226
                self._index_add_entry(new_path, ie.kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1227
        self.flush()
1228
        self._set_merges_from_parent_ids([])
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1229
1230
    def move(self, from_paths, to_dir=None, after=None):
1231
        rename_tuples = []
1232
        with self.lock_tree_write():
1233
            to_abs = self.abspath(to_dir)
1234
            if not os.path.isdir(to_abs):
1235
                raise errors.BzrMoveFailedError('', to_dir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1236
                                                errors.NotADirectory(to_abs))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1237
1238
            for from_rel in from_paths:
1239
                from_tail = os.path.split(from_rel)[-1]
1240
                to_rel = os.path.join(to_dir, from_tail)
1241
                self.rename_one(from_rel, to_rel, after=after)
1242
                rename_tuples.append((from_rel, to_rel))
1243
            self.flush()
1244
            return rename_tuples
1245
1246
    def rename_one(self, from_rel, to_rel, after=None):
1247
        from_path = from_rel.encode("utf-8")
1248
        to_rel, can_access = osutils.normalized_filename(to_rel)
1249
        if not can_access:
1250
            raise errors.InvalidNormalization(to_rel)
1251
        to_path = to_rel.encode("utf-8")
1252
        with self.lock_tree_write():
1253
            if not after:
1254
                # Perhaps it's already moved?
1255
                after = (
1256
                    not self.has_filename(from_rel) and
1257
                    self.has_filename(to_rel) and
1258
                    not self.is_versioned(to_rel))
1259
            if after:
1260
                if not self.has_filename(to_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1261
                    raise errors.BzrMoveFailedError(
1262
                        from_rel, to_rel, errors.NoSuchFile(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1263
                if self.basis_tree().is_versioned(to_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1264
                    raise errors.BzrMoveFailedError(
1265
                        from_rel, to_rel, errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1266
1267
                kind = self.kind(to_rel)
1268
            else:
1269
                try:
1270
                    to_kind = self.kind(to_rel)
1271
                except errors.NoSuchFile:
1272
                    exc_type = errors.BzrRenameFailedError
1273
                    to_kind = None
1274
                else:
1275
                    exc_type = errors.BzrMoveFailedError
1276
                if self.is_versioned(to_rel):
1277
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1278
                                   errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1279
                if not self.has_filename(from_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1280
                    raise errors.BzrMoveFailedError(
1281
                        from_rel, to_rel, errors.NoSuchFile(from_rel))
0.388.1 by Jelmer Vernooij
Don't print error moving to an unversioned directory.
1282
                kind = self.kind(from_rel)
1283
                if not self.is_versioned(from_rel) and kind != 'directory':
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1284
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1285
                                   errors.NotVersionedError(from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1286
                if self.has_filename(to_rel):
1287
                    raise errors.RenameFailedFilesExist(
1288
                        from_rel, to_rel, errors.FileExists(to_rel))
1289
1290
                kind = self.kind(from_rel)
1291
0.429.1 by Jelmer Vernooij
Abstract away index access.
1292
            if not after and kind != 'directory':
1293
                (index, from_subpath) = self._lookup_index(from_path)
1294
                if from_subpath not in index:
1295
                    # It's not a file
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1296
                    raise errors.BzrMoveFailedError(
1297
                        from_rel, to_rel,
1298
                        errors.NotVersionedError(path=from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1299
1300
            if not after:
1301
                try:
1302
                    self._rename_one(from_rel, to_rel)
1303
                except OSError as e:
1304
                    if e.errno == errno.ENOENT:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1305
                        raise errors.BzrMoveFailedError(
1306
                            from_rel, to_rel, errors.NoSuchFile(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1307
                    raise
1308
            if kind != 'directory':
0.429.13 by Jelmer Vernooij
Fix regressions.
1309
                (index, from_index_path) = self._lookup_index(from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1310
                try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1311
                    self._index_del_entry(index, from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1312
                except KeyError:
1313
                    pass
1314
                self._index_add_entry(to_rel, kind)
1315
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1316
                todo = [(p, i) for (p, i) in self._recurse_index_entries()
1317
                        if p.startswith(from_path + b'/')]
0.429.13 by Jelmer Vernooij
Fix regressions.
1318
                for child_path, child_value in todo:
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1319
                    (child_to_index, child_to_index_path) = self._lookup_index(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1320
                        posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
0.429.13 by Jelmer Vernooij
Fix regressions.
1321
                    child_to_index[child_to_index_path] = child_value
0.429.25 by Jelmer Vernooij
Merge trunk.
1322
                    # TODO(jelmer): Mark individual index as dirty
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1323
                    self._index_dirty = True
7143.15.2 by Jelmer Vernooij
Run autopep8.
1324
                    (child_from_index, child_from_index_path) = self._lookup_index(
1325
                        child_path)
1326
                    self._index_del_entry(
1327
                        child_from_index, child_from_index_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1328
1329
            self._versioned_dirs = None
1330
            self.flush()
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1331
1332
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1333
                                        require_versioned=True):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1334
        if paths is None:
1335
            return None
1336
1337
        if require_versioned:
1338
            trees = [self] + (trees if trees is not None else [])
1339
            unversioned = set()
1340
            for p in paths:
1341
                for t in trees:
1342
                    if t.is_versioned(p):
1343
                        break
1344
                else:
1345
                    unversioned.add(p)
1346
            if unversioned:
1347
                raise errors.PathsNotVersionedError(unversioned)
1348
1349
        return filter(self.is_versioned, paths)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1350
1351
    def path_content_summary(self, path):
1352
        """See Tree.path_content_summary."""
1353
        try:
1354
            stat_result = self._lstat(path)
1355
        except OSError as e:
1356
            if getattr(e, 'errno', None) == errno.ENOENT:
1357
                # no file.
1358
                return ('missing', None, None, None)
1359
            # propagate other errors
1360
            raise
1361
        kind = mode_kind(stat_result.st_mode)
1362
        if kind == 'file':
1363
            return self._file_content_summary(path, stat_result)
1364
        elif kind == 'directory':
1365
            # perhaps it looks like a plain directory, but it's really a
1366
            # reference.
1367
            if self._directory_is_tree_reference(path):
1368
                kind = 'tree-reference'
1369
            return kind, None, None, None
1370
        elif kind == 'symlink':
1371
            target = osutils.readlink(self.abspath(path))
1372
            return ('symlink', None, None, target)
1373
        else:
1374
            return (kind, None, None, None)
1375
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1376
    def kind(self, relpath):
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1377
        kind = osutils.file_kind(self.abspath(relpath))
1378
        if kind == 'directory':
1379
            (index, index_path) = self._lookup_index(relpath.encode('utf-8'))
7065.1.1 by Jelmer Vernooij
Properly handle ignored directories in Git.
1380
            if index is None:
1381
                return kind
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1382
            try:
1383
                mode = index[index_path].mode
1384
            except KeyError:
1385
                return kind
1386
            else:
1387
                if S_ISGITLINK(mode):
1388
                    return 'tree-reference'
1389
                return 'directory'
1390
        else:
1391
            return kind
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1392
1393
    def _live_entry(self, relpath):
1394
        raise NotImplementedError(self._live_entry)
1395
1396
1397
class InterIndexGitTree(InterGitTrees):
1398
    """InterTree that works between a Git revision tree and an index."""
1399
1400
    def __init__(self, source, target):
1401
        super(InterIndexGitTree, self).__init__(source, target)
1402
        self._index = target.index
1403
1404
    @classmethod
1405
    def is_compatible(cls, source, target):
1406
        return (isinstance(source, GitRevisionTree) and
1407
                isinstance(target, MutableGitIndexTree))
1408
1409
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1410
                          require_versioned=False, extra_trees=None,
1411
                          want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1412
        trees = [self.source]
1413
        if extra_trees is not None:
1414
            trees.extend(extra_trees)
1415
        if specific_files is not None:
1416
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1417
                specific_files, trees,
1418
                require_versioned=require_versioned)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1419
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
1420
        with self.lock_read():
1421
            return changes_between_git_tree_and_working_copy(
1422
                self.source.store, self.source.tree,
1423
                self.target, want_unchanged=want_unchanged,
1424
                want_unversioned=want_unversioned)
1425
1426
1427
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
1428
1429
1430
def changes_between_git_tree_and_working_copy(store, from_tree_sha, target,
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1431
                                              want_unchanged=False,
1432
                                              want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1433
    """Determine the changes between a git tree and a working tree with index.
1434
1435
    """
1436
    extras = set()
1437
    blobs = {}
1438
    # Report dirified directories to commit_tree first, so that they can be
1439
    # replaced with non-empty directories if they have contents.
1440
    dirified = []
1441
    for path, index_entry in target._recurse_index_entries():
1442
        try:
7045.3.2 by Jelmer Vernooij
Fix tests.
1443
            live_entry = target._live_entry(path)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1444
        except EnvironmentError as e:
1445
            if e.errno == errno.ENOENT:
1446
                # Entry was removed; keep it listed, but mark it as gone.
1447
                blobs[path] = (ZERO_SHA, 0)
1448
            elif e.errno == errno.EISDIR:
7131.13.2 by Jelmer Vernooij
Add TODO.
1449
                # TODO(jelmer): Only do this if 'path' appears in .gitmodules?
7131.13.1 by Jelmer Vernooij
Don't show a delta for unchanged submodules.
1450
                if S_ISGITLINK(index_entry.mode):
1451
                    blobs[path] = (index_entry.sha, index_entry.mode)
1452
                else:
1453
                    # Entry was turned into a directory
1454
                    dirified.append((path, Tree().id, stat.S_IFDIR))
1455
                    store.add_object(Tree())
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1456
            else:
1457
                raise
1458
        else:
1459
            blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
1460
    if want_unversioned:
1461
        for e in target.extras():
1462
            st = target._lstat(e)
1463
            try:
1464
                np, accessible = osutils.normalized_filename(e)
1465
            except UnicodeDecodeError:
1466
                raise errors.BadFilenameEncoding(
1467
                    e, osutils._fs_enc)
1468
            if stat.S_ISDIR(st.st_mode):
1469
                blob = Tree()
1470
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1471
                blob = blob_from_path_and_stat(
1472
                    target.abspath(e).encode(osutils._fs_enc), st)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1473
            store.add_object(blob)
1474
            np = np.encode('utf-8')
1475
            blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1476
            extras.add(np)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1477
    to_tree_sha = commit_tree(
1478
        store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1479
    return store.tree_changes(
1480
        from_tree_sha, to_tree_sha, include_trees=True,
1481
        want_unchanged=want_unchanged, change_type_same=True), extras