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