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