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

  • Committer: John Arbash Meinel
  • Date: 2008-10-08 21:56:12 UTC
  • mto: This revision was merged to the branch mainline in revision 3773.
  • Revision ID: john@arbash-meinel.com-20081008215612-y9v94tqxreqoangx
Simplify the --raw mode.

I didn't realize, but the only node that is special cased is the 'root' node,
and to read it, you actually have to parse it directly, because the
compressed bytes start immediately after the end of the header, rather than
having any padding before the zlib bytes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
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
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
"""An adapter between a Git Repository and a Bazaar Branch"""
18
 
 
19
 
import git
20
 
import os
21
 
import time
22
 
 
23
 
import bzrlib
24
 
from bzrlib import (
25
 
    deprecated_graph,
26
 
    errors,
27
 
    inventory,
28
 
    osutils,
29
 
    repository,
30
 
    revision,
31
 
    revisiontree,
32
 
    urlutils,
33
 
    versionedfile,
34
 
    )
35
 
from bzrlib.transport import get_transport
36
 
 
37
 
from bzrlib.plugins.git.foreign import (
38
 
    versionedfiles
39
 
    )
40
 
from bzrlib.plugins.git.mapping import default_mapping
41
 
 
42
 
 
43
 
class GitRepository(repository.Repository):
44
 
    """An adapter to git repositories for bzr."""
45
 
 
46
 
    _serializer = None
47
 
 
48
 
    def __init__(self, gitdir, lockfiles):
49
 
        self.base = gitdir.root_transport.base
50
 
        self.bzrdir = gitdir
51
 
        self.control_files = lockfiles
52
 
        self._git = gitdir._git
53
 
        self.texts = None
54
 
        self.signatures = versionedfiles.VirtualSignatureTexts(self)
55
 
        self.revisions = versionedfiles.VirtualRevisionTexts(self)
56
 
        self._format = GitFormat()
57
 
        self._fallback_repositories = []
58
 
 
59
 
    def _all_revision_ids(self):
60
 
        if self._git.heads == []:
61
 
            return set()
62
 
        ret = set()
63
 
        skip = 0
64
 
        max_count = 1000
65
 
        cms = None
66
 
        while cms != []:
67
 
            cms = self._git.commits("--all", max_count=max_count, skip=skip)
68
 
            skip += max_count
69
 
            ret.update([default_mapping.revision_id_foreign_to_bzr(cm.id) for cm in cms])
70
 
        return ret
71
 
 
72
 
    def is_shared(self):
73
 
        return True
74
 
 
75
 
    def supports_rich_root(self):
76
 
        return False
77
 
 
78
 
    #def get_revision_delta(self, revision_id):
79
 
    #    parent_revid = self.get_revision(revision_id).parent_ids[0]
80
 
    #    diff = self._git.diff(ids.convert_revision_id_bzr_to_git(parent_revid),
81
 
    #                   ids.convert_revision_id_bzr_to_git(revision_id))
82
 
 
83
 
    def get_ancestry(self, revision_id):
84
 
        revision_id = revision.ensure_null(revision_id)
85
 
        ret = []
86
 
        if revision_id != revision.NULL_REVISION:
87
 
            skip = 0
88
 
            max_count = 1000
89
 
            cms = None
90
 
            while cms != []:
91
 
                cms = self._git.commits(self.lookup_git_revid(revision_id, default_mapping), max_count=max_count, skip=skip)
92
 
                skip += max_count
93
 
                ret += [default_mapping.revision_id_foreign_to_bzr(cm.id) for cm in cms]
94
 
        return [None] + ret
95
 
 
96
 
    def get_signature_text(self, revision_id):
97
 
        raise errors.NoSuchRevision(self, revision_id)
98
 
 
99
 
    def has_signature_for_revision_id(self, revision_id):
100
 
        return False
101
 
 
102
 
    def get_parent_map(self, revision_ids):
103
 
        ret = {}
104
 
        for revid in revision_ids:
105
 
            if revid == revision.NULL_REVISION:
106
 
                ret[revid] = ()
107
 
            else:
108
 
                commit = self._git.commit(self.lookup_git_revid(revid, default_mapping))
109
 
                ret[revid] = tuple([default_mapping.revision_id_foreign_to_bzr(p.id) for p in commit.parents])
110
 
        return ret
111
 
 
112
 
    def lookup_git_revid(self, bzr_revid, mapping):
113
 
        try:
114
 
            return mapping.revision_id_bzr_to_foreign(bzr_revid)
115
 
        except errors.InvalidRevisionId:
116
 
            raise errors.NoSuchRevision(bzr_revid, self)
117
 
 
118
 
    def get_revision(self, revision_id):
119
 
        git_commit_id = self.lookup_git_revid(revision_id, default_mapping)
120
 
        commit = self._git.commit(git_commit_id)
121
 
        # print "fetched revision:", git_commit_id
122
 
        revision = self._parse_rev(commit)
123
 
        return revision
124
 
 
125
 
    def has_revision(self, revision_id):
126
 
        try:
127
 
            self.get_revision(revision_id)
128
 
        except NoSuchRevision:
129
 
            return False
130
 
        else:
131
 
            return True
132
 
 
133
 
    def get_revisions(self, revisions):
134
 
        return [self.get_revision(r) for r in revisions]
135
 
 
136
 
    @classmethod
137
 
    def _parse_rev(klass, commit):
138
 
        """Convert a git commit to a bzr revision.
139
 
 
140
 
        :return: a `bzrlib.revision.Revision` object.
141
 
        """
142
 
        rev = revision.Revision(default_mapping.revision_id_foreign_to_bzr(commit.id))
143
 
        rev.parent_ids = tuple([default_mapping.revision_id_foreign_to_bzr(p.id) for p in commit.parents])
144
 
        rev.inventory_sha1 = ""
145
 
        rev.message = commit.message.decode("utf-8", "replace")
146
 
        rev.committer = str(commit.committer)
147
 
        rev.properties['author'] = str(commit.author)
148
 
        rev.timestamp = time.mktime(commit.committed_date)
149
 
        rev.timezone = 0
150
 
        return rev
151
 
 
152
 
    def revision_trees(self, revids):
153
 
        for revid in revids:
154
 
            yield self.revision_tree(revid)
155
 
 
156
 
    def revision_tree(self, revision_id):
157
 
        revision_id = revision.ensure_null(revision_id)
158
 
 
159
 
        if revision_id == revision.NULL_REVISION:
160
 
            inv = inventory.Inventory(root_id=None)
161
 
            inv.revision_id = revision_id
162
 
            return revisiontree.RevisionTree(self, inv, revision_id)
163
 
 
164
 
        return GitRevisionTree(self, revision_id)
165
 
 
166
 
    def get_inventory(self, revision_id):
167
 
        assert revision_id != None
168
 
        return self.revision_tree(revision_id).inventory
169
 
 
170
 
    def set_make_working_trees(self, trees):
171
 
        pass
172
 
 
173
 
 
174
 
def escape_file_id(file_id):
175
 
    return file_id.replace('_', '__').replace(' ', '_s')
176
 
 
177
 
 
178
 
def unescape_file_id(file_id):
179
 
    return file_id.replace("_s", " ").replace("__", "_")
180
 
 
181
 
 
182
 
class GitRevisionTree(revisiontree.RevisionTree):
183
 
 
184
 
    def __init__(self, repository, revision_id):
185
 
        self._repository = repository
186
 
        self.revision_id = revision_id
187
 
        git_id = repository.lookup_git_revid(revision_id, default_mapping)
188
 
        self.tree = repository._git.commit(git_id).tree
189
 
        self._inventory = inventory.Inventory(revision_id=revision_id)
190
 
        self._inventory.root.revision = revision_id
191
 
        self._build_inventory(self.tree, self._inventory.root, "")
192
 
 
193
 
    def get_revision_id(self):
194
 
        return self.revision_id
195
 
 
196
 
    def get_file_text(self, file_id):
197
 
        entry = self._inventory[file_id]
198
 
        if entry.kind == 'directory': return ""
199
 
        return self._repository._git.blob(entry.text_id).data
200
 
 
201
 
    def _build_inventory(self, tree, ie, path):
202
 
        assert isinstance(path, str)
203
 
        for b in tree.contents:
204
 
            basename = b.name.decode("utf-8")
205
 
            if path == "":
206
 
                child_path = b.name
207
 
            else:
208
 
                child_path = urlutils.join(path, b.name)
209
 
            file_id = escape_file_id(child_path.encode('utf-8'))
210
 
            if b.mode[0] == '0':
211
 
                child_ie = inventory.InventoryDirectory(file_id, basename, ie.file_id)
212
 
            elif b.mode[0] == '1':
213
 
                if b.mode[1] == '0':
214
 
                    child_ie = inventory.InventoryFile(file_id, basename, ie.file_id)
215
 
                    child_ie.text_sha1 = osutils.sha_string(b.data)
216
 
                elif b.mode[1] == '2':
217
 
                    child_ie = inventory.InventoryLink(file_id, basename, ie.file_id)
218
 
                    child_ie.text_sha1 = osutils.sha_string("")
219
 
                else:
220
 
                    raise AssertionError(
221
 
                        "Unknown file kind, perms=%r." % (b.mode,))
222
 
                child_ie.text_id = b.id
223
 
                child_ie.text_size = b.size
224
 
            else:
225
 
                raise AssertionError(
226
 
                    "Unknown blob kind, perms=%r." % (b.mode,))
227
 
            child_ie.executable = bool(int(b.mode[3:], 8) & 0111)
228
 
            child_ie.revision = self.revision_id
229
 
            self._inventory.add(child_ie)
230
 
            if b.mode[0] == '0':
231
 
                self._build_inventory(b, child_ie, child_path)
232
 
 
233
 
 
234
 
class GitFormat(object):
235
 
 
236
 
    supports_tree_reference = False
237
 
 
238
 
    def get_format_description(self):
239
 
        return "Git Repository"