/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

Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.

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
 
19
21
import bzrlib
20
 
 
21
 
from bzrlib.errors import NoSuchRevision
22
 
 
23
 
import os
 
22
from bzrlib.errors import (
 
23
    NoSuchRevision,
 
24
    )
24
25
 
25
26
 
26
27
def check_pysqlite_version(sqlite3):
47
48
 
48
49
 
49
50
class GitShaMap(object):
50
 
 
51
 
    def __init__(self, transport):
 
51
    """Git<->Bzr revision id mapping database."""
 
52
 
 
53
    def add_entry(self, sha, type, type_data):
 
54
        """Add a new entry to the database.
 
55
        """
 
56
        raise NotImplementedError(self.add_entry)
 
57
 
 
58
    def add_entries(self, entries):
 
59
        """Add multiple new entries to the database.
 
60
        """
 
61
        for e in entries:
 
62
            self.add_entry(*e)
 
63
 
 
64
    def lookup_tree(self, fileid, revid):
 
65
        """Lookup the SHA of a git tree."""
 
66
        raise NotImplementedError(self.lookup_tree)
 
67
 
 
68
    def lookup_blob(self, fileid, revid):
 
69
        raise NotImplementedError(self.lookup_blob)
 
70
 
 
71
    def lookup_git_sha(self, sha):
 
72
        """Lookup a Git sha in the database.
 
73
 
 
74
        :param sha: Git object sha
 
75
        :return: (type, type_data) with type_data:
 
76
            revision: revid, tree sha
 
77
        """
 
78
        raise NotImplementedError(self.lookup_git_sha)
 
79
 
 
80
    def revids(self):
 
81
        """List the revision ids known."""
 
82
        raise NotImplementedError(self.revids)
 
83
 
 
84
    def commit(self):
 
85
        """Commit any pending changes."""
 
86
 
 
87
 
 
88
class DictGitShaMap(GitShaMap):
 
89
 
 
90
    def __init__(self):
 
91
        self.dict = {}
 
92
 
 
93
    def add_entry(self, sha, type, type_data):
 
94
        self.dict[sha] = (type, type_data)
 
95
 
 
96
    def lookup_git_sha(self, sha):
 
97
        return self.dict[sha]
 
98
 
 
99
    def lookup_tree(self, fileid, revid):
 
100
        for k, v in self.dict.iteritems():
 
101
            if v == ("tree", (fileid, revid)):
 
102
                return k
 
103
        raise KeyError((fileid, revid))
 
104
 
 
105
    def lookup_blob(self, fileid, revid):
 
106
        for k, v in self.dict.iteritems():
 
107
            if v == ("blob", (fileid, revid)):
 
108
                return k
 
109
        raise KeyError((fileid, revid))
 
110
 
 
111
    def revids(self):
 
112
        for key, (type, type_data) in self.dict.iteritems():
 
113
            if type == "commit":
 
114
                yield type_data[0]
 
115
 
 
116
 
 
117
class SqliteGitShaMap(GitShaMap):
 
118
 
 
119
    def __init__(self, transport=None):
52
120
        self.transport = transport
53
 
        self.db = sqlite3.connect(
54
 
            os.path.join(self.transport.local_abspath("."), "git.db"))
 
121
        if transport is None:
 
122
            self.db = sqlite3.connect(":memory:")
 
123
        else:
 
124
            self.db = sqlite3.connect(
 
125
                os.path.join(self.transport.local_abspath("."), "git.db"))
55
126
        self.db.executescript("""
56
127
        create table if not exists commits(sha1 text, revid text, tree_sha text);
57
128
        create index if not exists commit_sha1 on commits(sha1);
 
129
        create unique index if not exists commit_revid on commits(revid);
58
130
        create table if not exists blobs(sha1 text, fileid text, revid text);
59
131
        create index if not exists blobs_sha1 on blobs(sha1);
 
132
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
60
133
        create table if not exists trees(sha1 text, fileid text, revid text);
61
134
        create index if not exists trees_sha1 on trees(sha1);
 
135
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
62
136
""")
63
137
 
64
138
    def _parent_lookup(self, revid):
65
 
        return self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()[0].encode("utf-8")
 
139
        row = self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()
 
140
        if row is not None:
 
141
            return row[0].encode("utf-8")
 
142
        raise KeyError
 
143
 
 
144
    def commit(self):
 
145
        self.db.commit()
66
146
 
67
147
    def add_entry(self, sha, type, type_data):
68
148
        """Add a new entry to the database.
71
151
        assert isinstance(sha, str), "type was %r" % sha
72
152
        if type == "commit":
73
153
            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]))
 
154
        elif type in ("blob", "tree"):
 
155
            self.db.execute("replace into %ss (sha1, fileid, revid) values (?, ?, ?)" % type, (sha, type_data[0], type_data[1]))
78
156
        else:
79
157
            raise AssertionError("Unknown type %s" % type)
80
158
 
 
159
    def lookup_tree(self, fileid, revid):
 
160
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid,revid)).fetchone()
 
161
        if row is None:
 
162
            raise KeyError((fileid, revid))
 
163
        return row[0].encode("utf-8")
 
164
 
 
165
    def lookup_blob(self, fileid, revid):
 
166
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
 
167
        if row is None:
 
168
            raise KeyError((fileid, revid))
 
169
        return row[0].encode("utf-8")
 
170
 
81
171
    def lookup_git_sha(self, sha):
82
172
        """Lookup a Git sha in the database.
83
173
 
85
175
        :return: (type, type_data) with type_data:
86
176
            revision: revid, tree sha
87
177
        """
 
178
        def format(type, row):
 
179
            return (type, (row[0].encode("utf-8"), row[1].encode("utf-8")))
88
180
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
89
181
        if row is not None:
90
 
            return ("commit", row)
 
182
            return format("commit", row)
91
183
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
92
184
        if row is not None:
93
 
            return ("blob", row)
 
185
            return format("blob", row)
94
186
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
95
187
        if row is not None:
96
 
            return ("tree", row)
 
188
            return format("tree", row)
97
189
        raise KeyError(sha)
98
190
 
99
191
    def revids(self):
 
192
        """List the revision ids known."""
100
193
        for row in self.db.execute("select revid from commits").fetchall():
101
 
            yield row[0]
 
194
            yield row[0].encode("utf-8")