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