/brz/remove-bazaar

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