86
def import_git_blob(texts, mapping, path, hexsha, base_inv, parent_id,
81
def import_git_blob(texts, mapping, path, hexsha, base_inv, base_ie, parent_id,
87
82
revision_id, parent_invs, shagitmap, lookup_object, executable, symlink):
88
83
"""Import a git blob object into a bzr repository.
160
152
shamap = [(hexsha, "blob", (ie.file_id, ie.revision))]
163
if file_id in base_inv:
156
if base_ie is not None:
164
157
old_path = base_inv.id2path(file_id)
158
if base_ie.kind == "directory":
159
invdelta.extend(remove_disappeared_children(old_path, base_ie.children, []))
167
invdelta = [(old_path, path, file_id, ie)]
168
invdelta.extend(remove_disappeared_children(base_inv, base_ie, []))
162
invdelta.append((old_path, path, file_id, ie))
169
163
return (invdelta, shamap)
172
def import_git_submodule(texts, mapping, path, hexsha, base_inv, parent_id,
173
revision_id, parent_invs, shagitmap, lookup_object):
174
raise NotImplementedError(import_git_submodule)
177
def remove_disappeared_children(base_inv, base_ie, existing_children):
178
if base_ie is None or base_ie.kind != 'directory':
166
class SubmodulesNotSupported(BzrError):
168
_fmt = """Submodules can not yet be imported (requires nested tree support in Bazaar)."""
172
def import_git_submodule(texts, mapping, path, hexsha, base_inv, base_ie,
173
parent_id, revision_id, parent_invs, shagitmap, lookup_object):
174
raise SubmodulesNotSupported()
177
def remove_disappeared_children(path, base_children, existing_children):
181
deletable = [v for k,v in base_ie.children.iteritems() if k not in existing_children]
179
deletable = [(osutils.pathjoin(path, k), v) for k,v in base_children.iteritems() if k not in existing_children]
184
ret.append((base_inv.id2path(ie.file_id), None, ie.file_id, None))
181
(path, ie) = deletable.pop()
182
ret.append((path, None, ie.file_id, None))
185
183
if ie.kind == "directory":
186
deletable.extend(ie.children.values())
184
for name, child_ie in ie.children.iteritems():
185
deletable.append((osutils.pathjoin(path, name), child_ie))
190
def import_git_tree(texts, mapping, path, hexsha, base_inv, parent_id,
189
def import_git_tree(texts, mapping, path, hexsha, base_inv, base_ie, parent_id,
191
190
revision_id, parent_invs, shagitmap, lookup_object):
192
191
"""Import a git tree object into a bzr repository.
202
201
# We just have to hope this is indeed utf-8:
203
202
ie = InventoryDirectory(file_id, urlutils.basename(path.decode("utf-8")),
206
base_ie = base_inv[file_id]
208
205
# Newly appeared here
210
206
ie.revision = revision_id
211
texts.add_lines((file_id, ie.revision), (), [])
207
texts.insert_record_stream([FulltextContentFactory((file_id, ie.revision), (), None, "")])
212
208
invdelta.append((None, path, file_id, ie))
214
210
# See if this has changed at all
222
218
return [], {}, []
223
219
if base_ie.kind != "directory":
224
220
ie.revision = revision_id
225
texts.add_lines((ie.file_id, ie.revision), (), [])
221
texts.insert_record_stream([FulltextContentFactory((ie.file_id, ie.revision), (), None, "")])
226
222
invdelta.append((base_inv.id2path(ie.file_id), path, ie.file_id, ie))
223
if base_ie is not None and base_ie.kind == "directory":
224
base_children = base_ie.children
227
227
# Remember for next time
228
228
existing_children = set()
236
236
if stat.S_ISDIR(mode):
237
237
subinvdelta, grandchildmodes, subshamap = import_git_tree(
238
238
texts, mapping, child_path, child_hexsha, base_inv,
239
file_id, revision_id, parent_invs, shagitmap, lookup_object)
239
base_children.get(basename), file_id, revision_id, parent_invs, shagitmap,
240
241
invdelta.extend(subinvdelta)
241
242
child_modes.update(grandchildmodes)
242
243
shamap.extend(subshamap)
243
244
elif S_ISGITLINK(mode): # submodule
244
245
subinvdelta, grandchildmodes, subshamap = import_git_submodule(
245
texts, mapping, child_path, child_hexsha, base_inv,
246
texts, mapping, child_path, child_hexsha, base_inv, base_children.get(basename),
246
247
file_id, revision_id, parent_invs, shagitmap, lookup_object)
247
248
invdelta.extend(subinvdelta)
248
249
child_modes.update(grandchildmodes)
249
250
shamap.extend(subshamap)
251
252
subinvdelta, subshamap = import_git_blob(texts, mapping,
252
child_path, child_hexsha, base_inv, file_id, revision_id,
253
parent_invs, shagitmap, lookup_object,
253
child_path, child_hexsha, base_inv, base_children.get(basename), file_id,
254
revision_id, parent_invs, shagitmap, lookup_object,
254
255
mode_is_executable(mode), stat.S_ISLNK(mode))
255
256
invdelta.extend(subinvdelta)
256
257
shamap.extend(subshamap)
258
259
stat.S_IFLNK, DEFAULT_FILE_MODE|0111):
259
260
child_modes[child_path] = mode
260
261
# Remove any children that have disappeared
261
invdelta.extend(remove_disappeared_children(base_inv, base_ie, existing_children))
262
if base_ie is not None and base_ie.kind == "directory":
263
invdelta.extend(remove_disappeared_children(base_inv.id2path(file_id),
264
base_children, existing_children))
262
265
shamap.append((hexsha, "tree", (file_id, revision_id)))
263
266
return invdelta, child_modes, shamap
328
332
parent_invs_cache[parent_id] = parent_inv
329
333
if parent_invs == []:
330
334
base_inv = Inventory(root_id=None)
332
337
base_inv = parent_invs[0]
338
base_ie = base_inv.root
333
339
inv_delta, unusual_modes, shamap = import_git_tree(repo.texts,
334
mapping, "", root_trees[revid], base_inv, None, revid,
340
mapping, "", root_trees[revid], base_inv, base_ie, None, revid,
335
341
parent_invs, target_git_object_retriever._idmap, lookup_object)
336
342
target_git_object_retriever._idmap.add_entries(shamap)
337
343
if unusual_modes != {}:
401
407
ret = [mapping.revision_id_bzr_to_foreign(revid)[0] for revid in interesting_heads if revid not in (None, NULL_REVISION)]
402
408
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
403
self.fetch_objects(determine_wants, mapping, pb)
409
pack_hint = self.fetch_objects(determine_wants, mapping, pb)
410
if pack_hint is not None and self.target._format.pack_compresses:
411
self.target.pack(hint=pack_hint)
412
if interesting_heads is not None:
413
present_interesting_heads = self.target.has_revisions(interesting_heads)
414
missing_interesting_heads = set(interesting_heads) - present_interesting_heads
415
if missing_interesting_heads:
416
raise AssertionError("Missing interesting heads: %r" % missing_interesting_heads)
404
417
return self._refs
420
_GIT_PROGRESS_RE = re.compile(r"(.*?): +(\d+)% \((\d+)/(\d+)\)")
421
def report_git_progress(pb, text):
422
text = text.rstrip("\r\n")
423
g = _GIT_PROGRESS_RE.match(text)
425
(text, pct, current, total) = g.groups()
426
pb.update(text, int(current), int(total))
428
pb.update(text, 0, 0)
407
431
class InterRemoteGitNonGitRepository(InterGitNonGitRepository):
408
432
"""InterRepository that copies revisions from a remote Git into a non-Git
435
def get_target_heads(self):
436
# FIXME: This should be more efficient
437
all_revs = self.target.all_revision_ids()
438
parent_map = self.target.get_parent_map(all_revs)
440
map(all_parents.update, parent_map.itervalues())
441
return set(all_revs) - all_parents
411
443
def fetch_objects(self, determine_wants, mapping, pb=None):
412
444
def progress(text):
413
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
445
report_git_progress(pb, text)
414
446
store = BazaarObjectStore(self.target, mapping)
415
447
self.target.lock_write()
417
heads = self.target.get_graph().heads(self.target.all_revision_ids())
449
heads = self.get_target_heads()
418
450
graph_walker = store.get_graph_walker(
419
451
[store._lookup_revision_sha1(head) for head in heads])
420
452
recorded_wants = []