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

Merge thin-pack work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
 
1
# Copyright (C) 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Map from Git sha's to Bazaar objects."""
18
18
 
19
 
import os
20
 
 
21
 
import bzrlib
22
 
from bzrlib.errors import (
23
 
    NoSuchRevision,
24
 
    )
25
 
 
26
 
 
27
 
def check_pysqlite_version(sqlite3):
28
 
    """Check that sqlite library is compatible.
29
 
 
30
 
    """
31
 
    if (sqlite3.sqlite_version_info[0] < 3 or 
32
 
            (sqlite3.sqlite_version_info[0] == 3 and 
33
 
             sqlite3.sqlite_version_info[1] < 3)):
34
 
        warning('Needs at least sqlite 3.3.x')
35
 
        raise bzrlib.errors.BzrError("incompatible sqlite library")
36
 
 
37
 
try:
38
 
    try:
39
 
        import sqlite3
40
 
        check_pysqlite_version(sqlite3)
41
 
    except (ImportError, bzrlib.errors.BzrError), e: 
42
 
        from pysqlite2 import dbapi2 as sqlite3
43
 
        check_pysqlite_version(sqlite3)
44
 
except:
45
 
    warning('Needs at least Python2.5 or Python2.4 with the pysqlite2 '
46
 
            'module')
47
 
    raise bzrlib.errors.BzrError("missing sqlite library")
48
 
 
 
19
from bzrlib.errors import NoSuchRevision
 
20
 
 
21
 
 
22
class GitObjectConverter(object):
 
23
 
 
24
    def __init__(self, repository, mapping=None):
 
25
        self.repository = repository
 
26
        if mapping is None:
 
27
            self.mapping = self.repository.get_mapping()
 
28
        else:
 
29
            self.mapping = mapping
 
30
 
 
31
    def __getitem__(self, sha):
 
32
        # Commit
 
33
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
 
34
        try:
 
35
            rev = self.repository.get_revision(revid)
 
36
        except NoSuchRevision:
 
37
            pass
 
38
        else:
 
39
            return reconstruct_git_commit(rev)
 
40
 
 
41
        # TODO: Yeah, this won't scale, but the only alternative is a 
 
42
        # custom map..
 
43
        for (fileid, revision) in self.repository.texts.keys():
 
44
            blob = self._get_blob(
 
45
            print revision
 
46
            
49
47
 
50
48
class GitShaMap(object):
51
 
    """Git<->Bzr revision id mapping database."""
 
49
 
 
50
    def __init__(self, transport):
 
51
        self.transport = transport
52
52
 
53
53
    def add_entry(self, sha, type, type_data):
54
54
        """Add a new entry to the database.
55
55
        """
56
56
        raise NotImplementedError(self.add_entry)
57
57
 
58
 
    def lookup_tree(self, path, revid):
59
 
        """Lookup the SHA of a git tree."""
60
 
        raise NotImplementedError(self.lookup_tree)
61
 
 
62
 
    def lookup_blob(self, fileid, revid):
63
 
        raise NotImplementedError(self.lookup_blob)
64
 
 
65
58
    def lookup_git_sha(self, sha):
66
59
        """Lookup a Git sha in the database.
67
60
 
71
64
        """
72
65
        raise NotImplementedError(self.lookup_git_sha)
73
66
 
74
 
    def revids(self):
75
 
        """List the revision ids known."""
76
 
        raise NotImplementedError(self.revids)
77
 
 
78
 
    def commit(self):
79
 
        """Commit any pending changes."""
80
 
 
81
 
 
82
 
class DictGitShaMap(GitShaMap):
83
 
 
84
 
    def __init__(self):
85
 
        self.dict = {}
86
 
 
87
 
    def add_entry(self, sha, type, type_data):
88
 
        self.dict[sha] = (type, type_data)
89
 
 
90
 
    def lookup_git_sha(self, sha):
91
 
        return self.dict[sha]
92
 
 
93
 
    def lookup_tree(self, path, revid):
94
 
        for k, v in self.dict.iteritems():
95
 
            if v == ("tree", (path, revid)):
96
 
                return k
97
 
        raise KeyError((path, revid))
98
 
 
99
 
    def lookup_blob(self, fileid, revid):
100
 
        for k, v in self.dict.iteritems():
101
 
            if v == ("blob", (fileid, revid)):
102
 
                return k
103
 
        raise KeyError((fileid, revid))
104
 
 
105
 
    def revids(self):
106
 
        for key, (type, type_data) in self.dict.iteritems():
107
 
            if type == "commit":
108
 
                yield type_data[0]
109
 
 
110
 
 
111
 
class SqliteGitShaMap(GitShaMap):
112
 
 
113
 
    def __init__(self, transport=None):
114
 
        self.transport = transport
115
 
        if transport is None:
116
 
            self.db = sqlite3.connect(":memory:")
117
 
        else:
118
 
            self.db = sqlite3.connect(
119
 
                os.path.join(self.transport.local_abspath("."), "git.db"))
120
 
        self.db.executescript("""
121
 
        create table if not exists commits(sha1 text, revid text, tree_sha text);
122
 
        create index if not exists commit_sha1 on commits(sha1);
123
 
        create unique index if not exists commit_revid on commits(revid);
124
 
        create table if not exists blobs(sha1 text, fileid text, revid text);
125
 
        create index if not exists blobs_sha1 on blobs(sha1);
126
 
        create unique index if not exists blobs_fileid_revid on blobs(fileid, revid);
127
 
        create table if not exists trees(sha1 text, path text, revid text);
128
 
        create index if not exists trees_sha1 on trees(sha1);
129
 
        create unique index if not exists trees_path_revid on trees(path, revid);
130
 
""")
131
 
 
132
 
    def _parent_lookup(self, revid):
133
 
        return self.db.execute("select sha1 from commits where revid = ?", (revid,)).fetchone()[0].encode("utf-8")
134
 
 
135
 
    def commit(self):
136
 
        self.db.commit()
137
 
 
138
 
    def add_entry(self, sha, type, type_data):
139
 
        """Add a new entry to the database.
140
 
        """
141
 
        assert isinstance(type_data, tuple)
142
 
        assert isinstance(sha, str), "type was %r" % sha
143
 
        if type == "commit":
144
 
            self.db.execute("replace into commits (sha1, revid, tree_sha) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
145
 
        elif type == "blob":
146
 
            self.db.execute("replace into blobs (sha1, fileid, revid) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
147
 
        elif type == "tree":
148
 
            self.db.execute("replace into trees (sha1, path, revid) values (?, ?, ?)", (sha, type_data[0], type_data[1]))
149
 
        else:
150
 
            raise AssertionError("Unknown type %s" % type)
151
 
 
152
 
    def lookup_tree(self, path, revid):
153
 
        row = self.db.execute("select sha1 from trees where path = ? and revid = ?", (path,revid)).fetchone()
154
 
        if row is None:
155
 
            raise KeyError((path, revid))
156
 
        return row[0]
157
 
 
158
 
    def lookup_blob(self, fileid, revid):
159
 
        row = self.db.execute("select sha1 from blobs where fileid = ? and revid = ?", (fileid, revid)).fetchone()
160
 
        if row is None:
161
 
            raise KeyError((fileid, revid))
162
 
        return row[0]
163
 
 
164
 
    def lookup_git_sha(self, sha):
165
 
        """Lookup a Git sha in the database.
166
 
 
167
 
        :param sha: Git object sha
168
 
        :return: (type, type_data) with type_data:
169
 
            revision: revid, tree sha
170
 
        """
171
 
        row = self.db.execute("select revid, tree_sha from commits where sha1 = ?", (sha,)).fetchone()
172
 
        if row is not None:
173
 
            return ("commit", row)
174
 
        row = self.db.execute("select fileid, revid from blobs where sha1 = ?", (sha,)).fetchone()
175
 
        if row is not None:
176
 
            return ("blob", row)
177
 
        row = self.db.execute("select path, revid from trees where sha1 = ?", (sha,)).fetchone()
178
 
        if row is not None:
179
 
            return ("tree", row)
180
 
        raise KeyError(sha)
181
 
 
182
 
    def revids(self):
183
 
        """List the revision ids known."""
184
 
        for row in self.db.execute("select revid from commits").fetchall():
185
 
            yield row[0]
 
67
 
 
68
class MappedGitObjectConverter(GitObjectConverter):
 
69
    
 
70
    def __init__(self, repository):
 
71
        self.repository = repository
 
72
        self._idmap = GitShaMap(self.repository._transport)
 
73
 
 
74
    def _update_sha_map(self):
 
75
        # TODO: Check which 
 
76
        raise NotImplementedError(self._update_sha_map)
 
77
 
 
78
    def __getitem__(self, sha):
 
79
        # See if sha is in map
 
80
        try:
 
81
            (type, type_data) = self._idmap.lookup_git_sha(sha)
 
82
        except KeyError:
 
83
            # if not, see if there are any unconverted revisions and add them 
 
84
            # to the map, search for sha in map again
 
85
            self._update_sha_map()
 
86
            (type, type_data) = self._idmap.lookup_git_sha(sha)
 
87
        # convert object to git object
 
88
        if type == "revision":
 
89
            return self._get_commit(*type_data)
 
90
        else:
 
91
            raise AssertionError("Unknown object type '%s'" % type)