/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 shamap.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 os
 
20
import threading
 
21
 
19
22
import bzrlib
20
 
 
21
 
from bzrlib.errors import NoSuchRevision
22
 
 
23
 
import os
 
23
from bzrlib.errors import (
 
24
    NoSuchRevision,
 
25
    )
24
26
 
25
27
 
26
28
def check_pysqlite_version(sqlite3):
46
48
    raise bzrlib.errors.BzrError("missing sqlite library")
47
49
 
48
50
 
 
51
_mapdbs = threading.local()
 
52
def mapdbs():
 
53
    """Get a cache for this thread's db connections."""
 
54
    try:
 
55
        return _mapdbs.cache
 
56
    except AttributeError:
 
57
        _mapdbs.cache = {}
 
58
        return _mapdbs.cache
 
59
 
 
60
 
49
61
class GitShaMap(object):
50
 
 
51
 
    def __init__(self, transport):
52
 
        self.transport = transport
53
 
        self.db = sqlite3.connect(
54
 
            os.path.join(self.transport.local_abspath("."), "git.db"))
 
62
    """Git<->Bzr revision id mapping database."""
 
63
 
 
64
    def add_entry(self, sha, type, type_data):
 
65
        """Add a new entry to the database.
 
66
        """
 
67
        raise NotImplementedError(self.add_entry)
 
68
 
 
69
    def add_entries(self, entries):
 
70
        """Add multiple new entries to the database.
 
71
        """
 
72
        for e in entries:
 
73
            self.add_entry(*e)
 
74
 
 
75
    def lookup_tree(self, fileid, revid):
 
76
        """Lookup the SHA of a git tree."""
 
77
        raise NotImplementedError(self.lookup_tree)
 
78
 
 
79
    def lookup_blob(self, fileid, revid):
 
80
        raise NotImplementedError(self.lookup_blob)
 
81
 
 
82
    def lookup_git_sha(self, sha):
 
83
        """Lookup a Git sha in the database.
 
84
 
 
85
        :param sha: Git object sha
 
86
        :return: (type, type_data) with type_data:
 
87
            revision: revid, tree sha
 
88
        """
 
89
        raise NotImplementedError(self.lookup_git_sha)
 
90
 
 
91
    def revids(self):
 
92
        """List the revision ids known."""
 
93
        raise NotImplementedError(self.revids)
 
94
 
 
95
    def sha1s(Self):
 
96
        """List the SHA1s."""
 
97
        raise NotImplementedError(self.sha1s)
 
98
 
 
99
    def commit(self):
 
100
        """Commit any pending changes."""
 
101
 
 
102
 
 
103
class DictGitShaMap(GitShaMap):
 
104
 
 
105
    def __init__(self):
 
106
        self.dict = {}
 
107
 
 
108
    def add_entry(self, sha, type, type_data):
 
109
        self.dict[sha] = (type, type_data)
 
110
 
 
111
    def lookup_git_sha(self, sha):
 
112
        return self.dict[sha]
 
113
 
 
114
    def lookup_tree(self, fileid, revid):
 
115
        for k, v in self.dict.iteritems():
 
116
            if v == ("tree", (fileid, revid)):
 
117
                return k
 
118
        raise KeyError((fileid, revid))
 
119
 
 
120
    def lookup_blob(self, fileid, revid):
 
121
        for k, v in self.dict.iteritems():
 
122
            if v == ("blob", (fileid, revid)):
 
123
                return k
 
124
        raise KeyError((fileid, revid))
 
125
 
 
126
    def revids(self):
 
127
        for key, (type, type_data) in self.dict.iteritems():
 
128
            if type == "commit":
 
129
                yield type_data[0]
 
130
 
 
131
    def sha1s(self):
 
132
        return self.dict.iterkeys()
 
133
 
 
134
 
 
135
class SqliteGitShaMap(GitShaMap):
 
136
 
 
137
    def __init__(self, path=None):
 
138
        self.path = path
 
139
        if path is None:
 
140
            self.db = sqlite3.connect(":memory:")
 
141
        else:
 
142
            if not mapdbs().has_key(path):
 
143
                mapdbs()[path] = sqlite3.connect(path)
 
144
            self.db = mapdbs()[path]    
55
145
        self.db.executescript("""
56
146
        create table if not exists commits(sha1 text, revid text, tree_sha text);
57
147
        create index if not exists commit_sha1 on commits(sha1);
 
148
        create unique index if not exists commit_revid on commits(revid);
58
149
        create table if not exists blobs(sha1 text, fileid text, revid text);
59
150
        create index if not exists blobs_sha1 on blobs(sha1);
 
151
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
60
152
        create table if not exists trees(sha1 text, fileid text, revid text);
61
153
        create index if not exists trees_sha1 on trees(sha1);
 
154
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
62
155
""")
63
156
 
 
157
    @classmethod
 
158
    def from_repository(cls, repository):
 
159
        return cls(os.path.join(repository._transport.local_abspath("."), "git.db"))
 
160
 
64
161
    def _parent_lookup(self, revid):
65
 
        return self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()[0].encode("utf-8")
 
162
        row = self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()
 
163
        if row is not None:
 
164
            return row[0].encode("utf-8")
 
165
        raise KeyError
 
166
 
 
167
    def commit(self):
 
168
        self.db.commit()
 
169
 
 
170
    def add_entries(self, entries):
 
171
        trees = []
 
172
        blobs = []
 
173
        for sha, type, type_data in entries:
 
174
            assert isinstance(type_data[0], str)
 
175
            assert isinstance(type_data[1], str)
 
176
            entry = (sha.decode("utf-8"), type_data[0].decode("utf-8"), 
 
177
                     type_data[1].decode("utf-8"))
 
178
            if type == "tree":
 
179
                trees.append(entry)
 
180
            elif type == "blob":
 
181
                blobs.append(entry)
 
182
            else:
 
183
                raise AssertionError
 
184
        if trees:
 
185
            self.db.executemany("replace into trees (sha1, fileid, revid) values (?, ?, ?)", trees)
 
186
        if blobs:
 
187
            self.db.executemany("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", blobs)
 
188
 
66
189
 
67
190
    def add_entry(self, sha, type, type_data):
68
191
        """Add a new entry to the database.
71
194
        assert isinstance(sha, str), "type was %r" % sha
72
195
        if type == "commit":
73
196
            self.db.execute("replace into commits (sha1, revid, tree_sha) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
74
 
        elif type == "blob":
75
 
            self.db.execute("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
76
 
        elif type == "tree":
77
 
            self.db.execute("replace into trees (sha1, fileid, revid) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
 
197
        elif type in ("blob", "tree"):
 
198
            self.db.execute("replace into %ss (sha1, fileid, revid) values (?, ?, ?)" % type, (sha, type_data[0], type_data[1]))
78
199
        else:
79
200
            raise AssertionError("Unknown type %s" % type)
80
201
 
 
202
    def lookup_tree(self, fileid, revid):
 
203
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid,revid)).fetchone()
 
204
        if row is None:
 
205
            raise KeyError((fileid, revid))
 
206
        return row[0].encode("utf-8")
 
207
 
 
208
    def lookup_blob(self, fileid, revid):
 
209
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
 
210
        if row is None:
 
211
            raise KeyError((fileid, revid))
 
212
        return row[0].encode("utf-8")
 
213
 
81
214
    def lookup_git_sha(self, sha):
82
215
        """Lookup a Git sha in the database.
83
216
 
85
218
        :return: (type, type_data) with type_data:
86
219
            revision: revid, tree sha
87
220
        """
 
221
        def format(type, row):
 
222
            return (type, (row[0].encode("utf-8"), row[1].encode("utf-8")))
88
223
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
89
224
        if row is not None:
90
 
            return ("commit", row)
 
225
            return format("commit", row)
91
226
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
92
227
        if row is not None:
93
 
            return ("blob", row)
 
228
            return format("blob", row)
94
229
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
95
230
        if row is not None:
96
 
            return ("tree", row)
 
231
            return format("tree", row)
97
232
        raise KeyError(sha)
98
233
 
99
234
    def revids(self):
 
235
        """List the revision ids known."""
100
236
        for row in self.db.execute("select revid from commits").fetchall():
101
 
            yield row[0]
 
237
            yield row[0].encode("utf-8")
 
238
 
 
239
    def sha1s(self):
 
240
        """List the SHA1s."""
 
241
        for table in ("blobs", "commits", "trees"):
 
242
            for row in self.db.execute("select sha1 from %s" % table).fetchall():
 
243
                yield row[0].encode("utf-8")