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