X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/6ad48e4898f40d58a236de38f0f49a9f8bfb7ab2..d3cf7d862f3ef6e3d6994714163a847e2ecba8e5:/stgit/stack.py diff --git a/stgit/stack.py b/stgit/stack.py index 1e45e72..7109186 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -92,7 +92,9 @@ def edit_file(series, string, comment, show_patch = True): f.close() # the editor - if 'EDITOR' in os.environ: + if config.has_option('stgit', 'editor'): + editor = config.get('stgit', 'editor') + elif 'EDITOR' in os.environ: editor = os.environ['EDITOR'] else: editor = 'vi' @@ -168,7 +170,11 @@ class Patch: def set_bottom(self, string, backup = False): if backup: - self.__set_field('bottom.old', self.__get_field('bottom')) + curr = self.__get_field('bottom') + if curr != string: + self.__set_field('bottom.old', curr) + else: + self.__set_field('bottom.old', None) self.__set_field('bottom', string) def get_top(self): @@ -176,7 +182,11 @@ class Patch: def set_top(self, string, backup = False): if backup: - self.__set_field('top.old', self.__get_field('top')) + curr = self.__get_field('top') + if curr != string: + self.__set_field('top.old', curr) + else: + self.__set_field('top.old', None) self.__set_field('top', string) def restore_old_boundaries(self): @@ -186,8 +196,9 @@ class Patch: if top and bottom: self.__set_field('bottom', bottom) self.__set_field('top', top) + return True else: - raise StackException, 'No patch undo information' + return False def get_description(self): return self.__get_field('description', True) @@ -255,6 +266,11 @@ class Series: self.__unapplied_file = os.path.join(self.__patch_dir, 'unapplied') self.__current_file = os.path.join(self.__patch_dir, 'current') + def get_branch(self): + """Return the branch name for the Series object + """ + return self.__name + def __set_current(self, name): """Sets the topmost patch """ @@ -406,7 +422,9 @@ class Series: return commit_id - def new_patch(self, name, message = None, edit = False, show_patch = False, + def new_patch(self, name, message = None, can_edit = True, + unapplied = False, show_patch = False, + top = None, bottom = None, author_name = None, author_email = None, author_date = None, committer_name = None, committer_email = None): """Creates a new patch @@ -414,7 +432,7 @@ class Series: if self.__patch_applied(name) or self.__patch_unapplied(name): raise StackException, 'Patch "%s" already exists' % name - if not message: + if not message and can_edit: descr = edit_file(self, None, \ 'Please enter the description for patch "%s" ' \ 'above.' % name, show_patch) @@ -427,8 +445,16 @@ class Series: patch = Patch(name, self.__patch_dir) patch.create() - patch.set_bottom(head) - patch.set_top(head) + + if bottom: + patch.set_bottom(bottom) + else: + patch.set_bottom(head) + if top: + patch.set_top(top) + else: + patch.set_top(head) + patch.set_description(descr) patch.set_authname(author_name) patch.set_authemail(author_email) @@ -436,8 +462,15 @@ class Series: patch.set_commname(committer_name) patch.set_commemail(committer_email) - append_string(self.__applied_file, patch.get_name()) - self.__set_current(name) + if unapplied: + patches = [patch.get_name()] + self.get_unapplied() + + f = file(self.__unapplied_file, 'w+') + f.writelines([line + '\n' for line in patches]) + f.close() + else: + append_string(self.__applied_file, patch.get_name()) + self.__set_current(name) def delete_patch(self, name): """Deletes a patch @@ -460,6 +493,80 @@ class Series: f.writelines([line + '\n' for line in unapplied]) f.close() + 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() + self.__begin_stack_check() + + forwarded = 0 + top = git.get_head() + + for name in names: + assert(name in unapplied) + + patch = Patch(name, self.__patch_dir) + + 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 + patch.set_bottom(head, backup = True) + 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_bottom(head, backup = True) + patch.set_top(top, backup = True) + else: + top = head + # stop the fast-forwarding, must do a real merge + break + + forwarded+=1 + unapplied.remove(name) + + git.switch(top) + + append_strings(self.__applied_file, names[0:forwarded]) + + f = file(self.__unapplied_file, 'w+') + f.writelines([line + '\n' for line in unapplied]) + f.close() + + self.__set_current(name) + + return forwarded + def push_patch(self, name): """Pushes a patch on the stack """ @@ -522,7 +629,7 @@ class Series: patch = Patch(name, self.__patch_dir) git.reset() self.pop_patch(name) - patch.restore_old_boundaries() + return patch.restore_old_boundaries() def pop_patch(self, name): """Pops the top patch from the stack