/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

Move push code to push.py.

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
31
    inventory_to_tree_and_blobs,
 
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(self.repository._transport)
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)
 
67
        objects = inventory_to_tree_and_blobs(inv, self.repository.texts, 
 
68
                                              self.mapping)
63
69
        for sha, o, path in objects:
64
70
            if path == "":
65
71
                tree_sha = sha
66
72
            ie = inv[inv.path2id(path)]
67
73
            if ie.kind in ("file", "symlink"):
68
 
                self._idmap.add_entry(sha, "blob", (ie.file_id, ie.revision))
 
74
                git_kind = "blob"
 
75
            elif ie.kind == "directory":
 
76
                git_kind = "tree"
69
77
            else:
70
 
                self._idmap.add_entry(sha, "tree", (ie.file_id, ie.revision))
 
78
                raise AssertionError()
 
79
            self._idmap.add_entry(sha, git_kind, (ie.file_id, ie.revision))
71
80
        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")
 
81
        commit_obj = revision_to_commit(rev, tree_sha,
 
82
            self._idmap._parent_lookup)
 
83
        try:
 
84
            foreign_revid, mapping = mapping_registry.parse_revision_id(revid)
 
85
        except errors.InvalidRevisionId:
 
86
            pass
 
87
        else:
 
88
            if foreign_revid != commit_obj.id:
 
89
                raise AssertionError("recreated git commit had different sha1: expected %s, got %s" % (foreign_revid, commit_obj.id))
 
90
        self._idmap.add_entry(commit_obj.id, "commit", (revid, tree_sha))
 
91
 
 
92
    def _check_expected_sha(self, expected_sha, object):
 
93
        if expected_sha is None:
 
94
            return
 
95
        if expected_sha != object.id:
 
96
            raise AssertionError("Invalid sha for %r: %s" % (object, expected_sha))
 
97
 
 
98
    def _get_blob(self, fileid, revision, expected_sha=None):
 
99
        """Return a Git Blob object from a fileid and revision stored in bzr.
 
100
        
 
101
        :param fileid: File id of the text
 
102
        :param revision: Revision of the text
 
103
        """
 
104
        text = self.repository.texts.get_record_stream([(fileid, revision)],
 
105
            "unordered", True).next().get_bytes_as("fulltext")
77
106
        blob = Blob()
78
107
        blob._text = text
 
108
        self._check_expected_sha(expected_sha, blob)
79
109
        return blob
80
110
 
81
 
    def _get_tree(self, fileid, revid):
82
 
        raise NotImplementedError(self._get_tree)
83
 
 
84
 
    def _get_commit(self, revid, tree_sha):
 
111
    def _get_tree(self, fileid, revid, inv=None, expected_sha=None):
 
112
        """Return a Git Tree object from a file id and a revision stored in bzr.
 
113
 
 
114
        :param fileid: fileid in the tree.
 
115
        :param revision: Revision of the tree.
 
116
        """
 
117
        if inv is None:
 
118
            inv = self.repository.get_inventory(revid)
 
119
        tree = Tree()
 
120
        children = inv[fileid].children
 
121
        for name in sorted(children):
 
122
            ie = children[name]
 
123
            if ie.kind == "directory":
 
124
                subtree = self._get_tree(ie.file_id, revid, inv)
 
125
                tree.add(stat.S_IFDIR, name.encode('UTF-8'), subtree.id)
 
126
            elif ie.kind == "file":
 
127
                blob = self._get_blob(ie.file_id, ie.revision)
 
128
                mode = stat.S_IFREG | 0644
 
129
                if ie.executable:
 
130
                    mode |= 0111
 
131
                tree.add(mode, name.encode('UTF-8'), blob.id)
 
132
            elif ie.kind == "symlink":
 
133
                raise AssertionError("Symlinks not yet supported")
 
134
        tree.serialize()
 
135
        self._check_expected_sha(expected_sha, tree)
 
136
        return tree
 
137
 
 
138
    def _get_commit(self, revid, tree_sha, expected_sha=None):
85
139
        rev = self.repository.get_revision(revid)
86
 
        return revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
140
        commit = revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
141
        self._check_expected_sha(expected_sha, commit)
 
142
        return commit
 
143
 
 
144
    def get_raw(self, sha):
 
145
        return self[sha]._text
87
146
 
88
147
    def __getitem__(self, sha):
89
148
        # See if sha is in map
96
155
            (type, type_data) = self._idmap.lookup_git_sha(sha)
97
156
        # convert object to git object
98
157
        if type == "commit":
99
 
            return self._get_commit(*type_data)
 
158
            return self._get_commit(type_data[0], type_data[1], 
 
159
                                    expected_sha=sha)
100
160
        elif type == "blob":
101
 
            return self._get_blob(*type_data)
 
161
            return self._get_blob(type_data[0], type_data[1], expected_sha=sha)
102
162
        elif type == "tree":
103
 
            return self._get_tree(*type_data)
 
163
            return self._get_tree(type_data[0], type_data[1], expected_sha=sha)
104
164
        else:
105
165
            raise AssertionError("Unknown object type '%s'" % type)