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