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