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