/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

make send_pack accessible.

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
 
 
65
    def __iter__(self):
 
66
        self._update_sha_map()
 
67
        return iter(self._idmap.sha1s())
 
68
 
60
69
    def _update_sha_map_revision(self, revid):
61
70
        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))
 
71
        tree_sha = self._get_ie_sha1(inv.root, inv)
71
72
        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")
 
73
        commit_obj = revision_to_commit(rev, tree_sha,
 
74
            self._idmap._parent_lookup)
 
75
        try:
 
76
            foreign_revid, mapping = mapping_registry.parse_revision_id(revid)
 
77
        except errors.InvalidRevisionId:
 
78
            pass
 
79
        else:
 
80
            if foreign_revid != commit_obj.id:
 
81
                raise AssertionError("recreated git commit had different sha1: expected %s, got %s" % (foreign_revid, commit_obj.id))
 
82
        self._idmap.add_entry(commit_obj.id, "commit", (revid, tree_sha))
 
83
 
 
84
    def _check_expected_sha(self, expected_sha, object):
 
85
        if expected_sha is None:
 
86
            return
 
87
        if expected_sha != object.id:
 
88
            raise AssertionError("Invalid sha for %r: %s" % (object, expected_sha))
 
89
 
 
90
    def _get_ie_object(self, entry, inv):  
 
91
        if entry.kind == "directory":
 
92
            return self._get_tree(entry.file_id, inv.revision_id, inv=inv)
 
93
        else:
 
94
            return self._get_blob(entry.file_id, entry.revision)
 
95
 
 
96
    def _get_ie_object_or_sha1(self, entry, inv):
 
97
        if entry.kind == "directory":
 
98
            try:
 
99
                return self._idmap.lookup_tree(entry.file_id, inv.revision_id), None
 
100
            except KeyError:
 
101
                ret = self._get_ie_object(entry, inv)
 
102
                self._idmap.add_entry(ret.id, "tree", (entry.file_id, inv.revision_id))
 
103
                return ret.id, ret
 
104
        else:
 
105
            try:
 
106
                return self._idmap.lookup_blob(entry.file_id, entry.revision), None
 
107
            except KeyError:
 
108
                ret = self._get_ie_object(entry, inv)
 
109
                self._idmap.add_entry(ret.id, "blob", (entry.file_id, entry.revision))
 
110
                return ret.id, ret
 
111
 
 
112
    def _get_ie_sha1(self, entry, inv):
 
113
        return self._get_ie_object_or_sha1(entry, inv)[0]
 
114
 
 
115
    def _get_blob(self, fileid, revision, expected_sha=None):
 
116
        """Return a Git Blob object from a fileid and revision stored in bzr.
 
117
        
 
118
        :param fileid: File id of the text
 
119
        :param revision: Revision of the text
 
120
        """
 
121
        text = self.repository.texts.get_record_stream([(fileid, revision)],
 
122
            "unordered", True).next().get_bytes_as("fulltext")
77
123
        blob = Blob()
78
124
        blob._text = text
 
125
        self._check_expected_sha(expected_sha, blob)
79
126
        return blob
80
127
 
81
 
    def _get_tree(self, fileid, revid):
82
 
        raise NotImplementedError(self._get_tree)
83
 
 
84
 
    def _get_commit(self, revid, tree_sha):
 
128
    def _get_tree(self, fileid, revid, inv=None, expected_sha=None):
 
129
        """Return a Git Tree object from a file id and a revision stored in bzr.
 
130
 
 
131
        :param fileid: fileid in the tree.
 
132
        :param revision: Revision of the tree.
 
133
        """
 
134
        if inv is None:
 
135
            inv = self.repository.get_inventory(revid)
 
136
        tree = directory_to_tree(inv[fileid], lambda ie: self._get_ie_sha1(ie, inv))
 
137
        self._check_expected_sha(expected_sha, tree)
 
138
        return tree
 
139
 
 
140
    def _get_commit(self, revid, tree_sha, expected_sha=None):
85
141
        rev = self.repository.get_revision(revid)
86
 
        return revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
142
        commit = revision_to_commit(rev, tree_sha, self._lookup_revision_sha1)
 
143
        self._check_expected_sha(expected_sha, commit)
 
144
        return commit
 
145
 
 
146
    def _lookup_revision_sha1(self, revid):
 
147
        try:
 
148
            return self._idmap._parent_lookup(revid)
 
149
        except KeyError:
 
150
            inv = self.repository.get_inventory(revid)
 
151
            tree_sha = self._get_ie_sha1(inv.root, inv)
 
152
            ret = self._get_commit(revid, tree_sha).id
 
153
            self._idmap.add_entry(ret, "commit", (revid, tree_sha))
 
154
            return ret
 
155
 
 
156
    def get_raw(self, sha):
 
157
        return self[sha].as_raw_string()
87
158
 
88
159
    def __getitem__(self, sha):
89
160
        # See if sha is in map
96
167
            (type, type_data) = self._idmap.lookup_git_sha(sha)
97
168
        # convert object to git object
98
169
        if type == "commit":
99
 
            return self._get_commit(*type_data)
 
170
            return self._get_commit(type_data[0], type_data[1], 
 
171
                                    expected_sha=sha)
100
172
        elif type == "blob":
101
 
            return self._get_blob(*type_data)
 
173
            return self._get_blob(type_data[0], type_data[1], expected_sha=sha)
102
174
        elif type == "tree":
103
 
            return self._get_tree(*type_data)
 
175
            return self._get_tree(type_data[0], type_data[1], expected_sha=sha)
104
176
        else:
105
177
            raise AssertionError("Unknown object type '%s'" % type)