/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)
540
        return ("GIT", self.index[path][-2])
541
542
    @needs_read_lock
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
543
    def get_file_sha1(self, file_id, path=None, stat_value=None):
544
        if not path:
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
545
            path = self.id2path(file_id)
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
546
        abspath = self.abspath(path).encode(osutils._fs_enc)
0.239.4 by Jelmer Vernooij
Cope with nonexistent files and directories in get_file_sha1.
547
        try:
0.200.1302 by Jelmer Vernooij
Significantly improve performance of WorkingTree.extras().
548
            return osutils.sha_file_by_name(abspath)
0.239.4 by Jelmer Vernooij
Cope with nonexistent files and directories in get_file_sha1.
549
        except OSError, (num, msg):
550
            if num in (errno.EISDIR, errno.ENOENT):
551
                return None
552
            raise
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
553
0.200.610 by Jelmer Vernooij
Support retrieving basis tree properly.
554
    def revision_tree(self, revid):
555
        return self.repository.revision_tree(revid)
556
0.200.1242 by Jelmer Vernooij
Support directories better.
557
    def _is_versioned(self, path):
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
558
        assert self._lock_mode is not None
0.200.1242 by Jelmer Vernooij
Support directories better.
559
        return (path in self.index or self._has_dir(path))
560
0.200.1239 by Jelmer Vernooij
Implement GitWorkingTree.filter_unversioned_files.
561
    def filter_unversioned_files(self, files):
0.200.1316 by Jelmer Vernooij
Fix filter_unversioned_files.
562
        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.
563
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
564
    def _get_dir_ie(self, path, parent_id):
0.200.1192 by Jelmer Vernooij
Implement path2id.
565
        file_id = self.path2id(path)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
566
        return inventory.InventoryDirectory(file_id,
0.200.1190 by Jelmer Vernooij
Fix get_symlink_target call.
567
            posixpath.basename(path).strip("/"), parent_id)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
568
569
    def _add_missing_parent_ids(self, path, dir_ids):
570
        if path in dir_ids:
571
            return []
572
        parent = posixpath.dirname(path).strip("/")
573
        ret = self._add_missing_parent_ids(parent, dir_ids)
574
        parent_id = dir_ids[parent]
575
        ie = self._get_dir_ie(path, parent_id)
576
        dir_ids[path] = ie.file_id
577
        ret.append((path, ie))
578
        return ret
579
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
580
    def _get_file_ie(self, name, path, value, parent_id):
581
        assert isinstance(name, unicode)
0.200.1192 by Jelmer Vernooij
Implement path2id.
582
        assert isinstance(path, unicode)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
583
        assert isinstance(value, tuple) and len(value) == 10
584
        (ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
0.200.1192 by Jelmer Vernooij
Implement path2id.
585
        file_id = self.path2id(path)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
586
        if type(file_id) != str:
587
            raise AssertionError
588
        kind = mode_kind(mode)
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
589
        ie = inventory.entry_factory[kind](file_id, name, parent_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
590
        if kind == 'symlink':
0.200.1190 by Jelmer Vernooij
Fix get_symlink_target call.
591
            ie.symlink_target = self.get_symlink_target(file_id)
0.264.10 by Jelmer Vernooij
Yield inventory entries.
592
        else:
593
            data = self.get_file_text(file_id, path)
594
            ie.text_sha1 = osutils.sha_string(data)
595
            ie.text_size = len(data)
596
            ie.executable = self.is_executable(file_id, path)
597
        ie.revision = None
598
        return ie
599
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
600
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
601
        mode = stat_result.st_mode
602
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
603
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
604
    @needs_read_lock
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
605
    def stored_kind(self, file_id, path=None):
606
        if path is None:
607
            path = self.id2path(file_id)
0.200.1328 by Jelmer Vernooij
More test fixes.
608
        try:
609
            return mode_kind(self.index[path.encode("utf-8")][4])
610
        except KeyError:
611
            # Maybe it's a directory?
612
            if self._has_dir(path):
613
                return "directory"
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
614
            raise errors.NoSuchId(self, file_id)
615
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
616
    def is_executable(self, file_id, path=None):
617
        if getattr(self, "_supports_executable", osutils.supports_executable)():
618
            if not path:
619
                path = self.id2path(file_id)
620
            mode = os.lstat(self.abspath(path)).st_mode
621
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
622
        else:
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
623
            basis_tree = self.basis_tree()
624
            if file_id in basis_tree:
625
                return basis_tree.is_executable(file_id)
626
            # Default to not executable
627
            return False
628
0.200.1539 by Jelmer Vernooij
Cope with new is_executable.
629
    def _is_executable_from_path_and_stat(self, path, stat_result):
630
        if getattr(self, "_supports_executable", osutils.supports_executable)():
631
            return self._is_executable_from_path_and_stat_from_stat(path, stat_result)
632
        else:
633
            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.
634
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
635
    @needs_read_lock
0.264.10 by Jelmer Vernooij
Yield inventory entries.
636
    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.
637
        # FIXME: Yield non-versioned files
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
638
        if from_dir is None:
639
            from_dir = ""
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
640
        dir_ids = {}
0.200.1339 by Jelmer Vernooij
Some reformatting.
641
        fk_entries = {'directory': workingtree.TreeDirectory,
642
                      'file': workingtree.TreeFile,
643
                      'symlink': workingtree.TreeLink}
0.200.1192 by Jelmer Vernooij
Implement path2id.
644
        root_ie = self._get_dir_ie(u"", None)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
645
        if include_root and not from_dir:
646
            yield "", "V", root_ie.kind, root_ie.file_id, root_ie
0.200.1192 by Jelmer Vernooij
Implement path2id.
647
        dir_ids[u""] = root_ie.file_id
0.200.1328 by Jelmer Vernooij
More test fixes.
648
        if recursive:
649
            path_iterator = self._iter_files_recursive(from_dir)
650
        else:
651
            if from_dir is None:
652
                start = self.basedir
653
            else:
654
                start = os.path.join(self.basedir, from_dir)
655
            path_iterator = sorted([os.path.join(from_dir, name) for name in
656
                os.listdir(start) if not self.bzrdir.is_control_filename(name)
657
                and not self.mapping.is_special_file(name)])
658
        for path in path_iterator:
659
            try:
660
                value = self.index[path]
661
            except KeyError:
662
                value = None
0.200.1192 by Jelmer Vernooij
Implement path2id.
663
            path = path.decode("utf-8")
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
664
            parent, name = posixpath.split(path)
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
665
            for dir_path, dir_ie in self._add_missing_parent_ids(parent, dir_ids):
666
                yield dir_path, "V", dir_ie.kind, dir_ie.file_id, dir_ie
0.200.1328 by Jelmer Vernooij
More test fixes.
667
            if value is not None:
668
                ie = self._get_file_ie(name, path, value, dir_ids[parent])
669
                yield path, "V", ie.kind, ie.file_id, ie
670
            else:
671
                kind = osutils.file_kind(self.abspath(path))
672
                ie = fk_entries[kind]()
673
                yield path, "?", kind, None, ie
0.264.10 by Jelmer Vernooij
Yield inventory entries.
674
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
675
    @needs_read_lock
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
676
    def all_file_ids(self):
677
        ids = {u"": self.path2id("")}
678
        for path in self.index:
0.200.1328 by Jelmer Vernooij
More test fixes.
679
            if self.mapping.is_special_file(path):
680
                continue
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
681
            path = path.decode("utf-8")
682
            parent = posixpath.dirname(path).strip("/")
683
            for e in self._add_missing_parent_ids(parent, ids):
684
                pass
685
            ids[path] = self.path2id(path)
686
        return set(ids.values())
687
0.200.1374 by Jelmer Vernooij
Implement GitWorkingTree._directory_is_tree_reference.
688
    def _directory_is_tree_reference(self, path):
689
        # FIXME: Check .gitsubmodules for path
690
        return False
691
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
692
    @needs_read_lock
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
693
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
694
        # FIXME: Is return order correct?
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
695
        if yield_parents:
696
            raise NotImplementedError(self.iter_entries_by_dir)
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
697
        if specific_file_ids is not None:
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
698
            specific_paths = [self.id2path(file_id) for file_id in specific_file_ids]
699
            if specific_paths in ([u""], []):
700
                specific_paths = None
701
            else:
702
                specific_paths = set(specific_paths)
703
        else:
704
            specific_paths = None
0.200.1192 by Jelmer Vernooij
Implement path2id.
705
        root_ie = self._get_dir_ie(u"", None)
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
706
        if specific_paths is None:
707
            yield u"", root_ie
0.200.1192 by Jelmer Vernooij
Implement path2id.
708
        dir_ids = {u"": root_ie.file_id}
0.264.10 by Jelmer Vernooij
Yield inventory entries.
709
        for path, value in self.index.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
710
            if self.mapping.is_special_file(path):
711
                continue
0.200.1192 by Jelmer Vernooij
Implement path2id.
712
            path = path.decode("utf-8")
0.200.1252 by Jelmer Vernooij
Support specific_file_ids in GitWorkingTree.iter_entries_by_dir.
713
            if specific_paths is not None and not path in specific_paths:
714
                continue
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
715
            (parent, name) = posixpath.split(path)
0.200.1251 by Jelmer Vernooij
Cope with files dissapearing in GitWorkingTree.
716
            try:
0.200.1321 by Jelmer Vernooij
More fixes for compatibility with bzr.dev testsuite.
717
                file_ie = self._get_file_ie(name, path, value, None)
0.200.1251 by Jelmer Vernooij
Cope with files dissapearing in GitWorkingTree.
718
            except IOError:
719
                continue
0.200.1207 by Jelmer Vernooij
Fix some formatting.
720
            for (dir_path, dir_ie) in self._add_missing_parent_ids(parent,
721
                    dir_ids):
0.264.11 by Jelmer Vernooij
Completer implementation of iter_entries_by_dir and list_files.
722
                yield dir_path, dir_ie
0.200.1251 by Jelmer Vernooij
Cope with files dissapearing in GitWorkingTree.
723
            file_ie.parent_id = self.path2id(parent)
724
            yield path, file_ie
0.264.9 by Jelmer Vernooij
Implement basic GitWorkingTree.iter_entries_by_dir.
725
0.200.619 by Jelmer Vernooij
Provide dummy WorkingTree.conflicts() implementation rather than spending a lot of time not finding any conflicts.
726
    @needs_read_lock
727
    def conflicts(self):
728
        # FIXME:
0.262.1 by Jelmer Vernooij
Fix WorkingTree.conflicts().
729
        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.
730
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
731
    def update_basis_by_delta(self, new_revid, delta):
0.200.1196 by Jelmer Vernooij
Implement GitWorkingTree.update_basis_by_delta.
732
        # The index just contains content, which won't have changed.
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
733
        self._reset_data()
0.200.1193 by Jelmer Vernooij
Implement GitWorkingTree.{move,rename_one}.
734
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
735
    @needs_read_lock
0.200.1328 by Jelmer Vernooij
More test fixes.
736
    def get_canonical_inventory_path(self, path):
737
        for p in self.index:
738
            if p.lower() == path.lower():
739
                return p
740
        else:
741
            return path
742
0.200.1525 by Jelmer Vernooij
Make sure to always use an up-to-date index.
743
    @needs_read_lock
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
744
    def _walkdirs(self, prefix=""):
745
        if prefix != "":
746
            prefix += "/"
747
        per_dir = defaultdict(list)
748
        for path, value in self.index.iteritems():
0.200.1328 by Jelmer Vernooij
More test fixes.
749
            if self.mapping.is_special_file(path):
750
                continue
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
751
            if not path.startswith(prefix):
752
                continue
753
            (dirname, child_name) = posixpath.split(path)
754
            dirname = dirname.decode("utf-8")
755
            dir_file_id = self.path2id(dirname)
756
            assert isinstance(value, tuple) and len(value) == 10
757
            (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
758
            stat_result = os.stat_result((mode, ino,
0.200.1211 by Jelmer Vernooij
Fix statresult.
759
                    dev, 1, uid, gid, size,
760
                    0, mtime, ctime))
0.200.1210 by Jelmer Vernooij
Implement GitWorkingTree._walkdirs.
761
            per_dir[(dirname, dir_file_id)].append(
762
                (path.decode("utf-8"), child_name.decode("utf-8"),
763
                mode_kind(mode), stat_result,
764
                self.path2id(path.decode("utf-8")),
765
                mode_kind(mode)))
766
        return per_dir.iteritems()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
767
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
768
    def _lookup_entry(self, path, update_index=False):
0.200.1543 by Jelmer Vernooij
Support symlinks.
769
        assert type(path) == str
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
770
        entry = self.index[path]
771
        index_mode = entry[-6]
772
        index_sha = entry[-2]
773
        disk_path = os.path.join(self.basedir, path)
774
        disk_stat = os.lstat(disk_path)
775
        disk_mtime = disk_stat.st_mtime
776
        if isinstance(entry[1], tuple):
777
            index_mtime = entry[1][0]
778
        else:
779
            index_mtime = int(entry[1])
780
        mtime_delta = (disk_mtime - index_mtime)
781
        disk_mode = cleanup_mode(disk_stat.st_mode)
782
        if mtime_delta > 0 or disk_mode != index_mode:
783
            if stat.S_ISDIR(disk_mode):
784
                try:
785
                    subrepo = Repo(disk_path)
786
                except NotGitRepository:
787
                    return (None, None)
788
                else:
789
                    disk_mode = S_IFGITLINK
790
                    git_id = subrepo.head()
0.200.1543 by Jelmer Vernooij
Support symlinks.
791
            elif stat.S_ISLNK(disk_mode):
0.200.1545 by Jelmer Vernooij
Some more test fixes.
792
                blob = Blob.from_string(os.readlink(disk_path).encode('utf-8'))
0.200.1543 by Jelmer Vernooij
Support symlinks.
793
                git_id = blob.id
794
            elif stat.S_ISREG(disk_mode):
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
795
                with open(disk_path, 'r') as f:
796
                    blob = Blob.from_string(f.read())
797
                git_id = blob.id
0.200.1543 by Jelmer Vernooij
Support symlinks.
798
            else:
799
                raise AssertionError
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
800
            if update_index:
801
                flags = 0 # FIXME
0.200.1545 by Jelmer Vernooij
Some more test fixes.
802
                self.index[path] = index_entry_from_stat(disk_stat, git_id, flags, disk_mode)
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
803
            return (git_id, disk_mode)
804
        return (index_sha, index_mode)
805
0.200.1308 by Jelmer Vernooij
Write index to disk after adding files.
806
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
807
class GitWorkingTreeFormat(workingtree.WorkingTreeFormat):
808
0.200.1206 by Jelmer Vernooij
Implement GitWorkingTree.all_file_ids.
809
    _tree_class = GitWorkingTree
810
0.200.1295 by Jelmer Vernooij
Mark working trees as not supporting directories.
811
    supports_versioned_directories = False
812
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
813
    @property
814
    def _matchingbzrdir(self):
0.200.1140 by Jelmer Vernooij
Update now that the control dir formats are no longer in __init__.
815
        from bzrlib.plugins.git.dir import LocalGitControlDirFormat
0.200.1013 by Jelmer Vernooij
More renames.
816
        return LocalGitControlDirFormat()
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
817
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
818
    def get_format_description(self):
819
        return "Git Working Tree"
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
820
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
821
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
822
                   accelerator_tree=None, hardlink=False):
823
        """See WorkingTreeFormat.initialize()."""
824
        if not isinstance(a_bzrdir, LocalGitDir):
825
            raise errors.IncompatibleFormat(self, a_bzrdir)
826
        index = Index(a_bzrdir.root_transport.local_abspath(".git/index"))
827
        index.write()
828
        return GitWorkingTree(a_bzrdir, a_bzrdir.open_repository(),
829
            a_bzrdir.open_branch(), index)
830
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
831
832
class InterIndexGitTree(tree.InterTree):
833
    """InterTree that works between a Git revision tree and an index."""
834
835
    def __init__(self, source, target):
836
        super(InterIndexGitTree, self).__init__(source, target)
837
        self._index = target.index
838
839
    @classmethod
840
    def is_compatible(cls, source, target):
841
        from bzrlib.plugins.git.repository import GitRevisionTree
842
        return (isinstance(source, GitRevisionTree) and 
843
                isinstance(target, GitWorkingTree))
844
0.200.1536 by Jelmer Vernooij
Fix locks.
845
    @needs_read_lock
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
846
    def compare(self, want_unchanged=False, specific_files=None,
847
                extra_trees=None, require_versioned=False, include_root=False,
848
                want_unversioned=False):
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
849
        # FIXME: Handle include_root
850
        changes = changes_between_git_tree_and_index(
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
851
            self.source.store, self.source.tree, 
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
852
            self.target, want_unchanged=want_unchanged,
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
853
            want_unversioned=want_unversioned)
0.200.1338 by Jelmer Vernooij
Simplify code for getting file id map.
854
        source_fileid_map = self.source._fileid_map
855
        target_fileid_map = self.target._fileid_map
0.200.1030 by Jelmer Vernooij
More work on supporting roundtripping push.
856
        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.
857
            (source_fileid_map, target_fileid_map),
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
858
            specific_file=specific_files, require_versioned=require_versioned)
859
        if want_unversioned:
860
            for e in self.target.extras():
0.200.1207 by Jelmer Vernooij
Fix some formatting.
861
                ret.unversioned.append((e, None,
862
                    osutils.file_kind(self.target.abspath(e))))
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
863
        return ret
864
0.200.1536 by Jelmer Vernooij
Fix locks.
865
    @needs_read_lock
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
866
    def iter_changes(self, include_unchanged=False, specific_files=None,
0.200.1207 by Jelmer Vernooij
Fix some formatting.
867
        pb=None, extra_trees=[], require_versioned=True,
868
        want_unversioned=False):
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
869
        changes = changes_between_git_tree_and_index(
0.200.1205 by Jelmer Vernooij
Implement GitWorkingTree.stored_kind.
870
            self.source.store, self.source.tree,
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
871
            self.target, want_unchanged=include_unchanged,
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
872
            want_unversioned=want_unversioned)
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
873
        return changes_from_git_changes(changes, self.target.mapping,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
874
            specific_file=specific_files)
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
875
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
876
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
877
tree.InterTree.register_optimiser(InterIndexGitTree)
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
878
879
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
880
def changes_between_git_tree_and_index(object_store, tree, target,
0.200.1529 by Jelmer Vernooij
Add changes_between_tree_and_index.
881
        want_unchanged=False, want_unversioned=False, update_index=False):
882
    """Determine the changes between a git tree and a working tree with index.
883
884
    """
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
885
0.200.1542 by Jelmer Vernooij
Refactor iter_changes.
886
    names = target.index._byname.keys()
887
    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.
888
            object_store, tree, want_unchanged=want_unchanged):
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
889
        if name == (None, None):
890
            continue
0.200.1531 by Jelmer Vernooij
Don't trust index contents - verify against file timestamps.
891
        yield (name, mode, sha)