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