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