/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

Actually put contents in the working tree inventory.

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 commit(self):
 
96
        """Commit any pending changes."""
 
97
 
 
98
 
 
99
class DictGitShaMap(GitShaMap):
 
100
 
 
101
    def __init__(self):
 
102
        self.dict = {}
 
103
 
 
104
    def add_entry(self, sha, type, type_data):
 
105
        self.dict[sha] = (type, type_data)
 
106
 
 
107
    def lookup_git_sha(self, sha):
 
108
        return self.dict[sha]
 
109
 
 
110
    def lookup_tree(self, fileid, revid):
 
111
        for k, v in self.dict.iteritems():
 
112
            if v == ("tree", (fileid, revid)):
 
113
                return k
 
114
        raise KeyError((fileid, revid))
 
115
 
 
116
    def lookup_blob(self, fileid, revid):
 
117
        for k, v in self.dict.iteritems():
 
118
            if v == ("blob", (fileid, revid)):
 
119
                return k
 
120
        raise KeyError((fileid, revid))
 
121
 
 
122
    def revids(self):
 
123
        for key, (type, type_data) in self.dict.iteritems():
 
124
            if type == "commit":
 
125
                yield type_data[0]
 
126
 
 
127
 
 
128
class SqliteGitShaMap(GitShaMap):
 
129
 
 
130
    def __init__(self, path=None):
 
131
        self.path = path
 
132
        if path is None:
 
133
            self.db = sqlite3.connect(":memory:")
 
134
        else:
 
135
            if not mapdbs().has_key(path):
 
136
                mapdbs()[path] = sqlite3.connect(path)
 
137
            self.db = mapdbs()[path]    
55
138
        self.db.executescript("""
56
139
        create table if not exists commits(sha1 text, revid text, tree_sha text);
57
140
        create index if not exists commit_sha1 on commits(sha1);
 
141
        create unique index if not exists commit_revid on commits(revid);
58
142
        create table if not exists blobs(sha1 text, fileid text, revid text);
59
143
        create index if not exists blobs_sha1 on blobs(sha1);
 
144
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
60
145
        create table if not exists trees(sha1 text, fileid text, revid text);
61
146
        create index if not exists trees_sha1 on trees(sha1);
 
147
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
62
148
""")
63
149
 
 
150
    @classmethod
 
151
    def from_repository(cls, repository):
 
152
        return cls(os.path.join(repository._transport.local_abspath("."), "git.db"))
 
153
 
64
154
    def _parent_lookup(self, revid):
65
 
        return self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()[0].encode("utf-8")
 
155
        row = self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()
 
156
        if row is not None:
 
157
            return row[0].encode("utf-8")
 
158
        raise KeyError
 
159
 
 
160
    def commit(self):
 
161
        self.db.commit()
 
162
 
 
163
    def add_entries(self, entries):
 
164
        trees = []
 
165
        blobs = []
 
166
        for sha, type, type_data in entries:
 
167
            if type == "tree":
 
168
                trees.append((sha, type_data[0], type_data[1]))
 
169
            elif type == "blob":
 
170
                blobs.append((sha, type_data[0], type_data[1]))
 
171
            else:
 
172
                raise AssertionError
 
173
        if trees:
 
174
            self.db.executemany("replace into trees (sha1, fileid, revid) values (?, ?, ?)", trees)
 
175
        if blobs:
 
176
            self.db.executemany("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", blobs)
 
177
 
66
178
 
67
179
    def add_entry(self, sha, type, type_data):
68
180
        """Add a new entry to the database.
71
183
        assert isinstance(sha, str), "type was %r" % sha
72
184
        if type == "commit":
73
185
            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]))
 
186
        elif type in ("blob", "tree"):
 
187
            self.db.execute("replace into %ss (sha1, fileid, revid) values (?, ?, ?)" % type, (sha, type_data[0], type_data[1]))
78
188
        else:
79
189
            raise AssertionError("Unknown type %s" % type)
80
190
 
 
191
    def lookup_tree(self, fileid, revid):
 
192
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid,revid)).fetchone()
 
193
        if row is None:
 
194
            raise KeyError((fileid, revid))
 
195
        return row[0].encode("utf-8")
 
196
 
 
197
    def lookup_blob(self, fileid, revid):
 
198
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
 
199
        if row is None:
 
200
            raise KeyError((fileid, revid))
 
201
        return row[0].encode("utf-8")
 
202
 
81
203
    def lookup_git_sha(self, sha):
82
204
        """Lookup a Git sha in the database.
83
205
 
85
207
        :return: (type, type_data) with type_data:
86
208
            revision: revid, tree sha
87
209
        """
 
210
        def format(type, row):
 
211
            return (type, (row[0].encode("utf-8"), row[1].encode("utf-8")))
88
212
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
89
213
        if row is not None:
90
 
            return ("commit", row)
 
214
            return format("commit", row)
91
215
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
92
216
        if row is not None:
93
 
            return ("blob", row)
 
217
            return format("blob", row)
94
218
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
95
219
        if row is not None:
96
 
            return ("tree", row)
 
220
            return format("tree", row)
97
221
        raise KeyError(sha)
98
222
 
99
223
    def revids(self):
 
224
        """List the revision ids known."""
100
225
        for row in self.db.execute("select revid from commits").fetchall():
101
 
            yield row[0]
 
226
            yield row[0].encode("utf-8")