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