/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

  • Committer: Andrew Bennetts
  • Date: 2009-10-21 11:13:40 UTC
  • mto: This revision was merged to the branch mainline in revision 4762.
  • Revision ID: andrew.bennetts@canonical.com-20091021111340-w7x4d5yf83qwjncc
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
"""Map from Git sha's to Bazaar objects."""
18
 
 
19
 
import os
20
 
import threading
21
 
 
22
 
import bzrlib
23
 
from bzrlib.errors import (
24
 
    NoSuchRevision,
25
 
    )
26
 
 
27
 
 
28
 
def check_pysqlite_version(sqlite3):
29
 
    """Check that sqlite library is compatible.
30
 
 
31
 
    """
32
 
    if (sqlite3.sqlite_version_info[0] < 3 or 
33
 
            (sqlite3.sqlite_version_info[0] == 3 and 
34
 
             sqlite3.sqlite_version_info[1] < 3)):
35
 
        warning('Needs at least sqlite 3.3.x')
36
 
        raise bzrlib.errors.BzrError("incompatible sqlite library")
37
 
 
38
 
try:
39
 
    try:
40
 
        import sqlite3
41
 
        check_pysqlite_version(sqlite3)
42
 
    except (ImportError, bzrlib.errors.BzrError), e: 
43
 
        from pysqlite2 import dbapi2 as sqlite3
44
 
        check_pysqlite_version(sqlite3)
45
 
except:
46
 
    warning('Needs at least Python2.5 or Python2.4 with the pysqlite2 '
47
 
            'module')
48
 
    raise bzrlib.errors.BzrError("missing sqlite library")
49
 
 
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
 
 
61
 
class GitShaMap(object):
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]    
138
 
        self.db.executescript("""
139
 
        create table if not exists commits(sha1 text, revid text, tree_sha text);
140
 
        create index if not exists commit_sha1 on commits(sha1);
141
 
        create unique index if not exists commit_revid on commits(revid);
142
 
        create table if not exists blobs(sha1 text, fileid text, revid text);
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);
145
 
        create table if not exists trees(sha1 text, fileid text, revid text);
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);
148
 
""")
149
 
 
150
 
    @classmethod
151
 
    def from_repository(cls, repository):
152
 
        return cls(os.path.join(repository._transport.local_abspath("."), "git.db"))
153
 
 
154
 
    def _parent_lookup(self, revid):
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
 
            assert isinstance(type_data[0], str)
168
 
            assert isinstance(type_data[1], str)
169
 
            entry = (sha.decode("utf-8"), type_data[0].decode("utf-8"), 
170
 
                     type_data[1].decode("utf-8"))
171
 
            if type == "tree":
172
 
                trees.append(entry)
173
 
            elif type == "blob":
174
 
                blobs.append(entry)
175
 
            else:
176
 
                raise AssertionError
177
 
        if trees:
178
 
            self.db.executemany("replace into trees (sha1, fileid, revid) values (?, ?, ?)", trees)
179
 
        if blobs:
180
 
            self.db.executemany("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", blobs)
181
 
 
182
 
 
183
 
    def add_entry(self, sha, type, type_data):
184
 
        """Add a new entry to the database.
185
 
        """
186
 
        assert isinstance(type_data, tuple)
187
 
        assert isinstance(sha, str), "type was %r" % sha
188
 
        if type == "commit":
189
 
            self.db.execute("replace into commits (sha1, revid, tree_sha) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
190
 
        elif type in ("blob", "tree"):
191
 
            self.db.execute("replace into %ss (sha1, fileid, revid) values (?, ?, ?)" % type, (sha, type_data[0], type_data[1]))
192
 
        else:
193
 
            raise AssertionError("Unknown type %s" % type)
194
 
 
195
 
    def lookup_tree(self, fileid, revid):
196
 
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid,revid)).fetchone()
197
 
        if row is None:
198
 
            raise KeyError((fileid, revid))
199
 
        return row[0].encode("utf-8")
200
 
 
201
 
    def lookup_blob(self, fileid, revid):
202
 
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
203
 
        if row is None:
204
 
            raise KeyError((fileid, revid))
205
 
        return row[0].encode("utf-8")
206
 
 
207
 
    def lookup_git_sha(self, sha):
208
 
        """Lookup a Git sha in the database.
209
 
 
210
 
        :param sha: Git object sha
211
 
        :return: (type, type_data) with type_data:
212
 
            revision: revid, tree sha
213
 
        """
214
 
        def format(type, row):
215
 
            return (type, (row[0].encode("utf-8"), row[1].encode("utf-8")))
216
 
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
217
 
        if row is not None:
218
 
            return format("commit", row)
219
 
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
220
 
        if row is not None:
221
 
            return format("blob", row)
222
 
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
223
 
        if row is not None:
224
 
            return format("tree", row)
225
 
        raise KeyError(sha)
226
 
 
227
 
    def revids(self):
228
 
        """List the revision ids known."""
229
 
        for row in self.db.execute("select revid from commits").fetchall():
230
 
            yield row[0].encode("utf-8")