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