/brz/remove-bazaar

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