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