from dulwich.objects import (
Blob,
Commit,
+ Tag,
format_timezone,
parse_timezone,
)
+from fastimport import (
+ commands,
+ errors as fastimport_errors,
+ processor,
+ )
import stat
-class FastExporter(object):
+
+class GitFastExporter(object):
"""Generate a fast-export output stream for Git objects."""
def __init__(self, outf, store):
def _allocate_marker(self):
self._marker_idx+=1
- return self._marker_idx
+ return str(self._marker_idx)
- def _dump_blob(self, blob, marker):
- self.outf.write("blob\nmark :%s\n" % marker)
- self.outf.write("data %s\n" % blob.raw_length())
- for chunk in blob.as_raw_chunks():
- self.outf.write(chunk)
- self.outf.write("\n")
+ def _dump_blob(self, blob, mark):
+ cmd = commands.BlobCommand(mark, blob.data)
+ self.outf.write(str(cmd)+"\n")
def export_blob(self, blob):
i = self._allocate_marker()
self._dump_blob(blob, i)
return i
- def _dump_commit(self, commit, marker, ref, file_changes):
- self.outf.write("commit %s\n" % ref)
- self.outf.write("mark :%s\n" % marker)
- self.outf.write("author %s %s %s\n" % (commit.author,
- commit.author_time, format_timezone(commit.author_timezone)))
- self.outf.write("committer %s %s %s\n" % (commit.committer,
- commit.commit_time, format_timezone(commit.commit_timezone)))
- self.outf.write("data %s\n" % len(commit.message))
- self.outf.write(commit.message)
- self.outf.write("\n")
- self.outf.write('\n'.join(file_changes))
- self.outf.write("\n\n")
+ def _dump_commit(self, commit, mark, ref, file_cmds):
+ if commit.parents:
+ from_ = commit.parents[0]
+ merges = commit.parents[1:]
+ else:
+ from_ = None
+ merges = []
+ cmd = commands.CommitCommand(ref, mark,
+ commit.author, commit.committer,
+ commit.message, from_, merges, file_cmds)
+ self.outf.write(str(cmd))
def export_commit(self, commit, ref, base_tree=None):
- file_changes = []
+ file_cmds = []
for (old_path, new_path), (old_mode, new_mode), (old_hexsha, new_hexsha) in \
self.store.tree_changes(base_tree, commit.tree):
if new_path is None:
- file_changes.append("D %s" % old_path)
+ file_cmds.append(commands.FileDeleteCommand(old_path))
continue
if not stat.S_ISDIR(new_mode):
marker = self.export_blob(self.store[new_hexsha])
- file_changes.append("M %o :%s %s" % (new_mode, marker, new_path))
-
+ if old_path != new_path and old_path is not None:
+ file_cmds.append(commands.FileRenameCommand(old_path, new_path))
+ if old_mode != new_mode or old_hexsha != new_hexsha:
+ file_cmds.append(commands.FileModifyCommand(new_mode, marker, new_path))
i = self._allocate_marker()
- self._dump_commit(commit, i, ref, file_changes)
+ self._dump_commit(commit, i, ref, file_cmds)
return i
else:
raise ValueError("invalid command '%s'" % line)
return marks
+
+
+class GitImportProcessor(processor.ImportProcessor):
+ """An import processor that imports into a Git repository using Dulwich.
+
+ """
+
+ def __init__(self, repo, params=None, verbose=False, outf=None):
+ processor.ImportProcessor.__init__(self, params, verbose)
+ self.repo = repo
+ self.last_commit = None
+
+ def blob_handler(self, cmd):
+ """Process a BlobCommand."""
+ self.repo.object_store.add_object(Blob.from_string(cmd.data))
+
+ def checkpoint_handler(self, cmd):
+ """Process a CheckpointCommand."""
+ pass
+
+ def commit_handler(self, cmd):
+ """Process a CommitCommand."""
+ commit = Commit()
+ commit.author = cmd.author
+ commit.committer = cmd.committer
+ commit.message = cmd.message
+ commit.parents = []
+ if self.last_commit is not None:
+ commit.parents.append(self.last_commit)
+ commit.parents += cmd.merges
+ self.repo[cmd.ref] = commit.id
+ self.last_commit = commit.id
+
+ def progress_handler(self, cmd):
+ """Process a ProgressCommand."""
+ pass
+
+ def reset_handler(self, cmd):
+ """Process a ResetCommand."""
+ self.last_commit = cmd.from_
+ self.rep.refs[cmd.from_] = cmd.id
+
+ def tag_handler(self, cmd):
+ """Process a TagCommand."""
+ tag = Tag()
+ tag.tagger = cmd.tagger
+ tag.message = cmd.message
+ tag.name = cmd.tag
+ self.repo.add_object(tag)
+ self.repo.refs["refs/tags/" + tag.name] = tag.id
+
+ def feature_handler(self, cmd):
+ """Process a FeatureCommand."""
+ raise fastimport_errors.UnknownFeature(cmd.feature_name)