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