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