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