Subject: [StGit PATCH 1/2] Convert "stg delete" to the new infrastructure

From: Karl Hasselström <[email-masked]>
Date: Sun, 10 Feb 2008 21:48:45 +0100

In the process, it gains the ability to delete any applied patch (not
just the topmost one, like before), even when deleting patches from
another branch. (However, when deleting patches on another branch, we
obviously can't represent a conflict in the index and worktree, so any
conflicts will make the operation abort.)

One of the t1600 subtests made sure that we couldn't delete
non-topmost patches, and had to be corrected.

Signed-off-by: Karl Hasselström <[email-masked]>

---

Unlike the "stg new" conversion, this resulted in a sizeable reduction
of lines of code, and of code complexity.

 stgit/commands/delete.py |   72 +++++++++++++++-------------------------------
 t/t1600-delete-one.sh    |    8 +++--
 2 files changed, 27 insertions(+), 53 deletions(-)

diff --git a/stgit/commands/delete.py b/stgit/commands/delete.py
index 1696cb9..106fbd2 100644
--- a/stgit/commands/delete.py
+++ b/stgit/commands/delete.py
@@ -16,67 +16,41 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
-import sys, os
-from optparse import OptionParser, make_option
-
-from stgit.commands.common import *
-from stgit.utils import *
-from stgit.out import *
-from stgit import stack, git
+from optparse import make_option
 
+from stgit.commands import common
+from stgit.lib import transaction
 
 help = 'delete patches'
 usage = """%prog [options] <patch1> [<patch2>] [<patch3>..<patch4>]
 
-Delete the patches passed as arguments. If an applied patch is to be
-deleted, all other patches applied on top of it must be deleted too,
-and they must be explicitly specified, since this command will not try
-to delete a patch unless you explicitly ask it to. If any applied
-patches are deleted, they are popped from the stack.
+Delete the patches passed as arguments.
 
 Note that the 'delete' operation is irreversible."""
 
-directory = DirectoryGotoToplevel()
+directory = common.DirectoryHasRepositoryLib()
 options = [make_option('-b', '--branch',
                        help = 'use BRANCH instead of the default one')]
 
 def func(parser, options, args):
-    """Deletes one or more patches.
-    """
-    applied_patches = crt_series.get_applied()
-    unapplied_patches = crt_series.get_unapplied()
-    all_patches = applied_patches + unapplied_patches
-
+    """Delete one or more patches."""
+    if options.branch:
+        stack = directory.repository.get_stack(options.branch)
+        iw = None # can't use index/workdir to manipulate another branch
+    else:
+        stack = directory.repository.current_stack
+        iw = stack.repository.default_iw
     if args:
-        patches = parse_patches(args, all_patches, len(applied_patches))
+        patches = set(common.parse_patches(
+                args, (list(stack.patchorder.applied)
+                       + list(stack.patchorder.unapplied))))
     else:
         parser.error('No patches specified')
-
-    applied = []
-
-    # find the applied patches to be deleted. We can only delete
-    # consecutive patches in the applied range
-    for patch in applied_patches[::-1]:
-        if patch in patches:
-            applied.append(patch)
-            patches.remove(patch)
-        else:
-            break
-
-    # any applied patches to be deleted but not in consecutive order?
-    for patch in patches:
-        if patch in applied_patches:
-            raise CmdException, 'Cannot delete the applied patch "%s"' % patch
-
-    if applied and not options.branch:
-        check_local_changes()
-        check_conflicts()
-        check_head_top_equal(crt_series)
-
-    # delete the patches
-    for patch in applied + patches:
-        crt_series.delete_patch(patch)
-        out.info('Patch "%s" successfully deleted' % patch)
-
-    if not options.branch:
-        print_crt_patch(crt_series)
+    trans = transaction.StackTransaction(stack, 'stg delete')
+    try:
+        to_push = trans.delete_patches(lambda pn: pn in patches)
+        for pn in to_push:
+            trans.push_patch(pn, iw)
+    except transaction.TransactionHalted:
+        pass
+    return trans.run(iw)
diff --git a/t/t1600-delete-one.sh b/t/t1600-delete-one.sh
index 3052b3a..c3451d8 100755
--- a/t/t1600-delete-one.sh
+++ b/t/t1600-delete-one.sh
@@ -77,8 +77,8 @@ test_expect_success \
     'Try to delete a non-topmost applied patch' \
     '
     [ $(stg applied | wc -l) -eq 2 ] &&
-    ! stg delete foo &&
-    [ $(stg applied | wc -l) -eq 2 ]
+    stg delete foo &&
+    [ $(stg applied | wc -l) -eq 1 ]
     '
 
 test_expect_success \
@@ -99,10 +99,10 @@ test_expect_success \
 test_expect_success \
     'Delete a patch in another branch' \
     '
-    [ $(stg applied | wc -l) -eq 3 ] &&
+    [ $(stg applied | wc -l) -eq 2 ] &&
     [ $(stg applied -b br | wc -l) -eq 1 ] &&
     stg delete -b br baz &&
-    [ $(stg applied | wc -l) -eq 3 ] &&
+    [ $(stg applied | wc -l) -eq 2 ] &&
     [ $(stg applied -b br | wc -l) -eq 0 ]
     '