/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
7357.1.6 by Jelmer Vernooij
Add find_source_path.
988
    def find_target_path(self, path, recurse='none'):
989
        ret = self.find_target_paths([path], recurse=recurse)
990
        return ret[path]
991
992
    def find_source_path(self, path, recurse='none'):
993
        ret = self.find_source_paths([path], recurse=recurse)
994
        return ret[path]
995
996
    def find_target_paths(self, paths, recurse='none'):
997
        paths = set(paths)
998
        ret = {}
999
        changes = self._iter_git_changes(specific_files=paths)[0]
1000
        for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
1001
            if oldpath in paths:
1002
                ret[oldpath] = newpath
7357.1.7 by Jelmer Vernooij
Add tests.
1003
        for path in paths:
1004
            if path not in ret:
1005
                if self.source.has_filename(path):
1006
                    if self.target.has_filename(path):
1007
                        ret[path] = path
1008
                    else:
1009
                        ret[path] = None
1010
                else:
1011
                    raise errors.NoSuchFile(path)
7357.1.6 by Jelmer Vernooij
Add find_source_path.
1012
        return ret
1013
1014
    def find_source_paths(self, paths, recurse='none'):
1015
        paths = set(paths)
1016
        ret = {}
1017
        changes = self._iter_git_changes(specific_files=paths)[0]
1018
        for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
1019
            if newpath in paths:
1020
                ret[newpath] = oldpath
7357.1.7 by Jelmer Vernooij
Add tests.
1021
        for path in paths:
1022
            if path not in ret:
1023
                if self.target.has_filename(path):
1024
                    if self.source.has_filename(path):
1025
                        ret[path] = path
1026
                    else:
1027
                        ret[path] = None
1028
                else:
1029
                    raise errors.NoSuchFile(path)
7357.1.6 by Jelmer Vernooij
Add find_source_path.
1030
        return ret
1031
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1032
1033
class InterGitRevisionTrees(InterGitTrees):
1034
    """InterTree that works between two git revision trees."""
1035
1036
    _matching_from_tree_format = None
1037
    _matching_to_tree_format = None
1038
    _test_mutable_trees_to_test_trees = None
1039
1040
    @classmethod
1041
    def is_compatible(cls, source, target):
1042
        return (isinstance(source, GitRevisionTree) and
1043
                isinstance(target, GitRevisionTree))
1044
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1045
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1046
                          require_versioned=True, extra_trees=None,
1047
                          want_unversioned=False):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1048
        trees = [self.source]
1049
        if extra_trees is not None:
1050
            trees.extend(extra_trees)
1051
        if specific_files is not None:
1052
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1053
                specific_files, trees,
1054
                require_versioned=require_versioned)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1055
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1056
        if (self.source._repository._git.object_store !=
1057
                self.target._repository._git.object_store):
1058
            store = OverlayObjectStore(
1059
                [self.source._repository._git.object_store,
1060
                    self.target._repository._git.object_store])
0.200.1780 by Jelmer Vernooij
Fix cross-object-store tree comparison.
1061
        else:
1062
            store = self.source._repository._git.object_store
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1063
        return store.tree_changes(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1064
            self.source.tree, self.target.tree, want_unchanged=want_unchanged,
0.391.2 by Jelmer Vernooij
Pass along target_missing.
1065
            include_trees=True, change_type_same=True), set()
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1066
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
1067
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1068
_mod_tree.InterTree.register_optimiser(InterGitRevisionTrees)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1069
1070
1071
class MutableGitIndexTree(mutabletree.MutableTree):
1072
1073
    def __init__(self):
1074
        self._lock_mode = None
1075
        self._lock_count = 0
1076
        self._versioned_dirs = None
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1077
        self._index_dirty = False
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1078
        self._submodules = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1079
1080
    def is_versioned(self, path):
1081
        with self.lock_read():
1082
            path = path.rstrip('/').encode('utf-8')
0.429.1 by Jelmer Vernooij
Abstract away index access.
1083
            (index, subpath) = self._lookup_index(path)
1084
            return (subpath in index or self._has_dir(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1085
1086
    def _has_dir(self, path):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1087
        if not isinstance(path, bytes):
1088
            raise TypeError(path)
1089
        if path == b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1090
            return True
1091
        if self._versioned_dirs is None:
1092
            self._load_dirs()
1093
        return path in self._versioned_dirs
1094
1095
    def _load_dirs(self):
0.361.3 by Jelmer Vernooij
Merge trunk,
1096
        if self._lock_mode is None:
1097
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1098
        self._versioned_dirs = set()
0.429.11 by Jelmer Vernooij
Merge trunk.
1099
        for p, i in self._recurse_index_entries():
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1100
            self._ensure_versioned_dir(posixpath.dirname(p))
1101
1102
    def _ensure_versioned_dir(self, dirname):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1103
        if not isinstance(dirname, bytes):
1104
            raise TypeError(dirname)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1105
        if dirname in self._versioned_dirs:
1106
            return
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1107
        if dirname != b"":
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1108
            self._ensure_versioned_dir(posixpath.dirname(dirname))
1109
        self._versioned_dirs.add(dirname)
1110
1111
    def path2id(self, path):
1112
        with self.lock_read():
1113
            path = path.rstrip('/')
1114
            if self.is_versioned(path.rstrip('/')):
7358.13.1 by Jelmer Vernooij
Drop file id roundtripping support in Git.
1115
                return self.mapping.generate_file_id(
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1116
                    osutils.safe_unicode(path))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1117
            return None
1118
7450.1.1 by Jelmer Vernooij
Support recurse argument to id2path.
1119
    def id2path(self, file_id, recurse='down'):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1120
        if file_id is None:
1121
            return ''
0.361.3 by Jelmer Vernooij
Merge trunk,
1122
        if type(file_id) is not bytes:
1123
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1124
        with self.lock_read():
1125
            try:
7358.13.1 by Jelmer Vernooij
Drop file id roundtripping support in Git.
1126
                path = self.mapping.parse_file_id(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1127
            except ValueError:
1128
                raise errors.NoSuchId(self, file_id)
1129
            if self.is_versioned(path):
1130
                return path
1131
            raise errors.NoSuchId(self, file_id)
1132
1133
    def _set_root_id(self, file_id):
7206.6.1 by Jelmer Vernooij
Drop file_id from record_iter_changes return value.
1134
        raise errors.UnsupportedOperation(self._set_root_id, self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1135
1136
    def _add(self, files, ids, kinds):
1137
        for (path, file_id, kind) in zip(files, ids, kinds):
1138
            if file_id is not None:
1139
                raise workingtree.SettingFileIdUnsupported()
0.366.1 by Jelmer Vernooij
Fix normalized filename checking in add.
1140
            path, can_access = osutils.normalized_filename(path)
1141
            if not can_access:
1142
                raise errors.InvalidNormalization(path)
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1143
            self._index_add_entry(path, kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1144
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1145
    def _read_submodule_head(self, path):
1146
        raise NotImplementedError(self._read_submodule_head)
1147
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1148
    def _submodule_info(self):
1149
        if self._submodules is None:
1150
            try:
1151
                with self.get_file('.gitmodules') as f:
1152
                    config = GitConfigFile.from_file(f)
1153
                    self._submodules = {
1154
                        path: (url, section)
1155
                        for path, url, section in parse_submodules(config)}
1156
            except errors.NoSuchFile:
1157
                self._submodules = {}
1158
        return self._submodules
1159
0.429.1 by Jelmer Vernooij
Abstract away index access.
1160
    def _lookup_index(self, encoded_path):
1161
        if not isinstance(encoded_path, bytes):
1162
            raise TypeError(encoded_path)
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1163
        # Common case:
1164
        if encoded_path in self.index:
1165
            return self.index, encoded_path
1166
        # TODO(jelmer): Perhaps have a cache with paths under which some
1167
        # submodules exist?
1168
        index = self.index
1169
        remaining_path = encoded_path
1170
        while True:
1171
            parts = remaining_path.split(b'/')
1172
            for i in range(1, len(parts)):
1173
                basepath = b'/'.join(parts[:i])
1174
                try:
1175
                    (ctime, mtime, dev, ino, mode, uid, gid, size, sha,
1176
                     flags) = index[basepath]
1177
                except KeyError:
1178
                    continue
1179
                else:
1180
                    if S_ISGITLINK(mode):
1181
                        index = self._get_submodule_index(basepath)
1182
                        remaining_path = b'/'.join(parts[i:])
1183
                        break
1184
                    else:
1185
                        return index, remaining_path
1186
            else:
1187
                return index, remaining_path
1188
        return index, remaining_path
0.429.1 by Jelmer Vernooij
Abstract away index access.
1189
0.429.25 by Jelmer Vernooij
Merge trunk.
1190
    def _index_del_entry(self, index, path):
1191
        del index[path]
1192
        # TODO(jelmer): Keep track of dirty per index
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1193
        self._index_dirty = True
1194
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1195
    def _index_add_entry(self, path, kind, flags=0, reference_revision=None):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1196
        if kind == "directory":
1197
            # Git indexes don't contain directories
1198
            return
1199
        if kind == "file":
1200
            blob = Blob()
1201
            try:
1202
                file, stat_val = self.get_file_with_stat(path)
1203
            except (errors.NoSuchFile, IOError):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1204
                # TODO: Rather than come up with something here, use the old
1205
                # index
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1206
                file = BytesIO()
1207
                stat_val = os.stat_result(
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
1208
                    (stat.S_IFREG | 0o644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
7027.4.7 by Jelmer Vernooij
Fix some tests.
1209
            with file:
1210
                blob.set_raw_string(file.read())
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1211
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1212
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1213
                self.store.add_object(blob)
1214
            hexsha = blob.id
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1215
        elif kind == "symlink":
1216
            blob = Blob()
1217
            try:
1218
                stat_val = self._lstat(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1219
            except EnvironmentError:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1220
                # TODO: Rather than come up with something here, use the
1221
                # old index
1222
                stat_val = os.stat_result(
1223
                    (stat.S_IFLNK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1224
            blob.set_raw_string(
1225
                self.get_symlink_target(path).encode("utf-8"))
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1226
            # Add object to the repository if it didn't exist yet
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1227
            if blob.id not in self.store:
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1228
                self.store.add_object(blob)
1229
            hexsha = blob.id
1230
        elif kind == "tree-reference":
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1231
            if reference_revision is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1232
                hexsha = self.branch.lookup_bzr_revision_id(
1233
                    reference_revision)[0]
0.429.16 by Jelmer Vernooij
Look at reference_revision on ie.
1234
            else:
1235
                hexsha = self._read_submodule_head(path)
1236
                if hexsha is None:
1237
                    raise errors.NoCommits(path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1238
            try:
1239
                stat_val = self._lstat(path)
1240
            except EnvironmentError:
1241
                stat_val = os.stat_result(
1242
                    (S_IFGITLINK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1243
            stat_val = os.stat_result((S_IFGITLINK, ) + stat_val[1:])
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1244
        else:
1245
            raise AssertionError("unknown kind '%s'" % kind)
1246
        # Add an entry to the index or update the existing entry
1247
        ensure_normalized_path(path)
1248
        encoded_path = path.encode("utf-8")
1249
        if b'\r' in encoded_path or b'\n' in encoded_path:
1250
            # TODO(jelmer): Why do we need to do this?
1251
            trace.mutter('ignoring path with invalid newline in it: %r', path)
1252
            return
0.429.1 by Jelmer Vernooij
Abstract away index access.
1253
        (index, index_path) = self._lookup_index(encoded_path)
0.429.2 by Jelmer Vernooij
Some more work on submodule support.
1254
        index[index_path] = index_entry_from_stat(stat_val, hexsha, flags)
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1255
        self._index_dirty = True
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1256
        if self._versioned_dirs is not None:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1257
            self._ensure_versioned_dir(index_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1258
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1259
    def _recurse_index_entries(self, index=None, basepath=b"",
7404.2.3 by Jelmer Vernooij
s/follow_tree_references/recurse_nested/g
1260
                               recurse_nested=False):
0.429.7 by Jelmer Vernooij
Consistent file ids.
1261
        # Iterate over all index entries
1262
        with self.lock_read():
1263
            if index is None:
1264
                index = self.index
6973.12.3 by Jelmer Vernooij
Fixes.
1265
            for path, value in index.items():
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1266
                (ctime, mtime, dev, ino, mode, uid, gid, size, sha,
1267
                 flags) = value
7404.2.3 by Jelmer Vernooij
s/follow_tree_references/recurse_nested/g
1268
                if S_ISGITLINK(mode) and recurse_nested:
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1269
                    subindex = self._get_submodule_index(path)
1270
                    for entry in self._recurse_index_entries(
1271
                            index=subindex, basepath=path,
7404.2.3 by Jelmer Vernooij
s/follow_tree_references/recurse_nested/g
1272
                            recurse_nested=recurse_nested):
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1273
                        yield entry
1274
                else:
1275
                    yield (posixpath.join(basepath, path), value)
0.429.7 by Jelmer Vernooij
Consistent file ids.
1276
7404.3.1 by Jelmer Vernooij
Add follow_tree_references argument to Tree.iter_entries_by_dir.
1277
    def iter_entries_by_dir(self, specific_files=None,
7404.3.2 by Jelmer Vernooij
Merge rename of flag to recurse_nested.
1278
                            recurse_nested=False):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1279
        with self.lock_read():
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1280
            if specific_files is not None:
1281
                specific_files = set(specific_files)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1282
            else:
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1283
                specific_files = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1284
            root_ie = self._get_dir_ie(u"", None)
1285
            ret = {}
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1286
            if specific_files is None or u"" in specific_files:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1287
                ret[(u"", u"")] = root_ie
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1288
            dir_ids = {u"": root_ie.file_id}
7404.3.1 by Jelmer Vernooij
Add follow_tree_references argument to Tree.iter_entries_by_dir.
1289
            for path, value in self._recurse_index_entries(
7404.3.2 by Jelmer Vernooij
Merge rename of flag to recurse_nested.
1290
                    recurse_nested=recurse_nested):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1291
                if self.mapping.is_special_file(path):
1292
                    continue
1293
                path = path.decode("utf-8")
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1294
                if specific_files is not None and path not in specific_files:
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1295
                    continue
1296
                (parent, name) = posixpath.split(path)
1297
                try:
1298
                    file_ie = self._get_file_ie(name, path, value, None)
1299
                except errors.NoSuchFile:
1300
                    continue
7397.2.3 by Jelmer Vernooij
Fix passing directories in specific_files in GitWorkingTree.
1301
                if specific_files is None:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1302
                    for (dir_path, dir_ie) in self._add_missing_parent_ids(
1303
                            parent, dir_ids):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1304
                        ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
0.429.12 by Jelmer Vernooij
Remove revision.
1305
                file_ie.parent_id = self.path2id(parent)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1306
                ret[(posixpath.dirname(path), path)] = file_ie
7397.2.3 by Jelmer Vernooij
Fix passing directories in specific_files in GitWorkingTree.
1307
            # Special casing for directories
1308
            if specific_files:
1309
                for path in specific_files:
1310
                    key = (posixpath.dirname(path), path)
1311
                    if key not in ret and self.is_versioned(path):
1312
                        ret[key] = self._get_dir_ie(path, self.path2id(key[0]))
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1313
            return ((path, ie) for ((_, path), ie) in sorted(viewitems(ret)))
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1314
0.429.7 by Jelmer Vernooij
Consistent file ids.
1315
    def iter_references(self):
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1316
        if self.supports_tree_reference():
1317
            # TODO(jelmer): Implement a more efficient version of this
1318
            for path, entry in self.iter_entries_by_dir():
1319
                if entry.kind == 'tree-reference':
1320
                    yield path
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1321
1322
    def _get_dir_ie(self, path, parent_id):
1323
        file_id = self.path2id(path)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1324
        return GitTreeDirectory(file_id,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1325
                                posixpath.basename(path).strip("/"), parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1326
1327
    def _get_file_ie(self, name, path, value, parent_id):
6973.6.2 by Jelmer Vernooij
Fix more tests.
1328
        if not isinstance(name, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1329
            raise TypeError(name)
6973.6.2 by Jelmer Vernooij
Fix more tests.
1330
        if not isinstance(path, text_type):
0.361.3 by Jelmer Vernooij
Merge trunk,
1331
            raise TypeError(path)
1332
        if not isinstance(value, tuple) or len(value) != 10:
1333
            raise TypeError(value)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1334
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
1335
        file_id = self.path2id(path)
7018.3.2 by Jelmer Vernooij
Fix some git tests.
1336
        if not isinstance(file_id, bytes):
1337
            raise TypeError(file_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1338
        kind = mode_kind(mode)
0.365.1 by Jelmer Vernooij
Add custom GitTree{Directory,File,Symlink}.
1339
        ie = entry_factory[kind](file_id, name, parent_id)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1340
        if kind == 'symlink':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1341
            ie.symlink_target = self.get_symlink_target(path)
0.429.7 by Jelmer Vernooij
Consistent file ids.
1342
        elif kind == 'tree-reference':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1343
            ie.reference_revision = self.get_reference_revision(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1344
        else:
1345
            try:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1346
                data = self.get_file_text(path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1347
            except errors.NoSuchFile:
1348
                data = None
1349
            except IOError as e:
1350
                if e.errno != errno.ENOENT:
1351
                    raise
1352
                data = None
1353
            if data is None:
1354
                data = self.branch.repository._git.object_store[sha].data
1355
            ie.text_sha1 = osutils.sha_string(data)
1356
            ie.text_size = len(data)
1357
            ie.executable = bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
1358
        return ie
1359
1360
    def _add_missing_parent_ids(self, path, dir_ids):
1361
        if path in dir_ids:
1362
            return []
1363
        parent = posixpath.dirname(path).strip("/")
1364
        ret = self._add_missing_parent_ids(parent, dir_ids)
1365
        parent_id = dir_ids[parent]
1366
        ie = self._get_dir_ie(path, parent_id)
1367
        dir_ids[path] = ie.file_id
1368
        ret.append((path, ie))
1369
        return ret
1370
1371
    def _comparison_data(self, entry, path):
1372
        if entry is None:
1373
            return None, False, None
1374
        return entry.kind, entry.executable, None
1375
1376
    def _unversion_path(self, path):
0.361.3 by Jelmer Vernooij
Merge trunk,
1377
        if self._lock_mode is None:
1378
            raise errors.ObjectNotLocked(self)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1379
        encoded_path = path.encode("utf-8")
1380
        count = 0
0.429.1 by Jelmer Vernooij
Abstract away index access.
1381
        (index, subpath) = self._lookup_index(encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1382
        try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1383
            self._index_del_entry(index, encoded_path)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1384
        except KeyError:
1385
            # A directory, perhaps?
0.429.1 by Jelmer Vernooij
Abstract away index access.
1386
            # TODO(jelmer): Deletes that involve submodules?
1387
            for p in list(index):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1388
                if p.startswith(subpath + b"/"):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1389
                    count += 1
0.429.25 by Jelmer Vernooij
Merge trunk.
1390
                    self._index_del_entry(index, p)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1391
        else:
1392
            count = 1
1393
        self._versioned_dirs = None
1394
        return count
1395
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1396
    def unversion(self, paths):
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1397
        with self.lock_tree_write():
1398
            for path in paths:
1399
                if self._unversion_path(path) == 0:
1400
                    raise errors.NoSuchFile(path)
1401
            self._versioned_dirs = None
1402
            self.flush()
1403
1404
    def flush(self):
1405
        pass
1406
1407
    def update_basis_by_delta(self, revid, delta):
1408
        # TODO(jelmer): This shouldn't be called, it's inventory specific.
1409
        for (old_path, new_path, file_id, ie) in delta:
0.429.1 by Jelmer Vernooij
Abstract away index access.
1410
            if old_path is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1411
                (index, old_subpath) = self._lookup_index(
1412
                    old_path.encode('utf-8'))
0.429.1 by Jelmer Vernooij
Abstract away index access.
1413
                if old_subpath in index:
0.429.25 by Jelmer Vernooij
Merge trunk.
1414
                    self._index_del_entry(index, old_subpath)
0.429.1 by Jelmer Vernooij
Abstract away index access.
1415
                    self._versioned_dirs = None
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1416
            if new_path is not None and ie.kind != 'directory':
6964.2.4 by Jelmer Vernooij
Fix running on python2.
1417
                self._index_add_entry(new_path, ie.kind)
0.360.1 by Jelmer Vernooij
Implement GitMemoryTree.
1418
        self.flush()
1419
        self._set_merges_from_parent_ids([])
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1420
1421
    def move(self, from_paths, to_dir=None, after=None):
1422
        rename_tuples = []
1423
        with self.lock_tree_write():
1424
            to_abs = self.abspath(to_dir)
1425
            if not os.path.isdir(to_abs):
1426
                raise errors.BzrMoveFailedError('', to_dir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1427
                                                errors.NotADirectory(to_abs))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1428
1429
            for from_rel in from_paths:
1430
                from_tail = os.path.split(from_rel)[-1]
1431
                to_rel = os.path.join(to_dir, from_tail)
1432
                self.rename_one(from_rel, to_rel, after=after)
1433
                rename_tuples.append((from_rel, to_rel))
1434
            self.flush()
1435
            return rename_tuples
1436
1437
    def rename_one(self, from_rel, to_rel, after=None):
1438
        from_path = from_rel.encode("utf-8")
1439
        to_rel, can_access = osutils.normalized_filename(to_rel)
1440
        if not can_access:
1441
            raise errors.InvalidNormalization(to_rel)
1442
        to_path = to_rel.encode("utf-8")
1443
        with self.lock_tree_write():
1444
            if not after:
1445
                # Perhaps it's already moved?
1446
                after = (
1447
                    not self.has_filename(from_rel) and
1448
                    self.has_filename(to_rel) and
1449
                    not self.is_versioned(to_rel))
1450
            if after:
1451
                if not self.has_filename(to_rel):
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
                if self.basis_tree().is_versioned(to_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1455
                    raise errors.BzrMoveFailedError(
1456
                        from_rel, to_rel, errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1457
1458
                kind = self.kind(to_rel)
1459
            else:
1460
                try:
1461
                    to_kind = self.kind(to_rel)
1462
                except errors.NoSuchFile:
1463
                    exc_type = errors.BzrRenameFailedError
1464
                    to_kind = None
1465
                else:
1466
                    exc_type = errors.BzrMoveFailedError
1467
                if self.is_versioned(to_rel):
1468
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1469
                                   errors.AlreadyVersionedError(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1470
                if not self.has_filename(from_rel):
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1471
                    raise errors.BzrMoveFailedError(
1472
                        from_rel, to_rel, errors.NoSuchFile(from_rel))
0.388.1 by Jelmer Vernooij
Don't print error moving to an unversioned directory.
1473
                kind = self.kind(from_rel)
1474
                if not self.is_versioned(from_rel) and kind != 'directory':
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1475
                    raise exc_type(from_rel, to_rel,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1476
                                   errors.NotVersionedError(from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1477
                if self.has_filename(to_rel):
1478
                    raise errors.RenameFailedFilesExist(
1479
                        from_rel, to_rel, errors.FileExists(to_rel))
1480
1481
                kind = self.kind(from_rel)
1482
0.429.1 by Jelmer Vernooij
Abstract away index access.
1483
            if not after and kind != 'directory':
1484
                (index, from_subpath) = self._lookup_index(from_path)
1485
                if from_subpath not in index:
1486
                    # It's not a file
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1487
                    raise errors.BzrMoveFailedError(
1488
                        from_rel, to_rel,
1489
                        errors.NotVersionedError(path=from_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1490
1491
            if not after:
1492
                try:
1493
                    self._rename_one(from_rel, to_rel)
1494
                except OSError as e:
1495
                    if e.errno == errno.ENOENT:
7143.15.3 by Jelmer Vernooij
Fix pep8 issues in breezy.git.
1496
                        raise errors.BzrMoveFailedError(
1497
                            from_rel, to_rel, errors.NoSuchFile(to_rel))
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1498
                    raise
1499
            if kind != 'directory':
0.429.13 by Jelmer Vernooij
Fix regressions.
1500
                (index, from_index_path) = self._lookup_index(from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1501
                try:
0.429.25 by Jelmer Vernooij
Merge trunk.
1502
                    self._index_del_entry(index, from_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1503
                except KeyError:
1504
                    pass
1505
                self._index_add_entry(to_rel, kind)
1506
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1507
                todo = [(p, i) for (p, i) in self._recurse_index_entries()
1508
                        if p.startswith(from_path + b'/')]
0.429.13 by Jelmer Vernooij
Fix regressions.
1509
                for child_path, child_value in todo:
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1510
                    (child_to_index, child_to_index_path) = self._lookup_index(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1511
                        posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
0.429.13 by Jelmer Vernooij
Fix regressions.
1512
                    child_to_index[child_to_index_path] = child_value
0.429.25 by Jelmer Vernooij
Merge trunk.
1513
                    # TODO(jelmer): Mark individual index as dirty
0.415.1 by Jelmer Vernooij
Only write index when it's dirty.
1514
                    self._index_dirty = True
7143.15.2 by Jelmer Vernooij
Run autopep8.
1515
                    (child_from_index, child_from_index_path) = self._lookup_index(
1516
                        child_path)
1517
                    self._index_del_entry(
1518
                        child_from_index, child_from_index_path)
0.360.4 by Jelmer Vernooij
Implement MemoryTree.rename_one, MemoryTree.mkdir.
1519
1520
            self._versioned_dirs = None
1521
            self.flush()
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1522
1523
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1524
                                        require_versioned=True):
0.385.1 by Jelmer Vernooij
Use specific_files argument to Tree.iter_entries_by_dir.
1525
        if paths is None:
1526
            return None
1527
1528
        if require_versioned:
1529
            trees = [self] + (trees if trees is not None else [])
1530
            unversioned = set()
1531
            for p in paths:
1532
                for t in trees:
1533
                    if t.is_versioned(p):
1534
                        break
1535
                else:
1536
                    unversioned.add(p)
1537
            if unversioned:
1538
                raise errors.PathsNotVersionedError(unversioned)
1539
1540
        return filter(self.is_versioned, paths)
0.429.5 by Jelmer Vernooij
Fix tree_content_summary test.
1541
1542
    def path_content_summary(self, path):
1543
        """See Tree.path_content_summary."""
1544
        try:
1545
            stat_result = self._lstat(path)
1546
        except OSError as e:
1547
            if getattr(e, 'errno', None) == errno.ENOENT:
1548
                # no file.
1549
                return ('missing', None, None, None)
1550
            # propagate other errors
1551
            raise
1552
        kind = mode_kind(stat_result.st_mode)
1553
        if kind == 'file':
1554
            return self._file_content_summary(path, stat_result)
1555
        elif kind == 'directory':
1556
            # perhaps it looks like a plain directory, but it's really a
1557
            # reference.
1558
            if self._directory_is_tree_reference(path):
1559
                kind = 'tree-reference'
1560
            return kind, None, None, None
1561
        elif kind == 'symlink':
1562
            target = osutils.readlink(self.abspath(path))
1563
            return ('symlink', None, None, target)
1564
        else:
1565
            return (kind, None, None, None)
1566
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1567
    def stored_kind(self, relpath):
1568
        (index, index_path) = self._lookup_index(relpath.encode('utf-8'))
1569
        if index is None:
1570
            return kind
1571
        try:
1572
            mode = index[index_path].mode
1573
        except KeyError:
1574
            return kind
1575
        else:
1576
            if S_ISGITLINK(mode):
1577
                return 'tree-reference'
1578
            return 'directory'
1579
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1580
    def kind(self, relpath):
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1581
        kind = osutils.file_kind(self.abspath(relpath))
1582
        if kind == 'directory':
7404.2.1 by Jelmer Vernooij
Add a follow_tree_references argument to Tree.list_files.
1583
            if self._directory_is_tree_reference(relpath):
1584
                return 'tree-reference'
1585
            return 'directory'
0.429.15 by Jelmer Vernooij
Autodetect tree-reference based on index.
1586
        else:
1587
            return kind
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1588
1589
    def _live_entry(self, relpath):
1590
        raise NotImplementedError(self._live_entry)
1591
7350.3.1 by Jelmer Vernooij
Add Tree.get_transform.
1592
    def get_transform(self, pb=None):
1593
        from ..transform import TreeTransform
7350.3.7 by Jelmer Vernooij
Fix pb propagation.
1594
        return TreeTransform(self, pb=pb)
7350.3.1 by Jelmer Vernooij
Add Tree.get_transform.
1595
1596
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1597
1598
class InterIndexGitTree(InterGitTrees):
1599
    """InterTree that works between a Git revision tree and an index."""
1600
1601
    def __init__(self, source, target):
1602
        super(InterIndexGitTree, self).__init__(source, target)
1603
        self._index = target.index
1604
1605
    @classmethod
1606
    def is_compatible(cls, source, target):
1607
        return (isinstance(source, GitRevisionTree) and
1608
                isinstance(target, MutableGitIndexTree))
1609
1610
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1611
                          require_versioned=False, extra_trees=None,
1612
                          want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1613
        trees = [self.source]
1614
        if extra_trees is not None:
1615
            trees.extend(extra_trees)
1616
        if specific_files is not None:
1617
            specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1618
                specific_files, trees,
1619
                require_versioned=require_versioned)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1620
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
1621
        with self.lock_read():
1622
            return changes_between_git_tree_and_working_copy(
1623
                self.source.store, self.source.tree,
1624
                self.target, want_unchanged=want_unchanged,
1625
                want_unversioned=want_unversioned)
1626
1627
1628
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
1629
1630
1631
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.
1632
                                              want_unchanged=False,
1633
                                              want_unversioned=False):
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1634
    """Determine the changes between a git tree and a working tree with index.
1635
1636
    """
1637
    extras = set()
1638
    blobs = {}
1639
    # Report dirified directories to commit_tree first, so that they can be
1640
    # replaced with non-empty directories if they have contents.
1641
    dirified = []
7122.7.5 by Jelmer Vernooij
Only trust filesystem for executable bit where supported.
1642
    trust_executable = target._supports_executable()
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1643
    for path, index_entry in target._recurse_index_entries():
1644
        try:
7045.3.2 by Jelmer Vernooij
Fix tests.
1645
            live_entry = target._live_entry(path)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1646
        except EnvironmentError as e:
1647
            if e.errno == errno.ENOENT:
1648
                # Entry was removed; keep it listed, but mark it as gone.
1649
                blobs[path] = (ZERO_SHA, 0)
7452.1.1 by Jelmer Vernooij
Don't show submodules that are not checked out as deltas.
1650
            else:
1651
                raise
1652
        else:
1653
            if live_entry is None:
1654
                # Entry was turned into a directory.
1655
                # 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.
1656
                if S_ISGITLINK(index_entry.mode):
1657
                    blobs[path] = (index_entry.sha, index_entry.mode)
1658
                else:
1659
                    dirified.append((path, Tree().id, stat.S_IFDIR))
1660
                    store.add_object(Tree())
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1661
            else:
7122.6.8 by Jelmer Vernooij
Merge trunk.
1662
                mode = live_entry.mode
1663
                if not trust_executable:
1664
                    if mode_is_executable(index_entry.mode):
1665
                        mode |= 0o111
1666
                    else:
1667
                        mode &= ~0o111
7296.1.2 by Jelmer Vernooij
Cope with API change in Dulwich.
1668
                blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1669
    if want_unversioned:
1670
        for e in target.extras():
1671
            st = target._lstat(e)
1672
            try:
1673
                np, accessible = osutils.normalized_filename(e)
1674
            except UnicodeDecodeError:
1675
                raise errors.BadFilenameEncoding(
1676
                    e, osutils._fs_enc)
1677
            if stat.S_ISDIR(st.st_mode):
1678
                blob = Tree()
1679
            else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1680
                blob = blob_from_path_and_stat(
1681
                    target.abspath(e).encode(osutils._fs_enc), st)
6973.1.1 by Jelmer Vernooij
Make InterIndexGitTree suitable for use with MemoryGitTree.
1682
            store.add_object(blob)
1683
            np = np.encode('utf-8')
1684
            blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1685
            extras.add(np)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1686
    to_tree_sha = commit_tree(
1687
        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.
1688
    return store.tree_changes(
1689
        from_tree_sha, to_tree_sha, include_trees=True,
1690
        want_unchanged=want_unchanged, change_type_same=True), extras