/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.358.2 by Jelmer Vernooij
Refresh copyright headers, add my email.
1
# Copyright (C) 2009-2018 Jelmer Vernooij <jelmer@jelmer.uk>
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
0.358.1 by Jelmer Vernooij
Fix FSF address.
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
16
17
"""Map from Git sha's to Bazaar objects."""
18
0.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
19
from __future__ import absolute_import
20
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
21
from dulwich.objects import (
22
    sha_to_hex,
23
    hex_to_sha,
24
    )
0.200.292 by Jelmer Vernooij
Fix formatting.
25
import os
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
26
import threading
0.200.292 by Jelmer Vernooij
Fix formatting.
27
0.254.44 by Jelmer Vernooij
Add knit-based content cache for trees.
28
from dulwich.objects import (
29
    ShaFile,
30
    )
31
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
32
from ... import (
33
    errors as bzr_errors,
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
34
    osutils,
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
35
    registry,
0.200.528 by Jelmer Vernooij
Fix import.
36
    trace,
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
37
    )
38
from ...bzr import (
39
    btree_index as _mod_btree_index,
40
    index as _mod_index,
0.254.31 by Jelmer Vernooij
Initial work on CHKMap support.
41
    versionedfile,
0.200.528 by Jelmer Vernooij
Fix import.
42
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
43
from ...transport import (
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
44
    get_transport,
45
    )
0.200.230 by Jelmer Vernooij
Implement sha cache.
46
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
47
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
48
def get_cache_dir():
49
    try:
50
        from xdg.BaseDirectory import xdg_cache_home
51
    except ImportError:
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
52
        from ...config import config_dir
0.200.558 by Jelmer Vernooij
Create cache dir if it doesn't exist yet.
53
        ret = os.path.join(config_dir(), "git")
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
54
    else:
0.417.1 by Jelmer Vernooij
Change cache directory name from bazaar => breezy.
55
        ret = os.path.join(xdg_cache_home, "breezy", "git")
0.200.558 by Jelmer Vernooij
Create cache dir if it doesn't exist yet.
56
    if not os.path.isdir(ret):
57
        os.makedirs(ret)
58
    return ret
0.200.534 by Jelmer Vernooij
Use XDG cache directory if the python xdg module is available.
59
60
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
61
def get_remote_cache_transport(repository):
0.200.1027 by Jelmer Vernooij
mark remote git directories as not supporting working trees.
62
    """Retrieve the transport to use when accessing (unwritable) remote 
63
    repositories.
64
    """
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
65
    uuid = getattr(repository, "uuid", None)
66
    if uuid is None:
67
        path = get_cache_dir()
68
    else:
69
        path = os.path.join(get_cache_dir(), uuid)
70
        if not os.path.isdir(path):
71
            os.mkdir(path)
72
    return get_transport(path)
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
73
74
0.200.228 by Jelmer Vernooij
Split out map.
75
def check_pysqlite_version(sqlite3):
76
    """Check that sqlite library is compatible.
77
78
    """
0.200.675 by Jelmer Vernooij
Fix formatting.
79
    if (sqlite3.sqlite_version_info[0] < 3 or
80
            (sqlite3.sqlite_version_info[0] == 3 and
0.200.228 by Jelmer Vernooij
Split out map.
81
             sqlite3.sqlite_version_info[1] < 3)):
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
82
        trace.warning('Needs at least sqlite 3.3.x')
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
83
        raise bzr_errors.BzrError("incompatible sqlite library")
0.200.228 by Jelmer Vernooij
Split out map.
84
85
try:
86
    try:
87
        import sqlite3
88
        check_pysqlite_version(sqlite3)
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
89
    except (ImportError, bzr_errors.BzrError) as e:
0.200.228 by Jelmer Vernooij
Split out map.
90
        from pysqlite2 import dbapi2 as sqlite3
91
        check_pysqlite_version(sqlite3)
92
except:
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
93
    trace.warning('Needs at least Python2.5 or Python2.4 with the pysqlite2 '
0.200.228 by Jelmer Vernooij
Split out map.
94
            'module')
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
95
    raise bzr_errors.BzrError("missing sqlite library")
0.200.228 by Jelmer Vernooij
Split out map.
96
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
97
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
98
_mapdbs = threading.local()
99
def mapdbs():
100
    """Get a cache for this thread's db connections."""
101
    try:
102
        return _mapdbs.cache
103
    except AttributeError:
104
        _mapdbs.cache = {}
105
        return _mapdbs.cache
106
107
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
108
class GitShaMap(object):
109
    """Git<->Bzr revision id mapping database."""
110
111
    def lookup_git_sha(self, sha):
112
        """Lookup a Git sha in the database.
113
        :param sha: Git object sha
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
114
        :return: list with (type, type_data) tuples with type_data:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
115
            commit: revid, tree_sha, verifiers
116
            blob: fileid, revid
117
            tree: fileid, revid
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
118
        """
119
        raise NotImplementedError(self.lookup_git_sha)
120
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
121
    def lookup_blob_id(self, file_id, revision):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
122
        """Retrieve a Git blob SHA by file id.
123
124
        :param file_id: File id of the file/symlink
0.200.806 by Jelmer Vernooij
Make revision_hint mandatory.
125
        :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.
126
        """
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
127
        raise NotImplementedError(self.lookup_blob_id)
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
128
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
129
    def lookup_tree_id(self, file_id, revision):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
130
        """Retrieve a Git tree SHA by file id.
131
        """
0.200.835 by Jelmer Vernooij
Rename lookup_{tree,blob} -> lookup_{tree,blob}_id.
132
        raise NotImplementedError(self.lookup_tree_id)
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
133
0.200.1039 by Jelmer Vernooij
Add stub.
134
    def lookup_commit(self, revid):
135
        """Retrieve a Git commit SHA by Bazaar revision id.
136
        """
137
        raise NotImplementedError(self.lookup_commit)
138
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
139
    def revids(self):
140
        """List the revision ids known."""
141
        raise NotImplementedError(self.revids)
142
0.200.677 by Jelmer Vernooij
Implement TdbCache.missing_revisions().
143
    def missing_revisions(self, revids):
144
        """Return set of all the revisions that are not present."""
145
        present_revids = set(self.revids())
146
        if not isinstance(revids, set):
147
            revids = set(revids)
148
        return revids - present_revids
149
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
150
    def sha1s(self):
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
151
        """List the SHA1s."""
152
        raise NotImplementedError(self.sha1s)
153
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
154
    def start_write_group(self):
155
        """Start writing changes."""
156
157
    def commit_write_group(self):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
158
        """Commit any pending changes."""
159
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
160
    def abort_write_group(self):
161
        """Abort any pending changes."""
162
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
163
0.254.44 by Jelmer Vernooij
Add knit-based content cache for trees.
164
class ContentCache(object):
165
    """Object that can cache Git objects."""
166
0.200.952 by Jelmer Vernooij
Write git pack files rather than loose objects.
167
    def add(self, object):
168
        """Add an object."""
169
        raise NotImplementedError(self.add)
170
171
    def add_multi(self, objects):
172
        """Add multiple objects."""
173
        for obj in objects:
174
            self.add(obj)
175
0.254.44 by Jelmer Vernooij
Add knit-based content cache for trees.
176
    def __getitem__(self, sha):
177
        """Retrieve an item, by SHA."""
178
        raise NotImplementedError(self.__getitem__)
179
180
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
181
class BzrGitCacheFormat(object):
0.254.51 by Jelmer Vernooij
Add some docstrings.
182
    """Bazaar-Git Cache Format."""
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
183
184
    def get_format_string(self):
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
185
        """Return a single-line unique format string for this cache format."""
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
186
        raise NotImplementedError(self.get_format_string)
187
188
    def open(self, transport):
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
189
        """Open this format on a transport."""
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
190
        raise NotImplementedError(self.open)
191
192
    def initialize(self, transport):
0.254.51 by Jelmer Vernooij
Add some docstrings.
193
        """Create a new instance of this cache format at transport."""
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
194
        transport.put_bytes('format', self.get_format_string())
195
196
    @classmethod
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
197
    def from_transport(self, transport):
198
        """Open a cache file present on a transport, or initialize one.
199
200
        :param transport: Transport to use
201
        :return: A BzrGitCache instance
202
        """
203
        try:
204
            format_name = transport.get_bytes('format')
205
            format = formats.get(format_name)
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
206
        except bzr_errors.NoSuchFile:
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
207
            format = formats.get('default')
208
            format.initialize(transport)
209
        return format.open(transport)
210
211
    @classmethod
212
    def from_repository(cls, repository):
213
        """Open a cache file for a repository.
214
215
        This will use the repository's transport to store the cache file, or
216
        use the users global cache directory if the repository has no 
217
        transport associated with it.
218
219
        :param repository: Repository to open the cache for
220
        :return: A `BzrGitCache`
221
        """
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
222
        from ...transport.local import LocalTransport
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
223
        repo_transport = getattr(repository, "_transport", None)
0.200.1414 by Jelmer Vernooij
Fix pulling into bound branches.
224
        if (repo_transport is not None and
225
            isinstance(repo_transport, LocalTransport)):
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
226
            # Even if we don't write to this repo, we should be able
0.200.865 by Jelmer Vernooij
Support serving without --allow-writes.
227
            # to update its cache.
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
228
            try:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
229
                repo_transport = remove_readonly_transport_decorator(repo_transport)
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
230
            except bzr_errors.ReadOnlyError:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
231
                transport = None
232
            else:
233
                try:
234
                    repo_transport.mkdir('git')
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
235
                except bzr_errors.FileExists:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
236
                    pass
237
                transport = repo_transport.clone('git')
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
238
        else:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
239
            transport = None
240
        if transport is None:
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
241
            transport = get_remote_cache_transport(repository)
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
242
        return cls.from_transport(transport)
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
243
244
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
245
class CacheUpdater(object):
0.254.51 by Jelmer Vernooij
Add some docstrings.
246
    """Base class for objects that can update a bzr-git cache."""
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
247
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
248
    def add_object(self, obj, bzr_key_data, path):
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
249
        """Add an object.
250
251
        :param obj: Object type ("commit", "blob" or "tree")
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
252
        :param bzr_key_data: bzr key store data or testament_sha in case
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
253
            of commit
254
        :param path: Path of the object (optional)
255
        """
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
256
        raise NotImplementedError(self.add_object)
257
258
    def finish(self):
259
        raise NotImplementedError(self.finish)
260
261
262
class BzrGitCache(object):
263
    """Caching backend."""
264
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
265
    def __init__(self, idmap, cache_updater_klass):
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
266
        self.idmap = idmap
267
        self._cache_updater_klass = cache_updater_klass
268
269
    def get_updater(self, rev):
0.254.51 by Jelmer Vernooij
Add some docstrings.
270
        """Update an object that implements the CacheUpdater interface for 
271
        updating this cache.
272
        """
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
273
        return self._cache_updater_klass(self, rev)
274
275
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
276
DictBzrGitCache = lambda: BzrGitCache(DictGitShaMap(), DictCacheUpdater)
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
277
278
279
class DictCacheUpdater(CacheUpdater):
0.254.51 by Jelmer Vernooij
Add some docstrings.
280
    """Cache updater for dict-based caches."""
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
281
282
    def __init__(self, cache, rev):
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
283
        self.cache = cache
284
        self.revid = rev.revision_id
285
        self.parent_revids = rev.parent_ids
286
        self._commit = None
287
        self._entries = []
288
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
289
    def add_object(self, obj, bzr_key_data, path):
0.423.1 by Jelmer Vernooij
Some performance fixes.
290
        if isinstance(obj, tuple):
291
            (type_name, hexsha) = obj
292
        else:
293
            type_name = obj.type_name
294
            hexsha = obj.id
295
        if type_name == "commit":
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
296
            self._commit = obj
0.361.1 by Jelmer Vernooij
Don't use assert.
297
            if type(bzr_key_data) is not dict:
298
                raise TypeError(bzr_key_data)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
299
            key = self.revid
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
300
            type_data = (self.revid, self._commit.tree, bzr_key_data)
0.423.1 by Jelmer Vernooij
Some performance fixes.
301
            self.cache.idmap._by_revid[self.revid] = hexsha
302
        elif type_name in ("blob", "tree"):
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
303
            if bzr_key_data is not None:
0.421.6 by Jelmer Vernooij
Some more simplifications.
304
                key = type_data = bzr_key_data
0.423.1 by Jelmer Vernooij
Some performance fixes.
305
                self.cache.idmap._by_fileid.setdefault(type_data[1], {})[type_data[0]] = hexsha
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
306
        else:
307
            raise AssertionError
0.423.1 by Jelmer Vernooij
Some performance fixes.
308
        entry = (type_name, type_data)
309
        self.cache.idmap._by_sha.setdefault(hexsha, {})[key] = entry
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
310
311
    def finish(self):
312
        if self._commit is None:
313
            raise AssertionError("No commit object added")
314
        return self._commit
315
316
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
317
class DictGitShaMap(GitShaMap):
0.254.51 by Jelmer Vernooij
Add some docstrings.
318
    """Git SHA map that uses a dictionary."""
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
319
320
    def __init__(self):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
321
        self._by_sha = {}
322
        self._by_fileid = {}
0.200.853 by Jelmer Vernooij
Fix lookup of commits in tdb.
323
        self._by_revid = {}
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
324
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
325
    def lookup_blob_id(self, fileid, revision):
326
        return self._by_fileid[revision][fileid]
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
327
328
    def lookup_git_sha(self, sha):
0.261.2 by Jelmer Vernooij
Fix cache tests.
329
        for entry in self._by_sha[sha].itervalues():
330
            yield entry
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
331
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
332
    def lookup_tree_id(self, fileid, revision):
0.200.860 by Jelmer Vernooij
Fix bugs in two lookup_tree_id implementations and add a test for it.
333
        return self._by_fileid[revision][fileid]
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
334
0.200.853 by Jelmer Vernooij
Fix lookup of commits in tdb.
335
    def lookup_commit(self, revid):
336
        return self._by_revid[revid]
337
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
338
    def revids(self):
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
339
        for key, entries in self._by_sha.iteritems():
340
            for (type, type_data) in entries.values():
341
                if type == "commit":
342
                    yield type_data[0]
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
343
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
344
    def sha1s(self):
0.200.753 by Jelmer Vernooij
Move lookup_tree/lookup_blob to a separate object.
345
        return self._by_sha.iterkeys()
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
346
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
347
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
348
class SqliteCacheUpdater(CacheUpdater):
349
350
    def __init__(self, cache, rev):
351
        self.cache = cache
0.200.850 by Jelmer Vernooij
Fix tests.
352
        self.db = self.cache.idmap.db
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
353
        self.revid = rev.revision_id
354
        self._commit = None
355
        self._trees = []
356
        self._blobs = []
357
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
358
    def add_object(self, obj, bzr_key_data, path):
0.423.1 by Jelmer Vernooij
Some performance fixes.
359
        if isinstance(obj, tuple):
360
            (type_name, hexsha) = obj
361
        else:
362
            type_name = obj.type_name
363
            hexsha = obj.id
364
        if type_name == "commit":
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
365
            self._commit = obj
0.361.1 by Jelmer Vernooij
Don't use assert.
366
            if type(bzr_key_data) is not dict:
367
                raise TypeError(bzr_key_data)
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
368
            self._testament3_sha1 = bzr_key_data.get("testament3-sha1")
0.423.1 by Jelmer Vernooij
Some performance fixes.
369
        elif type_name == "tree":
370
            if bzr_key_data is not None:
371
                self._trees.append((hexsha, bzr_key_data[0], bzr_key_data[1]))
372
        elif type_name == "blob":
373
            if bzr_key_data is not None:
374
                self._blobs.append((hexsha, bzr_key_data[0], bzr_key_data[1]))
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
375
        else:
376
            raise AssertionError
377
378
    def finish(self):
379
        if self._commit is None:
380
            raise AssertionError("No commit object added")
0.200.850 by Jelmer Vernooij
Fix tests.
381
        self.db.executemany(
382
            "replace into trees (sha1, fileid, revid) values (?, ?, ?)",
383
            self._trees)
384
        self.db.executemany(
385
            "replace into blobs (sha1, fileid, revid) values (?, ?, ?)",
386
            self._blobs)
387
        self.db.execute(
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
388
            "replace into commits (sha1, revid, tree_sha, testament3_sha1) values (?, ?, ?, ?)",
389
            (self._commit.id, self.revid, self._commit.tree, self._testament3_sha1))
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
390
        return self._commit
391
392
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
393
SqliteBzrGitCache = lambda p: BzrGitCache(SqliteGitShaMap(p), SqliteCacheUpdater)
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
394
395
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
396
class SqliteGitCacheFormat(BzrGitCacheFormat):
397
398
    def get_format_string(self):
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
399
        return b'bzr-git sha map version 1 using sqlite\n'
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
400
401
    def open(self, transport):
402
        try:
403
            basepath = transport.local_abspath(".")
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
404
        except bzr_errors.NotLocalUrl:
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
405
            basepath = get_cache_dir()
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
406
        return SqliteBzrGitCache(os.path.join(basepath, "idmap.db"))
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
407
408
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
409
class SqliteGitShaMap(GitShaMap):
0.254.51 by Jelmer Vernooij
Add some docstrings.
410
    """Bazaar GIT Sha map that uses a sqlite database for storage."""
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
411
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
412
    def __init__(self, path=None):
413
        self.path = path
414
        if path is None:
0.200.262 by Jelmer Vernooij
Add tests for GitShaMap.
415
            self.db = sqlite3.connect(":memory:")
416
        else:
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
417
            if path not in mapdbs():
0.200.365 by Jelmer Vernooij
Share sha map cache connections inside threads.
418
                mapdbs()[path] = sqlite3.connect(path)
0.200.675 by Jelmer Vernooij
Fix formatting.
419
            self.db = mapdbs()[path]
0.200.688 by Jelmer Vernooij
Use str text factory rather than encoding/decoding each time.
420
        self.db.text_factory = str
0.200.230 by Jelmer Vernooij
Implement sha cache.
421
        self.db.executescript("""
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
422
        create table if not exists commits(
423
            sha1 text not null check(length(sha1) == 40),
424
            revid text not null,
425
            tree_sha text not null check(length(tree_sha) == 40)
426
        );
0.200.230 by Jelmer Vernooij
Implement sha cache.
427
        create index if not exists commit_sha1 on commits(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
428
        create unique index if not exists commit_revid on commits(revid);
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
429
        create table if not exists blobs(
430
            sha1 text not null check(length(sha1) == 40),
431
            fileid text not null,
432
            revid text not null
433
        );
0.200.230 by Jelmer Vernooij
Implement sha cache.
434
        create index if not exists blobs_sha1 on blobs(sha1);
0.200.284 by Jelmer Vernooij
Add extra indexes.
435
        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.
436
        create table if not exists trees(
0.255.1 by Jelmer Vernooij
Remove use of lookup_tree.
437
            sha1 text unique not null check(length(sha1) == 40),
0.200.691 by Jelmer Vernooij
Add extra constraints in sqlite tables.
438
            fileid text not null,
439
            revid text not null
440
        );
0.255.1 by Jelmer Vernooij
Remove use of lookup_tree.
441
        create unique index if not exists trees_sha1 on trees(sha1);
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
442
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
0.200.230 by Jelmer Vernooij
Implement sha cache.
443
""")
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
444
        try:
445
            self.db.executescript(
446
                "ALTER TABLE commits ADD testament3_sha1 TEXT;")
447
        except sqlite3.OperationalError:
448
            pass # Column already exists.
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
449
0.254.19 by Jelmer Vernooij
Support upgrading sha maps.
450
    def __repr__(self):
451
        return "%s(%r)" % (self.__class__.__name__, self.path)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
452
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
453
    def lookup_commit(self, revid):
0.254.51 by Jelmer Vernooij
Add some docstrings.
454
        cursor = self.db.execute("select sha1 from commits where revid = ?", 
455
            (revid,))
456
        row = cursor.fetchone()
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
457
        if row is not None:
0.200.688 by Jelmer Vernooij
Use str text factory rather than encoding/decoding each time.
458
            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.
459
        raise KeyError
0.200.231 by Jelmer Vernooij
Partially fix pull.
460
0.200.687 by Jelmer Vernooij
Use start_write_group() / commit_write_group() mechanism when creating git SHA maps.
461
    def commit_write_group(self):
0.200.232 by Jelmer Vernooij
Fix pull from remote branches.
462
        self.db.commit()
463
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
464
    def lookup_blob_id(self, fileid, revision):
465
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revision)).fetchone()
466
        if row is not None:
467
            return row[0]
468
        raise KeyError(fileid)
469
470
    def lookup_tree_id(self, fileid, revision):
0.200.860 by Jelmer Vernooij
Fix bugs in two lookup_tree_id implementations and add a test for it.
471
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid, revision)).fetchone()
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
472
        if row is not None:
473
            return row[0]
474
        raise KeyError(fileid)
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
475
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
476
    def lookup_git_sha(self, sha):
477
        """Lookup a Git sha in the database.
478
479
        :param sha: Git object sha
480
        :return: (type, type_data) with type_data:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
481
            commit: revid, tree sha, verifiers
482
            tree: fileid, revid
483
            blob: fileid, revid
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
484
        """
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
485
        found = False
486
        cursor = self.db.execute("select revid, tree_sha, testament3_sha1 from commits where sha1 = ?", (sha,))
487
        for row in cursor.fetchall():
488
            found = True
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
489
            if row[2] is not None:
490
                verifiers = {"testament3-sha1": row[2]}
491
            else:
492
                verifiers = {}
493
            yield ("commit", (row[0], row[1], verifiers))
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
494
        cursor = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,))
495
        for row in cursor.fetchall():
496
            found = True
497
            yield ("blob", row)
498
        cursor = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,))
499
        for row in cursor.fetchall():
500
            found = True
501
            yield ("tree", row)
502
        if not found:
503
            raise KeyError(sha)
0.200.230 by Jelmer Vernooij
Implement sha cache.
504
505
    def revids(self):
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
506
        """List the revision ids known."""
0.248.7 by Jelmer Vernooij
Avoid fetching all sha1s at once.
507
        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.
508
509
    def sha1s(self):
510
        """List the SHA1s."""
511
        for table in ("blobs", "commits", "trees"):
0.254.26 by Jelmer Vernooij
Fix typo, cope with invalid shamaps a bit better.
512
            for (sha,) in self.db.execute("select sha1 from %s" % table):
513
                yield sha
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
514
515
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
516
class TdbCacheUpdater(CacheUpdater):
0.254.51 by Jelmer Vernooij
Add some docstrings.
517
    """Cache updater for tdb-based caches."""
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
518
519
    def __init__(self, cache, rev):
520
        self.cache = cache
521
        self.db = cache.idmap.db
522
        self.revid = rev.revision_id
523
        self.parent_revids = rev.parent_ids
524
        self._commit = None
525
        self._entries = []
526
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
527
    def add_object(self, obj, bzr_key_data, path):
0.423.1 by Jelmer Vernooij
Some performance fixes.
528
        if isinstance(obj, tuple):
529
            (type_name, hexsha) = obj
530
            sha = hex_to_sha(hexsha)
531
        else:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
532
            type_name = obj.type_name.decode('ascii')
0.423.1 by Jelmer Vernooij
Some performance fixes.
533
            sha = obj.sha().digest()
534
        if type_name == "commit":
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
535
            self.db[b"commit\0" + self.revid] = b"\0".join((sha, obj.tree))
0.361.1 by Jelmer Vernooij
Don't use assert.
536
            if type(bzr_key_data) is not dict:
537
                raise TypeError(bzr_key_data)
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
538
            type_data = (self.revid, obj.tree)
539
            try:
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
540
                type_data += (bzr_key_data["testament3-sha1"],)
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
541
            except KeyError:
542
                pass
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
543
            self._commit = obj
0.423.1 by Jelmer Vernooij
Some performance fixes.
544
        elif type_name == "blob":
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
545
            if bzr_key_data is None:
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
546
                return
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
547
            self.db[b"\0".join((b"blob", bzr_key_data[0], bzr_key_data[1]))] = sha
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
548
            type_data = bzr_key_data
0.423.1 by Jelmer Vernooij
Some performance fixes.
549
        elif type_name == "tree":
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
550
            if bzr_key_data is None:
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
551
                return
0.421.6 by Jelmer Vernooij
Some more simplifications.
552
            type_data = bzr_key_data
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
553
        else:
554
            raise AssertionError
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
555
        entry = b"\0".join((type_name.encode('ascii'), ) + type_data) + b"\n"
556
        key = b"git\0" + sha
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
557
        try:
558
            oldval = self.db[key]
559
        except KeyError:
560
            self.db[key] = entry
561
        else:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
562
            if not oldval.endswith(b'\n'):
563
                self.db[key] = b"".join([oldval, b"\n", entry])
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
564
            else:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
565
                self.db[key] = b"".join([oldval, entry])
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
566
567
    def finish(self):
568
        if self._commit is None:
569
            raise AssertionError("No commit object added")
570
        return self._commit
571
572
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
573
TdbBzrGitCache = lambda p: BzrGitCache(TdbGitShaMap(p), TdbCacheUpdater)
0.200.479 by Jelmer Vernooij
Version tdb sha map.
574
0.200.1140 by Jelmer Vernooij
Update now that the control dir formats are no longer in __init__.
575
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
576
class TdbGitCacheFormat(BzrGitCacheFormat):
0.254.51 by Jelmer Vernooij
Add some docstrings.
577
    """Cache format for tdb-based caches."""
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
578
579
    def get_format_string(self):
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
580
        return b'bzr-git sha map version 3 using tdb\n'
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
581
582
    def open(self, transport):
583
        try:
0.200.1075 by Jelmer Vernooij
Fix compatibility with older versions of python-tdb.
584
            basepath = transport.local_abspath(".").encode(osutils._fs_enc)
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
585
        except bzr_errors.NotLocalUrl:
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
586
            basepath = get_cache_dir()
0.361.1 by Jelmer Vernooij
Don't use assert.
587
        if type(basepath) is not str:
588
            raise TypeError(basepath)
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
589
        try:
0.200.850 by Jelmer Vernooij
Fix tests.
590
            return TdbBzrGitCache(os.path.join(basepath, "idmap.tdb"))
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
591
        except ImportError:
592
            raise ImportError(
593
                "Unable to open existing bzr-git cache because 'tdb' is not "
594
                "installed.")
595
596
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
597
class TdbGitShaMap(GitShaMap):
598
    """SHA Map that uses a TDB database.
599
600
    Entries:
601
0.200.476 by Jelmer Vernooij
Fix Tdb backend, use tdb if possible by default.
602
    "git <sha1>" -> "<type> <type-data1> <type-data2>"
603
    "commit revid" -> "<sha1> <tree-id>"
0.200.477 by Jelmer Vernooij
More tests for sha maps, fix cache misses in tdb.
604
    "tree fileid revid" -> "<sha1>"
605
    "blob fileid revid" -> "<sha1>"
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
606
    """
607
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
608
    TDB_MAP_VERSION = 3
609
    TDB_HASH_SIZE = 50000
610
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
611
    def __init__(self, path=None):
612
        import tdb
613
        self.path = path
614
        if path is None:
615
            self.db = {}
616
        else:
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
617
            if path not in mapdbs():
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
618
                mapdbs()[path] = tdb.Tdb(path, self.TDB_HASH_SIZE, tdb.DEFAULT,
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
619
                                          os.O_RDWR|os.O_CREAT)
0.200.676 by Jelmer Vernooij
Avoid iterating over all keys in the tdb database.
620
            self.db = mapdbs()[path]
621
        try:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
622
            if int(self.db[b"version"]) not in (2, 3):
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
623
                trace.warning("SHA Map is incompatible (%s -> %d), rebuilding database.",
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
624
                              self.db[b"version"], self.TDB_MAP_VERSION)
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
625
                self.db.clear()
0.200.676 by Jelmer Vernooij
Avoid iterating over all keys in the tdb database.
626
        except KeyError:
0.200.751 by Jelmer Vernooij
Unrelated small fixes - import, avoid storing tree info (no longer used).
627
            pass
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
628
        self.db[b"version"] = b'%d' % self.TDB_MAP_VERSION
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
629
0.200.809 by Jelmer Vernooij
Use tdb transactions for write groups.
630
    def start_write_group(self):
631
        """Start writing changes."""
0.200.778 by Jelmer Vernooij
Use transactions in tdb.
632
        self.db.transaction_start()
0.200.809 by Jelmer Vernooij
Use tdb transactions for write groups.
633
634
    def commit_write_group(self):
635
        """Commit any pending changes."""
636
        self.db.transaction_commit()
637
638
    def abort_write_group(self):
639
        """Abort any pending changes."""
640
        self.db.transaction_cancel()
0.200.778 by Jelmer Vernooij
Use transactions in tdb.
641
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
642
    def __repr__(self):
643
        return "%s(%r)" % (self.__class__.__name__, self.path)
644
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
645
    def lookup_commit(self, revid):
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
646
        try:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
647
            return sha_to_hex(self.db[b"commit\0" + revid][:20])
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
648
        except KeyError:
649
            raise KeyError("No cache entry for %r" % revid)
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
650
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
651
    def lookup_blob_id(self, fileid, revision):
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
652
        return sha_to_hex(self.db[b"\0".join(("blob", fileid, revision))])
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
653
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
654
    def lookup_git_sha(self, sha):
655
        """Lookup a Git sha in the database.
656
657
        :param sha: Git object sha
658
        :return: (type, type_data) with type_data:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
659
            commit: revid, tree sha
660
            blob: fileid, revid
661
            tree: fileid, revid
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
662
        """
0.200.564 by Jelmer Vernooij
Accept 'binary' shas.
663
        if len(sha) == 40:
664
            sha = hex_to_sha(sha)
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
665
        value = self.db[b"git\0" + sha]
0.261.2 by Jelmer Vernooij
Fix cache tests.
666
        for data in value.splitlines():
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
667
            data = data.split(b"\0")
668
            type_name = data[0].decode('ascii')
669
            if type_name == "commit":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
670
                if len(data) == 3:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
671
                    yield (type_name, (data[1], data[2], {}))
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
672
                else:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
673
                    yield (type_name, (data[1], data[2], {"testament3-sha1": data[3]}))
674
            elif type_name in ("tree", "blob"):
675
                yield (type_name, tuple(data[1:]))
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
676
            else:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
677
                raise AssertionError("unknown type %r" % type_name)
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
678
0.200.677 by Jelmer Vernooij
Implement TdbCache.missing_revisions().
679
    def missing_revisions(self, revids):
680
        ret = set()
681
        for revid in revids:
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
682
            if self.db.get(b"commit\0" + revid) is None:
0.200.677 by Jelmer Vernooij
Implement TdbCache.missing_revisions().
683
                ret.add(revid)
684
        return ret
685
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
686
    def revids(self):
687
        """List the revision ids known."""
688
        for key in self.db.iterkeys():
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
689
            if key.startswith(b"commit\0"):
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
690
                yield key[7:]
0.200.475 by Jelmer Vernooij
Add Tdb database backend.
691
692
    def sha1s(self):
693
        """List the SHA1s."""
694
        for key in self.db.iterkeys():
6973.11.12 by Jelmer Vernooij
Fix tdb cache tests when tdb is installed.
695
            if key.startswith(b"git\0"):
0.235.1 by Jelmer Vernooij
Store sha map more efficiently.
696
                yield sha_to_hex(key[4:])
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
697
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
698
0.254.44 by Jelmer Vernooij
Add knit-based content cache for trees.
699
class VersionedFilesContentCache(ContentCache):
700
701
    def __init__(self, vf):
702
        self._vf = vf
703
704
    def add(self, obj):
705
        self._vf.insert_record_stream(
706
            [versionedfile.ChunkedContentFactory((obj.id,), [], None,
707
                obj.as_legacy_object_chunks())])
708
709
    def __getitem__(self, sha):
710
        stream = self._vf.get_record_stream([(sha,)], 'unordered', True)
6973.10.5 by Jelmer Vernooij
Fix use of .next.
711
        entry = next(stream)
0.254.44 by Jelmer Vernooij
Add knit-based content cache for trees.
712
        if entry.storage_kind == 'absent':
713
            raise KeyError(sha)
714
        return ShaFile._parse_legacy_object(entry.get_bytes_as('fulltext'))
715
716
0.254.46 by Jelmer Vernooij
Merge trunk.
717
class IndexCacheUpdater(CacheUpdater):
718
719
    def __init__(self, cache, rev):
720
        self.cache = cache
721
        self.revid = rev.revision_id
722
        self.parent_revids = rev.parent_ids
723
        self._commit = None
724
        self._entries = []
725
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
726
    def add_object(self, obj, bzr_key_data, path):
0.423.1 by Jelmer Vernooij
Some performance fixes.
727
        if isinstance(obj, tuple):
728
            (type_name, hexsha) = obj
729
        else:
730
            type_name = obj.type_name
731
            hexsha = obj.id
732
        if type_name == "commit":
0.254.46 by Jelmer Vernooij
Merge trunk.
733
            self._commit = obj
0.361.1 by Jelmer Vernooij
Don't use assert.
734
            if type(bzr_key_data) is not dict:
735
                raise TypeError(bzr_key_data)
0.423.1 by Jelmer Vernooij
Some performance fixes.
736
            self.cache.idmap._add_git_sha(hexsha, "commit",
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
737
                (self.revid, obj.tree, bzr_key_data))
0.254.47 by Jelmer Vernooij
Merge trunk.
738
            self.cache.idmap._add_node(("commit", self.revid, "X"),
0.423.1 by Jelmer Vernooij
Some performance fixes.
739
                " ".join((hexsha, obj.tree)))
740
        elif type_name == "blob":
741
            self.cache.idmap._add_git_sha(hexsha, "blob", bzr_key_data)
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
742
            self.cache.idmap._add_node(("blob", bzr_key_data[0],
0.423.1 by Jelmer Vernooij
Some performance fixes.
743
                bzr_key_data[1]), hexsha)
744
        elif type_name == "tree":
745
            self.cache.idmap._add_git_sha(hexsha, "tree", bzr_key_data)
0.254.46 by Jelmer Vernooij
Merge trunk.
746
        else:
747
            raise AssertionError
748
749
    def finish(self):
750
        return self._commit
751
752
753
class IndexBzrGitCache(BzrGitCache):
754
755
    def __init__(self, transport=None):
756
        mapper = versionedfile.ConstantMapper("trees")
0.254.52 by Jelmer Vernooij
Merge trunk, use git objects to cache tree objects.
757
        shamap = IndexGitShaMap(transport.clone('index'))
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
758
        from .transportgit import TransportObjectStore
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
759
        super(IndexBzrGitCache, self).__init__(shamap, IndexCacheUpdater)
0.254.46 by Jelmer Vernooij
Merge trunk.
760
761
0.254.43 by Jelmer Vernooij
Merge trunk.
762
class IndexGitCacheFormat(BzrGitCacheFormat):
763
764
    def get_format_string(self):
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
765
        return b'bzr-git sha map with git object cache version 1\n'
0.254.43 by Jelmer Vernooij
Merge trunk.
766
767
    def initialize(self, transport):
768
        super(IndexGitCacheFormat, self).initialize(transport)
769
        transport.mkdir('index')
0.254.52 by Jelmer Vernooij
Merge trunk, use git objects to cache tree objects.
770
        transport.mkdir('objects')
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
771
        from .transportgit import TransportObjectStore
0.254.52 by Jelmer Vernooij
Merge trunk, use git objects to cache tree objects.
772
        TransportObjectStore.init(transport.clone('objects'))
0.254.43 by Jelmer Vernooij
Merge trunk.
773
774
    def open(self, transport):
0.254.46 by Jelmer Vernooij
Merge trunk.
775
        return IndexBzrGitCache(transport)
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
776
777
778
class IndexGitShaMap(GitShaMap):
0.254.31 by Jelmer Vernooij
Initial work on CHKMap support.
779
    """SHA Map that uses the Bazaar APIs to store a cache.
780
781
    BTree Index file with the following contents:
782
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
783
    ("git", <sha1>, "X") -> "<type> <type-data1> <type-data2>"
784
    ("commit", <revid>, "X") -> "<sha1> <tree-id>"
0.254.36 by Jelmer Vernooij
Merge trunk.
785
    ("blob", <fileid>, <revid>) -> <sha1>
786
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
787
    """
788
789
    def __init__(self, transport=None):
6962.1.1 by Jelmer Vernooij
Fix handling cache updates in bzr-based index formats.
790
        self._name = None
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
791
        if transport is None:
0.254.43 by Jelmer Vernooij
Merge trunk.
792
            self._transport = None
0.254.36 by Jelmer Vernooij
Merge trunk.
793
            self._index = _mod_index.InMemoryGraphIndex(0, key_elements=3)
0.254.2 by jelmer
use btree indexes
794
            self._builder = self._index
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
795
        else:
0.254.30 by Jelmer Vernooij
Move index to separate dir.
796
            self._builder = None
0.254.43 by Jelmer Vernooij
Merge trunk.
797
            self._transport = transport
0.254.2 by jelmer
use btree indexes
798
            self._index = _mod_index.CombinedGraphIndex([])
0.254.43 by Jelmer Vernooij
Merge trunk.
799
            for name in self._transport.list_dir("."):
0.254.2 by jelmer
use btree indexes
800
                if not name.endswith(".rix"):
801
                    continue
0.254.43 by Jelmer Vernooij
Merge trunk.
802
                x = _mod_btree_index.BTreeGraphIndex(self._transport, name,
803
                    self._transport.stat(name).st_size)
0.254.2 by jelmer
use btree indexes
804
                self._index.insert_index(0, x)
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
805
806
    @classmethod
807
    def from_repository(cls, repository):
808
        transport = getattr(repository, "_transport", None)
809
        if transport is not None:
0.254.2 by jelmer
use btree indexes
810
            try:
811
                transport.mkdir('git')
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
812
            except bzr_errors.FileExists:
0.254.2 by jelmer
use btree indexes
813
                pass
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
814
            return cls(transport.clone('git'))
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
815
        from ...transport import get_transport
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
816
        return cls(get_transport(get_cache_dir()))
817
0.254.19 by Jelmer Vernooij
Support upgrading sha maps.
818
    def __repr__(self):
819
        if self._transport is not None:
820
            return "%s(%r)" % (self.__class__.__name__, self._transport.base)
821
        else:
822
            return "%s()" % (self.__class__.__name__)
823
0.254.3 by John Arbash Meinel
Add repack function.
824
    def repack(self):
0.361.1 by Jelmer Vernooij
Don't use assert.
825
        if self._builder is not None:
826
            raise errors.BzrError('builder already open')
0.254.3 by John Arbash Meinel
Add repack function.
827
        self.start_write_group()
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
828
        self._builder.add_nodes(
829
            ((key, value) for (_, key, value) in
830
                self._index.iter_all_entries()))
0.254.3 by John Arbash Meinel
Add repack function.
831
        to_remove = []
0.254.43 by Jelmer Vernooij
Merge trunk.
832
        for name in self._transport.list_dir('.'):
0.254.3 by John Arbash Meinel
Add repack function.
833
            if name.endswith('.rix'):
834
                to_remove.append(name)
835
        self.commit_write_group()
836
        del self._index.indices[1:]
837
        for name in to_remove:
0.254.43 by Jelmer Vernooij
Merge trunk.
838
            self._transport.rename(name, name + '.old')
0.254.3 by John Arbash Meinel
Add repack function.
839
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
840
    def start_write_group(self):
0.361.1 by Jelmer Vernooij
Don't use assert.
841
        if self._builder is not None:
842
            raise errors.BzrError('builder already open')
0.254.36 by Jelmer Vernooij
Merge trunk.
843
        self._builder = _mod_btree_index.BTreeBuilder(0, key_elements=3)
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
844
        self._name = osutils.sha()
845
846
    def commit_write_group(self):
0.361.1 by Jelmer Vernooij
Don't use assert.
847
        if self._builder is None:
848
            raise errors.BzrError('builder not open')
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
849
        stream = self._builder.finish()
0.254.2 by jelmer
use btree indexes
850
        name = self._name.hexdigest() + ".rix"
0.254.43 by Jelmer Vernooij
Merge trunk.
851
        size = self._transport.put_file(name, stream)
852
        index = _mod_btree_index.BTreeGraphIndex(self._transport, name, size)
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
853
        self._index.insert_index(0, index)
854
        self._builder = None
855
        self._name = None
856
857
    def abort_write_group(self):
0.361.1 by Jelmer Vernooij
Don't use assert.
858
        if self._builder is None:
859
            raise errors.BzrError('builder not open')
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
860
        self._builder = None
861
        self._name = None
862
0.254.15 by Jelmer Vernooij
Convenience function for adding index nodes.
863
    def _add_node(self, key, value):
864
        try:
0.425.1 by Jelmer Vernooij
Add really basic check implementation.
865
            self._get_entry(key)
866
        except KeyError:
0.254.15 by Jelmer Vernooij
Convenience function for adding index nodes.
867
            self._builder.add_node(key, value)
0.425.1 by Jelmer Vernooij
Add really basic check implementation.
868
            return False
869
        else:
0.254.26 by Jelmer Vernooij
Fix typo, cope with invalid shamaps a bit better.
870
            return True
0.254.15 by Jelmer Vernooij
Convenience function for adding index nodes.
871
0.254.2 by jelmer
use btree indexes
872
    def _get_entry(self, key):
873
        entries = self._index.iter_entries([key])
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
874
        try:
6973.10.5 by Jelmer Vernooij
Fix use of .next.
875
            return next(entries)[2]
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
876
        except StopIteration:
0.254.2 by jelmer
use btree indexes
877
            if self._builder is None:
878
                raise KeyError
879
            entries = self._builder.iter_entries([key])
880
            try:
6973.10.5 by Jelmer Vernooij
Fix use of .next.
881
                return next(entries)[2]
0.254.2 by jelmer
use btree indexes
882
            except StopIteration:
883
                raise KeyError
884
0.261.2 by Jelmer Vernooij
Fix cache tests.
885
    def _iter_entries_prefix(self, prefix):
0.254.2 by jelmer
use btree indexes
886
        for entry in self._index.iter_entries_prefix([prefix]):
0.261.2 by Jelmer Vernooij
Fix cache tests.
887
            yield (entry[1], entry[2])
0.254.2 by jelmer
use btree indexes
888
        if self._builder is not None:
889
            for entry in self._builder.iter_entries_prefix([prefix]):
0.261.2 by Jelmer Vernooij
Fix cache tests.
890
                yield (entry[1], entry[2])
0.254.2 by jelmer
use btree indexes
891
892
    def lookup_commit(self, revid):
0.254.36 by Jelmer Vernooij
Merge trunk.
893
        return self._get_entry(("commit", revid, "X"))[:40]
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
894
0.254.33 by Jelmer Vernooij
Merge trunk.
895
    def _add_git_sha(self, hexsha, type, type_data):
0.254.2 by jelmer
use btree indexes
896
        if hexsha is not None:
897
            self._name.update(hexsha)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
898
            if type == "commit":
0.200.1179 by Jelmer Vernooij
Avoid using verifiers for natively imported revisions, save a lot of time.
899
                td = (type_data[0], type_data[1])
900
                try:
901
                    td += (type_data[2]["testament3-sha1"],)
902
                except KeyError:
903
                    pass
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
904
            else:
905
                td = type_data
906
            self._add_node(("git", hexsha, "X"), " ".join((type,) + td))
0.254.2 by jelmer
use btree indexes
907
        else:
908
            # This object is not represented in Git - perhaps an empty
909
            # directory?
910
            self._name.update(type + " ".join(type_data))
0.254.33 by Jelmer Vernooij
Merge trunk.
911
0.254.42 by Jelmer Vernooij
Merge trunk.
912
    def lookup_blob_id(self, fileid, revision):
913
        return self._get_entry(("blob", fileid, revision))
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
914
915
    def lookup_git_sha(self, sha):
916
        if len(sha) == 20:
917
            sha = sha_to_hex(sha)
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
918
        value = self._get_entry(("git", sha, "X"))
919
        data = value.split(" ", 3)
920
        if data[0] == "commit":
0.425.1 by Jelmer Vernooij
Add really basic check implementation.
921
            try:
922
                if data[3]:
923
                    verifiers = {"testament3-sha1": data[3]}
924
                else:
925
                    verifiers = {}
926
            except IndexError:
0.422.1 by Jelmer Vernooij
Remove content caching, fix index.
927
                verifiers = {}
928
            yield ("commit", (data[1], data[2], verifiers))
929
        else:
930
            yield (data[0], tuple(data[1:]))
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
931
932
    def revids(self):
933
        """List the revision ids known."""
0.261.2 by Jelmer Vernooij
Fix cache tests.
934
        for key, value in self._iter_entries_prefix(("commit", None, None)):
0.254.2 by jelmer
use btree indexes
935
            yield key[1]
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
936
0.254.21 by Jelmer Vernooij
Implement faster missing_revisions.
937
    def missing_revisions(self, revids):
938
        """Return set of all the revisions that are not present."""
939
        missing_revids = set(revids)
940
        for _, key, value in self._index.iter_entries((
0.254.37 by Jelmer Vernooij
merge trunk
941
            ("commit", revid, "X") for revid in revids)):
0.254.21 by Jelmer Vernooij
Implement faster missing_revisions.
942
            missing_revids.remove(key[1])
943
        return missing_revids
944
0.254.1 by Jelmer Vernooij
Add trivial index-based sha map.
945
    def sha1s(self):
946
        """List the SHA1s."""
0.261.2 by Jelmer Vernooij
Fix cache tests.
947
        for key, value in self._iter_entries_prefix(("git", None, None)):
0.254.2 by jelmer
use btree indexes
948
            yield key[1]
0.254.19 by Jelmer Vernooij
Support upgrading sha maps.
949
950
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
951
formats = registry.Registry()
952
formats.register(TdbGitCacheFormat().get_format_string(),
953
    TdbGitCacheFormat())
954
formats.register(SqliteGitCacheFormat().get_format_string(),
955
    SqliteGitCacheFormat())
0.254.43 by Jelmer Vernooij
Merge trunk.
956
formats.register(IndexGitCacheFormat().get_format_string(),
957
    IndexGitCacheFormat())
0.200.951 by Jelmer Vernooij
merge support for git object store-based caching mechanism.
958
# In the future, this will become the default:
0.425.1 by Jelmer Vernooij
Add really basic check implementation.
959
formats.register('default', IndexGitCacheFormat())
0.200.951 by Jelmer Vernooij
merge support for git object store-based caching mechanism.
960
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
961
962
963
def migrate_ancient_formats(repo_transport):
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
964
    # Migrate older cache formats
965
    repo_transport = remove_readonly_transport_decorator(repo_transport)
966
    has_sqlite = repo_transport.has("git.db")
967
    has_tdb = repo_transport.has("git.tdb")
968
    if not has_sqlite or has_tdb:
969
        return
970
    try:
971
        repo_transport.mkdir("git")
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
972
    except bzr_errors.FileExists:
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
973
        return
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
974
    # Prefer migrating git.db over git.tdb, since the latter may not 
975
    # be openable on some platforms.
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
976
    if has_sqlite:
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
977
        SqliteGitCacheFormat().initialize(repo_transport.clone("git"))
978
        repo_transport.rename("git.db", "git/idmap.db")
0.200.1221 by Jelmer Vernooij
Support cache for non-local transport properly.
979
    elif has_tdb:
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
980
        TdbGitCacheFormat().initialize(repo_transport.clone("git"))
981
        repo_transport.rename("git.tdb", "git/idmap.tdb")
982
983
0.200.865 by Jelmer Vernooij
Support serving without --allow-writes.
984
def remove_readonly_transport_decorator(transport):
985
    if transport.is_readonly():
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
986
        try:
987
            return transport._decorated
988
        except AttributeError:
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
989
            raise bzr_errors.ReadOnlyError(transport)
0.200.865 by Jelmer Vernooij
Support serving without --allow-writes.
990
    return transport
991
992
0.254.19 by Jelmer Vernooij
Support upgrading sha maps.
993
def from_repository(repository):
0.200.866 by Jelmer Vernooij
More docstrings, prefer migrating git.db to migrating git.tdb.
994
    """Open a cache file for a repository.
995
996
    If the repository is remote and there is no transport available from it
997
    this will use a local file in the users cache directory
998
    (typically ~/.cache/bazaar/git/)
999
1000
    :param repository: A repository object
1001
    """
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
1002
    repo_transport = getattr(repository, "_transport", None)
1003
    if repo_transport is not None:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
1004
        try:
1005
            migrate_ancient_formats(repo_transport)
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
1006
        except bzr_errors.ReadOnlyError:
0.200.1438 by Jelmer Vernooij
Cope with remote branches not being readonly at all better.
1007
            pass # Not much we can do
0.200.844 by Jelmer Vernooij
Add infrastructure for multiple cache formats.
1008
    return BzrGitCacheFormat.from_repository(repository)