"""Fast export/import functionality."""
+from dulwich.index import (
+ commit_tree,
+ )
from dulwich.objects import (
+ Blob,
+ Commit,
format_timezone,
+ parse_timezone,
)
import stat
i = self._allocate_marker()
self._dump_commit(commit, i, ref, file_changes)
return i
+
+
+class FastImporter(object):
+ """Class for importing fastimport streams.
+
+ Please note that this is mostly a stub implementation at the moment,
+ doing the bare mimimum.
+ """
+
+ def __init__(self, repo):
+ self.repo = repo
+
+ def _parse_person(self, line):
+ (name, timestr, timezonestr) = line.rsplit(" ", 2)
+ return name, int(timestr), parse_timezone(timezonestr)[0]
+
+ def _read_blob(self, stream):
+ line = stream.readline()
+ if line.startswith("mark :"):
+ mark = line[len("mark :"):-1]
+ line = stream.readline()
+ else:
+ mark = None
+ if not line.startswith("data "):
+ raise ValueError("Blob without valid data line: %s" % line)
+ size = int(line[len("data "):])
+ o = Blob()
+ o.data = stream.read(size)
+ stream.readline()
+ self.repo.object_store.add_object(o)
+ return mark, o.id
+
+ def _read_commit(self, stream, contents, marks):
+ line = stream.readline()
+ if line.startswith("mark :"):
+ mark = line[len("mark :"):-1]
+ line = stream.readline()
+ else:
+ mark = None
+ o = Commit()
+ o.author = None
+ o.author_time = None
+ while line.startswith("author "):
+ (o.author, o.author_time, o.author_timezone) = \
+ self._parse_person(line[len("author "):-1])
+ line = stream.readline()
+ while line.startswith("committer "):
+ (o.committer, o.commit_time, o.commit_timezone) = \
+ self._parse_person(line[len("committer "):-1])
+ line = stream.readline()
+ if o.author is None:
+ o.author = o.committer
+ if o.author_time is None:
+ o.author_time = o.commit_time
+ o.author_timezone = o.commit_timezone
+ if not line.startswith("data "):
+ raise ValueError("Blob without valid data line: %s" % line)
+ size = int(line[len("data "):])
+ o.message = stream.read(size)
+ stream.readline()
+ line = stream.readline()[:-1]
+ while line:
+ if line.startswith("M "):
+ (kind, modestr, val, path) = line.split(" ")
+ if val[0] == ":":
+ val = marks[int(val[1:])]
+ contents[path] = (int(modestr, 8), val)
+ else:
+ raise ValueError(line)
+ line = stream.readline()[:-1]
+ try:
+ o.parents = (self.repo.head(),)
+ except KeyError:
+ o.parents = ()
+ o.tree = commit_tree(self.repo.object_store,
+ ((path, hexsha, mode) for (path, (mode, hexsha)) in
+ contents.iteritems()))
+ self.repo.object_store.add_object(o)
+ return mark, o.id
+
+ def import_stream(self, stream):
+ """Import from a file-like object.
+
+ :param stream: File-like object to read a fastimport stream from.
+ :return: Dictionary with marks
+ """
+ contents = {}
+ marks = {}
+ while True:
+ line = stream.readline()
+ if not line:
+ break
+ line = line[:-1]
+ if line == "" or line[0] == "#":
+ continue
+ if line.startswith("blob"):
+ mark, hexsha = self._read_blob(stream)
+ if mark is not None:
+ marks[int(mark)] = hexsha
+ elif line.startswith("commit "):
+ ref = line[len("commit "):-1]
+ mark, hexsha = self._read_commit(stream, contents, marks)
+ if mark is not None:
+ marks[int(mark)] = hexsha
+ self.repo.refs["HEAD"] = self.repo.refs[ref] = hexsha
+ else:
+ raise ValueError("invalid command '%s'" % line)
+ return marks