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