/brz/remove-bazaar

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