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