/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
1
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
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.239.4 by Jelmer Vernooij
Cope with nonexistent files and directories in get_file_sha1.
24
import errno
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
25
from dulwich.index import (
26
    Index,
27
    )
0.200.383 by Jelmer Vernooij
Simplify, support rewriting index based on inventory.
28
from dulwich.objects import (
29
    Blob,
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
30
    ZERO_SHA,
31
    )
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
32
import os
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
33
import stat
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
34
35
from bzrlib import (
0.200.382 by Jelmer Vernooij
Support flushing index.
36
    errors,
0.262.1 by Jelmer Vernooij
Fix WorkingTree.conflicts().
37
    conflicts as _mod_conflicts,
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
38
    ignores,
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
39
    lockable_files,
40
    lockdir,
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
41
    osutils,
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
42
    transport,
0.200.519 by Jelmer Vernooij
Move imports down, might not be available in older bzr-git versions.
43
    tree,
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
44
    workingtree,
45
    )
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
46
from bzrlib.decorators import (
47
    needs_read_lock,
48
    )
49
50
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
51
from bzrlib.plugins.git.dir import (
52
    LocalGitDir,
53
    )
0.200.401 by Jelmer Vernooij
Move working tree inventory code to inventory.
54
from bzrlib.plugins.git.inventory import (
55
    GitIndexInventory,
56
    )
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
57
from bzrlib.plugins.git.tree import (
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
58
    changes_from_git_changes,
0.200.617 by Jelmer Vernooij
Add custom InterTree for use between git revision trees.
59
    tree_delta_from_git_changes,
60
    )
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
61
from bzrlib.plugins.git.mapping import (
62
    GitFileIdMap,
63
    )
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
64
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
65
IGNORE_FILENAME = ".gitignore"
66
67
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
68
class GitWorkingTree(workingtree.WorkingTree):
69
    """A Git working tree."""
70
0.200.803 by Jelmer Vernooij
Default to non-bare repositories when initializing a control directory.
71
    def __init__(self, bzrdir, repo, branch, index):
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
72
        self.basedir = bzrdir.root_transport.local_abspath('.')
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
73
        self.bzrdir = bzrdir
74
        self.repository = repo
0.200.384 by Jelmer Vernooij
Fix reading of inventory from index.
75
        self.mapping = self.repository.get_mapping()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
76
        self._branch = branch
77
        self._transport = bzrdir.transport
78
0.246.3 by Jelmer Vernooij
Simplify call to abspath, without involving private variables.
79
        self.controldir = self.bzrdir.transport.local_abspath('bzr')
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
80
81
        try:
82
            os.makedirs(self.controldir)
83
            os.makedirs(os.path.join(self.controldir, 'lock'))
84
        except OSError:
85
            pass
86
87
        self._control_files = lockable_files.LockableFiles(
88
            transport.get_transport(self.controldir), 'lock', lockdir.LockDir)
89
        self._format = GitWorkingTreeFormat()
0.200.803 by Jelmer Vernooij
Default to non-bare repositories when initializing a control directory.
90
        self.index = index
0.200.239 by Jelmer Vernooij
Provide views.
91
        self.views = self._make_views()
0.200.1173 by Jelmer Vernooij
Provide GitWorkingTree._rules_searcher.
92
        self._rules_searcher = None
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
93
        self._detect_case_handling()
0.200.173 by Jelmer Vernooij
Merge changes, open index.
94
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
95
    def _index_add_entry(self, path, file_id, kind):
96
        if kind == "directory":
97
            # Git indexes don't contain directories
98
            return
99
        if kind == "file":
100
            blob = Blob()
101
            try:
102
                file, stat_val = self.get_file_with_stat(file_id, path)
103
            except (errors.NoSuchFile, IOError):
104
                # TODO: Rather than come up with something here, use the old index
105
                file = StringIO()
106
                from posix import stat_result
107
                stat_val = stat_result((stat.S_IFREG | 0644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
108
            blob.set_raw_string(file.read())
109
        elif kind == "symlink":
110
            blob = Blob()
111
            try:
112
                stat_val = os.lstat(self.abspath(path))
113
            except (errors.NoSuchFile, OSError):
114
                # TODO: Rather than come up with something here, use the 
115
                # old index
116
                from posix import stat_result
117
                stat_val = stat_result((stat.S_IFLNK, 0, 0, 0, 0, 0, 0, 0, 0, 0))
118
            blob.set_raw_string(self.get_symlink_target(file_id).encode("utf-8"))
119
        else:
120
            raise AssertionError("unknown kind '%s'" % kind)
121
        # Add object to the repository if it didn't exist yet
122
        if not blob.id in self.repository._git.object_store:
123
            self.repository._git.object_store.add_object(blob)
124
        # Add an entry to the index or update the existing entry
125
        flags = 0 # FIXME
126
        self.index[path.encode("utf-8")] = (stat_val.st_ctime,
127
                stat_val.st_mtime, stat_val.st_dev, stat_val.st_ino,
128
                stat_val.st_mode, stat_val.st_uid, stat_val.st_gid,
129
                stat_val.st_size, blob.id, flags)
130
131
    def _add(self, files, ids, kinds):
132
        for (path, file_id, kind) in zip(files, ids, kinds):
133
            self._index_add_entry(path, file_id, kind)
134
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
135
    def get_root_id(self):
136
        return self.mapping.generate_file_id("")
137
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
138
    def extras(self):
139
        """Yield all unversioned files in this WorkingTree.
140
        """
0.200.615 by Jelmer Vernooij
Optimize WorkingTree.extras().
141
        for (dirpath, dirnames, filenames) in os.walk(self.basedir):
142
            if self.bzrdir.is_control_filename(dirpath[len(self.basedir):].strip("/")):
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
143
                continue
0.200.615 by Jelmer Vernooij
Optimize WorkingTree.extras().
144
            for filename in filenames:
145
                relpath = os.path.join(dirpath[len(self.basedir):].strip("/"), filename)
146
                if not relpath in self.index:
0.200.605 by Jelmer Vernooij
Ignore directories in WorkingTree.extras().
147
                    yield relpath
148
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
149
    def unlock(self):
0.200.224 by Jelmer Vernooij
Fix working tree locking.
150
        # non-implementation specific cleanup
151
        self._cleanup()
152
153
        # reverse order of locking.
154
        try:
155
            return self._control_files.unlock()
156
        finally:
157
            self.branch.unlock()
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
158
0.200.383 by Jelmer Vernooij
Simplify, support rewriting index based on inventory.
159
    def _rewrite_index(self):
160
        self.index.clear()
161
        for path, entry in self._inventory.iter_entries():
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
162
            self._index_add_entry(path, entry.file_id, entry.kind)
0.200.383 by Jelmer Vernooij
Simplify, support rewriting index based on inventory.
163
0.200.382 by Jelmer Vernooij
Support flushing index.
164
    def flush(self):
165
        # TODO: Maybe this should only write on dirty ?
166
        if self._control_files._lock_mode != 'w':
167
            raise errors.NotWriteLocked(self)
0.200.983 by Jelmer Vernooij
Use support opening index of first revision.
168
        self._rewrite_index()
0.200.385 by Jelmer Vernooij
Cope with removed files.
169
        self.index.write()
0.200.382 by Jelmer Vernooij
Support flushing index.
170
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
171
    def __iter__(self):
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
172
        for path in self.index:
173
            yield self._fileid_map.lookup_file_id(path)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
174
175
    def id2path(self, file_id):
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
176
        if type(file_id) != str:
177
            raise AssertionError
178
        path = self._fileid_map.lookup_path(file_id)
179
        if path in self.index:
180
            return path
181
        raise errors.NoSuchId(None, file_id)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
182
0.200.409 by Jelmer Vernooij
Support parsing .gitignore.
183
    def get_ignore_list(self):
184
        ignoreset = getattr(self, '_ignoreset', None)
185
        if ignoreset is not None:
186
            return ignoreset
187
188
        ignore_globs = set()
189
        ignore_globs.update(ignores.get_runtime_ignores())
190
        ignore_globs.update(ignores.get_user_ignores())
191
        if self.has_filename(IGNORE_FILENAME):
192
            f = self.get_file_byname(IGNORE_FILENAME)
193
            try:
194
                ignore_globs.update(ignores.parse_ignore_file(f))
195
            finally:
196
                f.close()
197
        self._ignoreset = ignore_globs
198
        return ignore_globs
199
0.200.508 by Jelmer Vernooij
Skip inventory caching bits.
200
    def set_last_revision(self, revid):
201
        self._change_last_revision(revid)
202
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
203
    def _reset_data(self):
0.248.3 by Jelmer Vernooij
Handle working trees without valid HEAD branch.
204
        try:
205
            head = self.repository._git.head()
206
        except KeyError, name:
207
            raise errors.NotBranchError("branch %s at %s" % (name, self.repository.base))
0.252.44 by Jelmer Vernooij
Properly look up Bazaar revision ids for revision parents in case they are round-tripped.
208
        basis_inv = self.repository.get_inventory(self.branch.lookup_foreign_revision_id(head))
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
209
        store = self.repository._git.object_store
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
210
        if head == ZERO_SHA:
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
211
            self._fileid_map = GitFileIdMap({}, self.mapping)
0.200.983 by Jelmer Vernooij
Use support opening index of first revision.
212
            basis_inv = None
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
213
        else:
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
214
            self._fileid_map = self.mapping.get_fileid_map(store.__getitem__,
0.200.948 by Jelmer Vernooij
Cope with empty inventories.
215
                store[head].tree)
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
216
        result = GitIndexInventory(basis_inv, self._fileid_map, self.index, store)
0.264.1 by Jelmer Vernooij
Provide stubs using inventory for the moment.:
217
        self._bzr_inventory = result
0.200.379 by Jelmer Vernooij
Re-enable working tree support.
218
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
219
    @needs_read_lock
220
    def get_file_sha1(self, file_id, path=None, stat_value=None):
221
        if not path:
0.264.2 by Jelmer Vernooij
Implement GitWorkingTree.{_add,__iter__,id2path}.
222
            path = self.id2path(file_id)
0.239.4 by Jelmer Vernooij
Cope with nonexistent files and directories in get_file_sha1.
223
        try:
224
            return osutils.sha_file_by_name(self.abspath(path).encode(osutils._fs_enc))
225
        except OSError, (num, msg):
226
            if num in (errno.EISDIR, errno.ENOENT):
227
                return None
228
            raise
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
229
0.200.610 by Jelmer Vernooij
Support retrieving basis tree properly.
230
    def revision_tree(self, revid):
231
        return self.repository.revision_tree(revid)
232
0.200.619 by Jelmer Vernooij
Provide dummy WorkingTree.conflicts() implementation rather than spending a lot of time not finding any conflicts.
233
    @needs_read_lock
234
    def conflicts(self):
235
        # FIXME:
0.262.1 by Jelmer Vernooij
Fix WorkingTree.conflicts().
236
        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.
237
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
238
239
class GitWorkingTreeFormat(workingtree.WorkingTreeFormat):
240
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
241
    @property
242
    def _matchingbzrdir(self):
0.200.1140 by Jelmer Vernooij
Update now that the control dir formats are no longer in __init__.
243
        from bzrlib.plugins.git.dir import LocalGitControlDirFormat
0.200.1013 by Jelmer Vernooij
More renames.
244
        return LocalGitControlDirFormat()
0.200.656 by Jelmer Vernooij
Implement GitWorkingTreeFormat._matchingbzrdir.
245
0.200.90 by Jelmer Vernooij
Basic support for opening working trees.
246
    def get_format_description(self):
247
        return "Git Working Tree"
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
248
0.200.1096 by Jelmer Vernooij
Implement GitWorkingTreeFormat.initialize.
249
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
250
                   accelerator_tree=None, hardlink=False):
251
        """See WorkingTreeFormat.initialize()."""
252
        if not isinstance(a_bzrdir, LocalGitDir):
253
            raise errors.IncompatibleFormat(self, a_bzrdir)
254
        index = Index(a_bzrdir.root_transport.local_abspath(".git/index"))
255
        index.write()
256
        return GitWorkingTree(a_bzrdir, a_bzrdir.open_repository(),
257
            a_bzrdir.open_branch(), index)
258
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
259
260
class InterIndexGitTree(tree.InterTree):
261
    """InterTree that works between a Git revision tree and an index."""
262
263
    def __init__(self, source, target):
264
        super(InterIndexGitTree, self).__init__(source, target)
265
        self._index = target.index
266
267
    @classmethod
268
    def is_compatible(cls, source, target):
269
        from bzrlib.plugins.git.repository import GitRevisionTree
270
        return (isinstance(source, GitRevisionTree) and 
271
                isinstance(target, GitWorkingTree))
272
273
    def compare(self, want_unchanged=False, specific_files=None,
274
                extra_trees=None, require_versioned=False, include_root=False,
275
                want_unversioned=False):
276
        changes = self._index.changes_from_tree(
277
            self.source._repository._git.object_store, self.source.tree, 
278
            want_unchanged=want_unchanged)
0.200.920 by Jelmer Vernooij
Fix some more tests.
279
        source_fileid_map = self.source.mapping.get_fileid_map(
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
280
            self.source._repository._git.object_store.__getitem__,
281
            self.source.tree)
0.200.922 by Jelmer Vernooij
Fix remaining test.
282
        if self.target.mapping.BZR_FILE_IDS_FILE is not None:
0.200.1030 by Jelmer Vernooij
More work on supporting roundtripping push.
283
            file_id = self.target.path2id(
284
                self.target.mapping.BZR_FILE_IDS_FILE)
285
            if file_id is None:
0.200.922 by Jelmer Vernooij
Fix remaining test.
286
                target_fileid_map = {}
287
            else:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
288
                target_fileid_map = self.target.mapping.import_fileid_map(Blob.from_string(self.target.get_file_text(file_id)))
0.200.922 by Jelmer Vernooij
Fix remaining test.
289
        else:
290
            target_fileid_map = {}
0.200.971 by Chadrik
Fix 'bzr status' after 'bzr add' in native git working trees.
291
        target_fileid_map = GitFileIdMap(target_fileid_map, self.target.mapping)
0.200.1030 by Jelmer Vernooij
More work on supporting roundtripping push.
292
        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.
293
            (source_fileid_map, target_fileid_map),
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
294
            specific_file=specific_files, require_versioned=require_versioned)
295
        if want_unversioned:
296
            for e in self.target.extras():
297
                ret.unversioned.append((e, None, osutils.file_kind(self.target.abspath(e))))
298
        return ret
299
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
300
    def iter_changes(self, include_unchanged=False, specific_files=None,
301
        pb=None, extra_trees=[], require_versioned=True, want_unversioned=False):
302
        changes = self._index.changes_from_tree(
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
303
            self.source._repository._git.object_store, self.source.tree,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
304
            want_unchanged=include_unchanged)
305
        # FIXME: Handle want_unversioned
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
306
        return changes_from_git_changes(changes, self.target.mapping,
0.200.622 by Jelmer Vernooij
Implement InterTree.iter_changes() as well.
307
            specific_file=specific_files)
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
308
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
309
0.200.616 by Jelmer Vernooij
Provide custom intertree implementation for GitRevisionTree->GitWorkingTree.
310
tree.InterTree.register_optimiser(InterIndexGitTree)