/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
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
0.200.292 by Jelmer Vernooij
Fix formatting.
19
import os
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
20
import threading
0.200.292 by Jelmer Vernooij
Fix formatting.
21
0.200.228 by Jelmer Vernooij
Split out map.
22
import bzrlib
0.200.292 by Jelmer Vernooij
Fix formatting.
23
from bzrlib.errors import (
24
    NoSuchRevision,
25
    )
0.200.230 by Jelmer Vernooij
Implement sha cache.
26
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
27
0.200.228 by Jelmer Vernooij
Split out map.
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
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
50
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
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
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
61
class GitShaMap(object):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
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
0.200.361 by Jelmer Vernooij
Fix existing object lookup issues when pulling from remote branches.
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
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
75
    def lookup_tree(self, fileid, revid):
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
76
        """Lookup the SHA of a git tree."""
77
        raise NotImplementedError(self.lookup_tree)
78
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
79
    def lookup_blob(self, fileid, revid):
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
80
        """Lookup a blob by the fileid it has in a bzr revision."""
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
81
        raise NotImplementedError(self.lookup_blob)
82
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
83
    def lookup_git_sha(self, sha):
84
        """Lookup a Git sha in the database.
85
86
        :param sha: Git object sha
87
        :return: (type, type_data) with type_data:
88
            revision: revid, tree sha
89
        """
90
        raise NotImplementedError(self.lookup_git_sha)
91
92
    def revids(self):
93
        """List the revision ids known."""
94
        raise NotImplementedError(self.revids)
95
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
96
    def sha1s(Self):
97
        """List the SHA1s."""
98
        raise NotImplementedError(self.sha1s)
99
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
100
    def commit(self):
101
        """Commit any pending changes."""
102
103
104
class DictGitShaMap(GitShaMap):
105
106
    def __init__(self):
107
        self.dict = {}
108
109
    def add_entry(self, sha, type, type_data):
110
        self.dict[sha] = (type, type_data)
111
112
    def lookup_git_sha(self, sha):
113
        return self.dict[sha]
114
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
115
    def lookup_tree(self, fileid, revid):
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
116
        for k, v in self.dict.iteritems():
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
117
            if v == ("tree", (fileid, revid)):
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
118
                return k
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
119
        raise KeyError((fileid, revid))
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
120
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
121
    def lookup_blob(self, fileid, revid):
122
        for k, v in self.dict.iteritems():
123
            if v == ("blob", (fileid, revid)):
124
                return k
125
        raise KeyError((fileid, revid))
126
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
127
    def revids(self):
128
        for key, (type, type_data) in self.dict.iteritems():
129
            if type == "commit":
0.200.262 by Jelmer Vernooij
Add tests for GitShaMap.
130
                yield type_data[0]
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
131
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
132
    def sha1s(self):
133
        return self.dict.iterkeys()
134
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
135
136
class SqliteGitShaMap(GitShaMap):
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
137
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
138
    def __init__(self, path=None):
139
        self.path = path
140
        if path is None:
0.200.262 by Jelmer Vernooij
Add tests for GitShaMap.
141
            self.db = sqlite3.connect(":memory:")
142
        else:
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
143
            if not mapdbs().has_key(path):
144
                mapdbs()[path] = sqlite3.connect(path)
145
            self.db = mapdbs()[path]    
0.200.230 by Jelmer Vernooij
Implement sha cache.
146
        self.db.executescript("""
147
        create table if not exists commits(sha1 text, revid text, tree_sha text);
148
        create index if not exists commit_sha1 on commits(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
149
        create unique index if not exists commit_revid on commits(revid);
0.200.230 by Jelmer Vernooij
Implement sha cache.
150
        create table if not exists blobs(sha1 text, fileid text, revid text);
151
        create index if not exists blobs_sha1 on blobs(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
152
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
153
        create table if not exists trees(sha1 text, fileid text, revid text);
0.200.230 by Jelmer Vernooij
Implement sha cache.
154
        create index if not exists trees_sha1 on trees(sha1);
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
155
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
0.200.230 by Jelmer Vernooij
Implement sha cache.
156
""")
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
157
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
158
    @classmethod
159
    def from_repository(cls, repository):
160
        return cls(os.path.join(repository._transport.local_abspath("."), "git.db"))
161
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
162
    def lookup_commit(self, revid):
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
163
        row = self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()
164
        if row is not None:
165
            return row[0].encode("utf-8")
166
        raise KeyError
0.200.231 by Jelmer Vernooij
Partially fix pull.
167
0.200.232 by Jelmer Vernooij
Fix pull from remote branches.
168
    def commit(self):
169
        self.db.commit()
170
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
171
    def add_entries(self, entries):
172
        trees = []
173
        blobs = []
174
        for sha, type, type_data in entries:
0.200.410 by Jelmer Vernooij
Fix compatibility with python 2.4.
175
            assert isinstance(type_data[0], str)
176
            assert isinstance(type_data[1], str)
177
            entry = (sha.decode("utf-8"), type_data[0].decode("utf-8"), 
178
                     type_data[1].decode("utf-8"))
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
179
            if type == "tree":
0.200.410 by Jelmer Vernooij
Fix compatibility with python 2.4.
180
                trees.append(entry)
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
181
            elif type == "blob":
0.200.410 by Jelmer Vernooij
Fix compatibility with python 2.4.
182
                blobs.append(entry)
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
183
            else:
184
                raise AssertionError
185
        if trees:
186
            self.db.executemany("replace into trees (sha1, fileid, revid) values (?, ?, ?)", trees)
187
        if blobs:
188
            self.db.executemany("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", blobs)
189
190
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
191
    def add_entry(self, sha, type, type_data):
192
        """Add a new entry to the database.
193
        """
0.200.231 by Jelmer Vernooij
Partially fix pull.
194
        assert isinstance(type_data, tuple)
195
        assert isinstance(sha, str), "type was %r" % sha
0.200.230 by Jelmer Vernooij
Implement sha cache.
196
        if type == "commit":
197
            self.db.execute("replace into commits (sha1, revid, tree_sha) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
198
        elif type in ("blob", "tree"):
199
            self.db.execute("replace into %ss (sha1, fileid, revid) values (?, ?, ?)" % type, (sha, type_data[0], type_data[1]))
0.200.230 by Jelmer Vernooij
Implement sha cache.
200
        else:
201
            raise AssertionError("Unknown type %s" % type)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
202
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
203
    def lookup_tree(self, fileid, revid):
204
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid,revid)).fetchone()
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
205
        if row is None:
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
206
            raise KeyError((fileid, revid))
0.200.358 by Jelmer Vernooij
Use plain strings for sha1 strings, not unicode.
207
        return row[0].encode("utf-8")
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
208
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
209
    def lookup_blob(self, fileid, revid):
0.230.3 by Jelmer Vernooij
Fix blob lookup.
210
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
211
        if row is None:
212
            raise KeyError((fileid, revid))
0.200.358 by Jelmer Vernooij
Use plain strings for sha1 strings, not unicode.
213
        return row[0].encode("utf-8")
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
214
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
215
    def lookup_git_sha(self, sha):
216
        """Lookup a Git sha in the database.
217
218
        :param sha: Git object sha
219
        :return: (type, type_data) with type_data:
220
            revision: revid, tree sha
221
        """
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
222
        def format(type, row):
223
            return (type, (row[0].encode("utf-8"), row[1].encode("utf-8")))
0.200.230 by Jelmer Vernooij
Implement sha cache.
224
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
225
        if row is not None:
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
226
            return format("commit", row)
0.200.230 by Jelmer Vernooij
Implement sha cache.
227
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
228
        if row is not None:
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
229
            return format("blob", row)
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
230
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
0.200.230 by Jelmer Vernooij
Implement sha cache.
231
        if row is not None:
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
232
            return format("tree", row)
0.200.230 by Jelmer Vernooij
Implement sha cache.
233
        raise KeyError(sha)
234
235
    def revids(self):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
236
        """List the revision ids known."""
0.200.230 by Jelmer Vernooij
Implement sha cache.
237
        for row in self.db.execute("select revid from commits").fetchall():
0.200.347 by Jelmer Vernooij
Simplify converter a bit.
238
            yield row[0].encode("utf-8")
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
239
240
    def sha1s(self):
241
        """List the SHA1s."""
242
        for table in ("blobs", "commits", "trees"):
243
            for row in self.db.execute("select sha1 from %s" % table).fetchall():
244
                yield row[0].encode("utf-8")
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
245
246
0.200.479 by Jelmer Vernooij
Version tdb sha map.
247
TDB_MAP_VERSION = 1
248
249
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
250
class TdbGitShaMap(GitShaMap):
251
    """SHA Map that uses a TDB database.
252
253
    Entries:
254
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
255
    "git <sha1>" -> "<type> <type-data1> <type-data2>"
256
    "commit revid" -> "<sha1> <tree-id>"
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
257
    "tree fileid revid" -> "<sha1>"
258
    "blob fileid revid" -> "<sha1>"
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
259
    """
260
261
    def __init__(self, path=None):
262
        import tdb
263
        self.path = path
264
        if path is None:
265
            self.db = {}
266
        else:
267
            if not mapdbs().has_key(path):
268
                mapdbs()[path] = tdb.open(path, 0, tdb.DEFAULT, 
269
                                          os.O_RDWR|os.O_CREAT)
270
            self.db = mapdbs()[path]    
0.200.479 by Jelmer Vernooij
Version tdb sha map.
271
        if not "version" in self.db:
272
            self.db["version"] = str(TDB_MAP_VERSION)
273
        else:
274
            assert int(self.db["version"]) == TDB_MAP_VERSION
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
275
276
    @classmethod
277
    def from_repository(cls, repository):
0.200.482 by Jelmer Vernooij
Use tdb file in the config dir if it's remote.
278
        try:
0.200.500 by Jelmer Vernooij
Cope with repositories that don't have a _transport attribute.
279
            transport = getattr(repository, "_transport", None)
280
            if transport is not None:
281
                return cls(os.path.join(transport.local_abspath("."), "git.tdb"))
0.200.482 by Jelmer Vernooij
Use tdb file in the config dir if it's remote.
282
        except bzrlib.errors.NotLocalUrl:
0.200.500 by Jelmer Vernooij
Cope with repositories that don't have a _transport attribute.
283
            pass
284
        from bzrlib.config import config_dir
285
        return cls(os.path.join(config_dir(), "remote-git.tdb"))
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
286
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
287
    def lookup_commit(self, revid):
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
288
        return self.db["commit %s" % revid].split(" ")[0]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
289
290
    def commit(self):
291
        pass
292
293
    def add_entry(self, sha, type, type_data):
294
        """Add a new entry to the database.
295
        """
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
296
        self.db["git %s" % sha] = "%s %s %s" % (type, type_data[0], type_data[1])
297
        if type == "commit":
298
            self.db["commit %s" % type_data[0]] = "%s %s" % (sha, type_data[1])
299
        else:
300
            self.db["%s %s %s" % (type, type_data[0], type_data[1])] = sha
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
301
302
    def lookup_tree(self, fileid, revid):
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
303
        return self.db["tree %s %s" % (fileid, revid)]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
304
305
    def lookup_blob(self, fileid, revid):
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
306
        return self.db["blob %s %s" % (fileid, revid)]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
307
308
    def lookup_git_sha(self, sha):
309
        """Lookup a Git sha in the database.
310
311
        :param sha: Git object sha
312
        :return: (type, type_data) with type_data:
313
            revision: revid, tree sha
314
        """
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
315
        data = self.db["git %s" % sha].split(" ")
316
        return (data[0], (data[1], data[2]))
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
317
318
    def revids(self):
319
        """List the revision ids known."""
320
        for key in self.db.iterkeys():
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
321
            if key.startswith("commit "):
322
                yield key.split(" ")[1]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
323
324
    def sha1s(self):
325
        """List the SHA1s."""
326
        for key in self.db.iterkeys():
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
327
            if key.startswith("git "):
328
                yield key.split(" ")[1]