/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

Add 'github:' directory service.

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
 
221
            isinstance(repo_transport, LocalTransport)):
 
222
            # Even if we don't write to this repo, we should be able
209
223
            # to update its cache.
210
 
            repo_transport = remove_readonly_transport_decorator(repo_transport)
211
224
            try:
212
 
                repo_transport.mkdir('git')
213
 
            except bzrlib.errors.FileExists:
214
 
                pass
215
 
            transport = repo_transport.clone('git')
 
225
                repo_transport = remove_readonly_transport_decorator(repo_transport)
 
226
            except bzrlib.errors.ReadOnlyError:
 
227
                transport = None
 
228
            else:
 
229
                try:
 
230
                    repo_transport.mkdir('git')
 
231
                except bzrlib.errors.FileExists:
 
232
                    pass
 
233
                transport = repo_transport.clone('git')
216
234
        else:
217
 
            transport = get_remote_cache_transport()
 
235
            transport = None
 
236
        if transport is None:
 
237
            transport = get_remote_cache_transport(repository)
218
238
        return cls.from_transport(transport)
219
239
 
220
240
 
267
287
        if obj.type_name == "commit":
268
288
            self._commit = obj
269
289
            assert type(ie) is dict
 
290
            key = self.revid
270
291
            type_data = (self.revid, self._commit.tree, ie)
271
292
            self.cache.idmap._by_revid[self.revid] = obj.id
272
293
        elif obj.type_name in ("blob", "tree"):
275
296
                    revision = ie.revision
276
297
                else:
277
298
                    revision = self.revid
278
 
                type_data = (ie.file_id, revision)
 
299
                key = type_data = (ie.file_id, revision)
279
300
                self.cache.idmap._by_fileid.setdefault(type_data[1], {})[type_data[0]] = obj.id
280
301
        else:
281
302
            raise AssertionError
282
 
        self.cache.idmap._by_sha[obj.id] = (obj.type_name, type_data)
 
303
        entry = (obj.type_name, type_data)
 
304
        self.cache.idmap._by_sha.setdefault(obj.id, {})[key] = entry
283
305
 
284
306
    def finish(self):
285
307
        if self._commit is None:
299
321
        return self._by_fileid[revision][fileid]
300
322
 
301
323
    def lookup_git_sha(self, sha):
302
 
        return self._by_sha[sha]
 
324
        for entry in self._by_sha[sha].itervalues():
 
325
            yield entry
303
326
 
304
327
    def lookup_tree_id(self, fileid, revision):
305
328
        return self._by_fileid[revision][fileid]
308
331
        return self._by_revid[revid]
309
332
 
310
333
    def revids(self):
311
 
        for key, (type, type_data) in self._by_sha.iteritems():
312
 
            if type == "commit":
313
 
                yield type_data[0]
 
334
        for key, entries in self._by_sha.iteritems():
 
335
            for (type, type_data) in entries.values():
 
336
                if type == "commit":
 
337
                    yield type_data[0]
314
338
 
315
339
    def sha1s(self):
316
340
        return self._by_sha.iterkeys()
329
353
    def add_object(self, obj, ie, path):
330
354
        if obj.type_name == "commit":
331
355
            self._commit = obj
332
 
            self._testament3_sha1 = ie["testament3-sha1"]
 
356
            self._testament3_sha1 = ie.get("testament3-sha1")
333
357
            assert type(ie) is dict
334
358
        elif obj.type_name == "tree":
335
359
            if ie is not None:
447
471
            tree: fileid, revid
448
472
            blob: fileid, revid
449
473
        """
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)
 
474
        found = False
 
475
        cursor = self.db.execute("select revid, tree_sha, testament3_sha1 from commits where sha1 = ?", (sha,))
 
476
        for row in cursor.fetchall():
 
477
            found = True
 
478
            if row[2] is not None:
 
479
                verifiers = {"testament3-sha1": row[2]}
 
480
            else:
 
481
                verifiers = {}
 
482
            yield ("commit", (row[0], row[1], verifiers))
 
483
        cursor = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,))
 
484
        for row in cursor.fetchall():
 
485
            found = True
 
486
            yield ("blob", row)
 
487
        cursor = self.db.execute("select fileid, revid from trees where sha1 = ?", (sha,))
 
488
        for row in cursor.fetchall():
 
489
            found = True
 
490
            yield ("tree", row)
 
491
        if not found:
 
492
            raise KeyError(sha)
460
493
 
461
494
    def revids(self):
462
495
        """List the revision ids known."""
485
518
        if obj.type_name == "commit":
486
519
            self.db["commit\0" + self.revid] = "\0".join((sha, obj.tree))
487
520
            assert type(ie) is dict, "was %r" % ie
488
 
            type_data = (self.revid, obj.tree, ie["testament3-sha1"])
 
521
            type_data = (self.revid, obj.tree)
 
522
            try:
 
523
                type_data += (ie["testament3-sha1"],)
 
524
            except KeyError:
 
525
                pass
489
526
            self._commit = obj
490
527
        elif obj.type_name == "blob":
491
528
            if ie is None:
498
535
            type_data = (ie.file_id, self.revid)
499
536
        else:
500
537
            raise AssertionError
501
 
        self.db["git\0" + sha] = "\0".join((obj.type_name, ) + type_data)
 
538
        entry = "\0".join((obj.type_name, ) + type_data) + "\n"
 
539
        key = "git\0" + sha
 
540
        try:
 
541
            oldval = self.db[key]
 
542
        except KeyError:
 
543
            self.db[key] = entry
 
544
        else:
 
545
            if oldval[-1] != "\n":
 
546
                self.db[key] = "".join([oldval, "\n", entry])
 
547
            else:
 
548
                self.db[key] = "".join([oldval, entry])
502
549
 
503
550
    def finish(self):
504
551
        if self._commit is None:
508
555
 
509
556
TdbBzrGitCache = lambda p: BzrGitCache(TdbGitShaMap(p), None, TdbCacheUpdater)
510
557
 
 
558
 
511
559
class TdbGitCacheFormat(BzrGitCacheFormat):
512
560
    """Cache format for tdb-based caches."""
513
561
 
516
564
 
517
565
    def open(self, transport):
518
566
        try:
519
 
            basepath = transport.local_abspath(".")
 
567
            basepath = transport.local_abspath(".").encode(osutils._fs_enc)
520
568
        except bzrlib.errors.NotLocalUrl:
521
569
            basepath = get_cache_dir()
 
570
        assert isinstance(basepath, str)
522
571
        try:
523
572
            return TdbBzrGitCache(os.path.join(basepath, "idmap.tdb"))
524
573
        except ImportError:
547
596
        if path is None:
548
597
            self.db = {}
549
598
        else:
 
599
            assert isinstance(path, str)
550
600
            if not mapdbs().has_key(path):
551
601
                mapdbs()[path] = tdb.Tdb(path, self.TDB_HASH_SIZE, tdb.DEFAULT,
552
602
                                          os.O_RDWR|os.O_CREAT)
576
626
        return "%s(%r)" % (self.__class__.__name__, self.path)
577
627
 
578
628
    def lookup_commit(self, revid):
579
 
        return sha_to_hex(self.db["commit\0" + revid][:20])
 
629
        try:
 
630
            return sha_to_hex(self.db["commit\0" + revid][:20])
 
631
        except KeyError:
 
632
            raise KeyError("No cache entry for %r" % revid)
580
633
 
581
634
    def lookup_blob_id(self, fileid, revision):
582
635
        return sha_to_hex(self.db["\0".join(("blob", fileid, revision))])
592
645
        """
593
646
        if len(sha) == 40:
594
647
            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], {}))
 
648
        value = self.db["git\0" + sha]
 
649
        for data in value.splitlines():
 
650
            data = data.split("\0")
 
651
            if data[0] == "commit":
 
652
                if len(data) == 3:
 
653
                    yield (data[0], (data[1], data[2], {}))
 
654
                else:
 
655
                    yield (data[0], (data[1], data[2], {"testament3-sha1": data[3]}))
 
656
            elif data[0] in ("tree", "blob"):
 
657
                yield (data[0], tuple(data[1:]))
599
658
            else:
600
 
                return (data[0], (data[1], data[2], {"testament3-sha1": data[3]}))
601
 
        else:
602
 
            return (data[0], tuple(data[1:]))
 
659
                raise AssertionError("unknown type %r" % data[0])
603
660
 
604
661
    def missing_revisions(self, revids):
605
662
        ret = set()
822
879
            except StopIteration:
823
880
                raise KeyError
824
881
 
825
 
    def _iter_keys_prefix(self, prefix):
 
882
    def _iter_entries_prefix(self, prefix):
826
883
        for entry in self._index.iter_entries_prefix([prefix]):
827
 
            yield entry[1]
 
884
            yield (entry[1], entry[2])
828
885
        if self._builder is not None:
829
886
            for entry in self._builder.iter_entries_prefix([prefix]):
830
 
                yield entry[1]
 
887
                yield (entry[1], entry[2])
831
888
 
832
889
    def lookup_commit(self, revid):
833
890
        return self._get_entry(("commit", revid, "X"))[:40]
836
893
        if hexsha is not None:
837
894
            self._name.update(hexsha)
838
895
            if type == "commit":
839
 
                td = (type_data[0], type_data[1], type_data[2]["testament3-sha1"])
 
896
                td = (type_data[0], type_data[1])
 
897
                try:
 
898
                    td += (type_data[2]["testament3-sha1"],)
 
899
                except KeyError:
 
900
                    pass
840
901
            else:
841
902
                td = type_data
842
903
            self._add_node(("git", hexsha, "X"), " ".join((type,) + td))
851
912
    def lookup_git_sha(self, sha):
852
913
        if len(sha) == 20:
853
914
            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:]))
 
915
        found = False
 
916
        for key, value in self._iter_entries_prefix(("git", sha, None)):
 
917
            found = True
 
918
            data = value.split(" ", 3)
 
919
            if data[0] == "commit":
 
920
                if data[3]:
 
921
                    verifiers = {"testament3-sha1": data[3]}
 
922
                else:
 
923
                    verifiers = {}
 
924
                yield ("commit", (data[1], data[2], verifiers))
 
925
            else:
 
926
                yield (data[0], tuple(data[1:]))
 
927
        if not found:
 
928
            raise KeyError(sha)
859
929
 
860
930
    def revids(self):
861
931
        """List the revision ids known."""
862
 
        for key in self._iter_keys_prefix(("commit", None, None)):
 
932
        for key, value in self._iter_entries_prefix(("commit", None, None)):
863
933
            yield key[1]
864
934
 
865
935
    def missing_revisions(self, revids):
872
942
 
873
943
    def sha1s(self):
874
944
        """List the SHA1s."""
875
 
        for key in self._iter_keys_prefix(("git", None, None)):
 
945
        for key, value in self._iter_entries_prefix(("git", None, None)):
876
946
            yield key[1]
877
947
 
878
948
 
895
965
 
896
966
 
897
967
def migrate_ancient_formats(repo_transport):
 
968
    # Migrate older cache formats
 
969
    repo_transport = remove_readonly_transport_decorator(repo_transport)
 
970
    has_sqlite = repo_transport.has("git.db")
 
971
    has_tdb = repo_transport.has("git.tdb")
 
972
    if not has_sqlite or has_tdb:
 
973
        return
 
974
    try:
 
975
        repo_transport.mkdir("git")
 
976
    except bzrlib.errors.FileExists:
 
977
        return
898
978
    # Prefer migrating git.db over git.tdb, since the latter may not 
899
979
    # be openable on some platforms.
900
 
    if repo_transport.has("git.db"):
 
980
    if has_sqlite:
901
981
        SqliteGitCacheFormat().initialize(repo_transport.clone("git"))
902
982
        repo_transport.rename("git.db", "git/idmap.db")
903
 
    elif repo_transport.has("git.tdb"):
 
983
    elif has_tdb:
904
984
        TdbGitCacheFormat().initialize(repo_transport.clone("git"))
905
985
        repo_transport.rename("git.tdb", "git/idmap.tdb")
906
986
 
907
987
 
908
988
def remove_readonly_transport_decorator(transport):
909
989
    if transport.is_readonly():
910
 
        return transport._decorated
 
990
        try:
 
991
            return transport._decorated
 
992
        except AttributeError:
 
993
            raise bzrlib.errors.ReadOnlyError(transport)
911
994
    return transport
912
995
 
913
996
 
922
1005
    """
923
1006
    repo_transport = getattr(repository, "_transport", None)
924
1007
    if repo_transport is not None:
925
 
        # Migrate older cache formats
926
 
        repo_transport = remove_readonly_transport_decorator(repo_transport)
927
1008
        try:
928
 
            repo_transport.mkdir("git")
929
 
        except bzrlib.errors.FileExists:
930
 
            pass
931
 
        else:
932
1009
            migrate_ancient_formats(repo_transport)
 
1010
        except bzrlib.errors.ReadOnlyError:
 
1011
            pass # Not much we can do
933
1012
    return BzrGitCacheFormat.from_repository(repository)