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