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