/brz/remove-bazaar

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