def log_patch(self, patch, message, notes = None): """Generate a log commit for a patch """ top = git.get_commit(patch.get_top()) old_log = patch.get_log() if message is None: # replace the current log entry if not old_log: raise StackException('No log entry to annotate for patch "%s"' % patch.get_name()) replace = True log_commit = git.get_commit(old_log) msg = log_commit.get_log().split('\n')[0] log_parent = log_commit.get_parent() if log_parent: parents = [log_parent] else: parents = [] else: # generate a new log entry replace = False msg = '%s\t%s' % (message, top.get_id_hash()) if old_log: parents = [old_log] else: parents = [] if notes: msg += '\n\n' + notes log = git.commit(message = msg, parents = parents, cache_update = False, tree_id = top.get_tree(), allowempty = True) patch.set_log(log)
def log_patch(self, patch, message): """Generate a log commit for a patch """ top = git.get_commit(patch.get_top()) old_log = patch.get_log() # generate a new log entry msg = '%s\t%s' % (message, top.get_id_hash()) if old_log: parents = [old_log] else: parents = [] log = git.commit( message=msg, parents=parents, cache_update=False, tree_id=top.get_tree(), allowempty=True, ) patch.set_log(log)
def log_patch(self, patch, message, notes=None): """Generate a log commit for a patch """ top = git.get_commit(patch.get_top()) old_log = patch.get_log() if message is None: # replace the current log entry if not old_log: raise StackException, \ 'No log entry to annotate for patch "%s"' \ % patch.get_name() replace = True log_commit = git.get_commit(old_log) msg = log_commit.get_log().split('\n')[0] log_parent = log_commit.get_parent() if log_parent: parents = [log_parent] else: parents = [] else: # generate a new log entry replace = False msg = '%s\t%s' % (message, top.get_id_hash()) if old_log: parents = [old_log] else: parents = [] if notes: msg += '\n\n' + notes log = git.commit(message=msg, parents=parents, cache_update=False, tree_id=top.get_tree(), allowempty=True) patch.set_log(log)
def forward_patches(self, names): """Try to fast-forward an array of patches. On return, patches in names[0:returned_value] have been pushed on the stack. Apply the rest with push_patch """ unapplied = self.get_unapplied() forwarded = 0 top = git.get_head() for name in names: assert(name in unapplied) patch = self.get_patch(name) head = top bottom = patch.get_bottom() top = patch.get_top() # top != bottom always since we have a commit for each patch if head == bottom: # reset the backup information. No logging since the # patch hasn't changed patch.set_top(top, backup = True) else: head_tree = git.get_commit(head).get_tree() bottom_tree = git.get_commit(bottom).get_tree() if head_tree == bottom_tree: # We must just reparent this patch and create a new commit # for it descr = patch.get_description() author_name = patch.get_authname() author_email = patch.get_authemail() author_date = patch.get_authdate() committer_name = patch.get_commname() committer_email = patch.get_commemail() top_tree = git.get_commit(top).get_tree() top = git.commit(message = descr, parents = [head], cache_update = False, tree_id = top_tree, allowempty = True, author_name = author_name, author_email = author_email, author_date = author_date, committer_name = committer_name, committer_email = committer_email) patch.set_top(top, backup = True) self.log_patch(patch, 'push(f)') else: top = head # stop the fast-forwarding, must do a real merge break forwarded+=1 unapplied.remove(name) if forwarded == 0: return 0 git.switch(top) append_strings(self.__applied_file, names[0:forwarded]) write_strings(self.__unapplied_file, unapplied) return forwarded
def new_patch(self, name, message = None, can_edit = True, unapplied = False, show_patch = False, top = None, bottom = None, commit = True, author_name = None, author_email = None, author_date = None, committer_name = None, committer_email = None, before_existing = False, sign_str = None): """Creates a new patch, either pointing to an existing commit object, or by creating a new commit object. """ assert commit or (top and bottom) assert not before_existing or (top and bottom) assert not (commit and before_existing) assert (top and bottom) or (not top and not bottom) assert commit or (not top or (bottom == git.get_commit(top).get_parent())) if name is not None: self.__patch_name_valid(name) if self.patch_exists(name): raise StackException('Patch "%s" already exists' % name) # TODO: move this out of the stgit.stack module, it is really # for higher level commands to handle the user interaction def sign(msg): return add_sign_line(msg, sign_str, committer_name or git.committer().name, committer_email or git.committer().email) if not message and can_edit: descr = edit_file( self, sign(''), 'Please enter the description for the patch above.', show_patch) else: descr = sign(message) head = git.get_head() if name is None: name = make_patch_name(descr, self.patch_exists) patch = self.get_patch(name) patch.create() patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if before_existing: insert_string(self.__applied_file, patch.get_name()) elif unapplied: patches = [patch.get_name()] + self.get_unapplied() write_strings(self.__unapplied_file, patches) set_head = False else: append_string(self.__applied_file, patch.get_name()) set_head = True if commit: if top: top_commit = git.get_commit(top) else: bottom = head top_commit = git.get_commit(head) # create a commit for the patch (may be empty if top == bottom); # only commit on top of the current branch assert(unapplied or bottom == head) commit_id = git.commit(message = descr, parents = [bottom], cache_update = False, tree_id = top_commit.get_tree(), allowempty = True, set_head = set_head, author_name = author_name, author_email = author_email, author_date = author_date, committer_name = committer_name, committer_email = committer_email) # set the patch top to the new commit patch.set_top(commit_id) else: patch.set_top(top) self.log_patch(patch, 'new') return patch
def refresh_patch(self, files = None, message = None, edit = False, empty = False, show_patch = False, cache_update = True, author_name = None, author_email = None, author_date = None, committer_name = None, committer_email = None, backup = True, sign_str = None, log = 'refresh', notes = None, bottom = None): """Generates a new commit for the topmost patch """ patch = self.get_current_patch() if not patch: raise StackException('No patches applied') descr = patch.get_description() if not (message or descr): edit = True descr = '' elif message: descr = message # TODO: move this out of the stgit.stack module, it is really # for higher level commands to handle the user interaction if not message and edit: descr = edit_file(self, descr.rstrip(), \ 'Please edit the description for patch "%s" ' \ 'above.' % patch.get_name(), show_patch) if not author_name: author_name = patch.get_authname() if not author_email: author_email = patch.get_authemail() if not committer_name: committer_name = patch.get_commname() if not committer_email: committer_email = patch.get_commemail() descr = add_sign_line(descr, sign_str, committer_name, committer_email) if not bottom: bottom = patch.get_bottom() if empty: tree_id = git.get_commit(bottom).get_tree() else: tree_id = None commit_id = git.commit(files = files, message = descr, parents = [bottom], cache_update = cache_update, tree_id = tree_id, set_head = True, allowempty = True, author_name = author_name, author_email = author_email, author_date = author_date, committer_name = committer_name, committer_email = committer_email) patch.set_top(commit_id, backup = backup) patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if log: self.log_patch(patch, log, notes) return commit_id
def forward_patches(self, names): """Try to fast-forward an array of patches. On return, patches in names[0:returned_value] have been pushed on the stack. Apply the rest with push_patch """ unapplied = self.get_unapplied() forwarded = 0 top = git.get_head() for name in names: assert(name in unapplied) patch = self.get_patch(name) head = top bottom = patch.get_bottom() top = patch.get_top() # top != bottom always since we have a commit for each patch if head == bottom: # reset the backup information. No logging since the # patch hasn't changed patch.set_top(top, backup=True) else: head_tree = git.get_commit(head).get_tree() bottom_tree = git.get_commit(bottom).get_tree() if head_tree == bottom_tree: # We must just reparent this patch and create a new commit # for it descr = patch.get_description() author_name = patch.get_authname() author_email = patch.get_authemail() author_date = patch.get_authdate() committer_name = patch.get_commname() committer_email = patch.get_commemail() top_tree = git.get_commit(top).get_tree() top = git.commit( message=descr, parents=[head], cache_update=False, tree_id=top_tree, allowempty=True, author_name=author_name, author_email=author_email, author_date=author_date, committer_name=committer_name, committer_email=committer_email, ) patch.set_top(top, backup=True) self.log_patch(patch, 'push(f)') else: top = head # stop the fast-forwarding, must do a real merge break forwarded += 1 unapplied.remove(name) if forwarded == 0: return 0 git.switch(top) append_strings(self.__applied_file, names[0:forwarded]) write_strings(self.__unapplied_file, unapplied) return forwarded
def new_patch( self, name, message=None, can_edit=True, unapplied=False, show_patch=False, top=None, bottom=None, commit=True, author_name=None, author_email=None, author_date=None, committer_name=None, committer_email=None, sign_str=None, ): """Creates a new patch, either pointing to an existing commit object, or by creating a new commit object. """ assert commit or (top and bottom) assert (top and bottom) or (not top and not bottom) assert commit or ( not top or bottom == git.get_commit(top).get_parent() ) if name is not None: self.__patch_name_valid(name) if self.patch_exists(name): raise StackException('Patch "%s" already exists' % name) # TODO: move this out of the stgit.stack module, it is really # for higher level commands to handle the user interaction def sign(msg): return add_sign_line(msg, sign_str, committer_name or git.committer().name, committer_email or git.committer().email) if not message and can_edit: descr = edit_file( self, sign(''), 'Please enter the description for the patch above.', show_patch) else: descr = sign(message) head = git.get_head() if name is None: name = make_patch_name(descr, self.patch_exists) patch = self.get_patch(name) patch.create() patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if unapplied: patches = [patch.get_name()] + self.get_unapplied() write_strings(self.__unapplied_file, patches) set_head = False else: append_string(self.__applied_file, patch.get_name()) set_head = True if commit: if top: top_commit = git.get_commit(top) else: bottom = head top_commit = git.get_commit(head) # create a commit for the patch (may be empty if top == bottom); # only commit on top of the current branch assert(unapplied or bottom == head) commit_id = git.commit( message=descr, parents=[bottom], cache_update=False, tree_id=top_commit.get_tree(), allowempty=True, set_head=set_head, author_name=author_name, author_email=author_email, author_date=author_date, committer_name=committer_name, committer_email=committer_email, ) # set the patch top to the new commit patch.set_top(commit_id) else: patch.set_top(top) self.log_patch(patch, 'new') return patch
def refresh_patch( self, files=None, message=None, edit=False, empty=False, show_patch=False, cache_update=True, author_name=None, author_email=None, author_date=None, committer_name=None, committer_email=None, backup=True, sign_str=None, log='refresh', notes=None, bottom=None ): """Generates a new commit for the topmost patch """ patch = self.get_current_patch() if not patch: raise StackException('No patches applied') descr = patch.get_description() if not (message or descr): edit = True descr = '' elif message: descr = message # TODO: move this out of the stgit.stack module, it is really # for higher level commands to handle the user interaction if not message and edit: descr = edit_file( self, descr.rstrip(), 'Please edit the description for patch "%s" above.' % ( patch.get_name(), show_patch, ) ) if not author_name: author_name = patch.get_authname() if not author_email: author_email = patch.get_authemail() if not committer_name: committer_name = patch.get_commname() if not committer_email: committer_email = patch.get_commemail() descr = add_sign_line(descr, sign_str, committer_name, committer_email) if not bottom: bottom = patch.get_bottom() if empty: tree_id = git.get_commit(bottom).get_tree() else: tree_id = None commit_id = git.commit( files=files, message=descr, parents=[bottom], cache_update=cache_update, tree_id=tree_id, set_head=True, allowempty=True, author_name=author_name, author_email=author_email, author_date=author_date, committer_name=committer_name, committer_email=committer_email ) patch.set_top(commit_id, backup=backup) patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if log: self.log_patch(patch, log, notes) return commit_id
def new_patch(self, name, message=None, can_edit=True, unapplied=False, show_patch=False, top=None, bottom=None, commit=True, author_name=None, author_email=None, author_date=None, committer_name=None, committer_email=None, before_existing=False): """Creates a new patch """ if name != None: self.__patch_name_valid(name) if self.patch_exists(name): raise StackException, 'Patch "%s" already exists' % name if not message and can_edit: descr = edit_file( self, None, 'Please enter the description for the patch above.', show_patch) else: descr = message head = git.get_head() if name == None: name = make_patch_name(descr, self.patch_exists) patch = Patch(name, self.__patch_dir, self.__refs_dir) patch.create() if not bottom: bottom = head if not top: top = head patch.set_bottom(bottom) patch.set_top(top) patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if before_existing: insert_string(self.__applied_file, patch.get_name()) # no need to commit anything as the object is already # present (mainly used by 'uncommit') commit = False elif unapplied: patches = [patch.get_name()] + self.get_unapplied() write_strings(self.__unapplied_file, patches) set_head = False else: append_string(self.__applied_file, patch.get_name()) set_head = True if commit: # create a commit for the patch (may be empty if top == bottom); # only commit on top of the current branch assert (unapplied or bottom == head) top_commit = git.get_commit(top) commit_id = git.commit(message=descr, parents=[bottom], cache_update=False, tree_id=top_commit.get_tree(), allowempty=True, set_head=set_head, author_name=author_name, author_email=author_email, author_date=author_date, committer_name=committer_name, committer_email=committer_email) # set the patch top to the new commit patch.set_top(commit_id) self.log_patch(patch, 'new') return patch
def refresh_patch(self, files=None, message=None, edit=False, show_patch=False, cache_update=True, author_name=None, author_email=None, author_date=None, committer_name=None, committer_email=None, backup=False, sign_str=None, log='refresh', notes=None): """Generates a new commit for the given patch """ name = self.get_current() if not name: raise StackException, 'No patches applied' patch = Patch(name, self.__patch_dir, self.__refs_dir) descr = patch.get_description() if not (message or descr): edit = True descr = '' elif message: descr = message if not message and edit: descr = edit_file(self, descr.rstrip(), \ 'Please edit the description for patch "%s" ' \ 'above.' % name, show_patch) if not author_name: author_name = patch.get_authname() if not author_email: author_email = patch.get_authemail() if not author_date: author_date = patch.get_authdate() if not committer_name: committer_name = patch.get_commname() if not committer_email: committer_email = patch.get_commemail() if sign_str: descr = descr.rstrip() if descr.find("\nSigned-off-by:") < 0 \ and descr.find("\nAcked-by:") < 0: descr = descr + "\n" descr = '%s\n%s: %s <%s>\n' % (descr, sign_str, committer_name, committer_email) bottom = patch.get_bottom() commit_id = git.commit(files=files, message=descr, parents=[bottom], cache_update=cache_update, allowempty=True, author_name=author_name, author_email=author_email, author_date=author_date, committer_name=committer_name, committer_email=committer_email) patch.set_bottom(bottom, backup=backup) patch.set_top(commit_id, backup=backup) patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) patch.set_authdate(author_date) patch.set_commname(committer_name) patch.set_commemail(committer_email) if log: self.log_patch(patch, log, notes) return commit_id