def commit_handler(self, cmd): """Process a CommitCommand.""" commit = Commit() if cmd.author is not None: author = cmd.author else: author = cmd.committer (author_name, author_email, author_timestamp, author_timezone) = author (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer commit.author = "%s <%s>" % (author_name, author_email) commit.author_timezone = author_timezone commit.author_time = int(author_timestamp) commit.committer = "%s <%s>" % (committer_name, committer_email) commit.commit_timezone = commit_timezone commit.commit_time = int(commit_timestamp) commit.message = cmd.message commit.parents = [] if cmd.from_: self._reset_base(cmd.from_) for filecmd in cmd.iter_files(): if filecmd.name == "filemodify": if filecmd.data is not None: blob = Blob.from_string(filecmd.data) self.repo.object_store.add(blob) blob_id = blob.id else: assert filecmd.dataref[ 0] == ":", "non-marker refs not supported yet" blob_id = self.markers[filecmd.dataref[1:]] self._contents[filecmd.path] = (filecmd.mode, blob_id) elif filecmd.name == "filedelete": del self._contents[filecmd.path] elif filecmd.name == "filecopy": self._contents[filecmd.dest_path] = self._contents[ filecmd.src_path] elif filecmd.name == "filerename": self._contents[filecmd.new_path] = self._contents[ filecmd.old_path] del self._contents[filecmd.old_path] elif filecmd.name == "filedeleteall": self._contents = {} else: raise Exception("Command %s not supported" % filecmd.name) commit.tree = commit_tree( self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in self._contents.iteritems())) if self.last_commit is not None: commit.parents.append(self.last_commit) commit.parents += cmd.merges self.repo.object_store.add_object(commit) self.repo[cmd.ref] = commit.id self.last_commit = commit.id if cmd.mark: self.markers[cmd.mark] = commit.id
def git_am_patch_split(f): """Parse a git-am-style patch and split it up into bits. :param f: File-like object to parse :return: Tuple with commit object, diff contents and git version """ msg = rfc822.Message(f) c = Commit() c.author = msg["from"] c.committer = msg["from"] try: patch_tag_start = msg["subject"].index("[PATCH") except ValueError: subject = msg["subject"] else: close = msg["subject"].index("] ", patch_tag_start) subject = msg["subject"][close+2:] c.message = subject.replace("\n", "") + "\n" first = True for l in f: if l == "---\n": break if first: if l.startswith("From: "): c.author = l[len("From: "):].rstrip() else: c.message += "\n" + l first = False else: c.message += l diff = "" for l in f: if l == "-- \n": break diff += l try: version = f.next().rstrip("\n") except StopIteration: version = None return c, diff, version
def commit_handler(self, cmd): """Process a CommitCommand.""" commit = Commit() if cmd.author is not None: author = cmd.author else: author = cmd.committer (author_name, author_email, author_timestamp, author_timezone) = author (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer commit.author = "%s <%s>" % (author_name, author_email) commit.author_timezone = author_timezone commit.author_time = int(author_timestamp) commit.committer = "%s <%s>" % (committer_name, committer_email) commit.commit_timezone = commit_timezone commit.commit_time = int(commit_timestamp) commit.message = cmd.message commit.parents = [] if cmd.from_: self._reset_base(cmd.from_) for filecmd in cmd.iter_files(): if filecmd.name == "filemodify": if filecmd.data is not None: blob = Blob.from_string(filecmd.data) self.repo.object_store.add(blob) blob_id = blob.id else: assert filecmd.dataref[0] == ":", "non-marker refs not supported yet" blob_id = self.markers[filecmd.dataref[1:]] self._contents[filecmd.path] = (filecmd.mode, blob_id) elif filecmd.name == "filedelete": del self._contents[filecmd.path] elif filecmd.name == "filecopy": self._contents[filecmd.dest_path] = self._contents[filecmd.src_path] elif filecmd.name == "filerename": self._contents[filecmd.new_path] = self._contents[filecmd.old_path] del self._contents[filecmd.old_path] elif filecmd.name == "filedeleteall": self._contents = {} else: raise Exception("Command %s not supported" % filecmd.name) commit.tree = commit_tree(self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in self._contents.iteritems())) if self.last_commit is not None: commit.parents.append(self.last_commit) commit.parents += cmd.merges self.repo.object_store.add_object(commit) self.repo[cmd.ref] = commit.id self.last_commit = commit.id if cmd.mark: self.markers[cmd.mark] = commit.id
def do_commit(self, message, committer=None, author=None, commit_timestamp=None, commit_timezone=None, author_timestamp=None, author_timezone=None, tree=None, encoding=None): """Create a new commit. :param message: Commit message :param committer: Committer fullname :param author: Author fullname (defaults to committer) :param commit_timestamp: Commit timestamp (defaults to now) :param commit_timezone: Commit timestamp timezone (defaults to GMT) :param author_timestamp: Author timestamp (defaults to commit timestamp) :param author_timezone: Author timestamp timezone (defaults to commit timestamp timezone) :param tree: SHA1 of the tree root to use (if not specified the current index will be committed). :param encoding: Encoding :return: New commit SHA1 """ import time c = Commit() if tree is None: index = self.open_index() c.tree = index.commit(self.object_store) else: if len(tree) != 40: raise ValueError("tree must be a 40-byte hex sha string") c.tree = tree # TODO: Allow username to be missing, and get it from .git/config if committer is None: raise ValueError("committer not set") c.committer = committer if commit_timestamp is None: commit_timestamp = time.time() c.commit_time = int(commit_timestamp) if commit_timezone is None: # FIXME: Use current user timezone rather than UTC commit_timezone = 0 c.commit_timezone = commit_timezone if author is None: author = committer c.author = author if author_timestamp is None: author_timestamp = commit_timestamp c.author_time = int(author_timestamp) if author_timezone is None: author_timezone = commit_timezone c.author_timezone = author_timezone if encoding is not None: c.encoding = encoding c.message = message try: old_head = self.refs["HEAD"] c.parents = [old_head] self.object_store.add_object(c) ok = self.refs.set_if_equals("HEAD", old_head, c.id) except KeyError: c.parents = [] self.object_store.add_object(c) ok = self.refs.add_if_new("HEAD", c.id) if not ok: # Fail if the atomic compare-and-swap failed, leaving the commit and # all its objects as garbage. raise CommitError("HEAD changed during commit") return c.id