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