/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to converter.py

Override GitRevisionSpec.__nonzero__ as the default implementation uses has_revision(), which is not available on remote git repositories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Canonical Ltd
 
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Map from Git sha's to Bazaar objects."""
18
18
 
19
 
import bzrlib
20
 
 
21
 
from bzrlib import ui
22
 
 
23
 
from bzrlib.errors import NoSuchRevision
 
19
from dulwich.objects import (
 
20
    Blob,
 
21
    Tree,
 
22
    )
 
23
import stat
 
24
 
 
25
from bzrlib import (
 
26
    errors,
 
27
    ui,
 
28
    )
24
29
 
25
30
from bzrlib.plugins.git.mapping import (
26
 
    inventory_to_tree_and_blobs,
 
31
    directory_to_tree,
 
32
    mapping_registry,
27
33
    revision_to_commit,
28
34
    )
29
 
from bzrlib.plugins.git.shamap import GitShaMap
30
 
 
31
 
from dulwich.objects import (
32
 
    Blob,
 
35
from bzrlib.plugins.git.shamap import (
 
36
    SqliteGitShaMap,
33
37
    )
34
38
 
35
39
 
36
 
class GitObjectConverter(object):
 
40
class BazaarObjectStore(object):
 
41
    """A Git-style object store backed onto a Bazaar repository."""
37
42
 
38
43
    def __init__(self, repository, mapping=None):
39
44
        self.repository = repository
41
46
            self.mapping = self.repository.get_mapping()
42
47
        else:
43
48
            self.mapping = mapping
44
 
        self._idmap = GitShaMap(self.repository._transport)
 
49
        self._idmap = SqliteGitShaMap.from_repository(repository)
45
50
 
46
51
    def _update_sha_map(self):
47
52
        all_revids = self.repository.all_revision_ids()
48
53
        graph = self.repository.get_graph()
49
54
        present_revids = set(self._idmap.revids())
 
55
        missing_revids = [revid for revid in graph.iter_topo_order(all_revids) if revid not in present_revids]
50
56
        pb = ui.ui_factory.nested_progress_bar()
51
57
        try:
52
 
            for i, revid in enumerate(graph.iter_topo_order(all_revids)):
53
 
                if revid in present_revids:
54
 
                    continue
55
 
                pb.update("updating git map", i, len(all_revids))
 
58
            for i, revid in enumerate(missing_revids):
 
59
                pb.update("updating git map", i, len(missing_revids))
56
60
                self._update_sha_map_revision(revid)
57
61
        finally:
 
62
            self._idmap.commit()
58
63
            pb.finished()
59
64
 
60
65
    def _update_sha_map_revision(self, revid):
61
66
        inv = self.repository.get_inventory(revid)
62
 
        objects = inventory_to_tree_and_blobs(self.repository, self.mapping, revid)
63
 
        for sha, o, path in objects:
64
 
            if path == "":
65
 
                tree_sha = sha
66
 
            ie = inv[inv.path2id(path)]
67
 
            if ie.kind in ("file", "symlink"):
68
 
                self._idmap.add_entry(sha, "blob", (ie.file_id, ie.revision))
69
 
            else:
70
 
                self._idmap.add_entry(sha, "tree", (ie.file_id, ie.revision))
 
67
        tree_sha = self._get_ie_sha1(inv.root, inv)
71
68
        rev = self.repository.get_revision(revid)
72
 
        commit_obj = revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
73
 
        self._idmap.add_entry(commit_obj.sha().hexdigest(), "commit", (revid, tree_sha))
74
 
 
75
 
    def _get_blob(self, fileid, revision):
76
 
        text = self.repository.texts.get_record_stream([(fileid, revision)], "unordered", True).next().get_bytes_as("fulltext")
 
69
        commit_obj = revision_to_commit(rev, tree_sha,
 
70
            self._idmap._parent_lookup)
 
71
        try:
 
72
            foreign_revid, mapping = mapping_registry.parse_revision_id(revid)
 
73
        except errors.InvalidRevisionId:
 
74
            pass
 
75
        else:
 
76
            if foreign_revid != commit_obj.id:
 
77
                raise AssertionError("recreated git commit had different sha1: expected %s, got %s" % (foreign_revid, commit_obj.id))
 
78
        self._idmap.add_entry(commit_obj.id, "commit", (revid, tree_sha))
 
79
 
 
80
    def _check_expected_sha(self, expected_sha, object):
 
81
        if expected_sha is None:
 
82
            return
 
83
        if expected_sha != object.id:
 
84
            raise AssertionError("Invalid sha for %r: %s" % (object, expected_sha))
 
85
 
 
86
    def _get_ie_object(self, entry, inv):  
 
87
        if entry.kind == "directory":
 
88
            return self._get_tree(entry.file_id, inv.revision_id, inv=inv)
 
89
        else:
 
90
            return self._get_blob(entry.file_id, entry.revision)
 
91
 
 
92
    def _get_ie_object_or_sha1(self, entry, inv):
 
93
        if entry.kind == "directory":
 
94
            try:
 
95
                return self._idmap.lookup_tree(entry.file_id, inv.revision_id), None
 
96
            except KeyError:
 
97
                ret = self._get_ie_object(entry, inv)
 
98
                self._idmap.add_entry(ret.id, "tree", (entry.file_id, inv.revision_id))
 
99
                return ret.id, ret
 
100
        else:
 
101
            try:
 
102
                return self._idmap.lookup_blob(entry.file_id, entry.revision), None
 
103
            except KeyError:
 
104
                ret = self._get_ie_object(entry, inv)
 
105
                self._idmap.add_entry(ret.id, "blob", (entry.file_id, entry.revision))
 
106
                return ret.id, ret
 
107
 
 
108
    def _get_ie_sha1(self, entry, inv):
 
109
        return self._get_ie_object_or_sha1(entry, inv)[0]
 
110
 
 
111
    def _get_blob(self, fileid, revision, expected_sha=None):
 
112
        """Return a Git Blob object from a fileid and revision stored in bzr.
 
113
        
 
114
        :param fileid: File id of the text
 
115
        :param revision: Revision of the text
 
116
        """
 
117
        text = self.repository.texts.get_record_stream([(fileid, revision)],
 
118
            "unordered", True).next().get_bytes_as("fulltext")
77
119
        blob = Blob()
78
120
        blob._text = text
 
121
        self._check_expected_sha(expected_sha, blob)
79
122
        return blob
80
123
 
81
 
    def _get_tree(self, fileid, revid):
82
 
        raise NotImplementedError(self._get_tree)
83
 
 
84
 
    def _get_commit(self, revid, tree_sha):
 
124
    def _get_tree(self, fileid, revid, inv=None, expected_sha=None):
 
125
        """Return a Git Tree object from a file id and a revision stored in bzr.
 
126
 
 
127
        :param fileid: fileid in the tree.
 
128
        :param revision: Revision of the tree.
 
129
        """
 
130
        if inv is None:
 
131
            inv = self.repository.get_inventory(revid)
 
132
        tree = directory_to_tree(inv[fileid], lambda ie: self._get_ie_sha1(ie, inv))
 
133
        self._check_expected_sha(expected_sha, tree)
 
134
        return tree
 
135
 
 
136
    def _get_commit(self, revid, tree_sha, expected_sha=None):
85
137
        rev = self.repository.get_revision(revid)
86
 
        return revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
138
        commit = revision_to_commit(rev, tree_sha, self._lookup_revision_sha1)
 
139
        self._check_expected_sha(expected_sha, commit)
 
140
        return commit
 
141
 
 
142
    def _lookup_revision_sha1(self, revid):
 
143
        try:
 
144
            return self._idmap._parent_lookup(revid)
 
145
        except KeyError:
 
146
            inv = self.repository.get_inventory(revid)
 
147
            tree_sha = self._get_ie_sha1(inv.root, inv)
 
148
            ret = self._get_commit(revid, tree_sha).id
 
149
            self._idmap.add_entry(ret, "commit", (revid, tree_sha))
 
150
            return ret
 
151
 
 
152
    def get_raw(self, sha):
 
153
        return self[sha]._text
87
154
 
88
155
    def __getitem__(self, sha):
89
156
        # See if sha is in map
96
163
            (type, type_data) = self._idmap.lookup_git_sha(sha)
97
164
        # convert object to git object
98
165
        if type == "commit":
99
 
            return self._get_commit(*type_data)
 
166
            return self._get_commit(type_data[0], type_data[1], 
 
167
                                    expected_sha=sha)
100
168
        elif type == "blob":
101
 
            return self._get_blob(*type_data)
 
169
            return self._get_blob(type_data[0], type_data[1], expected_sha=sha)
102
170
        elif type == "tree":
103
 
            return self._get_tree(*type_data)
 
171
            return self._get_tree(type_data[0], type_data[1], expected_sha=sha)
104
172
        else:
105
173
            raise AssertionError("Unknown object type '%s'" % type)