/brz/remove-bazaar

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