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