/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/git/cache.py

  • Committer: Jelmer Vernooij
  • Date: 2019-03-04 00:16:27 UTC
  • mfrom: (7293 work)
  • mto: This revision was merged to the branch mainline in revision 7318.
  • Revision ID: jelmer@jelmer.uk-20190304001627-v6u7o6pf97tukhek
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
 
65
65
 
66
66
def get_remote_cache_transport(repository):
67
 
    """Retrieve the transport to use when accessing (unwritable) remote 
 
67
    """Retrieve the transport to use when accessing (unwritable) remote
68
68
    repositories.
69
69
    """
70
70
    uuid = getattr(repository, "uuid", None)
81
81
    """Check that sqlite library is compatible.
82
82
 
83
83
    """
84
 
    if (sqlite3.sqlite_version_info[0] < 3 or
85
 
            (sqlite3.sqlite_version_info[0] == 3 and
86
 
             sqlite3.sqlite_version_info[1] < 3)):
 
84
    if (sqlite3.sqlite_version_info[0] < 3
 
85
            or (sqlite3.sqlite_version_info[0] == 3 and
 
86
                sqlite3.sqlite_version_info[1] < 3)):
87
87
        trace.warning('Needs at least sqlite 3.3.x')
88
88
        raise bzr_errors.BzrError("incompatible sqlite library")
89
89
 
 
90
 
90
91
try:
91
92
    try:
92
93
        import sqlite3
93
94
        check_pysqlite_version(sqlite3)
94
 
    except (ImportError, bzr_errors.BzrError) as e:
 
95
    except (ImportError, bzr_errors.BzrError):
95
96
        from pysqlite2 import dbapi2 as sqlite3
96
97
        check_pysqlite_version(sqlite3)
97
 
except:
 
98
except BaseException:
98
99
    trace.warning('Needs at least Python2.5 or Python2.4 with the pysqlite2 '
99
 
            'module')
 
100
                  'module')
100
101
    raise bzr_errors.BzrError("missing sqlite library")
101
102
 
102
103
 
103
104
_mapdbs = threading.local()
 
105
 
 
106
 
104
107
def mapdbs():
105
108
    """Get a cache for this thread's db connections."""
106
109
    try:
218
221
        """Open a cache file for a repository.
219
222
 
220
223
        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 
 
224
        use the users global cache directory if the repository has no
222
225
        transport associated with it.
223
226
 
224
227
        :param repository: Repository to open the cache for
226
229
        """
227
230
        from ..transport.local import LocalTransport
228
231
        repo_transport = getattr(repository, "_transport", None)
229
 
        if (repo_transport is not None and
230
 
            isinstance(repo_transport, LocalTransport)):
 
232
        if (repo_transport is not None
 
233
                and isinstance(repo_transport, LocalTransport)):
231
234
            # Even if we don't write to this repo, we should be able
232
235
            # to update its cache.
233
236
            try:
234
 
                repo_transport = remove_readonly_transport_decorator(repo_transport)
 
237
                repo_transport = remove_readonly_transport_decorator(
 
238
                    repo_transport)
235
239
            except bzr_errors.ReadOnlyError:
236
240
                transport = None
237
241
            else:
272
276
        self._cache_updater_klass = cache_updater_klass
273
277
 
274
278
    def get_updater(self, rev):
275
 
        """Update an object that implements the CacheUpdater interface for 
 
279
        """Update an object that implements the CacheUpdater interface for
276
280
        updating this cache.
277
281
        """
278
282
        return self._cache_updater_klass(self, rev)
279
283
 
280
284
 
281
 
DictBzrGitCache = lambda: BzrGitCache(DictGitShaMap(), DictCacheUpdater)
 
285
def DictBzrGitCache():
 
286
    return BzrGitCache(DictGitShaMap(), DictCacheUpdater)
282
287
 
283
288
 
284
289
class DictCacheUpdater(CacheUpdater):
309
314
        elif type_name in ("blob", "tree"):
310
315
            if bzr_key_data is not None:
311
316
                key = type_data = bzr_key_data
312
 
                self.cache.idmap._by_fileid.setdefault(type_data[1], {})[type_data[0]] = hexsha
 
317
                self.cache.idmap._by_fileid.setdefault(type_data[1], {})[
 
318
                    type_data[0]] = hexsha
313
319
        else:
314
320
            raise AssertionError
315
321
        entry = (type_name, type_data)
396
402
            "replace into blobs (sha1, fileid, revid) values (?, ?, ?)",
397
403
            self._blobs)
398
404
        self.db.execute(
399
 
            "replace into commits (sha1, revid, tree_sha, testament3_sha1) values (?, ?, ?, ?)",
400
 
            (self._commit.id, self.revid, self._commit.tree, self._testament3_sha1))
 
405
            "replace into commits (sha1, revid, tree_sha, testament3_sha1) "
 
406
            "values (?, ?, ?, ?)",
 
407
            (self._commit.id, self.revid, self._commit.tree,
 
408
                self._testament3_sha1))
401
409
        return self._commit
402
410
 
403
411
 
404
 
SqliteBzrGitCache = lambda p: BzrGitCache(SqliteGitShaMap(p), SqliteCacheUpdater)
 
412
def SqliteBzrGitCache(p):
 
413
    return BzrGitCache(SqliteGitShaMap(p), SqliteCacheUpdater)
405
414
 
406
415
 
407
416
class SqliteGitCacheFormat(BzrGitCacheFormat):
443
452
            revid text not null
444
453
        );
445
454
        create index if not exists blobs_sha1 on blobs(sha1);
446
 
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
 
455
        create unique index if not exists blobs_fileid_revid on blobs(
 
456
            fileid, revid);
447
457
        create table if not exists trees(
448
458
            sha1 text unique not null check(length(sha1) == 40),
449
459
            fileid text not null,
450
460
            revid text not null
451
461
        );
452
462
        create unique index if not exists trees_sha1 on trees(sha1);
453
 
        create unique index if not exists trees_fileid_revid on trees(fileid, revid);
 
463
        create unique index if not exists trees_fileid_revid on trees(
 
464
            fileid, revid);
454
465
""")
455
466
        try:
456
467
            self.db.executescript(
457
468
                "ALTER TABLE commits ADD testament3_sha1 TEXT;")
458
469
        except sqlite3.OperationalError:
459
 
            pass # Column already exists.
 
470
            pass  # Column already exists.
460
471
 
461
472
    def __repr__(self):
462
473
        return "%s(%r)" % (self.__class__.__name__, self.path)
463
474
 
464
475
    def lookup_commit(self, revid):
465
 
        cursor = self.db.execute("select sha1 from commits where revid = ?", 
466
 
            (revid,))
 
476
        cursor = self.db.execute("select sha1 from commits where revid = ?",
 
477
                                 (revid,))
467
478
        row = cursor.fetchone()
468
479
        if row is not None:
469
480
            return row[0]
473
484
        self.db.commit()
474
485
 
475
486
    def lookup_blob_id(self, fileid, revision):
476
 
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revision)).fetchone()
 
487
        row = self.db.execute(
 
488
            "select sha1 from blobs where fileid = ? and revid = ?",
 
489
            (fileid, revision)).fetchone()
477
490
        if row is not None:
478
491
            return row[0]
479
492
        raise KeyError(fileid)
480
493
 
481
494
    def lookup_tree_id(self, fileid, revision):
482
 
        row = self.db.execute("select sha1 from trees where fileid = ? and revid = ?", (fileid, revision)).fetchone()
 
495
        row = self.db.execute(
 
496
            "select sha1 from trees where fileid = ? and revid = ?",
 
497
            (fileid, revision)).fetchone()
483
498
        if row is not None:
484
499
            return row[0]
485
500
        raise KeyError(fileid)
494
509
            blob: fileid, revid
495
510
        """
496
511
        found = False
497
 
        cursor = self.db.execute("select revid, tree_sha, testament3_sha1 from commits where sha1 = ?", (sha,))
 
512
        cursor = self.db.execute(
 
513
            "select revid, tree_sha, testament3_sha1 from commits where "
 
514
            "sha1 = ?", (sha,))
498
515
        for row in cursor.fetchall():
499
516
            found = True
500
517
            if row[2] is not None:
502
519
            else:
503
520
                verifiers = {}
504
521
            yield ("commit", (row[0], row[1], verifiers))
505
 
        cursor = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,))
 
522
        cursor = self.db.execute(
 
523
            "select fileid, revid from blobs where sha1 = ?", (sha,))
506
524
        for row in cursor.fetchall():
507
525
            found = True
508
526
            yield ("blob", row)
509
 
        cursor = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,))
 
527
        cursor = self.db.execute(
 
528
            "select fileid, revid from trees where sha1 = ?", (sha,))
510
529
        for row in cursor.fetchall():
511
530
            found = True
512
531
            yield ("tree", row)
555
574
        elif type_name == "blob":
556
575
            if bzr_key_data is None:
557
576
                return
558
 
            self.db[b"\0".join((b"blob", bzr_key_data[0], bzr_key_data[1]))] = sha
 
577
            self.db[b"\0".join(
 
578
                (b"blob", bzr_key_data[0], bzr_key_data[1]))] = sha
559
579
            type_data = bzr_key_data
560
580
        elif type_name == "tree":
561
581
            if bzr_key_data is None:
581
601
        return self._commit
582
602
 
583
603
 
584
 
TdbBzrGitCache = lambda p: BzrGitCache(TdbGitShaMap(p), TdbCacheUpdater)
 
604
def TdbBzrGitCache(p):
 
605
    return BzrGitCache(TdbGitShaMap(p), TdbCacheUpdater)
585
606
 
586
607
 
587
608
class TdbGitCacheFormat(BzrGitCacheFormat):
627
648
        else:
628
649
            if path not in mapdbs():
629
650
                mapdbs()[path] = tdb.Tdb(path, self.TDB_HASH_SIZE, tdb.DEFAULT,
630
 
                                          os.O_RDWR|os.O_CREAT)
 
651
                                         os.O_RDWR | os.O_CREAT)
631
652
            self.db = mapdbs()[path]
632
653
        try:
633
654
            if int(self.db[b"version"]) not in (2, 3):
634
 
                trace.warning("SHA Map is incompatible (%s -> %d), rebuilding database.",
635
 
                              self.db[b"version"], self.TDB_MAP_VERSION)
 
655
                trace.warning(
 
656
                    "SHA Map is incompatible (%s -> %d), rebuilding database.",
 
657
                    self.db[b"version"], self.TDB_MAP_VERSION)
636
658
                self.db.clear()
637
659
        except KeyError:
638
660
            pass
681
703
                if len(data) == 3:
682
704
                    yield (type_name, (data[1], data[2], {}))
683
705
                else:
684
 
                    yield (type_name, (data[1], data[2], {"testament3-sha1": data[3]}))
 
706
                    yield (type_name, (data[1], data[2],
 
707
                                       {"testament3-sha1": data[3]}))
685
708
            elif type_name in ("tree", "blob"):
686
709
                yield (type_name, tuple(data[1:]))
687
710
            else:
720
743
 
721
744
    def add(self, obj):
722
745
        self._vf.insert_record_stream(
723
 
            [versionedfile.ChunkedContentFactory((obj.id,), [], None,
724
 
                obj.as_legacy_object_chunks())])
 
746
            [versionedfile.ChunkedContentFactory(
 
747
                (obj.id,), [], None, obj.as_legacy_object_chunks())])
725
748
 
726
749
    def __getitem__(self, sha):
727
750
        stream = self._vf.get_record_stream([(sha,)], 'unordered', True)
751
774
            if type(bzr_key_data) is not dict:
752
775
                raise TypeError(bzr_key_data)
753
776
            self.cache.idmap._add_git_sha(hexsha, b"commit",
754
 
                (self.revid, obj.tree, bzr_key_data))
 
777
                                          (self.revid, obj.tree, bzr_key_data))
755
778
            self.cache.idmap._add_node((b"commit", self.revid, b"X"),
756
 
                b" ".join((hexsha, obj.tree)))
 
779
                                       b" ".join((hexsha, obj.tree)))
757
780
        elif type_name == "blob":
758
781
            self.cache.idmap._add_git_sha(hexsha, b"blob", bzr_key_data)
759
782
            self.cache.idmap._add_node((b"blob", bzr_key_data[0],
760
 
                bzr_key_data[1]), hexsha)
 
783
                                        bzr_key_data[1]), hexsha)
761
784
        elif type_name == "tree":
762
785
            self.cache.idmap._add_git_sha(hexsha, b"tree", bzr_key_data)
763
786
        else:
770
793
class IndexBzrGitCache(BzrGitCache):
771
794
 
772
795
    def __init__(self, transport=None):
773
 
        mapper = versionedfile.ConstantMapper("trees")
774
796
        shamap = IndexGitShaMap(transport.clone('index'))
775
 
        from .transportgit import TransportObjectStore
776
797
        super(IndexBzrGitCache, self).__init__(shamap, IndexCacheUpdater)
777
798
 
778
799
 
816
837
            for name in self._transport.list_dir("."):
817
838
                if not name.endswith(".rix"):
818
839
                    continue
819
 
                x = _mod_btree_index.BTreeGraphIndex(self._transport, name,
820
 
                    self._transport.stat(name).st_size)
 
840
                x = _mod_btree_index.BTreeGraphIndex(
 
841
                    self._transport, name, self._transport.stat(name).st_size)
821
842
                self._index.insert_index(0, x)
822
843
 
823
844
    @classmethod
840
861
 
841
862
    def repack(self):
842
863
        if self._builder is not None:
843
 
            raise errors.BzrError('builder already open')
 
864
            raise bzr_errors.BzrError('builder already open')
844
865
        self.start_write_group()
845
866
        self._builder.add_nodes(
846
867
            ((key, value) for (_, key, value) in
856
877
 
857
878
    def start_write_group(self):
858
879
        if self._builder is not None:
859
 
            raise errors.BzrError('builder already open')
 
880
            raise bzr_errors.BzrError('builder already open')
860
881
        self._builder = _mod_btree_index.BTreeBuilder(0, key_elements=3)
861
882
        self._name = osutils.sha()
862
883
 
863
884
    def commit_write_group(self):
864
885
        if self._builder is None:
865
 
            raise errors.BzrError('builder not open')
 
886
            raise bzr_errors.BzrError('builder not open')
866
887
        stream = self._builder.finish()
867
888
        name = self._name.hexdigest() + ".rix"
868
889
        size = self._transport.put_file(name, stream)
873
894
 
874
895
    def abort_write_group(self):
875
896
        if self._builder is None:
876
 
            raise errors.BzrError('builder not open')
 
897
            raise bzr_errors.BzrError('builder not open')
877
898
        self._builder = None
878
899
        self._name = None
879
900
 
955
976
        """Return set of all the revisions that are not present."""
956
977
        missing_revids = set(revids)
957
978
        for _, key, value in self._index.iter_entries((
958
 
            (b"commit", revid, b"X") for revid in revids)):
 
979
                (b"commit", revid, b"X") for revid in revids)):
959
980
            missing_revids.remove(key[1])
960
981
        return missing_revids
961
982
 
967
988
 
968
989
formats = registry.Registry()
969
990
formats.register(TdbGitCacheFormat().get_format_string(),
970
 
    TdbGitCacheFormat())
 
991
                 TdbGitCacheFormat())
971
992
formats.register(SqliteGitCacheFormat().get_format_string(),
972
 
    SqliteGitCacheFormat())
 
993
                 SqliteGitCacheFormat())
973
994
formats.register(IndexGitCacheFormat().get_format_string(),
974
 
    IndexGitCacheFormat())
 
995
                 IndexGitCacheFormat())
975
996
# In the future, this will become the default:
976
997
formats.register('default', IndexGitCacheFormat())
977
998
 
978
999
 
979
 
 
980
1000
def migrate_ancient_formats(repo_transport):
981
1001
    # Migrate older cache formats
982
1002
    repo_transport = remove_readonly_transport_decorator(repo_transport)
988
1008
        repo_transport.mkdir("git")
989
1009
    except bzr_errors.FileExists:
990
1010
        return
991
 
    # Prefer migrating git.db over git.tdb, since the latter may not 
 
1011
    # Prefer migrating git.db over git.tdb, since the latter may not
992
1012
    # be openable on some platforms.
993
1013
    if has_sqlite:
994
1014
        SqliteGitCacheFormat().initialize(repo_transport.clone("git"))
1021
1041
        try:
1022
1042
            migrate_ancient_formats(repo_transport)
1023
1043
        except bzr_errors.ReadOnlyError:
1024
 
            pass # Not much we can do
 
1044
            pass  # Not much we can do
1025
1045
    return BzrGitCacheFormat.from_repository(repository)