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