def pop_patch(self, name, keep=False): """Pops the top patch from the stack """ applied = self.get_applied() applied.reverse() assert(name in applied) patch = self.get_patch(name) if git.get_head_file() == self.get_name(): if keep and not git.apply_diff(git.get_head(), patch.get_bottom(), check_index=False): raise StackException( 'Failed to pop patches while preserving the local changes') git.switch(patch.get_bottom(), keep) else: git.set_branch(self.get_name(), patch.get_bottom()) # save the new applied list idx = applied.index(name) + 1 popped = applied[:idx] popped.reverse() unapplied = popped + self.get_unapplied() write_strings(self.__unapplied_file, unapplied) del applied[:idx] applied.reverse() write_strings(self.__applied_file, applied)
def pop_patch(self, name, keep = False): """Pops the top patch from the stack """ applied = self.get_applied() applied.reverse() assert(name in applied) patch = self.get_patch(name) if git.get_head_file() == self.get_name(): if keep and not git.apply_diff(git.get_head(), patch.get_bottom(), check_index = False): raise StackException( 'Failed to pop patches while preserving the local changes') git.switch(patch.get_bottom(), keep) else: git.set_branch(self.get_name(), patch.get_bottom()) # save the new applied list idx = applied.index(name) + 1 popped = applied[:idx] popped.reverse() unapplied = popped + self.get_unapplied() write_strings(self.__unapplied_file, unapplied) del applied[:idx] applied.reverse() write_strings(self.__applied_file, applied)
def func(parser, options, args): """Merge the applied patches into the base of the current stack and remove them from the series while advancing the base """ if len(args) != 0: parser.error('incorrect number of arguments') check_local_changes() check_conflicts() check_head_top_equal() applied = crt_series.get_applied() if not applied: raise CmdException, 'No patches applied' if crt_series.get_protected(): raise CmdException, 'This branch is protected. Commit is not permitted' crt_head = git.get_head() out.start('Committing %d patches' % len(applied)) crt_series.pop_patch(applied[0]) git.switch(crt_head) for patch in applied: crt_series.delete_patch(patch) out.done()
def push_patch(self, name, empty=False): """Pushes a patch on the stack """ unapplied = self.get_unapplied() assert (name in unapplied) patch = Patch(name, self.__patch_dir, self.__refs_dir) head = git.get_head() bottom = patch.get_bottom() top = patch.get_top() ex = None modified = False # top != bottom always since we have a commit for each patch if empty: # just make an empty patch (top = bottom = HEAD). This # option is useful to allow undoing already merged # patches. The top is updated by refresh_patch since we # need an empty commit patch.set_bottom(head, backup=True) patch.set_top(head, backup=True) modified = True elif head == bottom: # reset the backup information. No need for logging patch.set_bottom(bottom, backup=True) patch.set_top(top, backup=True) git.switch(top) else: # new patch needs to be refreshed. # The current patch is empty after merge. patch.set_bottom(head, backup=True) patch.set_top(head, backup=True) # Try the fast applying first. If this fails, fall back to the # three-way merge if not git.apply_diff(bottom, top): # if git.apply_diff() fails, the patch requires a diff3 # merge and can be reported as modified modified = True # merge can fail but the patch needs to be pushed try: git.merge(bottom, head, top, recursive=True) except git.GitException, ex: out.error( 'The merge failed during "push".', 'Use "refresh" after fixing the conflicts or' ' revert the operation with "push --undo".')
def push_patch(self, name): """Pushes a patch on the stack """ unapplied = self.get_unapplied() assert(name in unapplied) patch = self.get_patch(name) head = git.get_head() bottom = patch.get_bottom() top = patch.get_top() # top != bottom always since we have a commit for each patch if head == bottom: # A fast-forward push. Just reset the backup # information. No need for logging patch.set_top(top, backup = True) git.switch(top) append_string(self.__applied_file, name) unapplied.remove(name) write_strings(self.__unapplied_file, unapplied) return False # Need to create a new commit an merge in the old patch ex = None modified = False # Try the fast applying first. If this fails, fall back to the # three-way merge if not git.apply_diff(bottom, top): # if git.apply_diff() fails, the patch requires a diff3 # merge and can be reported as modified modified = True # merge can fail but the patch needs to be pushed try: git.merge_recursive(bottom, head, top) except git.GitException, ex: out.error('The merge failed during "push".', 'Revert the operation with "stg undo".')
def push_patch(self, name): """Pushes a patch on the stack """ unapplied = self.get_unapplied() assert(name in unapplied) patch = self.get_patch(name) head = git.get_head() bottom = patch.get_bottom() top = patch.get_top() # top != bottom always since we have a commit for each patch if head == bottom: # A fast-forward push. Just reset the backup # information. No need for logging patch.set_top(top, backup = True) git.switch(top) append_string(self.__applied_file, name) unapplied.remove(name) write_strings(self.__unapplied_file, unapplied) return False # Need to create a new commit an merge in the old patch ex = None modified = False # Try the fast applying first. If this fails, fall back to the # three-way merge if not git.apply_diff(bottom, top): # if git.apply_diff() fails, the patch requires a diff3 # merge and can be reported as modified modified = True # merge can fail but the patch needs to be pushed try: git.merge_recursive(bottom, head, top) except git.GitException: out.error('The merge failed during "push".', 'Revert the operation with "stg undo".') append_string(self.__applied_file, name) unapplied.remove(name) write_strings(self.__unapplied_file, unapplied) if not ex: # if the merge was OK and no conflicts, just refresh the patch # The GIT cache was already updated by the merge operation if modified: log = 'push(m)' else: log = 'push' self.refresh_patch(bottom = head, cache_update = False, log = log) else: # we make the patch empty, with the merged state in the # working tree. self.refresh_patch(bottom = head, cache_update = False, empty = True, log = 'push(c)') raise StackException(str(ex)) return modified
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 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 push_patch(self, name): """Pushes a patch on the stack """ unapplied = self.get_unapplied() assert(name in unapplied) patch = self.get_patch(name) head = git.get_head() bottom = patch.get_bottom() top = patch.get_top() # top != bottom always since we have a commit for each patch if head == bottom: # A fast-forward push. Just reset the backup # information. No need for logging patch.set_top(top, backup=True) git.switch(top) append_string(self.__applied_file, name) unapplied.remove(name) write_strings(self.__unapplied_file, unapplied) return False # Need to create a new commit an merge in the old patch ex = None modified = False # Try the fast applying first. If this fails, fall back to the # three-way merge if not git.apply_diff(bottom, top): # if git.apply_diff() fails, the patch requires a diff3 # merge and can be reported as modified modified = True # merge can fail but the patch needs to be pushed try: git.merge_recursive(bottom, head, top) except git.GitException: out.error('The merge failed during "push".', 'Revert the operation with "stg undo".') append_string(self.__applied_file, name) unapplied.remove(name) write_strings(self.__unapplied_file, unapplied) if not ex: # if the merge was OK and no conflicts, just refresh the patch # The GIT cache was already updated by the merge operation if modified: log = 'push(m)' else: log = 'push' self.refresh_patch(bottom=head, cache_update=False, log=log) else: # we make the patch empty, with the merged state in the # working tree. self.refresh_patch( bottom=head, cache_update=False, empty=True, log='push(c)', ) raise StackException(str(ex)) return modified