15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
from bzrlib import osutils, ui, urlutils
18
from bzrlib.errors import InvalidRevisionId
18
from bzrlib.errors import InvalidRevisionId, NoSuchRevision
19
19
from bzrlib.inventory import Inventory
20
20
from bzrlib.repository import InterRepository
21
21
from bzrlib.trace import info
73
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, executable):
78
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, gitmap, executable):
74
79
"""Import a git blob object into a bzr repository.
76
81
:param repo: bzr repository
87
92
ie.text_size = len(blob.data)
88
93
ie.text_sha1 = osutils.sha_string(blob.data)
89
94
ie.executable = executable
92
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, lookup_object):
95
gitmap._idmap.add_entry(blob.sha().hexdigest(), "blob", (ie.file_id, ie.revision))
98
def import_git_tree(repo, mapping, path, tree, inv, parent_invs,
99
gitmap, lookup_object):
93
100
"""Import a git tree object into a bzr repository.
95
102
:param repo: A Bzr repository object
105
112
ie = inv.add_path(path, "directory", file_id)
106
113
ie.revision = text_revision
114
gitmap._idmap.add_entry(tree.sha().hexdigest(), "tree", (file_id, text_revision))
107
115
for mode, name, hexsha in tree.entries():
108
116
entry_kind = (mode & 0700000) / 0100000
109
117
basename = name.decode("utf-8")
113
121
child_path = urlutils.join(path, name)
114
122
if entry_kind == 0:
115
123
tree = lookup_object(hexsha)
116
import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
124
import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, gitmap, lookup_object)
117
125
elif entry_kind == 1:
118
126
blob = lookup_object(hexsha)
119
127
fs_mode = mode & 0777
120
import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
128
import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, gitmap, bool(fs_mode & 0111))
122
130
raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
125
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
133
def import_git_objects(repo, mapping, object_iter, target_git_object_retriever,
126
135
"""Import a set of git objects into a bzr repository.
128
137
:param repo: Bazaar repository
129
138
:param mapping: Mapping to use
130
:param num_objects: Number of objects.
131
139
:param object_iter: Iterator over Git objects.
133
141
# TODO: a more (memory-)efficient implementation of this
135
for i, (o, _) in enumerate(object_iter):
137
pb.update("fetching objects", i, num_objects)
142
145
# Find and convert commit objects
143
for o in objects.itervalues():
146
for o in object_iter.iterobjects():
144
147
if isinstance(o, Commit):
145
148
rev = mapping.import_commit(o)
146
root_trees[rev.revision_id] = objects[o.tree]
149
root_trees[rev.revision_id] = object_iter[o.tree]
147
150
revisions[rev.revision_id] = rev
148
151
graph.append((rev.revision_id, rev.parent_ids))
152
target_git_object_retriever._idmap.add_entry(o.sha().hexdigest(), "commit", (rev.revision_id, o._tree))
149
153
# Order the revisions
150
154
# Create the inventory objects
151
155
for i, revid in enumerate(topo_sort(graph)):
159
163
inv = Inventory()
160
164
inv.revision_id = rev.revision_id
161
165
def lookup_object(sha):
164
return reconstruct_git_object(repo, mapping, sha)
166
if sha in object_iter:
167
return object_iter[sha]
168
return target_git_object_retriever[sha]
165
169
parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
166
170
import_git_tree(repo, mapping, "", root_tree, inv, parent_invs,
171
target_git_object_retriever, lookup_object)
168
172
repo.add_revision(rev.revision_id, rev, inv)
171
def reconstruct_git_commit(repo, rev):
172
raise NotImplementedError(self.reconstruct_git_commit)
175
def reconstruct_git_object(repo, mapping, sha):
177
revid = mapping.revision_id_foreign_to_bzr(sha)
179
rev = repo.get_revision(revid)
180
except NoSuchRevision:
183
return reconstruct_git_commit(rev)
187
raise KeyError("No such object %s" % sha)
190
175
class InterGitNonGitRepository(InterRepository):
192
177
_matching_repo_format = GitFormat()
199
184
"""See InterRepository.copy_content."""
200
185
self.fetch(revision_id, pb, find_ghosts=False)
202
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
205
mapping = self.source.get_mapping()
187
def fetch_objects(self, determine_wants, mapping, pb=None):
206
188
def progress(text):
207
189
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
208
def determine_wants(heads):
209
if revision_id is None:
212
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
213
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
214
190
graph_walker = BzrFetchGraphWalker(self.target, mapping)
217
193
create_pb = pb = ui.ui_factory.nested_progress_bar()
194
target_git_object_retriever = GitObjectConverter(self.target, mapping)
219
197
self.target.lock_write()
221
199
self.target.start_write_group()
223
(num_objects, objects_iter) = \
224
self.source.fetch_objects(determine_wants,
225
graph_walker, progress)
226
import_git_objects(self.target, mapping, num_objects,
201
objects_iter = self.source.fetch_objects(determine_wants,
203
target_git_object_retriever.__getitem__,
205
import_git_objects(self.target, mapping, objects_iter,
206
target_git_object_retriever, pb)
229
208
self.target.commit_write_group()
234
213
create_pb.finished()
215
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
218
mapping = self.source.get_mapping()
219
def determine_wants(heads):
220
if revision_id is None:
223
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
224
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
225
return self.fetch_objects(determine_wants, mapping, pb)
237
228
def is_compatible(source, target):
238
229
"""Be compatible with GitRepository."""