/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:
7143.19.5 by Jelmer Vernooij
Undo removal of kind.
412
            yield (from_dir, "V", root_ie.kind, 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.19.7 by Jelmer Vernooij
merge trunk
434
                yield (child_relpath.decode('utf-8'), "V", ie.kind, ie)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
435
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
436
    def _get_file_ie(self, store, path, name, mode, hexsha, parent_id):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
437
        if not isinstance(path, bytes):
0.361.1 by Jelmer Vernooij
Don't use assert.
438
            raise TypeError(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
439
        if not isinstance(name, bytes):
0.361.1 by Jelmer Vernooij
Don't use assert.
440
            raise TypeError(name)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
441
        kind = mode_kind(mode)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
442
        path = path.decode('utf-8')
443
        name = name.decode("utf-8")
0.200.1328 by Jelmer Vernooij
More test fixes.
444
        file_id = self._fileid_map.lookup_file_id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
445
        ie = entry_factory[kind](file_id, name, parent_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
446
        if kind == 'symlink':
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
447
            ie.symlink_target = store[hexsha].data.decode('utf-8')
0.200.1401 by Jelmer Vernooij
Cope with submodules in working trees.
448
        elif kind == 'tree-reference':
7143.15.2 by Jelmer Vernooij
Run autopep8.
449
            ie.reference_revision = self.mapping.revision_id_foreign_to_bzr(
450
                hexsha)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
451
        else:
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
452
            data = store[hexsha].data
0.264.10 by Jelmer Vernooij
Yield inventory entries.
453
            ie.text_sha1 = osutils.sha_string(data)
454
            ie.text_size = len(data)
455
            ie.executable = mode_is_executable(mode)
456
        return ie
457
458
    def _get_dir_ie(self, path, parent_id):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
459
        path = path.decode('utf-8')
0.200.1328 by Jelmer Vernooij
More test fixes.
460
        file_id = self._fileid_map.lookup_file_id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
461
        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.
462
7192.5.1 by Jelmer Vernooij
Remove more file ids.
463
    def iter_child_entries(self, path):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
464
        (store, mode, tree_sha) = self._lookup_path(path)
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
465
7096.3.1 by Jelmer Vernooij
Run tests against GitRevisionTree.
466
        if mode is not None and not stat.S_ISDIR(mode):
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
467
            return
468
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
469
        encoded_path = path.encode('utf-8')
470
        file_id = self.path2id(path)
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
471
        tree = store[tree_sha]
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
472
        for name, mode, hexsha in tree.iteritems():
473
            if self.mapping.is_special_file(name):
474
                continue
475
            child_path = posixpath.join(encoded_path, name)
476
            if stat.S_ISDIR(mode):
477
                yield self._get_dir_ie(child_path, file_id)
478
            else:
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
479
                yield self._get_file_ie(store, child_path, name, mode, hexsha,
0.374.1 by Jelmer Vernooij
Implement GitRevisionTree.iter_child_entries.
480
                                        file_id)
481
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
482
    def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
0.287.4 by Jelmer Vernooij
Fix GitRevisionTree behaviour for null:
483
        if self.tree is None:
484
            return
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
485
        if yield_parents:
486
            # TODO(jelmer): Support yield parents
487
            raise NotImplementedError
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
488
        if specific_files is not None:
489
            if specific_files in ([""], []):
490
                specific_files = None
0.200.1285 by Jelmer Vernooij
Support specific_file_ids argument to Tree.iter_entries_by_dir.
491
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
492
                specific_files = set([p.encode('utf-8')
493
                                      for p in specific_files])
7096.3.2 by Jelmer Vernooij
Fix some git tests.
494
        todo = deque([(self.store, b"", self.tree, self.get_root_id())])
495
        if specific_files is None or u"" in specific_files:
7096.3.7 by Jelmer Vernooij
Fix tests on python 3.
496
            yield u"", self._get_dir_ie(b"", None)
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
497
        while todo:
7096.3.2 by Jelmer Vernooij
Fix some git tests.
498
            store, path, tree_sha, parent_id = todo.popleft()
0.400.3 by Jelmer Vernooij
Pass store in a few more places.
499
            tree = store[tree_sha]
7096.3.2 by Jelmer Vernooij
Fix some git tests.
500
            extradirs = []
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
501
            for name, mode, hexsha in tree.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
502
                if self.mapping.is_special_file(name):
503
                    continue
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
504
                child_path = posixpath.join(path, name)
7096.3.2 by Jelmer Vernooij
Fix some git tests.
505
                child_path_decoded = child_path.decode('utf-8')
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
506
                if stat.S_ISDIR(mode):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
507
                    if (specific_files is None or
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
508
                            any([p for p in specific_files if p.startswith(
509
                                child_path)])):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
510
                        extradirs.append(
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
511
                            (store, child_path, hexsha,
512
                             self.path2id(child_path_decoded)))
7096.3.2 by Jelmer Vernooij
Fix some git tests.
513
                if specific_files is None or child_path in specific_files:
514
                    if stat.S_ISDIR(mode):
515
                        yield (child_path_decoded,
516
                               self._get_dir_ie(child_path, parent_id))
517
                    else:
518
                        yield (child_path_decoded,
519
                               self._get_file_ie(store, child_path, name, mode,
7143.15.2 by Jelmer Vernooij
Run autopep8.
520
                                                 hexsha, parent_id))
7096.3.2 by Jelmer Vernooij
Fix some git tests.
521
            todo.extendleft(reversed(extradirs))
0.264.6 by Jelmer Vernooij
Implement custom GitRevisionTree.iter_entries_by_dir, GitRevisionTree.list_files.
522
7096.3.5 by Jelmer Vernooij
Fix GitRevisionTree.iter_references.
523
    def iter_references(self):
524
        if self.supports_tree_reference():
525
            for path, entry in self.iter_entries_by_dir():
526
                if entry.kind == 'tree-reference':
7350.2.1 by Jelmer Vernooij
Drop file_id return value from Tree.iter_references.
527
                    yield path
7096.3.5 by Jelmer Vernooij
Fix GitRevisionTree.iter_references.
528
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
529
    def get_revision_id(self):
0.200.959 by Jelmer Vernooij
Improve docstrings.
530
        """See RevisionTree.get_revision_id."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
531
        return self._revision_id
532
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
533
    def get_file_sha1(self, path, stat_value=None):
0.287.6 by Jelmer Vernooij
Fix some more tests.
534
        if self.tree is None:
535
            raise errors.NoSuchFile(path)
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
536
        return osutils.sha_string(self.get_file_text(path))
0.200.1255 by Jelmer Vernooij
Implement GitRevisionTree.get_file_sha1.
537
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
538
    def get_file_verifier(self, path, stat_value=None):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
539
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
540
        return ("GIT", hexsha)
541
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
542
    def get_file_size(self, path):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
543
        (store, mode, hexsha) = self._lookup_path(path)
544
        if stat.S_ISREG(mode):
545
            return len(store[hexsha].data)
546
        return None
547
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
548
    def get_file_text(self, path):
0.200.959 by Jelmer Vernooij
Improve docstrings.
549
        """See RevisionTree.get_file_text."""
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
550
        (store, mode, hexsha) = self._lookup_path(path)
0.264.3 by Jelmer Vernooij
Make RevisionTree inventoryless.
551
        if stat.S_ISREG(mode):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
552
            return store[hexsha].data
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
553
        else:
0.335.1 by Jelmer Vernooij
Be a bit stricter about encodings.
554
            return b""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
555
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
556
    def get_symlink_target(self, path):
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
557
        """See RevisionTree.get_symlink_target."""
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
558
        (store, mode, hexsha) = self._lookup_path(path)
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
559
        if stat.S_ISLNK(mode):
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
560
            return store[hexsha].data.decode('utf-8')
0.200.1466 by Jelmer Vernooij
Implement GitRevisionTree.get_symlink_target.
561
        else:
562
            return None
563
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
564
    def get_reference_revision(self, path):
0.429.17 by Jelmer Vernooij
Fix some more tests.
565
        """See RevisionTree.get_symlink_target."""
0.429.25 by Jelmer Vernooij
Merge trunk.
566
        (store, mode, hexsha) = self._lookup_path(path)
0.429.17 by Jelmer Vernooij
Fix some more tests.
567
        if S_ISGITLINK(mode):
0.429.26 by Jelmer Vernooij
Fix remaining test.
568
            nested_repo = self._get_nested_repository(path)
569
            return nested_repo.lookup_foreign_revision_id(hexsha)
0.429.17 by Jelmer Vernooij
Fix some more tests.
570
        else:
571
            return None
572
0.264.10 by Jelmer Vernooij
Yield inventory entries.
573
    def _comparison_data(self, entry, path):
574
        if entry is None:
575
            return None, False, None
576
        return entry.kind, entry.executable, None
577
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
578
    def path_content_summary(self, path):
579
        """See Tree.path_content_summary."""
580
        try:
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
581
            (store, mode, hexsha) = self._lookup_path(path)
0.381.1 by Jelmer Vernooij
Standardize looking up entries in Git trees.
582
        except errors.NoSuchFile:
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
583
            return ('missing', None, None, None)
584
        kind = mode_kind(mode)
585
        if kind == 'file':
586
            executable = mode_is_executable(mode)
0.400.2 by Jelmer Vernooij
Return store from self._lookup_path.
587
            contents = store[hexsha].data
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
588
            return (kind, len(contents), executable,
589
                    osutils.sha_string(contents))
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
590
        elif kind == 'symlink':
7096.3.2 by Jelmer Vernooij
Fix some git tests.
591
            return (kind, None, None, store[hexsha].data.decode('utf-8'))
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
592
        elif kind == 'tree-reference':
0.429.26 by Jelmer Vernooij
Fix remaining test.
593
            nested_repo = self._get_nested_repository(path)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
594
            return (kind, None, None,
0.429.26 by Jelmer Vernooij
Fix remaining test.
595
                    nested_repo.lookup_foreign_revision_id(hexsha))
0.200.1568 by Jelmer Vernooij
Implement GitRevisionTree.path_content_summary.
596
        else:
597
            return (kind, None, None, None)
598
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
599
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
600
                                        require_versioned=True):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
601
        if paths is None:
602
            return None
603
        if require_versioned:
604
            trees = [self] + (trees if trees is not None else [])
605
            unversioned = set()
606
            for p in paths:
607
                for t in trees:
608
                    if t.is_versioned(p):
609
                        break
610
                else:
611
                    unversioned.add(p)
612
            if unversioned:
613
                raise errors.PathsNotVersionedError(unversioned)
614
        return filter(self.is_versioned, paths)
615
0.393.1 by Jelmer Vernooij
Avoid expensive bzr APIs in commit.
616
    def _iter_tree_contents(self, include_trees=False):
617
        if self.tree is None:
618
            return iter([])
619
        return self.store.iter_tree_contents(
7143.15.2 by Jelmer Vernooij
Run autopep8.
620
            self.tree, include_trees=include_trees)
0.393.1 by Jelmer Vernooij
Avoid expensive bzr APIs in commit.
621
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
622
    def annotate_iter(self, path, default_revision=CURRENT_REVISION):
6973.2.1 by Jelmer Vernooij
Implement GitRevisionTree.annotate_iter.
623
        """Return an iterator of revision_id, line tuples.
624
625
        For working trees (and mutable trees in general), the special
626
        revision_id 'current:' will be used for lines that are new in this
627
        tree, e.g. uncommitted changes.
628
        :param default_revision: For lines that don't match a basis, mark them
629
            with this revision id. Not all implementations will make use of
630
            this value.
631
        """
632
        with self.lock_read():
633
            # Now we have the parents of this content
634
            from breezy.annotate import Annotator
635
            from .annotate import AnnotateProvider
636
            annotator = Annotator(AnnotateProvider(
637
                self._repository._file_change_scanner))
638
            this_key = (path, self.get_file_revision(path))
639
            annotations = [(key[-1], line)
640
                           for key, line in annotator.annotate_flat(this_key)]
641
            return annotations
642
7096.3.2 by Jelmer Vernooij
Fix some git tests.
643
    def _get_rules_searcher(self, default_searcher):
644
        return default_searcher
645
7096.3.6 by Jelmer Vernooij
Fix tests, on python 2 at least.
646
    def walkdirs(self, prefix=u""):
7096.3.2 by Jelmer Vernooij
Fix some git tests.
647
        (store, mode, hexsha) = self._lookup_path(prefix)
7143.15.2 by Jelmer Vernooij
Run autopep8.
648
        todo = deque(
649
            [(store, prefix.encode('utf-8'), hexsha, self.path2id(prefix))])
7096.3.2 by Jelmer Vernooij
Fix some git tests.
650
        while todo:
7096.3.4 by Jelmer Vernooij
Fix returned paths.
651
            store, path, tree_sha, parent_id = todo.popleft()
7096.3.2 by Jelmer Vernooij
Fix some git tests.
652
            path_decoded = path.decode('utf-8')
653
            tree = store[tree_sha]
654
            children = []
655
            for name, mode, hexsha in tree.iteritems():
656
                if self.mapping.is_special_file(name):
657
                    continue
658
                child_path = posixpath.join(path, name)
659
                file_id = self.path2id(child_path.decode('utf-8'))
660
                if stat.S_ISDIR(mode):
7096.3.4 by Jelmer Vernooij
Fix returned paths.
661
                    todo.append((store, child_path, hexsha, file_id))
7096.3.6 by Jelmer Vernooij
Fix tests, on python 2 at least.
662
                children.append(
663
                    (child_path.decode('utf-8'), name.decode('utf-8'),
664
                        mode_kind(mode), None,
665
                        file_id, mode_kind(mode)))
7096.3.4 by Jelmer Vernooij
Fix returned paths.
666
            yield (path_decoded, parent_id), children
7096.3.2 by Jelmer Vernooij
Fix some git tests.
667
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
668
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
669
def tree_delta_from_git_changes(changes, mapping,
7143.15.2 by Jelmer Vernooij
Run autopep8.
670
                                fileid_maps, specific_files=None,
671
                                require_versioned=False, include_root=False,
672
                                target_extras=None):
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
673
    """Create a TreeDelta from two git trees.
0.200.959 by Jelmer Vernooij
Improve docstrings.
674
675
    source and target are iterators over tuples with:
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
676
        (filename, sha, mode)
677
    """
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
678
    (old_fileid_map, new_fileid_map) = fileid_maps
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
679
    if target_extras is None:
680
        target_extras = set()
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
681
    ret = delta.TreeDelta()
7211.10.2 by Jelmer Vernooij
Don't list directories without versioned files as 'added'.
682
    added = []
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
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:
7211.10.7 by Jelmer Vernooij
Fix on python 3.
709
            added.append((newpath, mode_kind(newmode)))
6977.1.2 by Jelmer Vernooij
Deal with missing files properly in 'bzr st'.
710
        elif newpath is None or newmode == 0:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
711
            file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
712
            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.
713
        elif oldpath != newpath:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
714
            file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
715
            ret.renamed.append(
7018.3.2 by Jelmer Vernooij
Fix some git tests.
716
                (oldpath_decoded, newpath.decode('utf-8'), file_id,
7143.15.2 by Jelmer Vernooij
Run autopep8.
717
                 mode_kind(newmode), (oldsha != newsha),
718
                 (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
719
        elif mode_kind(oldmode) != mode_kind(newmode):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
720
            file_id = new_fileid_map.lookup_file_id(newpath_decoded)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
721
            ret.kind_changed.append(
7018.3.2 by Jelmer Vernooij
Fix some git tests.
722
                (newpath_decoded, file_id, mode_kind(oldmode),
7143.15.2 by Jelmer Vernooij
Run autopep8.
723
                 mode_kind(newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
724
        elif oldsha != newsha or oldmode != newmode:
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
725
            if stat.S_ISDIR(oldmode) and stat.S_ISDIR(newmode):
726
                continue
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.modified.append(
7067.13.12 by Jelmer Vernooij
Handle decoded paths.
729
                (newpath_decoded, file_id, mode_kind(newmode),
7143.15.2 by Jelmer Vernooij
Run autopep8.
730
                 (oldsha != newsha), (oldmode != newmode)))
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
731
        else:
7018.3.2 by Jelmer Vernooij
Fix some git tests.
732
            file_id = new_fileid_map.lookup_file_id(newpath_decoded)
7143.15.2 by Jelmer Vernooij
Run autopep8.
733
            ret.unchanged.append(
734
                (newpath_decoded, file_id, mode_kind(newmode)))
0.394.1 by Jelmer Vernooij
Fix reporting of extras in TreeDelta.
735
7211.10.7 by Jelmer Vernooij
Fix on python 3.
736
    implicit_dirs = {b''}
7211.10.2 by Jelmer Vernooij
Don't list directories without versioned files as 'added'.
737
    for path, kind in added:
7211.10.7 by Jelmer Vernooij
Fix on python 3.
738
        if kind == 'directory' or path in target_extras:
7211.10.2 by Jelmer Vernooij
Don't list directories without versioned files as 'added'.
739
            continue
740
        implicit_dirs.update(osutils.parent_directories(path))
741
742
    for path, kind in added:
7211.10.5 by Jelmer Vernooij
Fix handling of directories.
743
        if kind == 'directory' and path not in implicit_dirs:
744
            continue
7211.10.7 by Jelmer Vernooij
Fix on python 3.
745
        path_decoded = osutils.normalized_filename(path)[0]
7211.10.5 by Jelmer Vernooij
Fix handling of directories.
746
        if path in target_extras:
7211.10.7 by Jelmer Vernooij
Fix on python 3.
747
            ret.unversioned.append((path_decoded, None, kind))
7211.10.2 by Jelmer Vernooij
Don't list directories without versioned files as 'added'.
748
        else:
7211.10.7 by Jelmer Vernooij
Fix on python 3.
749
            file_id = new_fileid_map.lookup_file_id(path_decoded)
750
            ret.added.append((path_decoded, file_id, kind))
7211.10.2 by Jelmer Vernooij
Don't list directories without versioned files as 'added'.
751
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
752
    return ret
753
754
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
755
def changes_from_git_changes(changes, mapping, specific_files=None,
756
                             include_unchanged=False, target_extras=None):
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
757
    """Create a iter_changes-like generator from a git stream.
0.200.959 by Jelmer Vernooij
Improve docstrings.
758
759
    source and target are iterators over tuples with:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
760
        (filename, sha, mode)
761
    """
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
762
    if target_extras is None:
763
        target_extras = set()
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
764
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
765
        if oldpath is not None:
766
            oldpath_decoded = oldpath.decode('utf-8')
767
        else:
768
            oldpath_decoded = None
769
        if newpath is not None:
770
            newpath_decoded = newpath.decode('utf-8')
771
        else:
772
            newpath_decoded = None
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
773
        if not (specific_files is None or
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
774
                (oldpath_decoded is not None and
775
                    osutils.is_inside_or_parent_of_any(
776
                        specific_files, oldpath_decoded)) or
777
                (newpath_decoded is not None and
778
                    osutils.is_inside_or_parent_of_any(
779
                        specific_files, newpath_decoded))):
0.200.1743 by Jelmer Vernooij
Fix some revision delta filtering.
780
            continue
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
781
        if oldpath is not None and mapping.is_special_file(oldpath):
782
            continue
783
        if newpath is not None and mapping.is_special_file(newpath):
0.200.1328 by Jelmer Vernooij
More test fixes.
784
            continue
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
785
        if oldpath_decoded is None:
786
            fileid = mapping.generate_file_id(newpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
787
            oldexe = None
788
            oldkind = None
789
            oldname = None
790
            oldparent = None
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
791
            oldversioned = False
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
792
        else:
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
793
            oldversioned = True
0.391.8 by Jelmer Vernooij
Allow missing items in old tree.
794
            if oldmode:
795
                oldexe = mode_is_executable(oldmode)
796
                oldkind = mode_kind(oldmode)
797
            else:
798
                oldexe = False
799
                oldkind = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
800
            if oldpath_decoded == u'':
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
801
                oldparent = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
802
                oldname = u''
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
803
            else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
804
                (oldparentpath, oldname) = osutils.split(oldpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
805
                oldparent = mapping.generate_file_id(oldparentpath)
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
806
            fileid = mapping.generate_file_id(oldpath_decoded)
807
        if newpath_decoded is None:
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
808
            newexe = None
809
            newkind = None
810
            newname = None
811
            newparent = None
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
812
            newversioned = False
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
813
        else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
814
            newversioned = (newpath_decoded not in target_extras)
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
815
            if newmode:
0.200.1576 by Jelmer Vernooij
Merge a bunch of fixes from store-roundtrip-info.
816
                newexe = mode_is_executable(newmode)
817
                newkind = mode_kind(newmode)
818
            else:
819
                newexe = False
820
                newkind = None
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
821
            if newpath_decoded == u'':
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
822
                newparent = None
0.316.1 by Jelmer Vernooij
Fix iter_changes behaviour for trees in the tree root.
823
                newname = u''
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
824
            else:
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
825
                newparentpath, newname = osutils.split(newpath_decoded)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
826
                newparent = mapping.generate_file_id(newparentpath)
0.357.3 by Jelmer Vernooij
More remove fixes.
827
        if (not include_unchanged and
828
            oldkind == 'directory' and newkind == 'directory' and
7143.15.2 by Jelmer Vernooij
Run autopep8.
829
                oldpath_decoded == newpath_decoded):
0.357.3 by Jelmer Vernooij
More remove fixes.
830
            continue
7322.1.2 by Jelmer Vernooij
Return TreeChange objects.
831
        yield _mod_tree.TreeChange(
832
            fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
833
            (oldversioned, newversioned),
834
            (oldparent, newparent), (oldname, newname),
835
            (oldkind, newkind), (oldexe, newexe))
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
836
837
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
838
class InterGitTrees(_mod_tree.InterTree):
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
839
    """InterTree that works between two git trees."""
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
840
0.200.659 by Jelmer Vernooij
Prevent tests using InterGitRevisionTrees.
841
    _matching_from_tree_format = None
842
    _matching_to_tree_format = None
843
    _test_mutable_trees_to_test_trees = None
844
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
845
    @classmethod
846
    def is_compatible(cls, source, target):
0.200.959 by Jelmer Vernooij
Improve docstrings.
847
        return (isinstance(source, GitRevisionTree) and
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
848
                isinstance(target, GitRevisionTree))
849
850
    def compare(self, want_unchanged=False, specific_files=None,
851
                extra_trees=None, require_versioned=False, include_root=False,
852
                want_unversioned=False):
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
853
        with self.lock_read():
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
854
            changes, target_extras = self._iter_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
855
                want_unchanged=want_unchanged,
856
                require_versioned=require_versioned,
857
                specific_files=specific_files,
858
                extra_trees=extra_trees,
859
                want_unversioned=want_unversioned)
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
860
            source_fileid_map = self.source._fileid_map
861
            target_fileid_map = self.target._fileid_map
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
862
            return tree_delta_from_git_changes(
863
                changes, self.target.mapping,
864
                (source_fileid_map, target_fileid_map),
865
                specific_files=specific_files,
866
                include_root=include_root, target_extras=target_extras)
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
867
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
868
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
869
                     pb=None, extra_trees=[], require_versioned=True,
870
                     want_unversioned=False):
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
871
        with self.lock_read():
0.391.7 by Jelmer Vernooij
Fix reporting of missing files in .iter_changes.
872
            changes, target_extras = self._iter_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
873
                want_unchanged=include_unchanged,
874
                require_versioned=require_versioned,
875
                specific_files=specific_files,
876
                extra_trees=extra_trees,
877
                want_unversioned=want_unversioned)
0.391.4 by Jelmer Vernooij
Simplify InterGitTrees implementation.
878
            return changes_from_git_changes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
879
                changes, self.target.mapping,
880
                specific_files=specific_files,
881
                include_unchanged=include_unchanged,
882
                target_extras=target_extras)
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
883
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
884
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
885
                          require_versioned=False, extra_trees=None,
886
                          want_unversioned=False):
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
887
        raise NotImplementedError(self._iter_git_changes)
888
889
890
class InterGitRevisionTrees(InterGitTrees):
891
    """InterTree that works between two git revision trees."""
892
893
    _matching_from_tree_format = None
894
    _matching_to_tree_format = None
895
    _test_mutable_trees_to_test_trees = None
896
897
    @classmethod
898
    def is_compatible(cls, source, target):
899
        return (isinstance(source, GitRevisionTree) and
900
                isinstance(target, GitRevisionTree))
901
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
902
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
903
                          require_versioned=True, extra_trees=None,
904
                          want_unversioned=False):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
905
        trees = [self.source]
906
        if extra_trees is not None:
907
            trees.extend(extra_trees)
908
        if specific_files is not None:
909
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
910
                specific_files, trees,
911
                require_versioned=require_versioned)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
912
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
913
        if (self.source._repository._git.object_store !=
914
                self.target._repository._git.object_store):
915
            store = OverlayObjectStore(
916
                [self.source._repository._git.object_store,
917
                    self.target._repository._git.object_store])
0.200.1780 by Jelmer Vernooij
Fix cross-object-store tree comparison.
918
        else:
919
            store = self.source._repository._git.object_store
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
920
        return store.tree_changes(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
921
            self.source.tree, self.target.tree, want_unchanged=want_unchanged,
0.391.2 by Jelmer Vernooij
Pass along target_missing.
922
            include_trees=True, change_type_same=True), set()
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
923
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
924
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
925
_mod_tree.InterTree.register_optimiser(InterGitRevisionTrees)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
926
927
928
class MutableGitIndexTree(mutabletree.MutableTree):
929
930
    def __init__(self):
931
        self._lock_mode = None
932
        self._lock_count = 0
933
        self._versioned_dirs = None
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
934
        self._index_dirty = False
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
935
936
    def is_versioned(self, path):
937
        with self.lock_read():
938
            path = path.rstrip('/').encode('utf-8')
0.429.1 by Jelmer Vernooij
Abstract away index access.
939
            (index, subpath) = self._lookup_index(path)
940
            return (subpath in index or self._has_dir(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
941
942
    def _has_dir(self, path):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
943
        if not isinstance(path, bytes):
944
            raise TypeError(path)
945
        if path == b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
946
            return True
947
        if self._versioned_dirs is None:
948
            self._load_dirs()
949
        return path in self._versioned_dirs
950
951
    def _load_dirs(self):
0.361.3 by Jelmer Vernooij
Merge trunk,
952
        if self._lock_mode is None:
953
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
954
        self._versioned_dirs = set()
0.429.1 by Jelmer Vernooij
Abstract away index access.
955
        # TODO(jelmer): Browse over all indexes
0.429.11 by Jelmer Vernooij
Merge trunk.
956
        for p, i in self._recurse_index_entries():
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
957
            self._ensure_versioned_dir(posixpath.dirname(p))
958
959
    def _ensure_versioned_dir(self, dirname):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
960
        if not isinstance(dirname, bytes):
961
            raise TypeError(dirname)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
962
        if dirname in self._versioned_dirs:
963
            return
7018.3.2 by Jelmer Vernooij
Fix some git tests.
964
        if dirname != b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
965
            self._ensure_versioned_dir(posixpath.dirname(dirname))
966
        self._versioned_dirs.add(dirname)
967
968
    def path2id(self, path):
969
        with self.lock_read():
970
            path = path.rstrip('/')
971
            if self.is_versioned(path.rstrip('/')):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
972
                return self._fileid_map.lookup_file_id(
973
                    osutils.safe_unicode(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
974
            return None
975
976
    def has_id(self, file_id):
977
        try:
978
            self.id2path(file_id)
979
        except errors.NoSuchId:
980
            return False
981
        else:
982
            return True
983
984
    def id2path(self, file_id):
985
        if file_id is None:
986
            return ''
0.361.3 by Jelmer Vernooij
Merge trunk,
987
        if type(file_id) is not bytes:
988
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
989
        with self.lock_read():
990
            try:
991
                path = self._fileid_map.lookup_path(file_id)
992
            except ValueError:
993
                raise errors.NoSuchId(self, file_id)
994
            if self.is_versioned(path):
995
                return path
996
            raise errors.NoSuchId(self, file_id)
997
998
    def _set_root_id(self, file_id):
7206.6.1 by Jelmer Vernooij
Drop file_id from record_iter_changes return value.
999
        raise errors.UnsupportedOperation(self._set_root_id, self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1000
1001
    def get_root_id(self):
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
1002
        return self.path2id(u"")
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1003
1004
    def _add(self, files, ids, kinds):
1005
        for (path, file_id, kind) in zip(files, ids, kinds):
1006
            if file_id is not None:
1007
                raise workingtree.SettingFileIdUnsupported()
0.366.1 by Jelmer Vernooij
Fix normalized filename checking in add.
1008
            path, can_access = osutils.normalized_filename(path)
1009
            if not can_access:
1010
                raise errors.InvalidNormalization(path)
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1011
            self._index_add_entry(path, kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1012
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1013
    def _read_submodule_head(self, path):
1014
        raise NotImplementedError(self._read_submodule_head)
1015
0.429.1 by Jelmer Vernooij
Abstract away index access.
1016
    def _lookup_index(self, encoded_path):
1017
        if not isinstance(encoded_path, bytes):
1018
            raise TypeError(encoded_path)
0.429.11 by Jelmer Vernooij
Merge trunk.
1019
        # TODO(jelmer): Look in other indexes
0.429.1 by Jelmer Vernooij
Abstract away index access.
1020
        return self.index, encoded_path
1021
0.429.25 by Jelmer Vernooij
Merge trunk.
1022
    def _index_del_entry(self, index, path):
1023
        del index[path]
1024
        # TODO(jelmer): Keep track of dirty per index
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1025
        self._index_dirty = True
1026
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1027
    def _index_add_entry(self, path, kind, flags=0, reference_revision=None):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1028
        if kind == "directory":
1029
            # Git indexes don't contain directories
1030
            return
1031
        if kind == "file":
1032
            blob = Blob()
1033
            try:
1034
                file, stat_val = self.get_file_with_stat(path)
1035
            except (errors.NoSuchFile, IOError):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1036
                # TODO: Rather than come up with something here, use the old
1037
                # index
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1038
                file = BytesIO()
1039
                stat_val = os.stat_result(
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
1040
                    (stat.S_IFREG | 0o644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
7027.4.7 by Jelmer Vernooij
Fix some tests.
1041
            with file:
1042
                blob.set_raw_string(file.read())
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1043
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1044
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1045
                self.store.add_object(blob)
1046
            hexsha = blob.id
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1047
        elif kind == "symlink":
1048
            blob = Blob()
1049
            try:
1050
                stat_val = self._lstat(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1051
            except EnvironmentError:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1052
                # TODO: Rather than come up with something here, use the
1053
                # old index
1054
                stat_val = os.stat_result(
1055
                    (stat.S_IFLNK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1056
            blob.set_raw_string(
1057
                self.get_symlink_target(path).encode("utf-8"))
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1058
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1059
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1060
                self.store.add_object(blob)
1061
            hexsha = blob.id
1062
        elif kind == "tree-reference":
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1063
            if reference_revision is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1064
                hexsha = self.branch.lookup_bzr_revision_id(
1065
                    reference_revision)[0]
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1066
            else:
1067
                hexsha = self._read_submodule_head(path)
1068
                if hexsha is None:
1069
                    raise errors.NoCommits(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1070
            try:
1071
                stat_val = self._lstat(path)
1072
            except EnvironmentError:
1073
                stat_val = os.stat_result(
1074
                    (S_IFGITLINK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1075
            stat_val = os.stat_result((S_IFGITLINK, ) + stat_val[1:])
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1076
        else:
1077
            raise AssertionError("unknown kind '%s'" % kind)
1078
        # Add an entry to the index or update the existing entry
1079
        ensure_normalized_path(path)
1080
        encoded_path = path.encode("utf-8")
1081
        if b'\r' in encoded_path or b'\n' in encoded_path:
1082
            # TODO(jelmer): Why do we need to do this?
1083
            trace.mutter('ignoring path with invalid newline in it: %r', path)
1084
            return
0.429.1 by Jelmer Vernooij
Abstract away index access.
1085
        (index, index_path) = self._lookup_index(encoded_path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1086
        index[index_path] = index_entry_from_stat(stat_val, hexsha, flags)
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1087
        self._index_dirty = True
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1088
        if self._versioned_dirs is not None:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1089
            self._ensure_versioned_dir(index_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1090
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1091
    def _recurse_index_entries(self, index=None, basepath=b""):
0.429.7 by Jelmer Vernooij
Consistent file ids.
1092
        # Iterate over all index entries
1093
        with self.lock_read():
1094
            if index is None:
1095
                index = self.index
6973.12.3 by Jelmer Vernooij
Fixes.
1096
            for path, value in index.items():
0.429.7 by Jelmer Vernooij
Consistent file ids.
1097
                yield (posixpath.join(basepath, path), value)
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1098
                (ctime, mtime, dev, ino, mode, uid, gid, size, sha,
1099
                 flags) = value
0.429.10 by Jelmer Vernooij
use new read_submodule_head from dulwich.
1100
                if S_ISGITLINK(mode):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1101
                    pass  # TODO(jelmer): dive into submodule
0.429.7 by Jelmer Vernooij
Consistent file ids.
1102
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1103
    def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1104
        if yield_parents:
1105
            raise NotImplementedError(self.iter_entries_by_dir)
1106
        with self.lock_read():
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1107
            if specific_files is not None:
1108
                specific_files = set(specific_files)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1109
            else:
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1110
                specific_files = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1111
            root_ie = self._get_dir_ie(u"", None)
1112
            ret = {}
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1113
            if specific_files is None or u"" in specific_files:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1114
                ret[(u"", u"")] = root_ie
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1115
            dir_ids = {u"": root_ie.file_id}
0.429.7 by Jelmer Vernooij
Consistent file ids.
1116
            for path, value in self._recurse_index_entries():
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1117
                if self.mapping.is_special_file(path):
1118
                    continue
1119
                path = path.decode("utf-8")
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1120
                if specific_files is not None and path not in specific_files:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1121
                    continue
1122
                (parent, name) = posixpath.split(path)
1123
                try:
1124
                    file_ie = self._get_file_ie(name, path, value, None)
1125
                except errors.NoSuchFile:
1126
                    continue
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1127
                if yield_parents or specific_files is None:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1128
                    for (dir_path, dir_ie) in self._add_missing_parent_ids(
1129
                            parent, dir_ids):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1130
                        ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
0.429.12 by Jelmer Vernooij
Remove revision.
1131
                file_ie.parent_id = self.path2id(parent)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1132
                ret[(posixpath.dirname(path), path)] = file_ie
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1133
            return ((path, ie) for ((_, path), ie) in sorted(viewitems(ret)))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1134
0.429.7 by Jelmer Vernooij
Consistent file ids.
1135
    def iter_references(self):
1136
        # TODO(jelmer): Implement a more efficient version of this
1137
        for path, entry in self.iter_entries_by_dir():
1138
            if entry.kind == 'tree-reference':
7350.2.1 by Jelmer Vernooij
Drop file_id return value from Tree.iter_references.
1139
                yield path
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1140
1141
    def _get_dir_ie(self, path, parent_id):
1142
        file_id = self.path2id(path)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1143
        return GitTreeDirectory(file_id,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1144
                                posixpath.basename(path).strip("/"), parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1145
1146
    def _get_file_ie(self, name, path, value, parent_id):
6973.6.2 by Jelmer Vernooij
Fix more tests.
1147
        if not isinstance(name, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1148
            raise TypeError(name)
6973.6.2 by Jelmer Vernooij
Fix more tests.
1149
        if not isinstance(path, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1150
            raise TypeError(path)
1151
        if not isinstance(value, tuple) or len(value) != 10:
1152
            raise TypeError(value)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1153
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
1154
        file_id = self.path2id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1155
        if not isinstance(file_id, bytes):
1156
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1157
        kind = mode_kind(mode)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1158
        ie = entry_factory[kind](file_id, name, parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1159
        if kind == 'symlink':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1160
            ie.symlink_target = self.get_symlink_target(path)
0.429.7 by Jelmer Vernooij
Consistent file ids.
1161
        elif kind == 'tree-reference':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1162
            ie.reference_revision = self.get_reference_revision(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1163
        else:
1164
            try:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1165
                data = self.get_file_text(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1166
            except errors.NoSuchFile:
1167
                data = None
1168
            except IOError as e:
1169
                if e.errno != errno.ENOENT:
1170
                    raise
1171
                data = None
1172
            if data is None:
1173
                data = self.branch.repository._git.object_store[sha].data
1174
            ie.text_sha1 = osutils.sha_string(data)
1175
            ie.text_size = len(data)
1176
            ie.executable = bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
1177
        return ie
1178
1179
    def _add_missing_parent_ids(self, path, dir_ids):
1180
        if path in dir_ids:
1181
            return []
1182
        parent = posixpath.dirname(path).strip("/")
1183
        ret = self._add_missing_parent_ids(parent, dir_ids)
1184
        parent_id = dir_ids[parent]
1185
        ie = self._get_dir_ie(path, parent_id)
1186
        dir_ids[path] = ie.file_id
1187
        ret.append((path, ie))
1188
        return ret
1189
1190
    def _comparison_data(self, entry, path):
1191
        if entry is None:
1192
            return None, False, None
1193
        return entry.kind, entry.executable, None
1194
1195
    def _unversion_path(self, path):
0.361.3 by Jelmer Vernooij
Merge trunk,
1196
        if self._lock_mode is None:
1197
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1198
        encoded_path = path.encode("utf-8")
1199
        count = 0
0.429.1 by Jelmer Vernooij
Abstract away index access.
1200
        (index, subpath) = self._lookup_index(encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1201
        try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1202
            self._index_del_entry(index, encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1203
        except KeyError:
1204
            # A directory, perhaps?
0.429.1 by Jelmer Vernooij
Abstract away index access.
1205
            # TODO(jelmer): Deletes that involve submodules?
1206
            for p in list(index):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1207
                if p.startswith(subpath + b"/"):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1208
                    count += 1
0.429.25 by Jelmer Vernooij
Merge trunk.
1209
                    self._index_del_entry(index, p)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1210
        else:
1211
            count = 1
1212
        self._versioned_dirs = None
1213
        return count
1214
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1215
    def unversion(self, paths):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1216
        with self.lock_tree_write():
1217
            for path in paths:
1218
                if self._unversion_path(path) == 0:
1219
                    raise errors.NoSuchFile(path)
1220
            self._versioned_dirs = None
1221
            self.flush()
1222
1223
    def flush(self):
1224
        pass
1225
1226
    def update_basis_by_delta(self, revid, delta):
1227
        # TODO(jelmer): This shouldn't be called, it's inventory specific.
1228
        for (old_path, new_path, file_id, ie) in delta:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1229
            if old_path is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1230
                (index, old_subpath) = self._lookup_index(
1231
                    old_path.encode('utf-8'))
0.429.1 by Jelmer Vernooij
Abstract away index access.
1232
                if old_subpath in index:
0.429.25 by Jelmer Vernooij
Merge trunk.
1233
                    self._index_del_entry(index, old_subpath)
0.429.1 by Jelmer Vernooij
Abstract away index access.
1234
                    self._versioned_dirs = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1235
            if new_path is not None and ie.kind != 'directory':
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1236
                self._index_add_entry(new_path, ie.kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1237
        self.flush()
1238
        self._set_merges_from_parent_ids([])
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1239
1240
    def move(self, from_paths, to_dir=None, after=None):
1241
        rename_tuples = []
1242
        with self.lock_tree_write():
1243
            to_abs = self.abspath(to_dir)
1244
            if not os.path.isdir(to_abs):
1245
                raise errors.BzrMoveFailedError('', to_dir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1246
                                                errors.NotADirectory(to_abs))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1247
1248
            for from_rel in from_paths:
1249
                from_tail = os.path.split(from_rel)[-1]
1250
                to_rel = os.path.join(to_dir, from_tail)
1251
                self.rename_one(from_rel, to_rel, after=after)
1252
                rename_tuples.append((from_rel, to_rel))
1253
            self.flush()
1254
            return rename_tuples
1255
1256
    def rename_one(self, from_rel, to_rel, after=None):
1257
        from_path = from_rel.encode("utf-8")
1258
        to_rel, can_access = osutils.normalized_filename(to_rel)
1259
        if not can_access:
1260
            raise errors.InvalidNormalization(to_rel)
1261
        to_path = to_rel.encode("utf-8")
1262
        with self.lock_tree_write():
1263
            if not after:
1264
                # Perhaps it's already moved?
1265
                after = (
1266
                    not self.has_filename(from_rel) and
1267
                    self.has_filename(to_rel) and
1268
                    not self.is_versioned(to_rel))
1269
            if after:
1270
                if not self.has_filename(to_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1271
                    raise errors.BzrMoveFailedError(
1272
                        from_rel, to_rel, errors.NoSuchFile(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1273
                if self.basis_tree().is_versioned(to_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1274
                    raise errors.BzrMoveFailedError(
1275
                        from_rel, to_rel, errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1276
1277
                kind = self.kind(to_rel)
1278
            else:
1279
                try:
1280
                    to_kind = self.kind(to_rel)
1281
                except errors.NoSuchFile:
1282
                    exc_type = errors.BzrRenameFailedError
1283
                    to_kind = None
1284
                else:
1285
                    exc_type = errors.BzrMoveFailedError
1286
                if self.is_versioned(to_rel):
1287
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1288
                                   errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1289
                if not self.has_filename(from_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1290
                    raise errors.BzrMoveFailedError(
1291
                        from_rel, to_rel, errors.NoSuchFile(from_rel))
0.388.1 by Jelmer Vernooij
Don't print error moving to an unversioned directory.
1292
                kind = self.kind(from_rel)
1293
                if not self.is_versioned(from_rel) and kind != 'directory':
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1294
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1295
                                   errors.NotVersionedError(from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1296
                if self.has_filename(to_rel):
1297
                    raise errors.RenameFailedFilesExist(
1298
                        from_rel, to_rel, errors.FileExists(to_rel))
1299
1300
                kind = self.kind(from_rel)
1301
0.429.1 by Jelmer Vernooij
Abstract away index access.
1302
            if not after and kind != 'directory':
1303
                (index, from_subpath) = self._lookup_index(from_path)
1304
                if from_subpath not in index:
1305
                    # It's not a file
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1306
                    raise errors.BzrMoveFailedError(
1307
                        from_rel, to_rel,
1308
                        errors.NotVersionedError(path=from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1309
1310
            if not after:
1311
                try:
1312
                    self._rename_one(from_rel, to_rel)
1313
                except OSError as e:
1314
                    if e.errno == errno.ENOENT:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1315
                        raise errors.BzrMoveFailedError(
1316
                            from_rel, to_rel, errors.NoSuchFile(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1317
                    raise
1318
            if kind != 'directory':
0.429.13 by Jelmer Vernooij
Fix regressions.
1319
                (index, from_index_path) = self._lookup_index(from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1320
                try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1321
                    self._index_del_entry(index, from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1322
                except KeyError:
1323
                    pass
1324
                self._index_add_entry(to_rel, kind)
1325
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1326
                todo = [(p, i) for (p, i) in self._recurse_index_entries()
1327
                        if p.startswith(from_path + b'/')]
0.429.13 by Jelmer Vernooij
Fix regressions.
1328
                for child_path, child_value in todo:
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1329
                    (child_to_index, child_to_index_path) = self._lookup_index(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1330
                        posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
0.429.13 by Jelmer Vernooij
Fix regressions.
1331
                    child_to_index[child_to_index_path] = child_value
0.429.25 by Jelmer Vernooij
Merge trunk.
1332
                    # TODO(jelmer): Mark individual index as dirty
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1333
                    self._index_dirty = True
7143.15.2 by Jelmer Vernooij
Run autopep8.
1334
                    (child_from_index, child_from_index_path) = self._lookup_index(
1335
                        child_path)
1336
                    self._index_del_entry(
1337
                        child_from_index, child_from_index_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1338
1339
            self._versioned_dirs = None
1340
            self.flush()
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1341
1342
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1343
                                        require_versioned=True):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1344
        if paths is None:
1345
            return None
1346
1347
        if require_versioned:
1348
            trees = [self] + (trees if trees is not None else [])
1349
            unversioned = set()
1350
            for p in paths:
1351
                for t in trees:
1352
                    if t.is_versioned(p):
1353
                        break
1354
                else:
1355
                    unversioned.add(p)
1356
            if unversioned:
1357
                raise errors.PathsNotVersionedError(unversioned)
1358
1359
        return filter(self.is_versioned, paths)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1360
1361
    def path_content_summary(self, path):
1362
        """See Tree.path_content_summary."""
1363
        try:
1364
            stat_result = self._lstat(path)
1365
        except OSError as e:
1366
            if getattr(e, 'errno', None) == errno.ENOENT:
1367
                # no file.
1368
                return ('missing', None, None, None)
1369
            # propagate other errors
1370
            raise
1371
        kind = mode_kind(stat_result.st_mode)
1372
        if kind == 'file':
1373
            return self._file_content_summary(path, stat_result)
1374
        elif kind == 'directory':
1375
            # perhaps it looks like a plain directory, but it's really a
1376
            # reference.
1377
            if self._directory_is_tree_reference(path):
1378
                kind = 'tree-reference'
1379
            return kind, None, None, None
1380
        elif kind == 'symlink':
1381
            target = osutils.readlink(self.abspath(path))
1382
            return ('symlink', None, None, target)
1383
        else:
1384
            return (kind, None, None, None)
1385
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1386
    def kind(self, relpath):
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1387
        kind = osutils.file_kind(self.abspath(relpath))
1388
        if kind == 'directory':
1389
            (index, index_path) = self._lookup_index(relpath.encode('utf-8'))
7065.1.1 by Jelmer Vernooij
Properly handle ignored directories in Git.
1390
            if index is None:
1391
                return kind
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1392
            try:
1393
                mode = index[index_path].mode
1394
            except KeyError:
1395
                return kind
1396
            else:
1397
                if S_ISGITLINK(mode):
1398
                    return 'tree-reference'
1399
                return 'directory'
1400
        else:
1401
            return kind
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1402
1403
    def _live_entry(self, relpath):
1404
        raise NotImplementedError(self._live_entry)
1405
7350.3.1 by Jelmer Vernooij
Add Tree.get_transform.
1406
    def get_transform(self, pb=None):
1407
        from ..transform import TreeTransform
7350.3.7 by Jelmer Vernooij
Fix pb propagation.
1408
        return TreeTransform(self, pb=pb)
7350.3.1 by Jelmer Vernooij
Add Tree.get_transform.
1409
1410
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1411
1412
class InterIndexGitTree(InterGitTrees):
1413
    """InterTree that works between a Git revision tree and an index."""
1414
1415
    def __init__(self, source, target):
1416
        super(InterIndexGitTree, self).__init__(source, target)
1417
        self._index = target.index
1418
1419
    @classmethod
1420
    def is_compatible(cls, source, target):
1421
        return (isinstance(source, GitRevisionTree) and
1422
                isinstance(target, MutableGitIndexTree))
1423
1424
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1425
                          require_versioned=False, extra_trees=None,
1426
                          want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1427
        trees = [self.source]
1428
        if extra_trees is not None:
1429
            trees.extend(extra_trees)
1430
        if specific_files is not None:
1431
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1432
                specific_files, trees,
1433
                require_versioned=require_versioned)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1434
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
1435
        with self.lock_read():
1436
            return changes_between_git_tree_and_working_copy(
1437
                self.source.store, self.source.tree,
1438
                self.target, want_unchanged=want_unchanged,
1439
                want_unversioned=want_unversioned)
1440
1441
1442
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
1443
1444
1445
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.
1446
                                              want_unchanged=False,
1447
                                              want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1448
    """Determine the changes between a git tree and a working tree with index.
1449
1450
    """
1451
    extras = set()
1452
    blobs = {}
1453
    # Report dirified directories to commit_tree first, so that they can be
1454
    # replaced with non-empty directories if they have contents.
1455
    dirified = []
7122.7.5 by Jelmer Vernooij
Only trust filesystem for executable bit where supported.
1456
    trust_executable = target._supports_executable()
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1457
    for path, index_entry in target._recurse_index_entries():
1458
        try:
7045.3.2 by Jelmer Vernooij
Fix tests.
1459
            live_entry = target._live_entry(path)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1460
        except EnvironmentError as e:
1461
            if e.errno == errno.ENOENT:
1462
                # Entry was removed; keep it listed, but mark it as gone.
1463
                blobs[path] = (ZERO_SHA, 0)
1464
            elif e.errno == errno.EISDIR:
7296.1.2 by Jelmer Vernooij
Cope with API change in Dulwich.
1465
                # Backwards compatibility with Dulwich < 0.19.12;
1466
                # newer versions of Dulwich return either an entry for the
1467
                # submodule or None for directories.
7131.13.1 by Jelmer Vernooij
Don't show a delta for unchanged submodules.
1468
                if S_ISGITLINK(index_entry.mode):
1469
                    blobs[path] = (index_entry.sha, index_entry.mode)
1470
                else:
1471
                    # Entry was turned into a directory
1472
                    dirified.append((path, Tree().id, stat.S_IFDIR))
1473
                    store.add_object(Tree())
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1474
            else:
1475
                raise
1476
        else:
7296.1.2 by Jelmer Vernooij
Cope with API change in Dulwich.
1477
            if live_entry is None:
1478
                # Entry was turned into a directory
1479
                dirified.append((path, Tree().id, stat.S_IFDIR))
1480
                store.add_object(Tree())
1481
            else:
7122.6.8 by Jelmer Vernooij
Merge trunk.
1482
                mode = live_entry.mode
1483
                if not trust_executable:
1484
                    if mode_is_executable(index_entry.mode):
1485
                        mode |= 0o111
1486
                    else:
1487
                        mode &= ~0o111
7296.1.2 by Jelmer Vernooij
Cope with API change in Dulwich.
1488
                blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1489
    if want_unversioned:
1490
        for e in target.extras():
1491
            st = target._lstat(e)
1492
            try:
1493
                np, accessible = osutils.normalized_filename(e)
1494
            except UnicodeDecodeError:
1495
                raise errors.BadFilenameEncoding(
1496
                    e, osutils._fs_enc)
1497
            if stat.S_ISDIR(st.st_mode):
1498
                blob = Tree()
1499
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1500
                blob = blob_from_path_and_stat(
1501
                    target.abspath(e).encode(osutils._fs_enc), st)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1502
            store.add_object(blob)
1503
            np = np.encode('utf-8')
1504
            blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1505
            extras.add(np)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1506
    to_tree_sha = commit_tree(
1507
        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.
1508
    return store.tree_changes(
1509
        from_tree_sha, to_tree_sha, include_trees=True,
1510
        want_unchanged=want_unchanged, change_type_same=True), extras