/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.264.10 by Jelmer Vernooij
Yield inventory entries.
1
# Copyright (C) 2008-2011 Jelmer Vernooij <jelmer@samba.org>
0.200.90 by Jelmer Vernooij
Basic support for opening working 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
17
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
18
"""An adapter between a Git index and a Bazaar Working Tree"""
19
0.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
20
from __future__ import absolute_import
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
21
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
22
import itertools
0.200.385 by Jelmer Vernooij
Cope with removed files.
23
from cStringIO import (
24
    StringIO,
25
    )
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
26
from collections import defaultdict
0.239.4 by Jelmer Vernooij
Cope with nonexistent files and directories in get_file_sha1.
27
import errno
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
28
from dulwich.errors import NotGitRepository
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
29
from dulwich.ignore import (
0.200.1658 by Jelmer Vernooij
Fix handling of ignores - return patterns that matched.
30
    IgnoreFilterManager,
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
31
    )
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
32
from dulwich.index import (
33
    Index,
0.200.1531 by Jelmer Vernooij
Don't trust index contents - verify against file timestamps.
34
    changes_from_tree,
35
    cleanup_mode,
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
36
    commit_tree,
0.200.1531 by Jelmer Vernooij
Don't trust index contents - verify against file timestamps.
37
    index_entry_from_stat,
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
38
    iter_fresh_blobs,
0.323.1 by Jelmer Vernooij
Fix iter_changes of untracked changes.
39
    blob_from_path_and_stat,
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
40
    )
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
41
from dulwich.object_store import (
42
    tree_lookup_path,
43
    )
0.200.383 by Jelmer Vernooij
Simplify, support rewriting index based on inventory.
44
from dulwich.objects import (
45
    Blob,
0.357.1 by Jelmer Vernooij
Fix some remove tests.
46
    Tree,
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
47
    S_IFGITLINK,
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
48
    )
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
49
from dulwich.repo import Repo
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
50
import os
0.264.10 by Jelmer Vernooij
Yield inventory entries.
51
import posixpath
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
52
import re
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
53
import stat
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
54
import sys
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
55
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
56
from ... import (
0.200.382 by Jelmer Vernooij
Support flushing index.
57
    errors,
0.262.1 by Jelmer Vernooij
Fix WorkingTree.conflicts().
58
    conflicts as _mod_conflicts,
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
59
    controldir as _mod_controldir,
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
60
    globbing,
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
61
    ignores,
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
62
    lock,
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
63
    osutils,
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
64
    revision as _mod_revision,
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
65
    trace,
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
66
    transport as _mod_transport,
0.200.519 by Jelmer Vernooij
Move imports down, might not be available in older bzr-git versions.
67
    tree,
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
68
    workingtree,
69
    )
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
70
from ...bzr import (
71
    inventory,
72
    )
0.200.1680 by Jelmer Vernooij
Fix repo locks.
73
from ...mutabletree import (
74
    MutableTree,
75
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
76
77
78
from .dir import (
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
79
    LocalGitDir,
80
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
81
from .tree import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
82
    changes_from_git_changes,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
83
    tree_delta_from_git_changes,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
84
    InterGitTrees,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
85
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
86
from .mapping import (
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
87
    GitFileIdMap,
0.264.10 by Jelmer Vernooij
Yield inventory entries.
88
    mode_kind,
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
89
    )
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
90
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
91
IGNORE_FILENAME = ".gitignore"
92
93
0.200.1768 by Jelmer Vernooij
Fix handling of normalized filenames.
94
def ensure_normalized_path(path):
95
    """Check whether path is normalized.
96
97
    :raises InvalidNormalization: When path is not normalized, and cannot be
98
        accessed on this platform by the normalized path.
99
    :return: The NFC normalised version of path.
100
    """
101
    norm_path, can_access = osutils.normalized_filename(path)
102
    if norm_path != path:
103
        if can_access:
104
            return norm_path
105
        else:
106
            raise errors.InvalidNormalization(path)
107
    return path
108
109
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
110
class GitWorkingTree(workingtree.WorkingTree):
111
    """A Git working tree."""
112
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
113
    def __init__(self, controldir, repo, branch, index):
0.200.1741 by Jelmer Vernooij
Fix opentree tests.
114
        basedir = controldir.root_transport.local_abspath('.')
115
        self.basedir = osutils.realpath(basedir)
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
116
        self.controldir = controldir
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
117
        self.repository = repo
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
118
        self.store = self.repository._git.object_store
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
119
        self.mapping = self.repository.get_mapping()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
120
        self._branch = branch
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
121
        self._transport = controldir.transport
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
122
        self._format = GitWorkingTreeFormat()
0.200.803 by Jelmer Vernooij
Default to non-bare repositories when initializing a control directory.
123
        self.index = index
0.200.1242 by Jelmer Vernooij
Support directories better.
124
        self._versioned_dirs = None
0.200.239 by Jelmer Vernooij
Provide views.
125
        self.views = self._make_views()
0.200.1173 by Jelmer Vernooij
Provide GitWorkingTree._rules_searcher.
126
        self._rules_searcher = None
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
127
        self._detect_case_handling()
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
128
        self._reset_data()
129
        self._fileid_map = self._basis_fileid_map.copy()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
130
        self._lock_mode = None
131
        self._lock_count = 0
132
0.200.1650 by Jelmer Vernooij
Implement GitWorkingTree.supports_tree_reference.
133
    def supports_tree_reference(self):
134
        return False
135
0.349.1 by Jelmer Vernooij
Support supports_rename_tracking method.
136
    def supports_rename_tracking(self):
137
        return False
138
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
139
    def lock_read(self):
140
        """Lock the repository for read operations.
141
0.200.1646 by Jelmer Vernooij
Rename bzrlib to breezy.
142
        :return: A breezy.lock.LogicalLockResult.
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
143
        """
144
        if not self._lock_mode:
145
            self._lock_mode = 'r'
146
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
147
            self.index.read()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
148
        else:
149
            self._lock_count += 1
150
        self.branch.lock_read()
151
        return lock.LogicalLockResult(self.unlock)
152
0.200.1477 by Jelmer Vernooij
Implement GitWorkingTree.lock_tree_write.
153
    def lock_tree_write(self):
154
        if not self._lock_mode:
155
            self._lock_mode = 'w'
156
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
157
            self.index.read()
0.200.1477 by Jelmer Vernooij
Implement GitWorkingTree.lock_tree_write.
158
        elif self._lock_mode == 'r':
159
            raise errors.ReadOnlyError(self)
160
        else:
161
            self._lock_count +=1
162
        self.branch.lock_read()
163
        return lock.LogicalLockResult(self.unlock)
164
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
165
    def lock_write(self, token=None):
166
        if not self._lock_mode:
167
            self._lock_mode = 'w'
168
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
169
            self.index.read()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
170
        elif self._lock_mode == 'r':
171
            raise errors.ReadOnlyError(self)
172
        else:
173
            self._lock_count +=1
174
        self.branch.lock_write()
175
        return lock.LogicalLockResult(self.unlock)
176
177
    def is_locked(self):
178
        return self._lock_count >= 1
179
180
    def get_physical_lock_status(self):
181
        return False
182
183
    def unlock(self):
184
        if not self._lock_count:
185
            return lock.cant_unlock_not_held(self)
0.200.1530 by Jelmer Vernooij
Fix lock order.
186
        self.branch.unlock()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
187
        self._cleanup()
188
        self._lock_count -= 1
189
        if self._lock_count > 0:
190
            return
191
        self._lock_mode = None
0.200.173 by Jelmer Vernooij
Merge changes, open index.
192
0.200.1658 by Jelmer Vernooij
Fix handling of ignores - return patterns that matched.
193
    def _cleanup(self):
194
        pass
195
0.200.1322 by Jelmer Vernooij
Add case detection.
196
    def _detect_case_handling(self):
197
        try:
198
            self._transport.stat(".git/cOnFiG")
199
        except errors.NoSuchFile:
200
            self.case_sensitive = True
201
        else:
202
            self.case_sensitive = False
203
0.200.1315 by Jelmer Vernooij
Implement WorkingTree.merge_modified.
204
    def merge_modified(self):
205
        return {}
206
0.200.1696 by Jelmer Vernooij
Fix set_merge_modified.
207
    def set_merge_modified(self, modified_hashes):
0.298.1 by Jelmer Vernooij
mark GitWorkngTree.set_merge_modified as unsupported.
208
        raise errors.UnsupportedOperation(self.set_merge_modified, self)
0.200.1690 by Jelmer Vernooij
Implement WorkingTree.set_merge_modified.
209
0.200.1220 by Jelmer Vernooij
Support set_parent_trees.
210
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
211
        self.set_parent_ids([p for p, t in parents_list])
212
0.305.1 by Jelmer Vernooij
Reset RHS parents after commit.
213
    def _set_merges_from_parent_ids(self, rhs_parent_ids):
0.200.1779 by Jelmer Vernooij
Actually store git revision ids rather than bzr revision ids.
214
        try:
0.305.1 by Jelmer Vernooij
Reset RHS parents after commit.
215
            merges = [self.branch.lookup_bzr_revision_id(revid)[0] for revid in rhs_parent_ids]
0.200.1779 by Jelmer Vernooij
Actually store git revision ids rather than bzr revision ids.
216
        except errors.NoSuchRevision as e:
217
            raise errors.GhostRevisionUnusableHere(e.revision)
0.304.1 by Jelmer Vernooij
Delete MERGE_HEAD if there are no parent ids.
218
        if merges:
219
            self.control_transport.put_bytes('MERGE_HEAD', '\n'.join(merges),
220
                mode=self.controldir._get_file_mode())
221
        else:
222
            try:
223
                self.control_transport.delete('MERGE_HEAD')
224
            except errors.NoSuchFile:
225
                pass
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
226
227
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
228
        """Set the parent ids to revision_ids.
229
230
        See also set_parent_trees. This api will try to retrieve the tree data
231
        for each element of revision_ids from the trees repository. If you have
232
        tree data already available, it is more efficient to use
233
        set_parent_trees rather than set_parent_ids. set_parent_ids is however
234
        an easier API to use.
235
236
        :param revision_ids: The revision_ids to set as the parent ids of this
237
            working tree. Any of these may be ghosts.
238
        """
239
        with self.lock_tree_write():
240
            self._check_parents_for_ghosts(revision_ids,
241
                allow_leftmost_as_ghost=allow_leftmost_as_ghost)
242
            for revision_id in revision_ids:
243
                _mod_revision.check_not_reserved_id(revision_id)
244
245
            revision_ids = self._filter_parent_ids_by_ancestry(revision_ids)
246
247
            if len(revision_ids) > 0:
248
                self.set_last_revision(revision_ids[0])
249
            else:
250
                self.set_last_revision(_mod_revision.NULL_REVISION)
251
0.305.1 by Jelmer Vernooij
Reset RHS parents after commit.
252
            self._set_merges_from_parent_ids(revision_ids[1:])
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
253
254
    def get_parent_ids(self):
255
        """See Tree.get_parent_ids.
256
257
        This implementation reads the pending merges list and last_revision
258
        value and uses that to decide what the parents list should be.
259
        """
260
        last_rev = _mod_revision.ensure_null(self._last_revision())
261
        if _mod_revision.NULL_REVISION == last_rev:
262
            parents = []
263
        else:
264
            parents = [last_rev]
265
        try:
266
            merges_bytes = self.control_transport.get_bytes('MERGE_HEAD')
267
        except errors.NoSuchFile:
268
            pass
269
        else:
270
            for l in osutils.split_lines(merges_bytes):
271
                revision_id = l.rstrip('\n')
0.200.1779 by Jelmer Vernooij
Actually store git revision ids rather than bzr revision ids.
272
                parents.append(self.branch.lookup_foreign_revision_id(revision_id))
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
273
        return parents
274
0.200.1599 by Jelmer Vernooij
Implement GitWorkingTree.iter_children.
275
    def iter_children(self, file_id):
276
        dpath = self.id2path(file_id) + "/"
277
        if dpath in self.index:
278
            return
279
        for path in self.index:
280
            if not path.startswith(dpath):
281
                continue
282
            if "/" in path[len(dpath):]:
283
                # Not a direct child but something further down
284
                continue
285
            yield self.path2id(path)
286
0.316.2 by Jelmer Vernooij
Flush after modifying index.
287
    def _index_add_entry(self, path, kind, flags=0):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
288
        assert self._lock_mode is not None
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
289
        assert isinstance(path, basestring)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
290
        if kind == "directory":
291
            # Git indexes don't contain directories
292
            return
293
        if kind == "file":
294
            blob = Blob()
295
            try:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
296
                file, stat_val = self.get_file_with_stat(path)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
297
            except (errors.NoSuchFile, IOError):
298
                # TODO: Rather than come up with something here, use the old index
299
                file = StringIO()
0.265.1 by Martin
Don't import posix module, the os wrapper exists for portability
300
                stat_val = os.stat_result(
301
                    (stat.S_IFREG | 0644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
302
            blob.set_raw_string(file.read())
303
        elif kind == "symlink":
304
            blob = Blob()
305
            try:
306
                stat_val = os.lstat(self.abspath(path))
307
            except (errors.NoSuchFile, OSError):
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
308
                # TODO: Rather than come up with something here, use the
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
309
                # old index
0.265.1 by Martin
Don't import posix module, the os wrapper exists for portability
310
                stat_val = os.stat_result(
311
                    (stat.S_IFLNK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
312
            blob.set_raw_string(
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
313
                self.get_symlink_target(path).encode("utf-8"))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
314
        else:
315
            raise AssertionError("unknown kind '%s'" % kind)
316
        # Add object to the repository if it didn't exist yet
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
317
        if not blob.id in self.store:
318
            self.store.add_object(blob)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
319
        # Add an entry to the index or update the existing entry
0.200.1768 by Jelmer Vernooij
Fix handling of normalized filenames.
320
        ensure_normalized_path(path)
0.200.1242 by Jelmer Vernooij
Support directories better.
321
        encoded_path = path.encode("utf-8")
0.200.1770 by Jelmer Vernooij
Fix test for illegal characters in filenames.
322
        if b'\r' in encoded_path or b'\n' in encoded_path:
323
            # TODO(jelmer): Why do we need to do this?
324
            trace.mutter('ignoring path with invalid newline in it: %r', path)
325
            return
0.200.1531 by Jelmer Vernooij
Don't trust index contents - verify against file timestamps.
326
        self.index[encoded_path] = index_entry_from_stat(
327
            stat_val, blob.id, flags)
0.200.1242 by Jelmer Vernooij
Support directories better.
328
        if self._versioned_dirs is not None:
329
            self._ensure_versioned_dir(encoded_path)
330
331
    def _ensure_versioned_dir(self, dirname):
0.200.1249 by Jelmer Vernooij
Fix file id for tree root
332
        if dirname in self._versioned_dirs:
0.200.1242 by Jelmer Vernooij
Support directories better.
333
            return
0.200.1249 by Jelmer Vernooij
Fix file id for tree root
334
        if dirname != "":
335
            self._ensure_versioned_dir(posixpath.dirname(dirname))
0.200.1242 by Jelmer Vernooij
Support directories better.
336
        self._versioned_dirs.add(dirname)
337
338
    def _load_dirs(self):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
339
        assert self._lock_mode is not None
0.200.1242 by Jelmer Vernooij
Support directories better.
340
        self._versioned_dirs = set()
341
        for p in self.index:
342
            self._ensure_versioned_dir(posixpath.dirname(p))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
343
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
344
    def _unversion_path(self, path):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
345
        assert self._lock_mode is not None
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
346
        encoded_path = path.encode("utf-8")
0.287.6 by Jelmer Vernooij
Fix some more tests.
347
        count = 0
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
348
        try:
349
            del self.index[encoded_path]
350
        except KeyError:
351
            # A directory, perhaps?
352
            for p in list(self.index):
0.200.1692 by Jelmer Vernooij
Mark three more tests as xfail.
353
                if p.startswith(encoded_path+b"/"):
0.287.6 by Jelmer Vernooij
Fix some more tests.
354
                    count += 1
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
355
                    del self.index[p]
0.287.6 by Jelmer Vernooij
Fix some more tests.
356
        else:
357
            count = 1
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
358
        self._versioned_dirs = None
0.287.6 by Jelmer Vernooij
Fix some more tests.
359
        return count
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
360
0.285.8 by Jelmer Vernooij
Fix more tests for swapped arguments.
361
    def unversion(self, paths, file_ids=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
362
        with self.lock_tree_write():
0.200.1690 by Jelmer Vernooij
Implement WorkingTree.set_merge_modified.
363
            for path in paths:
0.351.1 by Jelmer Vernooij
Support recursive unversion.
364
                if self._unversion_path(path) == 0:
365
                    raise errors.NoSuchFile(path)
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
366
            self._versioned_dirs = None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
367
            self.flush()
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
368
0.200.1678 by Jelmer Vernooij
Fix tests.
369
    def update_basis_by_delta(self, revid, delta):
370
        # TODO(jelmer): This shouldn't be called, it's inventory specific.
0.316.2 by Jelmer Vernooij
Flush after modifying index.
371
        for (old_path, new_path, file_id, ie) in delta:
372
            if old_path is not None and old_path.encode('utf-8') in self.index:
373
                del self.index[old_path.encode('utf-8')]
374
                self._versioned_dirs = None
375
            if new_path is not None and ie.kind != 'directory':
376
                self._index_add_entry(new_path, ie.kind)
377
        self.flush()
378
        self._set_merges_from_parent_ids([])
0.200.1678 by Jelmer Vernooij
Fix tests.
379
0.200.1243 by Jelmer Vernooij
Implement WorkingTree.check_state.
380
    def check_state(self):
381
        """Check that the working state is/isn't valid."""
382
        pass
383
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
384
    def remove(self, files, verbose=False, to_file=None, keep_files=True,
385
        force=False):
386
        """Remove nominated files from the working tree metadata.
387
388
        :param files: File paths relative to the basedir.
389
        :param keep_files: If true, the files will also be kept.
390
        :param force: Delete files and directories, even if they are changed
391
            and even if the directories are not empty.
392
        """
393
        if isinstance(files, basestring):
394
            files = [files]
395
396
        if to_file is None:
397
            to_file = sys.stdout
398
399
        def backup(file_to_backup):
400
            abs_path = self.abspath(file_to_backup)
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
401
            backup_name = self.controldir._available_backup_name(file_to_backup)
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
402
            osutils.rename(abs_path, self.abspath(backup_name))
403
            return "removed %s (but kept a copy: %s)" % (
404
                file_to_backup, backup_name)
405
0.357.1 by Jelmer Vernooij
Fix some remove tests.
406
        # Sort needed to first handle directory content before the directory
407
        files_to_backup = []
408
0.357.2 by Jelmer Vernooij
Fix more remove tests.
409
        all_files = set()
410
411
        def recurse_directory_to_add_files(directory):
412
            # Recurse directory and add all files
413
            # so we can check if they have changed.
414
            for parent_info, file_infos in self.walkdirs(directory):
415
                for relpath, basename, kind, lstat, fileid, kind in file_infos:
416
                    # Is it versioned or ignored?
417
                    if self.is_versioned(relpath):
418
                        # Add nested content for deletion.
419
                        all_files.add(relpath)
420
                    else:
421
                        # Files which are not versioned
422
                        # should be treated as unknown.
423
                        files_to_backup.append(relpath)
424
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
425
        with self.lock_tree_write():
0.357.2 by Jelmer Vernooij
Fix more remove tests.
426
            for filepath in files:
427
                # Get file name into canonical form.
428
                abspath = self.abspath(filepath)
429
                filepath = self.relpath(abspath)
430
431
                if filepath:
432
                    all_files.add(filepath)
433
                    recurse_directory_to_add_files(filepath)
434
435
            files = list(all_files)
436
437
            if len(files) == 0:
438
                return # nothing to do
439
440
            # Sort needed to first handle directory content before the directory
441
            files.sort(reverse=True)
442
0.357.1 by Jelmer Vernooij
Fix some remove tests.
443
            # Bail out if we are going to delete files we shouldn't
444
            if not keep_files and not force:
445
                for (file_id, path, content_change, versioned, parent_id, name,
446
                     kind, executable) in self.iter_changes(self.basis_tree(),
447
                         include_unchanged=True, require_versioned=False,
448
                         want_unversioned=True, specific_files=files):
449
                    if versioned[0] == False:
450
                        # The record is unknown or newly added
451
                        files_to_backup.append(path[1])
0.357.2 by Jelmer Vernooij
Fix more remove tests.
452
                        files_to_backup.extend(osutils.parent_directories(path[1]))
0.357.1 by Jelmer Vernooij
Fix some remove tests.
453
                    elif (content_change and (kind[1] is not None) and
454
                            osutils.is_inside_any(files, path[1])):
455
                        # Versioned and changed, but not deleted, and still
456
                        # in one of the dirs to be deleted.
457
                        files_to_backup.append(path[1])
0.357.2 by Jelmer Vernooij
Fix more remove tests.
458
                        files_to_backup.extend(osutils.parent_directories(path[1]))
459
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
460
            for f in files:
0.200.1735 by Jelmer Vernooij
Fix remove tests.
461
                if f == '':
462
                    continue
0.357.1 by Jelmer Vernooij
Fix some remove tests.
463
464
                try:
465
                    kind = self.kind(f)
466
                except errors.NoSuchFile:
467
                    kind = None
468
469
                abs_path = self.abspath(f)
470
                if verbose:
471
                    # having removed it, it must be either ignored or unknown
472
                    if self.is_ignored(f):
473
                        new_status = 'I'
474
                    else:
475
                        new_status = '?'
476
                    kind_ch = osutils.kind_marker(kind)
477
                    to_file.write(new_status + '       ' + f + kind_ch + '\n')
478
                if kind is None:
479
                    message = "%s does not exist" % (f, )
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
480
                else:
0.357.1 by Jelmer Vernooij
Fix some remove tests.
481
                    if not keep_files:
482
                        if f in files_to_backup and not force:
0.357.2 by Jelmer Vernooij
Fix more remove tests.
483
                            message = backup(f)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
484
                        else:
0.357.1 by Jelmer Vernooij
Fix some remove tests.
485
                            if kind == 'directory':
486
                                osutils.rmtree(abs_path)
487
                            else:
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
488
                                osutils.delete_any(abs_path)
0.357.2 by Jelmer Vernooij
Fix more remove tests.
489
                            message = "deleted %s" % (f,)
490
                    else:
491
                        message = "removed %s" % (f,)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
492
                self._unversion_path(f)
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
493
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
494
                # print only one message (if any) per file.
495
                if message is not None:
496
                    trace.note(message)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
497
            self._versioned_dirs = None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
498
            self.flush()
0.200.1192 by Jelmer Vernooij
Implement path2id.
499
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
500
    def _add(self, files, ids, kinds):
501
        for (path, file_id, kind) in zip(files, ids, kinds):
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
502
            if file_id is not None:
0.200.1663 by Jelmer Vernooij
Raise SettingFileIdUnsupported
503
                raise workingtree.SettingFileIdUnsupported()
504
            self._index_add_entry(path, kind)
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
505
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
506
    def smart_add(self, file_list, recurse=True, action=None, save=True):
0.200.1771 by Jelmer Vernooij
Fix implicit tree unicode add test.
507
        if not file_list:
508
            file_list = [u'.']
0.200.1781 by Jelmer Vernooij
Support expanding symlinks.
509
510
        # expand any symlinks in the directory part, while leaving the
511
        # filename alone
512
        # only expanding if symlinks are supported avoids windows path bugs
513
        if osutils.has_symlinks():
514
            file_list = list(map(osutils.normalizepath, file_list))
515
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
516
        added = []
517
        ignored = {}
518
        user_dirs = []
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
519
        def call_action(filepath, kind):
520
            if action is not None:
521
                parent_path = posixpath.dirname(filepath)
522
                parent_id = self.path2id(parent_path)
523
                parent_ie = self._get_dir_ie(parent_path, parent_id)
524
                file_id = action(self, parent_ie, filepath, kind)
525
                if file_id is not None:
526
                    raise workingtree.SettingFileIdUnsupported()
527
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
528
        with self.lock_tree_write():
529
            for filepath in osutils.canonical_relpaths(self.basedir, file_list):
0.352.1 by Jelmer Vernooij
Check for normalization during add.
530
                filepath, can_access = osutils.normalized_filename(filepath)
531
                if not can_access:
532
                    raise errors.InvalidNormalization(filepath)
533
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
534
                abspath = self.abspath(filepath)
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
535
                kind = osutils.file_kind(abspath)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
536
                if kind in ("file", "symlink"):
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
537
                    call_action(filepath, kind)
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
538
                    if save:
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
539
                        self._index_add_entry(filepath, kind)
540
                    added.append(filepath)
541
                elif kind == "directory":
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
542
                    call_action(filepath, kind)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
543
                    if recurse:
544
                        user_dirs.append(filepath)
545
                else:
546
                    raise errors.BadFileKindError(filename=abspath, kind=kind)
547
            for user_dir in user_dirs:
548
                abs_user_dir = self.abspath(user_dir)
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
549
                if user_dir != '':
550
                    try:
551
                        transport = _mod_transport.get_transport_from_path(abs_user_dir)
552
                        _mod_controldir.ControlDirFormat.find_format(transport)
553
                        subtree = True
554
                    except errors.NotBranchError:
555
                        subtree = False
556
                    except errors.UnsupportedFormatError:
557
                        subtree = False
558
                else:
559
                    subtree = False
560
                if subtree:
0.200.1769 by Jelmer Vernooij
Raise proper error when encountering nested trees.
561
                    trace.warning('skipping nested tree %r', abs_user_dir)
0.200.1752 by Jelmer Vernooij
Don't traverse nested trees in WorkingTree.smart_add.
562
                    continue
563
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
564
                for name in os.listdir(abs_user_dir):
565
                    subp = os.path.join(user_dir, name)
566
                    if self.is_control_filename(subp) or self.mapping.is_special_file(subp):
567
                        continue
568
                    ignore_glob = self.is_ignored(subp)
569
                    if ignore_glob is not None:
570
                        ignored.setdefault(ignore_glob, []).append(subp)
571
                        continue
572
                    abspath = self.abspath(subp)
573
                    kind = osutils.file_kind(abspath)
574
                    if kind == "directory":
575
                        user_dirs.append(subp)
576
                    else:
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
577
                        call_action(filepath, kind)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
578
                        if save:
579
                            self._index_add_entry(subp, kind)
0.200.1751 by Jelmer Vernooij
Fix smart_add return value.
580
                        added.append(subp)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
581
            if added and save:
582
                self.flush()
583
            return added, ignored
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
584
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
585
    def _set_root_id(self, file_id):
586
        self._fileid_map.set_file_id("", file_id)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
587
0.347.5 by Jelmer Vernooij
Fix more move/rename errors.
588
    def move(self, from_paths, to_dir=None, after=None):
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
589
        rename_tuples = []
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
590
        with self.lock_tree_write():
591
            to_abs = self.abspath(to_dir)
592
            if not os.path.isdir(to_abs):
593
                raise errors.BzrMoveFailedError('', to_dir,
594
                    errors.NotADirectory(to_abs))
595
596
            for from_rel in from_paths:
597
                from_tail = os.path.split(from_rel)[-1]
598
                to_rel = os.path.join(to_dir, from_tail)
599
                self.rename_one(from_rel, to_rel, after=after)
600
                rename_tuples.append((from_rel, to_rel))
601
            self.flush()
602
            return rename_tuples
603
0.347.5 by Jelmer Vernooij
Fix more move/rename errors.
604
    def rename_one(self, from_rel, to_rel, after=None):
0.200.1203 by Jelmer Vernooij
Fix per_workingtree.test_rename_one.TestRenameOne.test_rename_after_non_existant_non_ascii
605
        from_path = from_rel.encode("utf-8")
0.200.1768 by Jelmer Vernooij
Fix handling of normalized filenames.
606
        ensure_normalized_path(to_rel)
0.200.1203 by Jelmer Vernooij
Fix per_workingtree.test_rename_one.TestRenameOne.test_rename_after_non_existant_non_ascii
607
        to_path = to_rel.encode("utf-8")
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
608
        with self.lock_tree_write():
0.354.1 by Jelmer Vernooij
Support rename after the fact.
609
            if not after:
0.347.5 by Jelmer Vernooij
Fix more move/rename errors.
610
                # Perhaps it's already moved?
611
                after = (
612
                    not self.has_filename(from_rel) and
613
                    self.has_filename(to_rel) and
614
                    not self.is_versioned(to_rel))
615
            if after:
616
                if not self.has_filename(to_rel):
617
                    raise errors.BzrMoveFailedError(from_rel, to_rel,
618
                        errors.NoSuchFile(to_rel))
619
                if self.basis_tree().is_versioned(to_rel):
620
                    raise errors.BzrMoveFailedError(from_rel, to_rel,
621
                        errors.AlreadyVersionedError(to_rel))
622
623
                kind = self.kind(to_rel)
624
            else:
0.347.1 by Jelmer Vernooij
Various rename fixes.
625
                try:
626
                    to_kind = self.kind(to_rel)
627
                except errors.NoSuchFile:
628
                    exc_type = errors.BzrRenameFailedError
0.347.2 by Jelmer Vernooij
Fix breezy.tests.per_workingtree.test_rename_one.TestRenameOne.test_rename_one_fail_consistent
629
                    to_kind = None
0.347.1 by Jelmer Vernooij
Various rename fixes.
630
                else:
631
                    exc_type = errors.BzrMoveFailedError
0.347.5 by Jelmer Vernooij
Fix more move/rename errors.
632
                if self.is_versioned(to_rel):
633
                    raise exc_type(from_rel, to_rel,
634
                        errors.AlreadyVersionedError(to_rel))
0.200.1737 by Jelmer Vernooij
Fix rename tests.
635
                if not self.has_filename(from_rel):
636
                    raise errors.BzrMoveFailedError(from_rel, to_rel,
637
                        errors.NoSuchFile(from_rel))
0.347.1 by Jelmer Vernooij
Various rename fixes.
638
                if not self.is_versioned(from_rel):
639
                    raise exc_type(from_rel, to_rel,
640
                        errors.NotVersionedError(from_rel))
0.347.2 by Jelmer Vernooij
Fix breezy.tests.per_workingtree.test_rename_one.TestRenameOne.test_rename_one_fail_consistent
641
                if self.has_filename(to_rel):
642
                    raise errors.RenameFailedFilesExist(
643
                        from_rel, to_rel, errors.FileExists(to_rel))
0.347.5 by Jelmer Vernooij
Fix more move/rename errors.
644
645
                kind = self.kind(from_rel)
646
0.354.1 by Jelmer Vernooij
Support rename after the fact.
647
            if not after and not from_path in self.index and kind != 'directory':
0.200.1748 by Jelmer Vernooij
Fix rename test.
648
                # It's not a file
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
649
                raise errors.BzrMoveFailedError(from_rel, to_rel,
650
                    errors.NotVersionedError(path=from_rel))
0.200.1737 by Jelmer Vernooij
Fix rename tests.
651
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
652
            if not after:
0.200.1737 by Jelmer Vernooij
Fix rename tests.
653
                try:
654
                    os.rename(self.abspath(from_rel), self.abspath(to_rel))
655
                except OSError as e:
656
                    if e.errno == errno.ENOENT:
657
                        raise errors.BzrMoveFailedError(from_rel, to_rel,
658
                            errors.NoSuchFile(to_rel))
659
                    raise
0.200.1748 by Jelmer Vernooij
Fix rename test.
660
            if kind != 'directory':
0.354.1 by Jelmer Vernooij
Support rename after the fact.
661
                try:
662
                    del self.index[from_path]
663
                except KeyError:
664
                    pass
665
                self._index_add_entry(to_rel, kind)
0.347.1 by Jelmer Vernooij
Various rename fixes.
666
            else:
667
                todo = [p for p in self.index if p.startswith(from_path+'/')]
668
                for p in todo:
0.347.3 by Jelmer Vernooij
Fix breezy.tests.per_workingtree.test_workingtree.TestWorkingTree.test_rename_dirs.
669
                    self.index[posixpath.join(to_path, posixpath.relpath(p, from_path))] = self.index[p]
0.347.1 by Jelmer Vernooij
Various rename fixes.
670
                    del self.index[p]
671
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
672
            self._versioned_dirs = None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
673
            self.flush()
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
674
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
675
    def get_root_id(self):
0.200.1192 by Jelmer Vernooij
Implement path2id.
676
        return self.path2id("")
677
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
678
    def has_filename(self, filename):
679
        return osutils.lexists(self.abspath(filename))
680
0.200.1242 by Jelmer Vernooij
Support directories better.
681
    def _has_dir(self, path):
0.200.1368 by Jelmer Vernooij
There is always a tree root.
682
        if path == "":
683
            return True
0.200.1242 by Jelmer Vernooij
Support directories better.
684
        if self._versioned_dirs is None:
685
            self._load_dirs()
686
        return path in self._versioned_dirs
687
0.200.1192 by Jelmer Vernooij
Implement path2id.
688
    def path2id(self, path):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
689
        with self.lock_read():
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
690
            path = path.rstrip('/')
691
            if self.is_versioned(path.rstrip('/')):
692
                return self._fileid_map.lookup_file_id(path.encode("utf-8"))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
693
            return None
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
694
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
695
    def _iter_files_recursive(self, from_dir=None, include_dirs=False):
0.200.1328 by Jelmer Vernooij
More test fixes.
696
        if from_dir is None:
697
            from_dir = ""
0.341.1 by Jelmer Vernooij
Fix BadFilenameEncoding raising during WorkingTree.extras.
698
        for (dirpath, dirnames, filenames) in os.walk(self.abspath(from_dir).encode(osutils._fs_enc)):
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
699
            dir_relpath = dirpath[len(self.basedir):].strip("/")
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
700
            if self.controldir.is_control_filename(dir_relpath):
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
701
                continue
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
702
            for name in list(dirnames):
703
                if self.controldir.is_control_filename(name):
704
                    dirnames.remove(name)
705
                    continue
706
                relpath = os.path.join(dir_relpath, name)
707
                if include_dirs:
0.341.1 by Jelmer Vernooij
Fix BadFilenameEncoding raising during WorkingTree.extras.
708
                    try:
709
                        yield relpath.decode(osutils._fs_enc)
710
                    except UnicodeDecodeError as e:
711
                        raise errors.BadFilenameEncoding(
712
                            relpath, osutils._fs_enc)
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
713
                if not self._has_dir(relpath):
714
                    dirnames.remove(name)
715
            for name in filenames:
716
                if not self.mapping.is_special_file(name):
0.341.1 by Jelmer Vernooij
Fix BadFilenameEncoding raising during WorkingTree.extras.
717
                    yp = os.path.join(dir_relpath, name)
718
                    try:
719
                        yield yp.decode(osutils._fs_enc)
720
                    except UnicodeDecodeError:
721
                        raise errors.BadFilenameEncoding(
722
                            yp, osutils._fs_enc)
0.200.1327 by Jelmer Vernooij
Factor out all file browsing in extras.
723
724
    def extras(self):
725
        """Yield all unversioned files in this WorkingTree.
726
        """
0.200.1676 by Jelmer Vernooij
Fix typo.
727
        with self.lock_read():
0.348.1 by Jelmer Vernooij
Support directories in WorkingTree.extras.
728
            for p in (set(self._iter_files_recursive(include_dirs=True)) - set(self.index)):
729
                try:
730
                    up = p.decode(osutils._fs_enc)
731
                except UnicodeDecodeError:
732
                    raise errors.BadFilenameEncoding(
733
                        p, osutils._fs_enc)
734
                if not self._has_dir(up):
735
                    yield up
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
736
0.200.382 by Jelmer Vernooij
Support flushing index.
737
    def flush(self):
0.287.6 by Jelmer Vernooij
Fix some more tests.
738
        # TODO: Maybe this should only write on dirty ?
739
        if self._lock_mode != 'w':
740
            raise errors.NotWriteLocked(self)
741
        self.index.write()
0.200.382 by Jelmer Vernooij
Support flushing index.
742
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
743
    def __iter__(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
744
        with self.lock_read():
745
            for path in self.index:
746
                yield self.path2id(path)
747
            self._load_dirs()
748
            for path in self._versioned_dirs:
749
                yield self.path2id(path)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
750
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
751
    def has_or_had_id(self, file_id):
752
        if self.has_id(file_id):
753
            return True
754
        if self.had_id(file_id):
755
            return True
756
        return False
757
758
    def had_id(self, file_id):
759
        path = self._basis_fileid_map.lookup_file_id(file_id)
760
        try:
761
            head = self.repository._git.head()
762
        except KeyError:
763
            # Assume no if basis is not accessible
764
            return False
0.336.2 by Jelmer Vernooij
Don't use ZERO_SHA outside of remote communication to indicate empty history.
765
        try:
766
            root_tree = self.store[head].tree
767
        except KeyError:
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
768
            return False
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
769
        try:
770
            tree_lookup_path(self.store.__getitem__, root_tree, path)
771
        except KeyError:
772
            return False
773
        else:
774
            return True
775
0.200.1198 by Jelmer Vernooij
Implement GitWorkingTree.has_id.
776
    def has_id(self, file_id):
777
        try:
778
            self.id2path(file_id)
779
        except errors.NoSuchId:
780
            return False
781
        else:
782
            return True
783
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
784
    def id2path(self, file_id):
0.200.1532 by Jelmer Vernooij
Cope with float timestamps.
785
        assert type(file_id) is str, "file id not a string: %r" % file_id
0.200.1411 by Jelmer Vernooij
Fix control files.
786
        file_id = osutils.safe_utf8(file_id)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
787
        with self.lock_read():
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
788
            try:
789
                path = self._fileid_map.lookup_path(file_id)
790
            except ValueError:
791
                raise errors.NoSuchId(self, file_id)
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
792
            path = path.decode('utf-8')
793
            if self.is_versioned(path):
794
                return path
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
795
            raise errors.NoSuchId(self, file_id)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
796
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
797
    def get_file_mtime(self, path, file_id=None):
0.200.1200 by Jelmer Vernooij
Support GitWorkingTree.get_file_mtime.
798
        """See Tree.get_file_mtime."""
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
799
        try:
800
            return os.lstat(self.abspath(path)).st_mtime
801
        except OSError, (num, msg):
802
            if num == errno.ENOENT:
803
                raise errors.NoSuchFile(path)
804
            raise
0.200.1200 by Jelmer Vernooij
Support GitWorkingTree.get_file_mtime.
805
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
806
    def is_ignored(self, filename):
807
        r"""Check whether the filename matches an ignore pattern.
808
809
        If the file is ignored, returns the pattern which caused it to
810
        be ignored, otherwise None.  So this can simply be used as a
811
        boolean if desired."""
812
        if getattr(self, '_global_ignoreglobster', None) is None:
813
            ignore_globs = set()
814
            ignore_globs.update(ignores.get_runtime_ignores())
815
            ignore_globs.update(ignores.get_user_ignores())
816
            self._global_ignoreglobster = globbing.ExceptionGlobster(ignore_globs)
0.200.1656 by Jelmer Vernooij
Report proper patterns, ignore files.
817
        match = self._global_ignoreglobster.match(filename)
818
        if match is not None:
819
            return match
0.200.1716 by Jelmer Vernooij
Fix some more tests.
820
        try:
821
            if self.kind(filename) == 'directory':
822
                filename += b'/'
823
        except errors.NoSuchFile:
824
            pass
825
        filename = filename.lstrip(b'/')
0.200.1658 by Jelmer Vernooij
Fix handling of ignores - return patterns that matched.
826
        ignore_manager = self._get_ignore_manager()
827
        ps = list(ignore_manager.find_matching(filename))
828
        if not ps:
829
            return None
830
        if not ps[-1].is_exclude:
831
            return None
832
        return bytes(ps[-1])
833
834
    def _get_ignore_manager(self):
835
        ignoremanager = getattr(self, '_ignoremanager', None)
836
        if ignoremanager is not None:
837
            return ignoremanager
838
839
        ignore_manager = IgnoreFilterManager.from_repo(self.repository._git)
840
        self._ignoremanager = ignore_manager
841
        return ignore_manager
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
842
0.200.1716 by Jelmer Vernooij
Fix some more tests.
843
    def _flush_ignore_list_cache(self):
844
        self._ignoremanager = None
845
0.200.508 by Jelmer Vernooij
Skip inventory caching bits.
846
    def set_last_revision(self, revid):
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
847
        if _mod_revision.is_null(revid):
848
            self.branch.set_last_revision_info(0, revid)
849
            return False
850
        _mod_revision.check_not_reserved_id(revid)
851
        try:
852
            self.branch.generate_revision_history(revid)
853
        except errors.NoSuchRevision:
854
            raise errors.GhostRevisionUnusableHere(revid)
0.200.508 by Jelmer Vernooij
Skip inventory caching bits.
855
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
856
    def _reset_data(self):
0.248.3 by Jelmer Vernooij
Handle working trees without valid HEAD branch.
857
        try:
858
            head = self.repository._git.head()
0.336.2 by Jelmer Vernooij
Don't use ZERO_SHA outside of remote communication to indicate empty history.
859
        except KeyError:
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
860
            self._basis_fileid_map = GitFileIdMap({}, self.mapping)
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
861
        else:
0.336.2 by Jelmer Vernooij
Don't use ZERO_SHA outside of remote communication to indicate empty history.
862
            self._basis_fileid_map = self.mapping.get_fileid_map(
863
                self.store.__getitem__, self.store[head].tree)
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
864
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
865
    def get_file_verifier(self, path, file_id=None, stat_value=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
866
        with self.lock_read():
867
            try:
868
                return ("GIT", self.index[path][-2])
869
            except KeyError:
870
                if self._has_dir(path):
871
                    return ("GIT", None)
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
872
                raise errors.NoSuchFile(path)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
873
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
874
    def get_file_sha1(self, path, file_id=None, stat_value=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
875
        with self.lock_read():
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
876
            if not self.is_versioned(path):
877
                raise errors.NoSuchFile(path)
878
            abspath = self.abspath(path)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
879
            try:
880
                return osutils.sha_file_by_name(abspath)
881
            except OSError, (num, msg):
882
                if num in (errno.EISDIR, errno.ENOENT):
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
883
                    return None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
884
                raise
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
885
0.200.610 by Jelmer Vernooij
Support retrieving basis tree properly.
886
    def revision_tree(self, revid):
887
        return self.repository.revision_tree(revid)
888
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
889
    def is_versioned(self, path):
890
        with self.lock_read():
891
            path = path.rstrip('/').encode('utf-8')
892
            return (path in self.index or self._has_dir(path))
0.200.1242 by Jelmer Vernooij
Support directories better.
893
0.200.1239 by Jelmer Vernooij
Implement GitWorkingTree.filter_unversioned_files.
894
    def filter_unversioned_files(self, files):
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
895
        return set([p for p in files if not self.is_versioned(p)])
0.200.1239 by Jelmer Vernooij
Implement GitWorkingTree.filter_unversioned_files.
896
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
897
    def _get_dir_ie(self, path, parent_id):
0.200.1192 by Jelmer Vernooij
Implement path2id.
898
        file_id = self.path2id(path)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
899
        return inventory.InventoryDirectory(file_id,
0.200.1190 by Jelmer Vernooij
Fix get_symlink_target call.
900
            posixpath.basename(path).strip("/"), parent_id)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
901
902
    def _add_missing_parent_ids(self, path, dir_ids):
903
        if path in dir_ids:
904
            return []
905
        parent = posixpath.dirname(path).strip("/")
906
        ret = self._add_missing_parent_ids(parent, dir_ids)
907
        parent_id = dir_ids[parent]
908
        ie = self._get_dir_ie(path, parent_id)
909
        dir_ids[path] = ie.file_id
910
        ret.append((path, ie))
911
        return ret
912
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
913
    def _get_file_ie(self, name, path, value, parent_id):
914
        assert isinstance(name, unicode)
0.200.1192 by Jelmer Vernooij
Implement path2id.
915
        assert isinstance(path, unicode)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
916
        assert isinstance(value, tuple) and len(value) == 10
917
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
0.200.1192 by Jelmer Vernooij
Implement path2id.
918
        file_id = self.path2id(path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
919
        if type(file_id) != str:
920
            raise AssertionError
921
        kind = mode_kind(mode)
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
922
        ie = inventory.entry_factory[kind](file_id, name, parent_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
923
        if kind == 'symlink':
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
924
            ie.symlink_target = self.get_symlink_target(path, file_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
925
        else:
0.347.4 by Jelmer Vernooij
Use index for ie data.
926
            try:
927
                data = self.get_file_text(path, file_id)
928
            except errors.NoSuchFile:
929
                data = None
930
            except IOError as e:
931
                if e.errno != errno.ENOENT:
932
                    raise
933
                data = None
934
            if data is None:
935
                data = self.repository._git.object_store[sha].data
0.264.10 by Jelmer Vernooij
Yield inventory entries.
936
            ie.text_sha1 = osutils.sha_string(data)
937
            ie.text_size = len(data)
0.347.4 by Jelmer Vernooij
Use index for ie data.
938
            ie.executable = bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
939
        ie.revision = None
940
        return ie
941
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
942
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
943
        mode = stat_result.st_mode
944
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
945
0.318.1 by Jelmer Vernooij
Fix executable test.
946
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
947
        return self.basis_tree().is_executable(path)
948
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
949
    def stored_kind(self, path, file_id=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
950
        with self.lock_read():
951
            try:
952
                return mode_kind(self.index[path.encode("utf-8")][4])
953
            except KeyError:
954
                # Maybe it's a directory?
955
                if self._has_dir(path):
956
                    return "directory"
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
957
                raise errors.NoSuchFile(path)
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
958
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
959
    def is_executable(self, path, file_id=None):
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
960
        if getattr(self, "_supports_executable", osutils.supports_executable)():
961
            mode = os.lstat(self.abspath(path)).st_mode
962
        else:
0.319.1 by Jelmer Vernooij
Support falling back on basis for executable bits.
963
            try:
964
                mode = self.index[path.encode('utf-8')].mode
965
            except KeyError:
966
                mode = 0
967
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
968
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
969
    def _is_executable_from_path_and_stat(self, path, stat_result):
970
        if getattr(self, "_supports_executable", osutils.supports_executable)():
971
            return self._is_executable_from_path_and_stat_from_stat(path, stat_result)
972
        else:
973
            return self._is_executable_from_path_and_stat_from_basis(path, stat_result)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
974
0.264.10 by Jelmer Vernooij
Yield inventory entries.
975
    def list_files(self, include_root=False, from_dir=None, recursive=True):
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
976
        if from_dir is None:
977
            from_dir = ""
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
978
        dir_ids = {}
0.200.1767 by Jelmer Vernooij
Fix references to Tree*.
979
        fk_entries = {'directory': tree.TreeDirectory,
980
                      'file': tree.TreeFile,
981
                      'symlink': tree.TreeLink}
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
982
        with self.lock_read():
983
            root_ie = self._get_dir_ie(u"", None)
984
            if include_root and not from_dir:
985
                yield "", "V", root_ie.kind, root_ie.file_id, root_ie
986
            dir_ids[u""] = root_ie.file_id
987
            if recursive:
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
988
                path_iterator = sorted(self._iter_files_recursive(from_dir, include_dirs=True))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
989
            else:
990
                if from_dir is None:
991
                    start = self.basedir
992
                else:
993
                    start = os.path.join(self.basedir, from_dir)
994
                path_iterator = sorted([os.path.join(from_dir, name) for name in
995
                    os.listdir(start) if not self.controldir.is_control_filename(name)
996
                    and not self.mapping.is_special_file(name)])
997
            for path in path_iterator:
998
                try:
999
                    value = self.index[path]
1000
                except KeyError:
1001
                    value = None
0.348.1 by Jelmer Vernooij
Support directories in WorkingTree.extras.
1002
                try:
1003
                    path = path.decode("utf-8")
1004
                except UnicodeDecodeError:
1005
                    raise errors.BadFilenameEncoding(
1006
                        path, osutils._fs_enc)
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
1007
                kind = osutils.file_kind(self.abspath(path))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1008
                parent, name = posixpath.split(path)
1009
                for dir_path, dir_ie in self._add_missing_parent_ids(parent, dir_ids):
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
1010
                    pass
1011
                if kind == 'directory':
1012
                    if path != from_dir:
1013
                        if self._has_dir(path):
1014
                            ie = self._get_dir_ie(path, self.path2id(path))
1015
                            status = "V"
1016
                            file_id = ie.file_id
1017
                        elif self.is_ignored(path):
1018
                            status = "I"
1019
                            ie = fk_entries[kind]()
1020
                            file_id = None
1021
                        else:
1022
                            status = "?"
1023
                            ie = fk_entries[kind]()
1024
                            file_id = None
1025
                        yield posixpath.relpath(path, from_dir), status, kind, file_id, ie
1026
                    continue
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1027
                if value is not None:
1028
                    ie = self._get_file_ie(name, path, value, dir_ids[parent])
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
1029
                    yield posixpath.relpath(path, from_dir), "V", ie.kind, ie.file_id, ie
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1030
                else:
1031
                    ie = fk_entries[kind]()
0.200.1766 by Jelmer Vernooij
Fix another list_files test, integrate is_versioned.
1032
                    yield posixpath.relpath(path, from_dir), ("I" if self.is_ignored(path) else "?"), kind, None, ie
0.264.10 by Jelmer Vernooij
Yield inventory entries.
1033
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
1034
    def all_file_ids(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1035
        with self.lock_read():
1036
            ids = {u"": self.path2id("")}
1037
            for path in self.index:
1038
                if self.mapping.is_special_file(path):
1039
                    continue
1040
                path = path.decode("utf-8")
1041
                parent = posixpath.dirname(path).strip("/")
1042
                for e in self._add_missing_parent_ids(parent, ids):
1043
                    pass
1044
                ids[path] = self.path2id(path)
1045
            return set(ids.values())
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
1046
0.200.1710 by Jelmer Vernooij
Regenerate xfail.
1047
    def all_versioned_paths(self):
1048
        with self.lock_read():
1049
            paths = {u""}
1050
            for path in self.index:
1051
                if self.mapping.is_special_file(path):
1052
                    continue
1053
                path = path.decode("utf-8")
1054
                paths.add(path)
1055
                while path != "":
1056
                    path = posixpath.dirname(path).strip("/")
1057
                    if path in paths:
1058
                        break
1059
                    paths.add(path)
1060
            return paths
1061
0.200.1374 by Jelmer Vernooij
Implement GitWorkingTree._directory_is_tree_reference.
1062
    def _directory_is_tree_reference(self, path):
1063
        # FIXME: Check .gitsubmodules for path
1064
        return False
1065
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1066
    def iter_child_entries(self, path, file_id=None):
1067
        encoded_path = path.encode('utf-8')
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
1068
        parent_id = self.path2id(path)
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
1069
        found_any = False
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
1070
        seen_children = set()
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1071
        for item_path, value in self.index.iteritems():
1072
            if self.mapping.is_special_file(item_path):
1073
                continue
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
1074
            if not osutils.is_inside(encoded_path, item_path):
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1075
                continue
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
1076
            found_any = True
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
1077
            subpath = posixpath.relpath(item_path, encoded_path)
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1078
            if b'/' in subpath:
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
1079
                dirname = subpath.split(b'/', 1)[0]
1080
                file_ie = self._get_dir_ie(posixpath.join(path, dirname), parent_id)
1081
            else:
1082
                (parent, name) = posixpath.split(item_path)
1083
                try:
1084
                    file_ie = self._get_file_ie(name, item_path, value, parent_id)
1085
                except IOError:
1086
                    continue
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1087
            yield file_ie
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
1088
        if not found_any:
1089
            raise errors.NoSuchFile(path)
0.200.1716 by Jelmer Vernooij
Fix some more tests.
1090
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
1091
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
1092
        if yield_parents:
1093
            raise NotImplementedError(self.iter_entries_by_dir)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1094
        with self.lock_read():
1095
            if specific_file_ids is not None:
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
1096
                specific_paths = []
1097
                for file_id in specific_file_ids:
0.315.1 by Jelmer Vernooij
Allow file ids passed to Tree.iter_entries_by_dir to be None.
1098
                    if file_id is None:
1099
                        continue
0.309.1 by Jelmer Vernooij
Allow file-ids to Tree.iter_entries_by_dir to be absent.
1100
                    try:
1101
                        specific_paths.append(self.id2path(file_id))
1102
                    except errors.NoSuchId:
1103
                        pass
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1104
                if specific_paths in ([u""], []):
1105
                    specific_paths = None
1106
                else:
1107
                    specific_paths = set(specific_paths)
1108
            else:
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
1109
                specific_paths = None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1110
            root_ie = self._get_dir_ie(u"", None)
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
1111
            ret = {}
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1112
            if specific_paths is None:
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
1113
                ret[(None, u"")] = root_ie
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1114
            dir_ids = {u"": root_ie.file_id}
1115
            for path, value in self.index.iteritems():
1116
                if self.mapping.is_special_file(path):
1117
                    continue
1118
                path = path.decode("utf-8")
1119
                if specific_paths is not None and not path in specific_paths:
1120
                    continue
1121
                (parent, name) = posixpath.split(path)
1122
                try:
1123
                    file_ie = self._get_file_ie(name, path, value, None)
0.319.1 by Jelmer Vernooij
Support falling back on basis for executable bits.
1124
                except errors.NoSuchFile:
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1125
                    continue
0.200.1730 by Jelmer Vernooij
Fix test_is_executable_dir.
1126
                if yield_parents or specific_file_ids is None:
1127
                    for (dir_path, dir_ie) in self._add_missing_parent_ids(parent,
1128
                            dir_ids):
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
1129
                        ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1130
                file_ie.parent_id = self.path2id(parent)
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
1131
                ret[(posixpath.dirname(path), path)] = file_ie
1132
            return ((path, ie) for ((_, path), ie) in sorted(ret.items()))
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
1133
0.200.619 by Jelmer Vernooij
Provide dummy WorkingTree.conflicts() implementation rather than spending a lot of time not finding any conflicts.
1134
    def conflicts(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1135
        with self.lock_read():
1136
            # FIXME:
1137
            return _mod_conflicts.ConflictList()
0.200.619 by Jelmer Vernooij
Provide dummy WorkingTree.conflicts() implementation rather than spending a lot of time not finding any conflicts.
1138
0.200.1705 by Jelmer Vernooij
Fix walkdirs.
1139
    def walkdirs(self, prefix=""):
0.324.1 by Jelmer Vernooij
initial work fixing walkdirs.
1140
        """Walk the directories of this tree.
1141
1142
        returns a generator which yields items in the form:
1143
                ((curren_directory_path, fileid),
1144
                 [(file1_path, file1_name, file1_kind, (lstat), file1_id,
1145
                   file1_kind), ... ])
1146
1147
        This API returns a generator, which is only valid during the current
1148
        tree transaction - within a single lock_read or lock_write duration.
1149
1150
        If the tree is not locked, it may cause an error to be raised,
1151
        depending on the tree implementation.
1152
        """
1153
        from bisect import bisect_left
1154
        import operator
1155
        disk_top = self.abspath(prefix)
1156
        if disk_top.endswith('/'):
1157
            disk_top = disk_top[:-1]
1158
        top_strip_len = len(disk_top) + 1
1159
        inventory_iterator = self._walkdirs(prefix)
1160
        disk_iterator = osutils.walkdirs(disk_top, prefix)
1161
        try:
1162
            current_disk = next(disk_iterator)
1163
            disk_finished = False
1164
        except OSError as e:
1165
            if not (e.errno == errno.ENOENT or
1166
                (sys.platform == 'win32' and e.errno == ERROR_PATH_NOT_FOUND)):
1167
                raise
1168
            current_disk = None
1169
            disk_finished = True
1170
        try:
1171
            current_inv = next(inventory_iterator)
1172
            inv_finished = False
1173
        except StopIteration:
1174
            current_inv = None
1175
            inv_finished = True
1176
        while not inv_finished or not disk_finished:
1177
            if current_disk:
1178
                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
1179
                    cur_disk_dir_content) = current_disk
1180
            else:
1181
                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
1182
                    cur_disk_dir_content) = ((None, None), None)
1183
            if not disk_finished:
1184
                # strip out .bzr dirs
1185
                if (cur_disk_dir_path_from_top[top_strip_len:] == '' and
1186
                    len(cur_disk_dir_content) > 0):
1187
                    # osutils.walkdirs can be made nicer -
1188
                    # yield the path-from-prefix rather than the pathjoined
1189
                    # value.
1190
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
1191
                        ('.git', '.git'))
1192
                    if (bzrdir_loc < len(cur_disk_dir_content)
1193
                        and self.controldir.is_control_filename(
1194
                            cur_disk_dir_content[bzrdir_loc][0])):
1195
                        # we dont yield the contents of, or, .bzr itself.
1196
                        del cur_disk_dir_content[bzrdir_loc]
1197
            if inv_finished:
1198
                # everything is unknown
1199
                direction = 1
1200
            elif disk_finished:
1201
                # everything is missing
1202
                direction = -1
1203
            else:
1204
                direction = cmp(current_inv[0][0], cur_disk_dir_relpath)
1205
            if direction > 0:
1206
                # disk is before inventory - unknown
1207
                dirblock = [(relpath, basename, kind, stat, None, None) for
1208
                    relpath, basename, kind, stat, top_path in
1209
                    cur_disk_dir_content]
1210
                yield (cur_disk_dir_relpath, None), dirblock
1211
                try:
1212
                    current_disk = next(disk_iterator)
1213
                except StopIteration:
1214
                    disk_finished = True
1215
            elif direction < 0:
1216
                # inventory is before disk - missing.
1217
                dirblock = [(relpath, basename, 'unknown', None, fileid, kind)
1218
                    for relpath, basename, dkind, stat, fileid, kind in
1219
                    current_inv[1]]
1220
                yield (current_inv[0][0], current_inv[0][1]), dirblock
1221
                try:
1222
                    current_inv = next(inventory_iterator)
1223
                except StopIteration:
1224
                    inv_finished = True
1225
            else:
1226
                # versioned present directory
1227
                # merge the inventory and disk data together
1228
                dirblock = []
1229
                for relpath, subiterator in itertools.groupby(sorted(
1230
                    current_inv[1] + cur_disk_dir_content,
1231
                    key=operator.itemgetter(0)), operator.itemgetter(1)):
1232
                    path_elements = list(subiterator)
1233
                    if len(path_elements) == 2:
1234
                        inv_row, disk_row = path_elements
1235
                        # versioned, present file
1236
                        dirblock.append((inv_row[0],
1237
                            inv_row[1], disk_row[2],
1238
                            disk_row[3], inv_row[4],
1239
                            inv_row[5]))
1240
                    elif len(path_elements[0]) == 5:
1241
                        # unknown disk file
1242
                        dirblock.append((path_elements[0][0],
1243
                            path_elements[0][1], path_elements[0][2],
1244
                            path_elements[0][3], None, None))
1245
                    elif len(path_elements[0]) == 6:
1246
                        # versioned, absent file.
1247
                        dirblock.append((path_elements[0][0],
1248
                            path_elements[0][1], 'unknown', None,
1249
                            path_elements[0][4], path_elements[0][5]))
1250
                    else:
1251
                        raise NotImplementedError('unreachable code')
1252
                yield current_inv[0], dirblock
1253
                try:
1254
                    current_inv = next(inventory_iterator)
1255
                except StopIteration:
1256
                    inv_finished = True
1257
                try:
1258
                    current_disk = next(disk_iterator)
1259
                except StopIteration:
1260
                    disk_finished = True
1261
1262
    def _walkdirs(self, prefix=""):
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
1263
        if prefix != "":
1264
            prefix += "/"
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1265
        per_dir = defaultdict(set)
0.325.2 by Jelmer Vernooij
Handle root in walkdirs.
1266
        if prefix == "":
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1267
            per_dir[('', self.get_root_id())] = set()
1268
        def add_entry(path, kind):
1269
            if path == '' or not path.startswith(prefix):
1270
                return
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
1271
            (dirname, child_name) = posixpath.split(path)
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1272
            add_entry(dirname, 'directory')
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
1273
            dirname = dirname.decode("utf-8")
1274
            dir_file_id = self.path2id(dirname)
1275
            assert isinstance(value, tuple) and len(value) == 10
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1276
            per_dir[(dirname, dir_file_id)].add(
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
1277
                (path.decode("utf-8"), child_name.decode("utf-8"),
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1278
                kind, None,
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
1279
                self.path2id(path.decode("utf-8")),
0.353.1 by Jelmer Vernooij
Iterate over dirs in _walkdirs.
1280
                kind))
1281
        for path, value in self.index.iteritems():
1282
            if self.mapping.is_special_file(path):
1283
                continue
1284
            if not path.startswith(prefix):
1285
                continue
1286
            add_entry(path, mode_kind(value.mode))
1287
        return ((k, sorted(v)) for (k, v) in sorted(per_dir.iteritems()))
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
1288
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1289
    def get_shelf_manager(self):
0.200.1729 by Jelmer Vernooij
ShelvingUnsupported doesn't take an argument.
1290
        raise workingtree.ShelvingUnsupported()
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1291
0.200.1678 by Jelmer Vernooij
Fix tests.
1292
    def store_uncommitted(self):
1293
        raise errors.StoringUncommittedNotSupported(self)
1294
0.200.1703 by Jelmer Vernooij
Implement apply_inventory_delta.
1295
    def apply_inventory_delta(self, changes):
1296
        for (old_path, new_path, file_id, ie) in changes:
1297
            if old_path is not None:
1298
                del self.index[old_path.encode('utf-8')]
0.200.1772 by Jelmer Vernooij
Fix handling of unversioned file in get_file_sha1.
1299
                self._versioned_dirs = None
0.200.1703 by Jelmer Vernooij
Implement apply_inventory_delta.
1300
            if new_path is not None and ie.kind != 'directory':
1301
                self._index_add_entry(new_path, ie.kind)
0.316.2 by Jelmer Vernooij
Flush after modifying index.
1302
        self.flush()
0.200.1703 by Jelmer Vernooij
Implement apply_inventory_delta.
1303
0.200.1756 by Jelmer Vernooij
Initial work on annotate support.
1304
    def annotate_iter(self, path, file_id=None,
1305
                      default_revision=_mod_revision.CURRENT_REVISION):
1306
        """See Tree.annotate_iter
1307
1308
        This implementation will use the basis tree implementation if possible.
1309
        Lines not in the basis are attributed to CURRENT_REVISION
1310
1311
        If there are pending merges, lines added by those merges will be
1312
        incorrectly attributed to CURRENT_REVISION (but after committing, the
1313
        attribution will be correct).
1314
        """
1315
        with self.lock_read():
1316
            maybe_file_parent_keys = []
1317
            for parent_id in self.get_parent_ids():
1318
                try:
1319
                    parent_tree = self.revision_tree(parent_id)
1320
                except errors.NoSuchRevisionInTree:
1321
                    parent_tree = self.branch.repository.revision_tree(
1322
                            parent_id)
1323
                with parent_tree.lock_read():
1324
                    # TODO(jelmer): Use rename/copy tracker to find path name in parent
1325
                    parent_path = path
1326
                    try:
1327
                        kind = parent_tree.kind(parent_path)
1328
                    except errors.NoSuchFile:
1329
                        continue
1330
                    if kind != 'file':
1331
                        # Note: this is slightly unnecessary, because symlinks and
1332
                        # directories have a "text" which is the empty text, and we
1333
                        # know that won't mess up annotations. But it seems cleaner
1334
                        continue
1335
                    parent_text_key = (
1336
                        parent_path,
1337
                        parent_tree.get_file_revision(parent_path))
1338
                    if parent_text_key not in maybe_file_parent_keys:
1339
                        maybe_file_parent_keys.append(parent_text_key)
1340
            graph = self.branch.repository.get_file_graph()
1341
            heads = graph.heads(maybe_file_parent_keys)
1342
            file_parent_keys = []
1343
            for key in maybe_file_parent_keys:
1344
                if key in heads:
1345
                    file_parent_keys.append(key)
1346
1347
            # Now we have the parents of this content
1348
            from breezy.annotate import Annotator
1349
            from .annotate import AnnotateProvider
1350
            annotator = Annotator(AnnotateProvider(
1351
                self.branch.repository._file_change_scanner))
1352
            text = self.get_file_text(path)
1353
            this_key = (path, default_revision)
1354
            annotator.add_special_text(this_key, file_parent_keys, text)
1355
            annotations = [(key[-1], line)
1356
                           for key, line in annotator.annotate_flat(this_key)]
1357
            return annotations
1358
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
1359
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
1360
class GitWorkingTreeFormat(workingtree.WorkingTreeFormat):
1361
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
1362
    _tree_class = GitWorkingTree
1363
0.200.1295 by Jelmer Vernooij
Mark working trees as not supporting directories.
1364
    supports_versioned_directories = False
1365
0.200.1661 by Jelmer Vernooij
Set supports_setting_file_ids to False.
1366
    supports_setting_file_ids = False
1367
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1368
    supports_store_uncommitted = False
1369
0.200.1723 by Jelmer Vernooij
Set supports_leftmost_parent_id_as_ghost property.
1370
    supports_leftmost_parent_id_as_ghost = False
1371
0.200.1779 by Jelmer Vernooij
Actually store git revision ids rather than bzr revision ids.
1372
    supports_righthand_parent_id_as_ghost = False
1373
0.200.1768 by Jelmer Vernooij
Fix handling of normalized filenames.
1374
    requires_normalized_unicode_filenames = True
1375
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
1376
    @property
0.200.1665 by Jelmer Vernooij
Rename _matchingbzrdir to _matchingcnotroldir.
1377
    def _matchingcontroldir(self):
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
1378
        from .dir import LocalGitControlDirFormat
0.200.1013 by Jelmer Vernooij
More renames.
1379
        return LocalGitControlDirFormat()
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
1380
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
1381
    def get_format_description(self):
1382
        return "Git Working Tree"
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1383
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
1384
    def initialize(self, a_controldir, revision_id=None, from_branch=None,
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1385
                   accelerator_tree=None, hardlink=False):
1386
        """See WorkingTreeFormat.initialize()."""
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
1387
        if not isinstance(a_controldir, LocalGitDir):
1388
            raise errors.IncompatibleFormat(self, a_controldir)
1389
        index = Index(a_controldir.root_transport.local_abspath(".git/index"))
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1390
        index.write()
0.308.1 by Jelmer Vernooij
Set revision id if specified to WorkingTreeFormat.initialize.
1391
        branch = a_controldir.open_branch()
1392
        if revision_id is not None:
1393
            branch.set_last_revision(revision_id)
0.200.1680 by Jelmer Vernooij
Fix repo locks.
1394
        wt = GitWorkingTree(
0.308.1 by Jelmer Vernooij
Set revision id if specified to WorkingTreeFormat.initialize.
1395
                a_controldir, a_controldir.open_repository(), branch, index)
0.200.1680 by Jelmer Vernooij
Fix repo locks.
1396
        for hook in MutableTree.hooks['post_build_tree']:
1397
            hook(wt)
1398
        return wt
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1399
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1400
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1401
class InterIndexGitTree(InterGitTrees):
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1402
    """InterTree that works between a Git revision tree and an index."""
1403
1404
    def __init__(self, source, target):
1405
        super(InterIndexGitTree, self).__init__(source, target)
1406
        self._index = target.index
1407
1408
    @classmethod
1409
    def is_compatible(cls, source, target):
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
1410
        from .repository import GitRevisionTree
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
1411
        return (isinstance(source, GitRevisionTree) and
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1412
                isinstance(target, GitWorkingTree))
1413
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1414
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1415
            require_versioned=False, include_root=False):
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1416
        if require_versioned and specific_files:
1417
            for path in specific_files:
1418
                if (not self.source.is_versioned(path) and
1419
                    not self.target.is_versioned(path)):
1420
                    raise errors.PathsNotVersionedError(path)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1421
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
1422
        with self.lock_read():
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
1423
            return changes_between_git_tree_and_working_copy(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1424
                self.source.store, self.source.tree,
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1425
                self.target, want_unchanged=want_unchanged,
1426
                include_root=include_root)
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1427
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1428
    def compare(self, want_unchanged=False, specific_files=None,
1429
                extra_trees=None, require_versioned=False, include_root=False,
1430
                want_unversioned=False):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1431
        with self.lock_read():
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1432
            changes = self._iter_git_changes(
1433
                    want_unchanged=want_unchanged,
1434
                    specific_files=specific_files,
1435
                    require_versioned=require_versioned,
1436
                    include_root=include_root)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1437
            source_fileid_map = self.source._fileid_map
1438
            target_fileid_map = self.target._fileid_map
1439
            ret = tree_delta_from_git_changes(changes, self.target.mapping,
1440
                (source_fileid_map, target_fileid_map),
0.287.6 by Jelmer Vernooij
Fix some more tests.
1441
                specific_files=specific_files, require_versioned=require_versioned,
1442
                include_root=include_root)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1443
            if want_unversioned:
1444
                for e in self.target.extras():
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1445
                    ret.unversioned.append(
0.200.1732 by Jelmer Vernooij
Fix ignore.
1446
                        (osutils.normalized_filename(e)[0], None,
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1447
                        osutils.file_kind(self.target.abspath(e))))
1448
            return ret
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1449
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
1450
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1451
                     pb=None, extra_trees=[], require_versioned=True,
1452
                     want_unversioned=False):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1453
        with self.lock_read():
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1454
            changes = self._iter_git_changes(
1455
                    want_unchanged=include_unchanged,
1456
                    specific_files=specific_files,
1457
                    require_versioned=require_versioned)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1458
            if want_unversioned:
1459
                changes = itertools.chain(
1460
                        changes,
1461
                        untracked_changes(self.target))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1462
            return changes_from_git_changes(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1463
                    changes, self.target.mapping,
0.357.3 by Jelmer Vernooij
More remove fixes.
1464
                    specific_files=specific_files,
1465
                    include_unchanged=include_unchanged)
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1466
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
1467
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1468
tree.InterTree.register_optimiser(InterIndexGitTree)
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
1469
1470
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1471
def untracked_changes(tree):
1472
    for e in tree.extras():
1473
        ap = tree.abspath(e)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1474
        st = os.lstat(ap)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1475
        try:
1476
            np, accessible  = osutils.normalized_filename(e)
1477
        except UnicodeDecodeError:
1478
            raise errors.BadFilenameEncoding(
1479
                e, osutils._fs_enc)
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1480
        if stat.S_ISDIR(st.st_mode):
1481
            obj_id = Tree().id
1482
        else:
1483
            obj_id = blob_from_path_and_stat(ap.encode('utf-8'), st).id
1484
        yield ((None, np), (None, st.st_mode), (None, obj_id))
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1485
1486
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1487
def changes_between_git_tree_and_index(store, from_tree_sha, target,
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1488
        want_unchanged=False, update_index=False):
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
1489
    """Determine the changes between a git tree and a working tree with index.
1490
1491
    """
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1492
    to_tree_sha = target.index.commit(store)
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
1493
    return store.tree_changes(from_tree_sha, to_tree_sha, include_trees=True,
0.339.2 by Jelmer Vernooij
Use change_type_same in workingtree.
1494
            want_unchanged=want_unchanged, change_type_same=True)
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
1495
1496
1497
def changes_between_git_tree_and_working_copy(store, from_tree_sha, target,
0.357.1 by Jelmer Vernooij
Fix some remove tests.
1498
        want_unchanged=False, update_index=False, include_root=False):
0.200.1754 by Jelmer Vernooij
Avoid updating index when just comparing trees.
1499
    """Determine the changes between a git tree and a working tree with index.
1500
1501
    """
1502
    blobs = iter_fresh_blobs(target.index, target.abspath('.').encode(sys.getfilesystemencoding()))
1503
    to_tree_sha = commit_tree(store, blobs)
0.357.3 by Jelmer Vernooij
More remove fixes.
1504
    return store.tree_changes(from_tree_sha, to_tree_sha, include_trees=True,
1505
            want_unchanged=want_unchanged, change_type_same=True)