/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 cache.py

Implement GitRevisionTree.get_file_sha1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
    return ret
55
55
 
56
56
 
57
 
def get_remote_cache_transport():
 
57
def get_remote_cache_transport(repository):
58
58
    """Retrieve the transport to use when accessing (unwritable) remote 
59
59
    repositories.
60
60
    """
61
 
    return get_transport(get_cache_dir())
 
61
    uuid = getattr(repository, "uuid", None)
 
62
    if uuid is None:
 
63
        path = get_cache_dir()
 
64
    else:
 
65
        path = os.path.join(get_cache_dir(), uuid)
 
66
        if not os.path.isdir(path):
 
67
            os.mkdir(path)
 
68
    return get_transport(path)
62
69
 
63
70
 
64
71
def check_pysqlite_version(sqlite3):
100
107
    def lookup_git_sha(self, sha):
101
108
        """Lookup a Git sha in the database.
102
109
        :param sha: Git object sha
103
 
        :return: (type, type_data) with type_data:
 
110
        :return: list with (type, type_data) tuples with type_data:
104
111
            commit: revid, tree_sha, verifiers
105
112
            blob: fileid, revid
106
113
            tree: fileid, revid
120
127
        """
121
128
        raise NotImplementedError(self.lookup_tree_id)
122
129
 
 
130
    def lookup_commit(self, revid):
 
131
        """Retrieve a Git commit SHA by Bazaar revision id.
 
132
        """
 
133
        raise NotImplementedError(self.lookup_commit)
 
134
 
123
135
    def revids(self):
124
136
        """List the revision ids known."""
125
137
        raise NotImplementedError(self.revids)
203
215
        :param repository: Repository to open the cache for
204
216
        :return: A `BzrGitCache`
205
217
        """
 
218
        from bzrlib.transport.local import LocalTransport
206
219
        repo_transport = getattr(repository, "_transport", None)
207
 
        if repo_transport is not None:
208
 
            # Even if we don't write to this repo, we should be able 
 
220
        if repo_transport is not None and isinstance(repo_transport, LocalTransport):
 
221
            # Even if we don't write to this repo, we should be able
209
222
            # to update its cache.
210
223
            repo_transport = remove_readonly_transport_decorator(repo_transport)
211
224
            try:
214
227
                pass
215
228
            transport = repo_transport.clone('git')
216
229
        else:
217
 
            transport = get_remote_cache_transport()
 
230
            transport = get_remote_cache_transport(repository)
218
231
        return cls.from_transport(transport)
219
232
 
220
233
 
267
280
        if obj.type_name == "commit":
268
281
            self._commit = obj
269
282
            assert type(ie) is dict
 
283
            key = self.revid
270
284
            type_data = (self.revid, self._commit.tree, ie)
271
285
            self.cache.idmap._by_revid[self.revid] = obj.id
272
286
        elif obj.type_name in ("blob", "tree"):
275
289
                    revision = ie.revision
276
290
                else:
277
291
                    revision = self.revid
278
 
                type_data = (ie.file_id, revision)
 
292
                key = type_data = (ie.file_id, revision)
279
293
                self.cache.idmap._by_fileid.setdefault(type_data[1], {})[type_data[0]] = obj.id
280
294
        else:
281
295
            raise AssertionError
282
 
        self.cache.idmap._by_sha[obj.id] = (obj.type_name, type_data)
 
296
        entry = (obj.type_name, type_data)
 
297
        self.cache.idmap._by_sha.setdefault(obj.id, {})[key] = entry
283
298
 
284
299
    def finish(self):
285
300
        if self._commit is None:
299
314
        return self._by_fileid[revision][fileid]
300
315
 
301
316
    def lookup_git_sha(self, sha):
302
 
        return self._by_sha[sha]
 
317
        for entry in self._by_sha[sha].itervalues():
 
318
            yield entry
303
319
 
304
320
    def lookup_tree_id(self, fileid, revision):
305
321
        return self._by_fileid[revision][fileid]
308
324
        return self._by_revid[revid]
309
325
 
310
326
    def revids(self):
311
 
        for key, (type, type_data) in self._by_sha.iteritems():
312
 
            if type == "commit":
313
 
                yield type_data[0]
 
327
        for key, entries in self._by_sha.iteritems():
 
328
            for (type, type_data) in entries.values():
 
329
                if type == "commit":
 
330
                    yield type_data[0]
314
331
 
315
332
    def sha1s(self):
316
333
        return self._by_sha.iterkeys()
329
346
    def add_object(self, obj, ie, path):
330
347
        if obj.type_name == "commit":
331
348
            self._commit = obj
332
 
            self._testament3_sha1 = ie["testament3-sha1"]
 
349
            self._testament3_sha1 = ie.get("testament3-sha1")
333
350
            assert type(ie) is dict
334
351
        elif obj.type_name == "tree":
335
352
            if ie is not None:
447
464
            tree: fileid, revid
448
465
            blob: fileid, revid
449
466
        """
450
 
        row = self.db.execute("select revid, tree_sha, testament3_sha1 from commits where sha1 = ?", (sha,)).fetchone()
451
 
        if row is not None:
452
 
            return ("commit", (row[0], row[1], {"testament3-sha1": row[2]}))
453
 
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
454
 
        if row is not None:
455
 
            return ("blob", row)
456
 
        row = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,)).fetchone()
457
 
        if row is not None:
458
 
            return ("tree", row)
459
 
        raise KeyError(sha)
 
467
        found = False
 
468
        cursor = self.db.execute("select revid, tree_sha, testament3_sha1 from commits where sha1 = ?", (sha,))
 
469
        for row in cursor.fetchall():
 
470
            found = True
 
471
            if row[2] is not None:
 
472
                verifiers = {"testament3-sha1": row[2]}
 
473
            else:
 
474
                verifiers = {}
 
475
            yield ("commit", (row[0], row[1], verifiers))
 
476
        cursor = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,))
 
477
        for row in cursor.fetchall():
 
478
            found = True
 
479
            yield ("blob", row)
 
480
        cursor = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,))
 
481
        for row in cursor.fetchall():
 
482
            found = True
 
483
            yield ("tree", row)
 
484
        if not found:
 
485
            raise KeyError(sha)
460
486
 
461
487
    def revids(self):
462
488
        """List the revision ids known."""
485
511
        if obj.type_name == "commit":
486
512
            self.db["commit\0" + self.revid] = "\0".join((sha, obj.tree))
487
513
            assert type(ie) is dict, "was %r" % ie
488
 
            type_data = (self.revid, obj.tree, ie["testament3-sha1"])
 
514
            type_data = (self.revid, obj.tree)
 
515
            try:
 
516
                type_data += (ie["testament3-sha1"],)
 
517
            except KeyError:
 
518
                pass
489
519
            self._commit = obj
490
520
        elif obj.type_name == "blob":
491
521
            if ie is None:
498
528
            type_data = (ie.file_id, self.revid)
499
529
        else:
500
530
            raise AssertionError
501
 
        self.db["git\0" + sha] = "\0".join((obj.type_name, ) + type_data)
 
531
        entry = "\0".join((obj.type_name, ) + type_data) + "\n"
 
532
        key = "git\0" + sha
 
533
        try:
 
534
            oldval = self.db[key]
 
535
        except KeyError:
 
536
            self.db[key] = entry
 
537
        else:
 
538
            if oldval[-1] != "\n":
 
539
                self.db[key] = "".join([oldval, "\n", entry])
 
540
            else:
 
541
                self.db[key] = "".join([oldval, entry])
502
542
 
503
543
    def finish(self):
504
544
        if self._commit is None:
508
548
 
509
549
TdbBzrGitCache = lambda p: BzrGitCache(TdbGitShaMap(p), None, TdbCacheUpdater)
510
550
 
 
551
 
511
552
class TdbGitCacheFormat(BzrGitCacheFormat):
512
553
    """Cache format for tdb-based caches."""
513
554
 
516
557
 
517
558
    def open(self, transport):
518
559
        try:
519
 
            basepath = transport.local_abspath(".")
 
560
            basepath = transport.local_abspath(".").encode(osutils._fs_enc)
520
561
        except bzrlib.errors.NotLocalUrl:
521
562
            basepath = get_cache_dir()
 
563
        assert isinstance(basepath, str)
522
564
        try:
523
565
            return TdbBzrGitCache(os.path.join(basepath, "idmap.tdb"))
524
566
        except ImportError:
547
589
        if path is None:
548
590
            self.db = {}
549
591
        else:
 
592
            assert isinstance(path, str)
550
593
            if not mapdbs().has_key(path):
551
594
                mapdbs()[path] = tdb.Tdb(path, self.TDB_HASH_SIZE, tdb.DEFAULT,
552
595
                                          os.O_RDWR|os.O_CREAT)
592
635
        """
593
636
        if len(sha) == 40:
594
637
            sha = hex_to_sha(sha)
595
 
        data = self.db["git\0" + sha].split("\0")
596
 
        if data[0] == "commit":
597
 
            if len(data) == 3:
598
 
                return (data[0], (data[1], data[2], {}))
 
638
        value = self.db["git\0" + sha]
 
639
        for data in value.splitlines():
 
640
            data = data.split("\0")
 
641
            if data[0] == "commit":
 
642
                if len(data) == 3:
 
643
                    yield (data[0], (data[1], data[2], {}))
 
644
                else:
 
645
                    yield (data[0], (data[1], data[2], {"testament3-sha1": data[3]}))
 
646
            elif data[0] in ("tree", "blob"):
 
647
                yield (data[0], tuple(data[1:]))
599
648
            else:
600
 
                return (data[0], (data[1], data[2], {"testament3-sha1": data[3]}))
601
 
        else:
602
 
            return (data[0], tuple(data[1:]))
 
649
                raise AssertionError("unknown type %r" % data[0])
603
650
 
604
651
    def missing_revisions(self, revids):
605
652
        ret = set()
822
869
            except StopIteration:
823
870
                raise KeyError
824
871
 
825
 
    def _iter_keys_prefix(self, prefix):
 
872
    def _iter_entries_prefix(self, prefix):
826
873
        for entry in self._index.iter_entries_prefix([prefix]):
827
 
            yield entry[1]
 
874
            yield (entry[1], entry[2])
828
875
        if self._builder is not None:
829
876
            for entry in self._builder.iter_entries_prefix([prefix]):
830
 
                yield entry[1]
 
877
                yield (entry[1], entry[2])
831
878
 
832
879
    def lookup_commit(self, revid):
833
880
        return self._get_entry(("commit", revid, "X"))[:40]
836
883
        if hexsha is not None:
837
884
            self._name.update(hexsha)
838
885
            if type == "commit":
839
 
                td = (type_data[0], type_data[1], type_data[2]["testament3-sha1"])
 
886
                td = (type_data[0], type_data[1])
 
887
                try:
 
888
                    td += (type_data[2]["testament3-sha1"],)
 
889
                except KeyError:
 
890
                    pass
840
891
            else:
841
892
                td = type_data
842
893
            self._add_node(("git", hexsha, "X"), " ".join((type,) + td))
851
902
    def lookup_git_sha(self, sha):
852
903
        if len(sha) == 20:
853
904
            sha = sha_to_hex(sha)
854
 
        data = self._get_entry(("git", sha, "X")).split(" ", 3)
855
 
        if data[0] == "commit":
856
 
            return ("commit", (data[1], data[2], {"testament3-sha1": data[3]}))
857
 
        else:
858
 
            return (data[0], tuple(data[1:]))
 
905
        found = False
 
906
        for key, value in self._iter_entries_prefix(("git", sha, None)):
 
907
            found = True
 
908
            data = value.split(" ", 3)
 
909
            if data[0] == "commit":
 
910
                if data[3]:
 
911
                    verifiers = {"testament3-sha1": data[3]}
 
912
                else:
 
913
                    verifiers = {}
 
914
                yield ("commit", (data[1], data[2], verifiers))
 
915
            else:
 
916
                yield (data[0], tuple(data[1:]))
 
917
        if not found:
 
918
            raise KeyError(sha)
859
919
 
860
920
    def revids(self):
861
921
        """List the revision ids known."""
862
 
        for key in self._iter_keys_prefix(("commit", None, None)):
 
922
        for key, value in self._iter_entries_prefix(("commit", None, None)):
863
923
            yield key[1]
864
924
 
865
925
    def missing_revisions(self, revids):
872
932
 
873
933
    def sha1s(self):
874
934
        """List the SHA1s."""
875
 
        for key in self._iter_keys_prefix(("git", None, None)):
 
935
        for key, value in self._iter_entries_prefix(("git", None, None)):
876
936
            yield key[1]
877
937
 
878
938
 
895
955
 
896
956
 
897
957
def migrate_ancient_formats(repo_transport):
 
958
    # Migrate older cache formats
 
959
    repo_transport = remove_readonly_transport_decorator(repo_transport)
 
960
    has_sqlite = repo_transport.has("git.db")
 
961
    has_tdb = repo_transport.has("git.tdb")
 
962
    if not has_sqlite or has_tdb:
 
963
        return
 
964
    try:
 
965
        repo_transport.mkdir("git")
 
966
    except bzrlib.errors.FileExists:
 
967
        return
898
968
    # Prefer migrating git.db over git.tdb, since the latter may not 
899
969
    # be openable on some platforms.
900
 
    if repo_transport.has("git.db"):
 
970
    if has_sqlite:
901
971
        SqliteGitCacheFormat().initialize(repo_transport.clone("git"))
902
972
        repo_transport.rename("git.db", "git/idmap.db")
903
 
    elif repo_transport.has("git.tdb"):
 
973
    elif has_tdb:
904
974
        TdbGitCacheFormat().initialize(repo_transport.clone("git"))
905
975
        repo_transport.rename("git.tdb", "git/idmap.tdb")
906
976
 
922
992
    """
923
993
    repo_transport = getattr(repository, "_transport", None)
924
994
    if repo_transport is not None:
925
 
        # Migrate older cache formats
926
 
        repo_transport = remove_readonly_transport_decorator(repo_transport)
927
 
        try:
928
 
            repo_transport.mkdir("git")
929
 
        except bzrlib.errors.FileExists:
930
 
            pass
931
 
        else:
932
 
            migrate_ancient_formats(repo_transport)
 
995
        migrate_ancient_formats(repo_transport)
933
996
    return BzrGitCacheFormat.from_repository(repository)