/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,
36
    index_entry_from_stat,
0.287.6 by Jelmer Vernooij
Fix some more tests.
37
    refresh_index,
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
38
    )
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
39
from dulwich.object_store import (
40
    tree_lookup_path,
41
    )
0.200.383 by Jelmer Vernooij
Simplify, support rewriting index based on inventory.
42
from dulwich.objects import (
43
    Blob,
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
44
    S_IFGITLINK,
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
45
    ZERO_SHA,
46
    )
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
47
from dulwich.repo import Repo
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
48
import os
0.264.10 by Jelmer Vernooij
Yield inventory entries.
49
import posixpath
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
50
import re
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
51
import stat
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
52
import sys
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
53
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
54
from ... import (
0.200.382 by Jelmer Vernooij
Support flushing index.
55
    errors,
0.262.1 by Jelmer Vernooij
Fix WorkingTree.conflicts().
56
    conflicts as _mod_conflicts,
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
57
    globbing,
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
58
    ignores,
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
59
    lock,
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
60
    osutils,
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
61
    revision as _mod_revision,
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
62
    trace,
0.200.519 by Jelmer Vernooij
Move imports down, might not be available in older bzr-git versions.
63
    tree,
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
64
    workingtree,
65
    )
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
66
from ...bzr import (
67
    inventory,
68
    )
0.200.1680 by Jelmer Vernooij
Fix repo locks.
69
from ...mutabletree import (
70
    MutableTree,
71
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
72
73
74
from .dir import (
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
75
    LocalGitDir,
76
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
77
from .tree import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
78
    changes_from_git_changes,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
79
    tree_delta_from_git_changes,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
80
    InterGitTrees,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
81
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
82
from .mapping import (
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
83
    GitFileIdMap,
0.264.10 by Jelmer Vernooij
Yield inventory entries.
84
    mode_kind,
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
85
    )
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
86
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
87
IGNORE_FILENAME = ".gitignore"
88
89
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
90
class GitWorkingTree(workingtree.WorkingTree):
91
    """A Git working tree."""
92
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
93
    def __init__(self, controldir, repo, branch, index):
0.200.1741 by Jelmer Vernooij
Fix opentree tests.
94
        basedir = controldir.root_transport.local_abspath('.')
95
        self.basedir = osutils.realpath(basedir)
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
96
        self.controldir = controldir
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
97
        self.repository = repo
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
98
        self.store = self.repository._git.object_store
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
99
        self.mapping = self.repository.get_mapping()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
100
        self._branch = branch
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
101
        self._transport = controldir.transport
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
102
        self._format = GitWorkingTreeFormat()
0.200.803 by Jelmer Vernooij
Default to non-bare repositories when initializing a control directory.
103
        self.index = index
0.200.1242 by Jelmer Vernooij
Support directories better.
104
        self._versioned_dirs = None
0.200.239 by Jelmer Vernooij
Provide views.
105
        self.views = self._make_views()
0.200.1173 by Jelmer Vernooij
Provide GitWorkingTree._rules_searcher.
106
        self._rules_searcher = None
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
107
        self._detect_case_handling()
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
108
        self._reset_data()
109
        self._fileid_map = self._basis_fileid_map.copy()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
110
        self._lock_mode = None
111
        self._lock_count = 0
112
0.200.1650 by Jelmer Vernooij
Implement GitWorkingTree.supports_tree_reference.
113
    def supports_tree_reference(self):
114
        return False
115
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
116
    def lock_read(self):
117
        """Lock the repository for read operations.
118
0.200.1646 by Jelmer Vernooij
Rename bzrlib to breezy.
119
        :return: A breezy.lock.LogicalLockResult.
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
120
        """
121
        if not self._lock_mode:
122
            self._lock_mode = 'r'
123
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
124
            self.index.read()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
125
        else:
126
            self._lock_count += 1
127
        self.branch.lock_read()
128
        return lock.LogicalLockResult(self.unlock)
129
0.200.1477 by Jelmer Vernooij
Implement GitWorkingTree.lock_tree_write.
130
    def lock_tree_write(self):
131
        if not self._lock_mode:
132
            self._lock_mode = 'w'
133
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
134
            self.index.read()
0.200.1477 by Jelmer Vernooij
Implement GitWorkingTree.lock_tree_write.
135
        elif self._lock_mode == 'r':
136
            raise errors.ReadOnlyError(self)
137
        else:
138
            self._lock_count +=1
139
        self.branch.lock_read()
140
        return lock.LogicalLockResult(self.unlock)
141
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
142
    def lock_write(self, token=None):
143
        if not self._lock_mode:
144
            self._lock_mode = 'w'
145
            self._lock_count = 1
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
146
            self.index.read()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
147
        elif self._lock_mode == 'r':
148
            raise errors.ReadOnlyError(self)
149
        else:
150
            self._lock_count +=1
151
        self.branch.lock_write()
152
        return lock.LogicalLockResult(self.unlock)
153
154
    def is_locked(self):
155
        return self._lock_count >= 1
156
157
    def get_physical_lock_status(self):
158
        return False
159
160
    def unlock(self):
161
        if not self._lock_count:
162
            return lock.cant_unlock_not_held(self)
0.200.1530 by Jelmer Vernooij
Fix lock order.
163
        self.branch.unlock()
0.200.1476 by Jelmer Vernooij
Cope with working tree refactoring.
164
        self._cleanup()
165
        self._lock_count -= 1
166
        if self._lock_count > 0:
167
            return
168
        self._lock_mode = None
0.200.173 by Jelmer Vernooij
Merge changes, open index.
169
0.200.1658 by Jelmer Vernooij
Fix handling of ignores - return patterns that matched.
170
    def _cleanup(self):
171
        pass
172
0.200.1322 by Jelmer Vernooij
Add case detection.
173
    def _detect_case_handling(self):
174
        try:
175
            self._transport.stat(".git/cOnFiG")
176
        except errors.NoSuchFile:
177
            self.case_sensitive = True
178
        else:
179
            self.case_sensitive = False
180
0.200.1315 by Jelmer Vernooij
Implement WorkingTree.merge_modified.
181
    def merge_modified(self):
182
        return {}
183
0.200.1696 by Jelmer Vernooij
Fix set_merge_modified.
184
    def set_merge_modified(self, modified_hashes):
0.200.1690 by Jelmer Vernooij
Implement WorkingTree.set_merge_modified.
185
        # TODO(jelmer)
186
        pass
187
0.200.1220 by Jelmer Vernooij
Support set_parent_trees.
188
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
189
        self.set_parent_ids([p for p, t in parents_list])
190
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
191
    def _set_merges_from_parent_ids(self, parent_ids):
192
        merges = parent_ids[1:]
193
        self.control_transport.put_bytes('MERGE_HEAD', '\n'.join(merges),
194
            mode=self.controldir._get_file_mode())
195
196
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
197
        """Set the parent ids to revision_ids.
198
199
        See also set_parent_trees. This api will try to retrieve the tree data
200
        for each element of revision_ids from the trees repository. If you have
201
        tree data already available, it is more efficient to use
202
        set_parent_trees rather than set_parent_ids. set_parent_ids is however
203
        an easier API to use.
204
205
        :param revision_ids: The revision_ids to set as the parent ids of this
206
            working tree. Any of these may be ghosts.
207
        """
208
        with self.lock_tree_write():
209
            self._check_parents_for_ghosts(revision_ids,
210
                allow_leftmost_as_ghost=allow_leftmost_as_ghost)
211
            for revision_id in revision_ids:
212
                _mod_revision.check_not_reserved_id(revision_id)
213
214
            revision_ids = self._filter_parent_ids_by_ancestry(revision_ids)
215
216
            if len(revision_ids) > 0:
217
                self.set_last_revision(revision_ids[0])
218
            else:
219
                self.set_last_revision(_mod_revision.NULL_REVISION)
220
221
            self._set_merges_from_parent_ids(revision_ids)
222
223
    def get_parent_ids(self):
224
        """See Tree.get_parent_ids.
225
226
        This implementation reads the pending merges list and last_revision
227
        value and uses that to decide what the parents list should be.
228
        """
229
        last_rev = _mod_revision.ensure_null(self._last_revision())
230
        if _mod_revision.NULL_REVISION == last_rev:
231
            parents = []
232
        else:
233
            parents = [last_rev]
234
        try:
235
            merges_bytes = self.control_transport.get_bytes('MERGE_HEAD')
236
        except errors.NoSuchFile:
237
            pass
238
        else:
239
            for l in osutils.split_lines(merges_bytes):
240
                revision_id = l.rstrip('\n')
241
                parents.append(revision_id)
242
        return parents
243
0.200.1599 by Jelmer Vernooij
Implement GitWorkingTree.iter_children.
244
    def iter_children(self, file_id):
245
        dpath = self.id2path(file_id) + "/"
246
        if dpath in self.index:
247
            return
248
        for path in self.index:
249
            if not path.startswith(dpath):
250
                continue
251
            if "/" in path[len(dpath):]:
252
                # Not a direct child but something further down
253
                continue
254
            yield self.path2id(path)
255
0.200.1663 by Jelmer Vernooij
Raise SettingFileIdUnsupported
256
    def _index_add_entry(self, path, kind):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
257
        assert self._lock_mode is not None
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
258
        assert isinstance(path, basestring)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
259
        if kind == "directory":
260
            # Git indexes don't contain directories
261
            return
262
        if kind == "file":
263
            blob = Blob()
264
            try:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
265
                file, stat_val = self.get_file_with_stat(path)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
266
            except (errors.NoSuchFile, IOError):
267
                # TODO: Rather than come up with something here, use the old index
268
                file = StringIO()
0.265.1 by Martin
Don't import posix module, the os wrapper exists for portability
269
                stat_val = os.stat_result(
270
                    (stat.S_IFREG | 0644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
271
            blob.set_raw_string(file.read())
272
        elif kind == "symlink":
273
            blob = Blob()
274
            try:
275
                stat_val = os.lstat(self.abspath(path))
276
            except (errors.NoSuchFile, OSError):
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
277
                # TODO: Rather than come up with something here, use the
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
278
                # old index
0.265.1 by Martin
Don't import posix module, the os wrapper exists for portability
279
                stat_val = os.stat_result(
280
                    (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.
281
            blob.set_raw_string(
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
282
                self.get_symlink_target(path).encode("utf-8"))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
283
        else:
284
            raise AssertionError("unknown kind '%s'" % kind)
285
        # Add object to the repository if it didn't exist yet
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
286
        if not blob.id in self.store:
287
            self.store.add_object(blob)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
288
        # Add an entry to the index or update the existing entry
289
        flags = 0 # FIXME
0.200.1242 by Jelmer Vernooij
Support directories better.
290
        encoded_path = path.encode("utf-8")
0.200.1531 by Jelmer Vernooij
Don't trust index contents - verify against file timestamps.
291
        self.index[encoded_path] = index_entry_from_stat(
292
            stat_val, blob.id, flags)
0.200.1242 by Jelmer Vernooij
Support directories better.
293
        if self._versioned_dirs is not None:
294
            self._ensure_versioned_dir(encoded_path)
295
296
    def _ensure_versioned_dir(self, dirname):
0.200.1249 by Jelmer Vernooij
Fix file id for tree root
297
        if dirname in self._versioned_dirs:
0.200.1242 by Jelmer Vernooij
Support directories better.
298
            return
0.200.1249 by Jelmer Vernooij
Fix file id for tree root
299
        if dirname != "":
300
            self._ensure_versioned_dir(posixpath.dirname(dirname))
0.200.1242 by Jelmer Vernooij
Support directories better.
301
        self._versioned_dirs.add(dirname)
302
303
    def _load_dirs(self):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
304
        assert self._lock_mode is not None
0.200.1242 by Jelmer Vernooij
Support directories better.
305
        self._versioned_dirs = set()
306
        for p in self.index:
307
            self._ensure_versioned_dir(posixpath.dirname(p))
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
308
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
309
    def _unversion_path(self, path):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
310
        assert self._lock_mode is not None
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
311
        encoded_path = path.encode("utf-8")
0.287.6 by Jelmer Vernooij
Fix some more tests.
312
        count = 0
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
313
        try:
314
            del self.index[encoded_path]
315
        except KeyError:
316
            # A directory, perhaps?
317
            for p in list(self.index):
0.200.1692 by Jelmer Vernooij
Mark three more tests as xfail.
318
                if p.startswith(encoded_path+b"/"):
0.287.6 by Jelmer Vernooij
Fix some more tests.
319
                    count += 1
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
320
                    del self.index[p]
0.287.6 by Jelmer Vernooij
Fix some more tests.
321
        else:
322
            count = 1
323
        return count
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
324
0.285.8 by Jelmer Vernooij
Fix more tests for swapped arguments.
325
    def unversion(self, paths, file_ids=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
326
        with self.lock_tree_write():
0.200.1690 by Jelmer Vernooij
Implement WorkingTree.set_merge_modified.
327
            for path in paths:
0.200.1742 by Jelmer Vernooij
Fix some unversion tests.
328
                encoded_path = path.encode("utf-8")
329
                try:
330
                    del self.index[encoded_path]
331
                except KeyError:
332
                    if not self._has_dir(path):
333
                        raise errors.NoSuchFile(path)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
334
            self.flush()
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
335
0.200.1678 by Jelmer Vernooij
Fix tests.
336
    def update_basis_by_delta(self, revid, delta):
337
        # TODO(jelmer): This shouldn't be called, it's inventory specific.
338
        pass
339
0.200.1243 by Jelmer Vernooij
Implement WorkingTree.check_state.
340
    def check_state(self):
341
        """Check that the working state is/isn't valid."""
342
        pass
343
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
344
    def remove(self, files, verbose=False, to_file=None, keep_files=True,
345
        force=False):
346
        """Remove nominated files from the working tree metadata.
347
348
        :param files: File paths relative to the basedir.
349
        :param keep_files: If true, the files will also be kept.
350
        :param force: Delete files and directories, even if they are changed
351
            and even if the directories are not empty.
352
        """
353
        if isinstance(files, basestring):
354
            files = [files]
355
356
        if to_file is None:
357
            to_file = sys.stdout
358
0.200.1735 by Jelmer Vernooij
Fix remove tests.
359
        files = list(files)
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
360
361
        if len(files) == 0:
362
            return # nothing to do
363
364
        # Sort needed to first handle directory content before the directory
365
        files.sort(reverse=True)
366
367
        def backup(file_to_backup):
368
            abs_path = self.abspath(file_to_backup)
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
369
            backup_name = self.controldir._available_backup_name(file_to_backup)
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
370
            osutils.rename(abs_path, self.abspath(backup_name))
371
            return "removed %s (but kept a copy: %s)" % (
372
                file_to_backup, backup_name)
373
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
374
        with self.lock_tree_write():
375
            for f in files:
0.200.1735 by Jelmer Vernooij
Fix remove tests.
376
                if f == '':
377
                    continue
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
378
                else:
379
                    abs_path = self.abspath(f)
380
                    if verbose:
381
                        # having removed it, it must be either ignored or unknown
382
                        if self.is_ignored(f):
383
                            new_status = 'I'
384
                        else:
385
                            new_status = '?'
386
                        # XXX: Really should be a more abstract reporter interface
0.287.6 by Jelmer Vernooij
Fix some more tests.
387
                        kind_ch = osutils.kind_marker(self.kind(f))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
388
                        to_file.write(new_status + '       ' + f + kind_ch + '\n')
389
                    # Unversion file
0.287.6 by Jelmer Vernooij
Fix some more tests.
390
                    # TODO(jelmer): _unversion_path() is O(size-of-index) for directories
391
                    if self._unversion_path(f) == 0:
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
392
                        if (osutils.isdir(abs_path) and
0.287.6 by Jelmer Vernooij
Fix some more tests.
393
                            len(os.listdir(abs_path)) == 0):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
394
                            if not keep_files:
395
                                osutils.delete_any(abs_path)
0.287.6 by Jelmer Vernooij
Fix some more tests.
396
                            message = "removed %s" % (f,)
397
                        else:
398
                            message = "%s is not versioned." % (f,)
399
                    else:
400
                        message = "removed %s" % (f,)
401
                        if osutils.lexists(abs_path):
402
                            if (osutils.isdir(abs_path) and
403
                                len(os.listdir(abs_path)) > 0):
404
                                if force:
405
                                    osutils.rmtree(abs_path)
406
                                    message = "deleted %s" % (f,)
407
                                else:
408
                                    message = backup(f)
409
                            else:
410
                                if not keep_files:
411
                                    osutils.delete_any(abs_path)
412
                                    message = "deleted %s" % (f,)
0.200.1215 by Jelmer Vernooij
Implement GitWorkingTree.remove.
413
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
414
                # print only one message (if any) per file.
415
                if message is not None:
416
                    trace.note(message)
417
            self.flush()
0.200.1192 by Jelmer Vernooij
Implement path2id.
418
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
419
    def _add(self, files, ids, kinds):
420
        for (path, file_id, kind) in zip(files, ids, kinds):
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
421
            if file_id is not None:
0.200.1663 by Jelmer Vernooij
Raise SettingFileIdUnsupported
422
                raise workingtree.SettingFileIdUnsupported()
423
            self._index_add_entry(path, kind)
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
424
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
425
    def smart_add(self, file_list, recurse=True, action=None, save=True):
426
        added = []
427
        ignored = {}
428
        user_dirs = []
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
429
        def call_action(filepath, kind):
430
            if action is not None:
431
                parent_path = posixpath.dirname(filepath)
432
                parent_id = self.path2id(parent_path)
433
                parent_ie = self._get_dir_ie(parent_path, parent_id)
434
                file_id = action(self, parent_ie, filepath, kind)
435
                if file_id is not None:
436
                    raise workingtree.SettingFileIdUnsupported()
437
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
438
        with self.lock_tree_write():
439
            for filepath in osutils.canonical_relpaths(self.basedir, file_list):
440
                abspath = self.abspath(filepath)
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
441
                kind = osutils.file_kind(abspath)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
442
                if kind in ("file", "symlink"):
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
443
                    call_action(filepath, kind)
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
444
                    if save:
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
445
                        self._index_add_entry(filepath, kind)
446
                    added.append(filepath)
447
                elif kind == "directory":
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
448
                    call_action(filepath, kind)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
449
                    if recurse:
450
                        user_dirs.append(filepath)
451
                else:
452
                    raise errors.BadFileKindError(filename=abspath, kind=kind)
453
            for user_dir in user_dirs:
454
                abs_user_dir = self.abspath(user_dir)
455
                for name in os.listdir(abs_user_dir):
456
                    subp = os.path.join(user_dir, name)
457
                    if self.is_control_filename(subp) or self.mapping.is_special_file(subp):
458
                        continue
459
                    ignore_glob = self.is_ignored(subp)
460
                    if ignore_glob is not None:
461
                        ignored.setdefault(ignore_glob, []).append(subp)
462
                        continue
463
                    abspath = self.abspath(subp)
464
                    kind = osutils.file_kind(abspath)
465
                    if kind == "directory":
466
                        user_dirs.append(subp)
467
                    else:
0.200.1733 by Jelmer Vernooij
Support handling of custom ids in smart_add.
468
                        call_action(filepath, kind)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
469
                        if save:
470
                            self._index_add_entry(subp, kind)
0.200.1751 by Jelmer Vernooij
Fix smart_add return value.
471
                        added.append(subp)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
472
            if added and save:
473
                self.flush()
474
            return added, ignored
0.200.1240 by Jelmer Vernooij
Implement GitWorkingTree.smart_add.
475
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
476
    def _set_root_id(self, file_id):
477
        self._fileid_map.set_file_id("", file_id)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
478
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
479
    def move(self, from_paths, to_dir=None, after=False):
480
        rename_tuples = []
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
481
        with self.lock_tree_write():
482
            to_abs = self.abspath(to_dir)
483
            if not os.path.isdir(to_abs):
484
                raise errors.BzrMoveFailedError('', to_dir,
485
                    errors.NotADirectory(to_abs))
486
487
            for from_rel in from_paths:
488
                from_tail = os.path.split(from_rel)[-1]
489
                to_rel = os.path.join(to_dir, from_tail)
490
                self.rename_one(from_rel, to_rel, after=after)
491
                rename_tuples.append((from_rel, to_rel))
492
            self.flush()
493
            return rename_tuples
494
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
495
    def rename_one(self, from_rel, to_rel, after=False):
0.200.1203 by Jelmer Vernooij
Fix per_workingtree.test_rename_one.TestRenameOne.test_rename_after_non_existant_non_ascii
496
        from_path = from_rel.encode("utf-8")
497
        to_path = to_rel.encode("utf-8")
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
498
        with self.lock_tree_write():
0.200.1737 by Jelmer Vernooij
Fix rename tests.
499
            if not after:
500
                if not self.has_filename(from_rel):
501
                    raise errors.BzrMoveFailedError(from_rel, to_rel,
502
                        errors.NoSuchFile(from_rel))
503
            else:
504
                if not self.has_filename(to_rel):
505
                    raise errors.BzrMoveFailedError(from_rel, to_rel,
506
                        errors.NoSuchFile(to_rel))
507
0.200.1748 by Jelmer Vernooij
Fix rename test.
508
            kind = self.kind(from_rel)
509
            if not from_path in self.index and kind != 'directory':
510
                # It's not a file
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
511
                raise errors.BzrMoveFailedError(from_rel, to_rel,
512
                    errors.NotVersionedError(path=from_rel))
0.200.1737 by Jelmer Vernooij
Fix rename tests.
513
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
514
            if not after:
0.200.1737 by Jelmer Vernooij
Fix rename tests.
515
                try:
516
                    os.rename(self.abspath(from_rel), self.abspath(to_rel))
517
                except OSError as e:
518
                    if e.errno == errno.ENOENT:
519
                        raise errors.BzrMoveFailedError(from_rel, to_rel,
520
                            errors.NoSuchFile(to_rel))
521
                    raise
0.200.1748 by Jelmer Vernooij
Fix rename test.
522
            if kind != 'directory':
523
                self.index[to_path] = self.index[from_path]
524
                del self.index[from_path]
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
525
            self.flush()
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
526
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
527
    def get_root_id(self):
0.200.1192 by Jelmer Vernooij
Implement path2id.
528
        return self.path2id("")
529
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
530
    def has_filename(self, filename):
531
        return osutils.lexists(self.abspath(filename))
532
0.200.1242 by Jelmer Vernooij
Support directories better.
533
    def _has_dir(self, path):
0.200.1368 by Jelmer Vernooij
There is always a tree root.
534
        if path == "":
535
            return True
0.200.1242 by Jelmer Vernooij
Support directories better.
536
        if self._versioned_dirs is None:
537
            self._load_dirs()
538
        return path in self._versioned_dirs
539
0.200.1192 by Jelmer Vernooij
Implement path2id.
540
    def path2id(self, path):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
541
        with self.lock_read():
0.200.1750 by Jelmer Vernooij
Fix add tests.
542
            encoded_path = path.rstrip('/').encode("utf-8")
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
543
            if self._is_versioned(encoded_path):
544
                return self._fileid_map.lookup_file_id(encoded_path)
545
            return None
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
546
0.200.1328 by Jelmer Vernooij
More test fixes.
547
    def _iter_files_recursive(self, from_dir=None):
548
        if from_dir is None:
549
            from_dir = ""
550
        for (dirpath, dirnames, filenames) in os.walk(self.abspath(from_dir)):
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
551
            dir_relpath = dirpath[len(self.basedir):].strip("/")
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
552
            if self.controldir.is_control_filename(dir_relpath):
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
553
                continue
0.200.615 by Jelmer Vernooij
Optimize WorkingTree.extras().
554
            for filename in filenames:
0.200.1328 by Jelmer Vernooij
More test fixes.
555
                if not self.mapping.is_special_file(filename):
556
                    yield os.path.join(dir_relpath, filename)
0.200.1327 by Jelmer Vernooij
Factor out all file browsing in extras.
557
558
    def extras(self):
559
        """Yield all unversioned files in this WorkingTree.
560
        """
0.200.1676 by Jelmer Vernooij
Fix typo.
561
        with self.lock_read():
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
562
            return set(self._iter_files_recursive()) - set(self.index)
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
563
0.200.382 by Jelmer Vernooij
Support flushing index.
564
    def flush(self):
0.287.6 by Jelmer Vernooij
Fix some more tests.
565
        # TODO: Maybe this should only write on dirty ?
566
        if self._lock_mode != 'w':
567
            raise errors.NotWriteLocked(self)
568
        self.index.write()
0.200.382 by Jelmer Vernooij
Support flushing index.
569
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
570
    def __iter__(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
571
        with self.lock_read():
572
            for path in self.index:
573
                yield self.path2id(path)
574
            self._load_dirs()
575
            for path in self._versioned_dirs:
576
                yield self.path2id(path)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
577
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
578
    def has_or_had_id(self, file_id):
579
        if self.has_id(file_id):
580
            return True
581
        if self.had_id(file_id):
582
            return True
583
        return False
584
585
    def had_id(self, file_id):
586
        path = self._basis_fileid_map.lookup_file_id(file_id)
587
        try:
588
            head = self.repository._git.head()
589
        except KeyError:
590
            # Assume no if basis is not accessible
591
            return False
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
592
        if head == ZERO_SHA:
593
            return False
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
594
        root_tree = self.store[head].tree
595
        try:
596
            tree_lookup_path(self.store.__getitem__, root_tree, path)
597
        except KeyError:
598
            return False
599
        else:
600
            return True
601
0.200.1198 by Jelmer Vernooij
Implement GitWorkingTree.has_id.
602
    def has_id(self, file_id):
603
        try:
604
            self.id2path(file_id)
605
        except errors.NoSuchId:
606
            return False
607
        else:
608
            return True
609
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
610
    def id2path(self, file_id):
0.200.1532 by Jelmer Vernooij
Cope with float timestamps.
611
        assert type(file_id) is str, "file id not a string: %r" % file_id
0.200.1411 by Jelmer Vernooij
Fix control files.
612
        file_id = osutils.safe_utf8(file_id)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
613
        with self.lock_read():
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
614
            try:
615
                path = self._fileid_map.lookup_path(file_id)
616
            except ValueError:
617
                raise errors.NoSuchId(self, file_id)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
618
            if self._is_versioned(path):
619
                return path.decode("utf-8")
620
            raise errors.NoSuchId(self, file_id)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
621
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
622
    def get_file_mtime(self, path, file_id=None):
0.200.1200 by Jelmer Vernooij
Support GitWorkingTree.get_file_mtime.
623
        """See Tree.get_file_mtime."""
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
624
        try:
625
            return os.lstat(self.abspath(path)).st_mtime
626
        except OSError, (num, msg):
627
            if num == errno.ENOENT:
628
                raise errors.NoSuchFile(path)
629
            raise
0.200.1200 by Jelmer Vernooij
Support GitWorkingTree.get_file_mtime.
630
0.200.1655 by Jelmer Vernooij
Basic support for git ignores.
631
    def is_ignored(self, filename):
632
        r"""Check whether the filename matches an ignore pattern.
633
634
        If the file is ignored, returns the pattern which caused it to
635
        be ignored, otherwise None.  So this can simply be used as a
636
        boolean if desired."""
637
        if getattr(self, '_global_ignoreglobster', None) is None:
638
            ignore_globs = set()
639
            ignore_globs.update(ignores.get_runtime_ignores())
640
            ignore_globs.update(ignores.get_user_ignores())
641
            self._global_ignoreglobster = globbing.ExceptionGlobster(ignore_globs)
0.200.1656 by Jelmer Vernooij
Report proper patterns, ignore files.
642
        match = self._global_ignoreglobster.match(filename)
643
        if match is not None:
644
            return match
0.200.1716 by Jelmer Vernooij
Fix some more tests.
645
        try:
646
            if self.kind(filename) == 'directory':
647
                filename += b'/'
648
        except errors.NoSuchFile:
649
            pass
650
        filename = filename.lstrip(b'/')
0.200.1658 by Jelmer Vernooij
Fix handling of ignores - return patterns that matched.
651
        ignore_manager = self._get_ignore_manager()
652
        ps = list(ignore_manager.find_matching(filename))
653
        if not ps:
654
            return None
655
        if not ps[-1].is_exclude:
656
            return None
657
        return bytes(ps[-1])
658
659
    def _get_ignore_manager(self):
660
        ignoremanager = getattr(self, '_ignoremanager', None)
661
        if ignoremanager is not None:
662
            return ignoremanager
663
664
        ignore_manager = IgnoreFilterManager.from_repo(self.repository._git)
665
        self._ignoremanager = ignore_manager
666
        return ignore_manager
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
667
0.200.1716 by Jelmer Vernooij
Fix some more tests.
668
    def _flush_ignore_list_cache(self):
669
        self._ignoremanager = None
670
0.200.508 by Jelmer Vernooij
Skip inventory caching bits.
671
    def set_last_revision(self, revid):
0.200.1720 by Jelmer Vernooij
Fix handling of pending merges.
672
        if _mod_revision.is_null(revid):
673
            self.branch.set_last_revision_info(0, revid)
674
            return False
675
        _mod_revision.check_not_reserved_id(revid)
676
        try:
677
            self.branch.generate_revision_history(revid)
678
        except errors.NoSuchRevision:
679
            raise errors.GhostRevisionUnusableHere(revid)
0.200.508 by Jelmer Vernooij
Skip inventory caching bits.
680
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
681
    def _reset_data(self):
0.248.3 by Jelmer Vernooij
Handle working trees without valid HEAD branch.
682
        try:
683
            head = self.repository._git.head()
684
        except KeyError, name:
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
685
            raise errors.NotBranchError("branch %s at %s" % (name,
686
                self.repository.base))
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
687
        if head == ZERO_SHA:
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
688
            self._basis_fileid_map = GitFileIdMap({}, self.mapping)
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
689
        else:
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
690
            self._basis_fileid_map = self.mapping.get_fileid_map(
691
                self.store.__getitem__, self.store[head].tree)
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
692
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
693
    def get_file_verifier(self, path, file_id=None, stat_value=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
694
        with self.lock_read():
695
            try:
696
                return ("GIT", self.index[path][-2])
697
            except KeyError:
698
                if self._has_dir(path):
699
                    return ("GIT", None)
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
700
                raise errors.NoSuchFile(path)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
701
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
702
    def get_file_sha1(self, path, file_id=None, stat_value=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
703
        with self.lock_read():
704
            abspath = self.abspath(path).encode(osutils._fs_enc)
705
            try:
706
                return osutils.sha_file_by_name(abspath)
707
            except OSError, (num, msg):
708
                if num in (errno.EISDIR, errno.ENOENT):
709
                    return None
710
                raise
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
711
0.200.610 by Jelmer Vernooij
Support retrieving basis tree properly.
712
    def revision_tree(self, revid):
713
        return self.repository.revision_tree(revid)
714
0.200.1242 by Jelmer Vernooij
Support directories better.
715
    def _is_versioned(self, path):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
716
        assert self._lock_mode is not None
0.200.1242 by Jelmer Vernooij
Support directories better.
717
        return (path in self.index or self._has_dir(path))
718
0.200.1239 by Jelmer Vernooij
Implement GitWorkingTree.filter_unversioned_files.
719
    def filter_unversioned_files(self, files):
0.200.1316 by Jelmer Vernooij
Fix filter_unversioned_files.
720
        return set([p for p in files if not self._is_versioned(p.encode("utf-8"))])
0.200.1239 by Jelmer Vernooij
Implement GitWorkingTree.filter_unversioned_files.
721
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
722
    def _get_dir_ie(self, path, parent_id):
0.200.1192 by Jelmer Vernooij
Implement path2id.
723
        file_id = self.path2id(path)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
724
        return inventory.InventoryDirectory(file_id,
0.200.1190 by Jelmer Vernooij
Fix get_symlink_target call.
725
            posixpath.basename(path).strip("/"), parent_id)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
726
727
    def _add_missing_parent_ids(self, path, dir_ids):
728
        if path in dir_ids:
729
            return []
730
        parent = posixpath.dirname(path).strip("/")
731
        ret = self._add_missing_parent_ids(parent, dir_ids)
732
        parent_id = dir_ids[parent]
733
        ie = self._get_dir_ie(path, parent_id)
734
        dir_ids[path] = ie.file_id
735
        ret.append((path, ie))
736
        return ret
737
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
738
    def _get_file_ie(self, name, path, value, parent_id):
739
        assert isinstance(name, unicode)
0.200.1192 by Jelmer Vernooij
Implement path2id.
740
        assert isinstance(path, unicode)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
741
        assert isinstance(value, tuple) and len(value) == 10
742
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
0.200.1192 by Jelmer Vernooij
Implement path2id.
743
        file_id = self.path2id(path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
744
        if type(file_id) != str:
745
            raise AssertionError
746
        kind = mode_kind(mode)
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
747
        ie = inventory.entry_factory[kind](file_id, name, parent_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
748
        if kind == 'symlink':
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
749
            ie.symlink_target = self.get_symlink_target(path, file_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
750
        else:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
751
            data = self.get_file_text(path, file_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
752
            ie.text_sha1 = osutils.sha_string(data)
753
            ie.text_size = len(data)
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
754
            ie.executable = self.is_executable(path, file_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
755
        ie.revision = None
756
        return ie
757
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
758
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
759
        mode = stat_result.st_mode
760
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
761
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
762
    def stored_kind(self, path, file_id=None):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
763
        with self.lock_read():
764
            try:
765
                return mode_kind(self.index[path.encode("utf-8")][4])
766
            except KeyError:
767
                # Maybe it's a directory?
768
                if self._has_dir(path):
769
                    return "directory"
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
770
                raise errors.NoSuchFile(path)
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
771
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
772
    def is_executable(self, path, file_id=None):
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
773
        if getattr(self, "_supports_executable", osutils.supports_executable)():
774
            mode = os.lstat(self.abspath(path)).st_mode
775
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
776
        else:
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
777
            basis_tree = self.basis_tree()
778
            if file_id in basis_tree:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
779
                return basis_tree.is_executable(path, file_id)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
780
            # Default to not executable
781
            return False
782
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
783
    def _is_executable_from_path_and_stat(self, path, stat_result):
784
        if getattr(self, "_supports_executable", osutils.supports_executable)():
785
            return self._is_executable_from_path_and_stat_from_stat(path, stat_result)
786
        else:
787
            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.
788
0.264.10 by Jelmer Vernooij
Yield inventory entries.
789
    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.
790
        if from_dir is None:
791
            from_dir = ""
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
792
        dir_ids = {}
0.200.1339 by Jelmer Vernooij
Some reformatting.
793
        fk_entries = {'directory': workingtree.TreeDirectory,
794
                      'file': workingtree.TreeFile,
795
                      'symlink': workingtree.TreeLink}
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
796
        with self.lock_read():
797
            root_ie = self._get_dir_ie(u"", None)
798
            if include_root and not from_dir:
799
                yield "", "V", root_ie.kind, root_ie.file_id, root_ie
800
            dir_ids[u""] = root_ie.file_id
801
            if recursive:
802
                path_iterator = self._iter_files_recursive(from_dir)
803
            else:
804
                if from_dir is None:
805
                    start = self.basedir
806
                else:
807
                    start = os.path.join(self.basedir, from_dir)
808
                path_iterator = sorted([os.path.join(from_dir, name) for name in
809
                    os.listdir(start) if not self.controldir.is_control_filename(name)
810
                    and not self.mapping.is_special_file(name)])
811
            for path in path_iterator:
812
                try:
813
                    value = self.index[path]
814
                except KeyError:
815
                    value = None
816
                path = path.decode("utf-8")
817
                parent, name = posixpath.split(path)
818
                for dir_path, dir_ie in self._add_missing_parent_ids(parent, dir_ids):
819
                    yield dir_path, "V", dir_ie.kind, dir_ie.file_id, dir_ie
820
                if value is not None:
821
                    ie = self._get_file_ie(name, path, value, dir_ids[parent])
822
                    yield path, "V", ie.kind, ie.file_id, ie
823
                else:
824
                    kind = osutils.file_kind(self.abspath(path))
825
                    ie = fk_entries[kind]()
826
                    yield path, ("I" if self.is_ignored(path) else "?"), kind, None, ie
0.264.10 by Jelmer Vernooij
Yield inventory entries.
827
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
828
    def all_file_ids(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
829
        with self.lock_read():
830
            ids = {u"": self.path2id("")}
831
            for path in self.index:
832
                if self.mapping.is_special_file(path):
833
                    continue
834
                path = path.decode("utf-8")
835
                parent = posixpath.dirname(path).strip("/")
836
                for e in self._add_missing_parent_ids(parent, ids):
837
                    pass
838
                ids[path] = self.path2id(path)
839
            return set(ids.values())
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
840
0.200.1710 by Jelmer Vernooij
Regenerate xfail.
841
    def all_versioned_paths(self):
842
        with self.lock_read():
843
            paths = {u""}
844
            for path in self.index:
845
                if self.mapping.is_special_file(path):
846
                    continue
847
                path = path.decode("utf-8")
848
                paths.add(path)
849
                while path != "":
850
                    path = posixpath.dirname(path).strip("/")
851
                    if path in paths:
852
                        break
853
                    paths.add(path)
854
            return paths
855
0.200.1374 by Jelmer Vernooij
Implement GitWorkingTree._directory_is_tree_reference.
856
    def _directory_is_tree_reference(self, path):
857
        # FIXME: Check .gitsubmodules for path
858
        return False
859
0.200.1716 by Jelmer Vernooij
Fix some more tests.
860
    def iter_child_entries(self, path, file_id=None):
861
        encoded_path = path.encode('utf-8')
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
862
        parent_id = self.path2id(path)
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
863
        found_any = False
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
864
        seen_children = set()
0.200.1716 by Jelmer Vernooij
Fix some more tests.
865
        for item_path, value in self.index.iteritems():
866
            if self.mapping.is_special_file(item_path):
867
                continue
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
868
            if not osutils.is_inside(encoded_path, item_path):
0.200.1716 by Jelmer Vernooij
Fix some more tests.
869
                continue
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
870
            found_any = True
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
871
            subpath = posixpath.relpath(item_path, encoded_path)
0.200.1716 by Jelmer Vernooij
Fix some more tests.
872
            if b'/' in subpath:
0.200.1739 by Jelmer Vernooij
Fix iteration order for iter_child_entries.
873
                dirname = subpath.split(b'/', 1)[0]
874
                file_ie = self._get_dir_ie(posixpath.join(path, dirname), parent_id)
875
            else:
876
                (parent, name) = posixpath.split(item_path)
877
                try:
878
                    file_ie = self._get_file_ie(name, item_path, value, parent_id)
879
                except IOError:
880
                    continue
0.200.1716 by Jelmer Vernooij
Fix some more tests.
881
            yield file_ie
0.200.1738 by Jelmer Vernooij
Fix test_does_not_exist.
882
        if not found_any:
883
            raise errors.NoSuchFile(path)
0.200.1716 by Jelmer Vernooij
Fix some more tests.
884
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
885
    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.
886
        if yield_parents:
887
            raise NotImplementedError(self.iter_entries_by_dir)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
888
        with self.lock_read():
889
            if specific_file_ids is not None:
0.200.1712 by Jelmer Vernooij
Add file_id prefix.
890
                specific_paths = []
891
                for file_id in specific_file_ids:
892
                    assert file_id is not None, "file id %r" % file_id
893
                    specific_paths.append(self.id2path(file_id))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
894
                if specific_paths in ([u""], []):
895
                    specific_paths = None
896
                else:
897
                    specific_paths = set(specific_paths)
898
            else:
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
899
                specific_paths = None
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
900
            root_ie = self._get_dir_ie(u"", None)
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
901
            ret = {}
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
902
            if specific_paths is None:
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
903
                ret[(None, u"")] = root_ie
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
904
            dir_ids = {u"": root_ie.file_id}
905
            for path, value in self.index.iteritems():
906
                if self.mapping.is_special_file(path):
907
                    continue
908
                path = path.decode("utf-8")
909
                if specific_paths is not None and not path in specific_paths:
910
                    continue
911
                (parent, name) = posixpath.split(path)
912
                try:
913
                    file_ie = self._get_file_ie(name, path, value, None)
914
                except IOError:
915
                    continue
0.200.1730 by Jelmer Vernooij
Fix test_is_executable_dir.
916
                if yield_parents or specific_file_ids is None:
917
                    for (dir_path, dir_ie) in self._add_missing_parent_ids(parent,
918
                            dir_ids):
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
919
                        ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
920
                file_ie.parent_id = self.path2id(parent)
0.200.1740 by Jelmer Vernooij
Fix iter_entries_by_dir order.
921
                ret[(posixpath.dirname(path), path)] = file_ie
922
            return ((path, ie) for ((_, path), ie) in sorted(ret.items()))
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
923
0.200.619 by Jelmer Vernooij
Provide dummy WorkingTree.conflicts() implementation rather than spending a lot of time not finding any conflicts.
924
    def conflicts(self):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
925
        with self.lock_read():
926
            # FIXME:
927
            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.
928
0.200.1328 by Jelmer Vernooij
More test fixes.
929
    def get_canonical_inventory_path(self, path):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
930
        with self.lock_read():
931
            for p in self.index:
932
                if p.lower() == path.lower():
933
                    return p
934
            else:
935
                return path
0.200.1328 by Jelmer Vernooij
More test fixes.
936
0.200.1705 by Jelmer Vernooij
Fix walkdirs.
937
    def walkdirs(self, prefix=""):
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
938
        if prefix != "":
939
            prefix += "/"
940
        per_dir = defaultdict(list)
941
        for path, value in self.index.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
942
            if self.mapping.is_special_file(path):
943
                continue
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
944
            if not path.startswith(prefix):
945
                continue
946
            (dirname, child_name) = posixpath.split(path)
947
            dirname = dirname.decode("utf-8")
948
            dir_file_id = self.path2id(dirname)
949
            assert isinstance(value, tuple) and len(value) == 10
950
            (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
0.265.1 by Martin
Don't import posix module, the os wrapper exists for portability
951
            stat_result = os.stat_result((mode, ino,
0.200.1211 by Jelmer Vernooij
Fix statresult.
952
                    dev, 1, uid, gid, size,
0.200.1736 by Jelmer Vernooij
Fix a walkdirs test.
953
                    int(mtime), int(mtime), int(ctime)))
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
954
            per_dir[(dirname, dir_file_id)].append(
955
                (path.decode("utf-8"), child_name.decode("utf-8"),
956
                mode_kind(mode), stat_result,
957
                self.path2id(path.decode("utf-8")),
958
                mode_kind(mode)))
959
        return per_dir.iteritems()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
960
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
961
    def _lookup_entry(self, path, update_index=False):
0.200.1543 by Jelmer Vernooij
Support symlinks.
962
        assert type(path) == str
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
963
        entry = self.index[path]
964
        index_mode = entry[-6]
965
        index_sha = entry[-2]
0.200.1741 by Jelmer Vernooij
Fix opentree tests.
966
        disk_path = self.abspath(path.decode('utf-8')).encode(
967
            osutils._fs_enc)
0.284.1 by Jelmer Vernooij
Raise KeyError when file was removed.
968
        try:
969
            disk_stat = os.lstat(disk_path)
970
        except OSError, (num, msg):
971
            if num in (errno.EISDIR, errno.ENOENT):
972
                raise KeyError(path)
973
            raise
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
974
        disk_mtime = disk_stat.st_mtime
975
        if isinstance(entry[1], tuple):
976
            index_mtime = entry[1][0]
977
        else:
978
            index_mtime = int(entry[1])
979
        mtime_delta = (disk_mtime - index_mtime)
980
        disk_mode = cleanup_mode(disk_stat.st_mode)
981
        if mtime_delta > 0 or disk_mode != index_mode:
982
            if stat.S_ISDIR(disk_mode):
983
                try:
984
                    subrepo = Repo(disk_path)
985
                except NotGitRepository:
986
                    return (None, None)
987
                else:
988
                    disk_mode = S_IFGITLINK
989
                    git_id = subrepo.head()
0.200.1543 by Jelmer Vernooij
Support symlinks.
990
            elif stat.S_ISLNK(disk_mode):
0.200.1715 by Jelmer Vernooij
Fix some more tests.
991
                blob = Blob.from_string(os.readlink(disk_path))
0.200.1543 by Jelmer Vernooij
Support symlinks.
992
                git_id = blob.id
993
            elif stat.S_ISREG(disk_mode):
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
994
                with open(disk_path, 'r') as f:
995
                    blob = Blob.from_string(f.read())
996
                git_id = blob.id
0.200.1543 by Jelmer Vernooij
Support symlinks.
997
            else:
998
                raise AssertionError
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
999
            if update_index:
1000
                flags = 0 # FIXME
0.200.1545 by Jelmer Vernooij
Some more test fixes.
1001
                self.index[path] = index_entry_from_stat(disk_stat, git_id, flags, disk_mode)
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
1002
            return (git_id, disk_mode)
1003
        return (index_sha, index_mode)
1004
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1005
    def get_shelf_manager(self):
0.200.1729 by Jelmer Vernooij
ShelvingUnsupported doesn't take an argument.
1006
        raise workingtree.ShelvingUnsupported()
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1007
0.200.1678 by Jelmer Vernooij
Fix tests.
1008
    def store_uncommitted(self):
1009
        raise errors.StoringUncommittedNotSupported(self)
1010
0.200.1703 by Jelmer Vernooij
Implement apply_inventory_delta.
1011
    def apply_inventory_delta(self, changes):
1012
        for (old_path, new_path, file_id, ie) in changes:
1013
            if old_path is not None:
1014
                del self.index[old_path.encode('utf-8')]
1015
            if new_path is not None and ie.kind != 'directory':
1016
                self._index_add_entry(new_path, ie.kind)
1017
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
1018
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
1019
class GitWorkingTreeFormat(workingtree.WorkingTreeFormat):
1020
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
1021
    _tree_class = GitWorkingTree
1022
0.200.1295 by Jelmer Vernooij
Mark working trees as not supporting directories.
1023
    supports_versioned_directories = False
1024
0.200.1661 by Jelmer Vernooij
Set supports_setting_file_ids to False.
1025
    supports_setting_file_ids = False
1026
0.200.1677 by Jelmer Vernooij
Mark shelving as unsupported.
1027
    supports_store_uncommitted = False
1028
0.200.1723 by Jelmer Vernooij
Set supports_leftmost_parent_id_as_ghost property.
1029
    supports_leftmost_parent_id_as_ghost = False
1030
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
1031
    @property
0.200.1665 by Jelmer Vernooij
Rename _matchingbzrdir to _matchingcnotroldir.
1032
    def _matchingcontroldir(self):
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
1033
        from .dir import LocalGitControlDirFormat
0.200.1013 by Jelmer Vernooij
More renames.
1034
        return LocalGitControlDirFormat()
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
1035
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
1036
    def get_format_description(self):
1037
        return "Git Working Tree"
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1038
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
1039
    def initialize(self, a_controldir, revision_id=None, from_branch=None,
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1040
                   accelerator_tree=None, hardlink=False):
1041
        """See WorkingTreeFormat.initialize()."""
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
1042
        if not isinstance(a_controldir, LocalGitDir):
1043
            raise errors.IncompatibleFormat(self, a_controldir)
1044
        index = Index(a_controldir.root_transport.local_abspath(".git/index"))
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1045
        index.write()
0.200.1680 by Jelmer Vernooij
Fix repo locks.
1046
        wt = GitWorkingTree(
1047
                a_controldir, a_controldir.open_repository(),
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
1048
            a_controldir.open_branch(), index)
0.200.1680 by Jelmer Vernooij
Fix repo locks.
1049
        for hook in MutableTree.hooks['post_build_tree']:
1050
            hook(wt)
1051
        return wt
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
1052
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1053
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1054
class InterIndexGitTree(InterGitTrees):
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1055
    """InterTree that works between a Git revision tree and an index."""
1056
1057
    def __init__(self, source, target):
1058
        super(InterIndexGitTree, self).__init__(source, target)
1059
        self._index = target.index
1060
1061
    @classmethod
1062
    def is_compatible(cls, source, target):
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
1063
        from .repository import GitRevisionTree
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
1064
        return (isinstance(source, GitRevisionTree) and
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1065
                isinstance(target, GitWorkingTree))
1066
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1067
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1068
            require_versioned=False, include_root=False):
1069
        # TODO(jelmer): Handle include_root
1070
        # TODO(jelmer): Handle require_versioned
1071
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
1072
        with self.lock_read():
1073
            return changes_between_git_tree_and_index(
1074
                self.source.store, self.source.tree,
1075
                self.target, want_unchanged=want_unchanged)
1076
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1077
    def compare(self, want_unchanged=False, specific_files=None,
1078
                extra_trees=None, require_versioned=False, include_root=False,
1079
                want_unversioned=False):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1080
        with self.lock_read():
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1081
            changes = self._iter_git_changes(
1082
                    want_unchanged=want_unchanged,
1083
                    specific_files=specific_files,
1084
                    require_versioned=require_versioned,
1085
                    include_root=include_root)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1086
            source_fileid_map = self.source._fileid_map
1087
            target_fileid_map = self.target._fileid_map
1088
            ret = tree_delta_from_git_changes(changes, self.target.mapping,
1089
                (source_fileid_map, target_fileid_map),
0.287.6 by Jelmer Vernooij
Fix some more tests.
1090
                specific_files=specific_files, require_versioned=require_versioned,
1091
                include_root=include_root)
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1092
            if want_unversioned:
1093
                for e in self.target.extras():
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1094
                    ret.unversioned.append(
0.200.1732 by Jelmer Vernooij
Fix ignore.
1095
                        (osutils.normalized_filename(e)[0], None,
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1096
                        osutils.file_kind(self.target.abspath(e))))
1097
            return ret
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1098
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
1099
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1100
                     pb=None, extra_trees=[], require_versioned=True,
1101
                     want_unversioned=False):
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1102
        with self.lock_read():
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1103
            changes = self._iter_git_changes(
1104
                    want_unchanged=include_unchanged,
1105
                    specific_files=specific_files,
1106
                    require_versioned=require_versioned)
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1107
            if want_unversioned:
1108
                changes = itertools.chain(
1109
                        changes,
1110
                        untracked_changes(self.target))
0.200.1675 by Jelmer Vernooij
Remove uses of decorators.
1111
            return changes_from_git_changes(
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1112
                    changes, self.target.mapping,
1113
                    specific_files=specific_files)
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1114
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
1115
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
1116
tree.InterTree.register_optimiser(InterIndexGitTree)
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
1117
1118
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1119
def untracked_changes(tree):
1120
    for e in tree.extras():
1121
        ap = tree.abspath(e)
1122
        st = os.stat(ap)
1123
        try:
1124
            np, accessible  = osutils.normalized_filename(e)
1125
        except UnicodeDecodeError:
1126
            raise errors.BadFilenameEncoding(
1127
                e, osutils._fs_enc)
1128
        yield (np, st.st_mode,
1129
               blob_from_path_and_stat(ap, st).id)
1130
1131
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1132
def changes_between_git_tree_and_index(store, from_tree_sha, target,
0.200.1731 by Jelmer Vernooij
Add support for checking untracked changes.
1133
        want_unchanged=False, update_index=False):
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
1134
    """Determine the changes between a git tree and a working tree with index.
1135
1136
    """
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1137
    # TODO(jelmer): Avoid creating and storing tree objects; ideally, use
1138
    # dulwich.index.changes_from_tree with a include_trees argument.
0.287.6 by Jelmer Vernooij
Fix some more tests.
1139
    refresh_index(target.index, target.abspath('.').encode(sys.getfilesystemencoding()))
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1140
    to_tree_sha = target.index.commit(store)
0.287.6 by Jelmer Vernooij
Fix some more tests.
1141
    target.index.write()
0.287.3 by Jelmer Vernooij
Some improvements to changes iterator.
1142
    return store.tree_changes(from_tree_sha, to_tree_sha, include_trees=True,
1143
            want_unchanged=want_unchanged)