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