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