/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 (
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
28
    registry,
0.200.528 by Jelmer Vernooij
Fix import.
29
    trace,
30
    )
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
31
from bzrlib.transport import (
32
    get_transport,
33
    )
0.200.230 by Jelmer Vernooij
Implement sha cache.
34
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
35
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
36
def get_cache_dir():
37
    try:
38
        from xdg.BaseDirectory import xdg_cache_home
39
    except ImportError:
0.200.558 by Jelmer Vernooij
Create cache dir if it doesn't exist yet.
40
        from bzrlib.config import config_dir
41
        ret = os.path.join(config_dir(), "git")
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
42
    else:
0.200.558 by Jelmer Vernooij
Create cache dir if it doesn't exist yet.
43
        ret = os.path.join(xdg_cache_home, "bazaar", "git")
44
    if not os.path.isdir(ret):
45
        os.makedirs(ret)
46
    return ret
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
47
48
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
49
def get_remote_cache_transport():
50
    return get_transport(get_cache_dir())
51
52
0.200.228 by Jelmer Vernooij
Split out map.
53
def check_pysqlite_version(sqlite3):
54
    """Check that sqlite library is compatible.
55
56
    """
0.200.675 by Jelmer Vernooij
Fix formatting.
57
    if (sqlite3.sqlite_version_info[0] < 3 or
58
            (sqlite3.sqlite_version_info[0] == 3 and
0.200.228 by Jelmer Vernooij
Split out map.
59
             sqlite3.sqlite_version_info[1] < 3)):
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
60
        trace.warning('Needs at least sqlite 3.3.x')
0.200.228 by Jelmer Vernooij
Split out map.
61
        raise bzrlib.errors.BzrError("incompatible sqlite library")
62
63
try:
64
    try:
65
        import sqlite3
66
        check_pysqlite_version(sqlite3)
0.200.675 by Jelmer Vernooij
Fix formatting.
67
    except (ImportError, bzrlib.errors.BzrError), e:
0.200.228 by Jelmer Vernooij
Split out map.
68
        from pysqlite2 import dbapi2 as sqlite3
69
        check_pysqlite_version(sqlite3)
70
except:
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
71
    trace.warning('Needs at least Python2.5 or Python2.4 with the pysqlite2 '
0.200.228 by Jelmer Vernooij
Split out map.
72
            'module')
73
    raise bzrlib.errors.BzrError("missing sqlite library")
74
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
75
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
76
_mapdbs = threading.local()
77
def mapdbs():
78
    """Get a cache for this thread's db connections."""
79
    try:
80
        return _mapdbs.cache
81
    except AttributeError:
82
        _mapdbs.cache = {}
83
        return _mapdbs.cache
84
85
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
86
class GitShaMap(object):
87
    """Git<->Bzr revision id mapping database."""
88
89
    def _add_entry(self, sha, type, type_data):
90
        """Add a new entry to the database.
91
        """
92
        raise NotImplementedError(self._add_entry)
93
94
    def add_entries(self, revid, parent_revids, commit_sha, root_tree_sha, 
95
                    entries):
96
        """Add multiple new entries to the database.
97
        """
98
        for (fileid, kind, hexsha, revision) in entries:
99
            self._add_entry(hexsha, kind, (fileid, revision))
100
        self._add_entry(commit_sha, "commit", (revid, root_tree_sha))
101
102
    def lookup_git_sha(self, sha):
103
        """Lookup a Git sha in the database.
104
        :param sha: Git object sha
105
        :return: (type, type_data) with type_data:
106
            revision: revid, tree sha
107
        """
108
        raise NotImplementedError(self.lookup_git_sha)
109
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
110
    def lookup_blob_id(self, file_id, revision):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
111
        """Retrieve a Git blob SHA by file id.
112
113
        :param file_id: File id of the file/symlink
0.200.806 by Jelmer Vernooij
Make revision_hint mandatory.
114
        :param revision: revision in which the file was last changed.
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
115
        """
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
116
        raise NotImplementedError(self.lookup_blob_id)
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
117
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
118
    def lookup_tree_id(self, file_id, revision):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
119
        """Retrieve a Git tree SHA by file id.
120
        """
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
121
        raise NotImplementedError(self.lookup_tree_id)
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
122
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
123
    def revids(self):
124
        """List the revision ids known."""
125
        raise NotImplementedError(self.revids)
126
0.200.677 by Jelmer Vernooij
Implement TdbCache.missing_revisions().
127
    def missing_revisions(self, revids):
128
        """Return set of all the revisions that are not present."""
129
        present_revids = set(self.revids())
130
        if not isinstance(revids, set):
131
            revids = set(revids)
132
        return revids - present_revids
133
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
134
    def sha1s(self):
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
135
        """List the SHA1s."""
136
        raise NotImplementedError(self.sha1s)
137
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
138
    def start_write_group(self):
139
        """Start writing changes."""
140
141
    def commit_write_group(self):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
142
        """Commit any pending changes."""
143
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
144
    def abort_write_group(self):
145
        """Abort any pending changes."""
146
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
147
0.200.845 by Jelmer Vernooij
Couple of minor fixes.
148
class ContentCache(object):
149
    """Object that can cache Git objects."""
150
151
    def __getitem__(self, sha):
152
        """Retrieve an item, by SHA."""
153
        raise NotImplementedError(self.__getitem__)
154
155
    def add(self, obj):
156
        """Add an object to the cache."""
157
        raise NotImplementedError(self.add)
158
159
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
160
class BzrGitCacheFormat(object):
161
162
    def get_format_string(self):
163
        raise NotImplementedError(self.get_format_string)
164
165
    def open(self, transport):
166
        raise NotImplementedError(self.open)
167
168
    def initialize(self, transport):
169
        transport.put_bytes('format', self.get_format_string())
170
171
    @classmethod
172
    def from_repository(self, repository):
173
        repo_transport = getattr(repository, "_transport", None)
174
        if repo_transport is not None:
175
            try:
176
                repo_transport.mkdir('git')
177
            except bzrlib.errors.FileExists:
178
                pass
179
            transport = repo_transport.clone('git')
180
        else:
181
            transport = get_remote_cache_transport()
182
        try:
183
            format_name = transport.get_bytes('format')
184
            format = formats.get(format_name)
185
        except bzrlib.errors.NoSuchFile:
186
            format = formats.get('default')
187
            format.initialize(transport)
188
        return format.open(transport)
189
190
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
191
class CacheUpdater(object):
192
193
    def __init__(self, cache, rev, content_cache_types):
194
        self.cache = cache
195
        self.content_cache_types = content_cache_types
196
        self.revid = rev.revision_id
197
        self.parent_revids = rev.parent_ids
198
        self._commit = None
199
        self._entries = []
200
201
    def add_object(self, obj, ie):
202
        if obj.type_name == "commit":
203
            self._commit = obj
204
            assert ie is None
205
        elif obj.type_name in ("blob", "tree"):
206
            if obj.type_name == "blob":
207
                revision = ie.revision
208
            else:
209
                revision = self.revid
210
            self._entries.append((ie.file_id, obj.type_name, obj.id, revision))
211
        else:
212
            raise AssertionError
213
        if (self.cache.content_cache and 
214
            obj.type_name in self.content_cache_types):
215
            self.cache.content_cache.add(obj)
216
217
    def finish(self):
218
        if self._commit is None:
219
            raise AssertionError("No commit object added")
220
        self.cache.idmap.add_entries(self.revid, self.parent_revids,
221
            self._commit.id, self._commit.tree, self._entries)
222
        return self._commit
223
224
225
class BzrGitCache(object):
226
    """Caching backend."""
227
228
    def __init__(self, idmap, content_cache):
229
        self.idmap = idmap
230
        self.content_cache = content_cache
231
232
    def get_updater(self, rev, content_cache_types):
233
        return CacheUpdater(self, rev, content_cache_types)
234
235
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
236
class DictGitShaMap(GitShaMap):
237
238
    def __init__(self):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
239
        self._by_sha = {}
240
        self._by_fileid = {}
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
241
0.200.760 by Jelmer Vernooij
make add_entry private.
242
    def _add_entry(self, sha, type, type_data):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
243
        self._by_sha[sha] = (type, type_data)
244
        if type in ("blob", "tree"):
245
            self._by_fileid.setdefault(type_data[1], {})[type_data[0]] = sha
246
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
247
    def lookup_blob_id(self, fileid, revision):
248
        return self._by_fileid[revision][fileid]
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
249
250
    def lookup_git_sha(self, sha):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
251
        return self._by_sha[sha]
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
252
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
253
    def lookup_tree_id(self, fileid, revision):
254
        return self._base._by_fileid[revision][fileid]
255
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
256
    def revids(self):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
257
        for key, (type, type_data) in self._by_sha.iteritems():
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
258
            if type == "commit":
0.200.262 by Jelmer Vernooij
Add tests for GitShaMap.
259
                yield type_data[0]
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
260
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
261
    def sha1s(self):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
262
        return self._by_sha.iterkeys()
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
263
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
264
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
265
class SqliteGitCacheFormat(BzrGitCacheFormat):
266
267
    def get_format_string(self):
268
        return 'bzr-git sha map version 1 using sqlite\n'
269
270
    def open(self, transport):
271
        try:
272
            basepath = transport.local_abspath(".")
273
        except bzrlib.errors.NotLocalUrl:
274
            basepath = get_cache_dir()
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
275
        return BzrGitCache(
276
            SqliteGitShaMap(os.path.join(get_cache_dir(), "idmap.db")),
277
            None)
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
278
279
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
280
class SqliteGitShaMap(GitShaMap):
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
281
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
282
    def __init__(self, path=None):
283
        self.path = path
284
        if path is None:
0.200.262 by Jelmer Vernooij
Add tests for GitShaMap.
285
            self.db = sqlite3.connect(":memory:")
286
        else:
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
287
            if not mapdbs().has_key(path):
288
                mapdbs()[path] = sqlite3.connect(path)
0.200.675 by Jelmer Vernooij
Fix formatting.
289
            self.db = mapdbs()[path]
0.200.688 by Jelmer Vernooij
Use str text factory rather than encoding/decoding each time.
290
        self.db.text_factory = str
0.200.230 by Jelmer Vernooij
Implement sha cache.
291
        self.db.executescript("""
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
292
        create table if not exists commits(
293
            sha1 text not null check(length(sha1) == 40),
294
            revid text not null,
295
            tree_sha text not null check(length(tree_sha) == 40)
296
        );
0.200.230 by Jelmer Vernooij
Implement sha cache.
297
        create index if not exists commit_sha1 on commits(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
298
        create unique index if not exists commit_revid on commits(revid);
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
299
        create table if not exists blobs(
300
            sha1 text not null check(length(sha1) == 40),
301
            fileid text not null,
302
            revid text not null
303
        );
0.200.230 by Jelmer Vernooij
Implement sha cache.
304
        create index if not exists blobs_sha1 on blobs(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
305
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
306
        create table if not exists trees(
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
307
            sha1 text unique not null check(length(sha1) == 40),
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
308
            fileid text not null,
309
            revid text not null
310
        );
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
311
        create unique index if not exists trees_sha1 on trees(sha1);
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
312
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
0.200.230 by Jelmer Vernooij
Implement sha cache.
313
""")
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
314
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
315
    def __repr__(self):
316
        return "%s(%r)" % (self.__class__.__name__, self.path)
317
    
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
318
    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.
319
        row = self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()
320
        if row is not None:
0.200.688 by Jelmer Vernooij
Use str text factory rather than encoding/decoding each time.
321
            return row[0]
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
322
        raise KeyError
0.200.231 by Jelmer Vernooij
Partially fix pull.
323
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
324
    def commit_write_group(self):
0.200.232 by Jelmer Vernooij
Fix pull from remote branches.
325
        self.db.commit()
326
0.200.756 by Jelmer Vernooij
Move more logic into add_entries.
327
    def add_entries(self, revid, parent_revids, commit_sha, root_tree_sha,
0.200.759 by Jelmer Vernooij
Prepare for using add_entries everywhere.
328
                    entries):
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
329
        trees = []
330
        blobs = []
0.200.759 by Jelmer Vernooij
Prepare for using add_entries everywhere.
331
        for (fileid, kind, hexsha, revision) in entries:
0.200.846 by Jelmer Vernooij
Remove pointless check.
332
            if kind == "tree":
0.200.790 by Jelmer Vernooij
Fix regression in SQLite sha map backend.
333
                trees.append((hexsha, fileid, revid))
0.200.759 by Jelmer Vernooij
Prepare for using add_entries everywhere.
334
            elif kind == "blob":
0.200.790 by Jelmer Vernooij
Fix regression in SQLite sha map backend.
335
                blobs.append((hexsha, fileid, revision))
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
336
            else:
337
                raise AssertionError
338
        if trees:
339
            self.db.executemany("replace into trees (sha1, fileid, revid) values (?, ?, ?)", trees)
340
        if blobs:
341
            self.db.executemany("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", blobs)
0.200.778 by Jelmer Vernooij
Use transactions in tdb.
342
        self._add_entry(commit_sha, "commit", (revid, root_tree_sha))
0.200.377 by Jelmer Vernooij
use executemany when inserting sha map entries.
343
0.200.760 by Jelmer Vernooij
make add_entry private.
344
    def _add_entry(self, sha, type, type_data):
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
345
        """Add a new entry to the database.
346
        """
0.200.231 by Jelmer Vernooij
Partially fix pull.
347
        assert isinstance(type_data, tuple)
0.200.705 by Jelmer Vernooij
Cope with imports.
348
        if sha is None:
349
            return
0.200.231 by Jelmer Vernooij
Partially fix pull.
350
        assert isinstance(sha, str), "type was %r" % sha
0.200.230 by Jelmer Vernooij
Implement sha cache.
351
        if type == "commit":
352
            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.
353
        elif type in ("blob", "tree"):
354
            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.
355
        else:
356
            raise AssertionError("Unknown type %s" % type)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
357
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
358
    def lookup_blob_id(self, fileid, revision):
359
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revision)).fetchone()
360
        if row is not None:
361
            return row[0]
362
        raise KeyError(fileid)
363
364
    def lookup_tree_id(self, fileid, revision):
365
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid, self.revid)).fetchone()
366
        if row is not None:
367
            return row[0]
368
        raise KeyError(fileid)
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
369
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
370
    def lookup_git_sha(self, sha):
371
        """Lookup a Git sha in the database.
372
373
        :param sha: Git object sha
374
        :return: (type, type_data) with type_data:
375
            revision: revid, tree sha
376
        """
0.200.230 by Jelmer Vernooij
Implement sha cache.
377
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
378
        if row is not None:
0.200.845 by Jelmer Vernooij
Couple of minor fixes.
379
            return ("commit", row)
0.200.230 by Jelmer Vernooij
Implement sha cache.
380
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
381
        if row is not None:
0.200.845 by Jelmer Vernooij
Couple of minor fixes.
382
            return ("blob", row)
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
383
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
0.200.230 by Jelmer Vernooij
Implement sha cache.
384
        if row is not None:
0.200.845 by Jelmer Vernooij
Couple of minor fixes.
385
            return ("tree", row)
0.200.230 by Jelmer Vernooij
Implement sha cache.
386
        raise KeyError(sha)
387
388
    def revids(self):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
389
        """List the revision ids known."""
0.248.7 by Jelmer Vernooij
Avoid fetching all sha1s at once.
390
        return (row for (row,) in self.db.execute("select revid from commits"))
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
391
392
    def sha1s(self):
393
        """List the SHA1s."""
394
        for table in ("blobs", "commits", "trees"):
0.200.845 by Jelmer Vernooij
Couple of minor fixes.
395
            for (sha,) in self.db.execute("select sha1 from %s" % table):
396
                yield sha
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
397
398
0.200.751 by Jelmer Vernooij
Unrelated small fixes - import, avoid storing tree info (no longer used).
399
TDB_MAP_VERSION = 3
0.239.2 by Jelmer Vernooij
Increase hash size.
400
TDB_HASH_SIZE = 50000
0.200.479 by Jelmer Vernooij
Version tdb sha map.
401
402
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
403
class TdbGitCacheFormat(BzrGitCacheFormat):
404
405
    def get_format_string(self):
406
        return 'bzr-git sha map version 3 using tdb\n'
407
408
    def open(self, transport):
409
        try:
410
            basepath = transport.local_abspath(".")
411
        except bzrlib.errors.NotLocalUrl:
412
            basepath = get_cache_dir()
413
        try:
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
414
            return BzrGitCache(
415
                    TdbGitShaMap(os.path.join(get_cache_dir(), "idmap.tdb")),
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
416
                    None)
417
        except ImportError:
418
            raise ImportError(
419
                "Unable to open existing bzr-git cache because 'tdb' is not "
420
                "installed.")
421
422
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
423
class TdbGitShaMap(GitShaMap):
424
    """SHA Map that uses a TDB database.
425
426
    Entries:
427
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
428
    "git <sha1>" -> "<type> <type-data1> <type-data2>"
429
    "commit revid" -> "<sha1> <tree-id>"
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
430
    "tree fileid revid" -> "<sha1>"
431
    "blob fileid revid" -> "<sha1>"
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
432
    """
433
434
    def __init__(self, path=None):
435
        import tdb
436
        self.path = path
437
        if path is None:
438
            self.db = {}
439
        else:
440
            if not mapdbs().has_key(path):
0.200.676 by Jelmer Vernooij
Avoid iterating over all keys in the tdb database.
441
                mapdbs()[path] = tdb.Tdb(path, TDB_HASH_SIZE, tdb.DEFAULT,
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
442
                                          os.O_RDWR|os.O_CREAT)
0.200.676 by Jelmer Vernooij
Avoid iterating over all keys in the tdb database.
443
            self.db = mapdbs()[path]
444
        try:
0.200.751 by Jelmer Vernooij
Unrelated small fixes - import, avoid storing tree info (no longer used).
445
            if int(self.db["version"]) not in (2, 3):
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
446
                trace.warning("SHA Map is incompatible (%s -> %d), rebuilding database.",
447
                              self.db["version"], TDB_MAP_VERSION)
448
                self.db.clear()
0.200.676 by Jelmer Vernooij
Avoid iterating over all keys in the tdb database.
449
        except KeyError:
0.200.751 by Jelmer Vernooij
Unrelated small fixes - import, avoid storing tree info (no longer used).
450
            pass
451
        self.db["version"] = str(TDB_MAP_VERSION)
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
452
0.200.809 by Jelmer Vernooij
Use tdb transactions for write groups.
453
    def start_write_group(self):
454
        """Start writing changes."""
0.200.778 by Jelmer Vernooij
Use transactions in tdb.
455
        self.db.transaction_start()
0.200.809 by Jelmer Vernooij
Use tdb transactions for write groups.
456
457
    def commit_write_group(self):
458
        """Commit any pending changes."""
459
        self.db.transaction_commit()
460
461
    def abort_write_group(self):
462
        """Abort any pending changes."""
463
        self.db.transaction_cancel()
0.200.778 by Jelmer Vernooij
Use transactions in tdb.
464
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
465
    def __repr__(self):
466
        return "%s(%r)" % (self.__class__.__name__, self.path)
467
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
468
    def lookup_commit(self, revid):
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
469
        return sha_to_hex(self.db["commit\0" + revid][:20])
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
470
0.200.760 by Jelmer Vernooij
make add_entry private.
471
    def _add_entry(self, hexsha, type, type_data):
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
472
        """Add a new entry to the database.
473
        """
0.200.593 by Jelmer Vernooij
Avoid writing empty trees.
474
        if hexsha is None:
475
            sha = ""
476
        else:
477
            sha = hex_to_sha(hexsha)
478
            self.db["git\0" + 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.
479
        if type == "commit":
0.200.593 by Jelmer Vernooij
Avoid writing empty trees.
480
            self.db["commit\0" + type_data[0]] = "\0".join((sha, type_data[1]))
0.200.751 by Jelmer Vernooij
Unrelated small fixes - import, avoid storing tree info (no longer used).
481
        elif type == "blob":
482
            self.db["\0".join(("blob", type_data[0], type_data[1]))] = sha
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
483
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
484
    def lookup_blob_id(self, fileid, revision):
485
        return sha_to_hex(self.db["\0".join(("blob", fileid, revision))])
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
486
                
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
487
    def lookup_git_sha(self, sha):
488
        """Lookup a Git sha in the database.
489
490
        :param sha: Git object sha
491
        :return: (type, type_data) with type_data:
492
            revision: revid, tree sha
493
        """
0.200.564 by Jelmer Vernooij
Accept 'binary' shas.
494
        if len(sha) == 40:
495
            sha = hex_to_sha(sha)
496
        data = self.db["git\0" + sha].split("\0")
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
497
        return (data[0], (data[1], data[2]))
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
498
0.200.677 by Jelmer Vernooij
Implement TdbCache.missing_revisions().
499
    def missing_revisions(self, revids):
500
        ret = set()
501
        for revid in revids:
502
            if self.db.get("commit\0" + revid) is None:
503
                ret.add(revid)
504
        return ret
505
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
506
    def revids(self):
507
        """List the revision ids known."""
508
        for key in self.db.iterkeys():
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
509
            if key.startswith("commit\0"):
510
                yield key[7:]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
511
512
    def sha1s(self):
513
        """List the SHA1s."""
514
        for key in self.db.iterkeys():
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
515
            if key.startswith("git\0"):
516
                yield sha_to_hex(key[4:])
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
517
518
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
519
formats = registry.Registry()
520
formats.register(TdbGitCacheFormat().get_format_string(),
521
    TdbGitCacheFormat())
522
formats.register(SqliteGitCacheFormat().get_format_string(),
523
    SqliteGitCacheFormat())
524
try:
525
    import tdb
526
except ImportError:
527
    formats.register('default', SqliteGitCacheFormat())
528
else:
529
    formats.register('default', TdbGitCacheFormat())
530
531
532
def migrate_ancient_formats(repo_transport):
533
    if repo_transport.has("git.tdb"):
534
        TdbGitCacheFormat().initialize(repo_transport.clone("git"))
535
        repo_transport.rename("git.tdb", "git/idmap.tdb")
536
    elif repo_transport.has("git.db"):
537
        SqliteGitCacheFormat().initialize(repo_transport.clone("git"))
538
        repo_transport.rename("git.db", "git/idmap.db")
539
540
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
541
def from_repository(repository):
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
542
    repo_transport = getattr(repository, "_transport", None)
543
    if repo_transport is not None:
544
        # Migrate older cache formats
545
        try:
546
            repo_transport.mkdir("git")
547
        except bzrlib.errors.FileExists:
548
            pass
549
        else:
550
            migrate_ancient_formats(repo_transport)
551
    return BzrGitCacheFormat.from_repository(repository)