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