/brz/remove-bazaar

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