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