Use the ".." syntax for patch ranges
authorCatalin Marinas <catalin.marinas@gmail.com>
Fri, 11 Aug 2006 16:32:33 +0000 (17:32 +0100)
committerCatalin Marinas <catalin.marinas@gmail.com>
Fri, 11 Aug 2006 17:54:26 +0000 (18:54 +0100)
This patch also adapt the push/mail/diff/export commands to the new
syntax.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
stgit/commands/common.py
stgit/commands/diff.py
stgit/commands/export.py
stgit/commands/mail.py
stgit/commands/pop.py
stgit/commands/push.py

index 6843dcf..b8ea3bb 100644 (file)
@@ -209,6 +209,51 @@ def pop_patches(patches):
 
     print 'done'
 
+def parse_patches(patch_args, patch_list):
+    """Parse patch_args list for patch names in patch_list and return
+    a list. The names can be individual patches and/or in the
+    patch1..patch2 format.
+    """
+    patches = []
+
+    for name in patch_args:
+        pair = name.split('..')
+        for p in pair:
+            if p and not p in patch_list:
+                raise CmdException, 'Unknown patch name: %s' % p
+
+        if len(pair) == 1:
+            # single patch name
+            pl = pair
+        elif len(pair) == 2:
+            # patch range [p1]..[p2]
+            # inclusive boundary
+            if pair[0]:
+                first = patch_list.index(pair[0])
+            else:
+                first = 0
+            # exclusive boundary
+            if pair[1]:
+                last = patch_list.index(pair[1]) + 1
+            else:
+                last = len(patch_list)
+
+            if last > first:
+                pl = patch_list[first:last]
+            else:
+                pl = patch_list[(last - 1):(first + 1)]
+                pl.reverse()
+        else:
+            raise CmdException, 'Malformed patch name: %s' % name
+
+        for p in pl:
+            if p in patches:
+                raise CmdException, 'Duplicate patch name: %s' % p
+
+        patches += pl
+
+    return patches
+
 def name_email(address):
     """Return a tuple consisting of the name and email parsed from a
     standard 'name <email>' or 'email (name)' string
index 9abd438..977f899 100644 (file)
@@ -41,7 +41,7 @@ rev = '([patch][//[bottom | top]]) | <tree-ish> | base'
 If neither bottom nor top are given but a '//' is present, the command
 shows the specified patch (defaulting to the current one)."""
 
-options = [make_option('-r', metavar = 'rev1[:[rev2]]', dest = 'revs',
+options = [make_option('-r', metavar = 'rev1[..[rev2]]', dest = 'revs',
                        help = 'show the diff between revisions'),
            make_option('-s', '--stat',
                        help = 'show the stat instead of the diff',
@@ -52,7 +52,7 @@ def func(parser, options, args):
     """Show the tree diff
     """
     if options.revs:
-        rev_list = options.revs.split(':')
+        rev_list = options.revs.split('..')
         rev_list_len = len(rev_list)
         if rev_list_len == 1:
             rev = rev_list[0]
index 4136b7f..ea349c3 100644 (file)
@@ -61,7 +61,7 @@ options = [make_option('-n', '--numbered',
            make_option('-t', '--template', metavar = 'FILE',
                        help = 'Use FILE as a template'),
            make_option('-r', '--range',
-                       metavar = '[PATCH1][:[PATCH2]]',
+                       metavar = '[PATCH1][..[PATCH2]]',
                        help = 'export patches between PATCH1 and PATCH2'),
            make_option('-b', '--branch',
                        help = 'use BRANCH instead of the default one'),
@@ -88,48 +88,11 @@ def func(parser, options, args):
         series = file(os.path.join(dirname, 'series'), 'w+')
 
     applied = crt_series.get_applied()
-    unapplied = crt_series.get_unapplied()
 
     if options.range:
-        boundaries = options.range.split(':')
-        if len(boundaries) == 1:
-            start = boundaries[0]
-            stop = boundaries[0]
-        elif len(boundaries) == 2:
-            if boundaries[0] == '':
-                start = applied[0]
-            else:
-                start = boundaries[0]
-            if boundaries[1] == '':
-                stop = applied[-1]
-            else:
-                stop = boundaries[1]
-        else:
-            raise CmdException, 'incorrect parameters to "--range"'
-
-        if start in applied:
-            start_idx = applied.index(start)
-        else:
-            if start in unapplied:
-                raise CmdException, 'Patch "%s" not applied' % start
-            else:
-                raise CmdException, 'Patch "%s" does not exist' % start
-
-        if stop in applied:
-            stop_idx = applied.index(stop) + 1
-        else:
-            if stop in unapplied:
-                raise CmdException, 'Patch "%s" not applied' % stop
-            else:
-                raise CmdException, 'Patch "%s" does not exist' % stop
-
-        if start_idx >= stop_idx:
-            raise CmdException, 'Incorrect patch range order'
+        patches = parse_patches([options.range], applied)
     else:
-        start_idx = 0
-        stop_idx = len(applied)
-
-    patches = applied[start_idx:stop_idx]
+        patches = applied
 
     num = len(patches)
     if num == 0:
index 3cc71f6..fff069c 100644 (file)
@@ -25,13 +25,13 @@ from stgit.config import config
 
 
 help = 'send a patch or series of patches by e-mail'
-usage = """%prog [options] [<patch> [<patch2...]]
+usage = """%prog [options] [<patch1>] [<patch2>] [<patch3>..<patch4>]
 
-Send a patch or a range of patches (defaulting to the applied patches)
-by e-mail using the 'smtpserver' configuration option. The From
-address and the e-mail format are generated from the template file
-passed as argument to '--template' (defaulting to
-'.git/patchmail.tmpl' or '~/.stgit/templates/patchmail.tmpl' or or
+Send a patch or a range of patches by e-mail using the 'smtpserver'
+configuration option. The From address and the e-mail format are
+generated from the template file passed as argument to '--template'
+(defaulting to '.git/patchmail.tmpl' or
+'~/.stgit/templates/patchmail.tmpl' or or
 '/usr/share/stgit/templates/patchmail.tmpl'). The To/Cc/Bcc addresses
 can either be added to the template file or passed via the
 corresponding command line options.
@@ -81,9 +81,6 @@ variables are supported."""
 options = [make_option('-a', '--all',
                        help = 'e-mail all the applied patches',
                        action = 'store_true'),
-           make_option('-r', '--range',
-                       metavar = '[PATCH1][:[PATCH2]]',
-                       help = 'e-mail patches between PATCH1 and PATCH2'),
            make_option('--to',
                        help = 'add TO to the To: list',
                        action = 'append'),
@@ -367,53 +364,11 @@ def func(parser, options, args):
         smtppassword = config.get('stgit', 'smtppassword')
 
     applied = crt_series.get_applied()
-    unapplied = crt_series.get_unapplied()
-
-    if len(args) >= 1:
-        for patch in args:
-            if patch in unapplied:
-                raise CmdException, 'Patch "%s" not applied' % patch
-            if not patch in applied:
-                raise CmdException, 'Patch "%s" does not exist' % patch
-        patches = args
-    elif options.all:
-        patches = applied
-    elif options.range:
-        boundaries = options.range.split(':')
-        if len(boundaries) == 1:
-            start = boundaries[0]
-            stop = boundaries[0]
-        elif len(boundaries) == 2:
-            if boundaries[0] == '':
-                start = applied[0]
-            else:
-                start = boundaries[0]
-            if boundaries[1] == '':
-                stop = applied[-1]
-            else:
-                stop = boundaries[1]
-        else:
-            raise CmdException, 'incorrect parameters to "--range"'
 
-        if start in applied:
-            start_idx = applied.index(start)
-        else:
-            if start in unapplied:
-                raise CmdException, 'Patch "%s" not applied' % start
-            else:
-                raise CmdException, 'Patch "%s" does not exist' % start
-        if stop in applied:
-            stop_idx = applied.index(stop) + 1
-        else:
-            if stop in unapplied:
-                raise CmdException, 'Patch "%s" not applied' % stop
-            else:
-                raise CmdException, 'Patch "%s" does not exist' % stop
-
-        if start_idx >= stop_idx:
-            raise CmdException, 'Incorrect patch range order'
-
-        patches = applied[start_idx:stop_idx]
+    if options.all:
+        patches = applied
+    elif len(args) >= 1:
+        patches = parse_patches(args, applied)
     else:
         raise CmdException, 'Incorrect options. Unknown patches to send'
 
index 9bee9f1..23aeeb3 100644 (file)
@@ -24,26 +24,25 @@ from stgit.utils import *
 from stgit import stack, git
 
 
-help = 'pop the top of the series'
-usage = """%prog [options]
+help = 'pop one or more patches from the stack'
+usage = """%prog [options] [<patch>]
 
 Pop the topmost patch or a range of patches starting with the topmost
 one from the stack. The command fails if there are local changes or
-conflicts."""
+conflicts. If a patch name is given as argument, the command will pop
+all the patches up to the given one."""
 
 options = [make_option('-a', '--all',
                        help = 'pop all the applied patches',
                        action = 'store_true'),
            make_option('-n', '--number', type = 'int',
-                       help = 'pop the specified number of patches'),
-           make_option('-t', '--to', metavar = 'PATCH',
-                       help = 'pop all patches up to PATCH')]
+                       help = 'pop the specified number of patches')]
 
 
 def func(parser, options, args):
     """Pop the topmost patch from the stack
     """
-    if len(args) != 0:
+    if len(args) > 1:
         parser.error('incorrect number of arguments')
 
     check_local_changes()
@@ -53,19 +52,22 @@ def func(parser, options, args):
     applied = crt_series.get_applied()
     if not applied:
         raise CmdException, 'No patches applied'
+    # the popping is done in reverse order
     applied.reverse()
 
-    if options.to:
-        if options.to not in applied:
-            if options.to in crt_series.get_unapplied():
-                raise CmdException, 'Patch "%s" is not currently applied.' % options.to
-            else:
-                raise CmdException, 'Patch "%s" does not exist.' % options.to
-        patches = applied[:applied.index(options.to)]
+    if options.all:
+        patches = applied
     elif options.number:
         patches = applied[:options.number]
-    elif options.all:
-        patches = applied
+    elif len(args) == 1:
+        upto_patch = args[0]
+        if upto_patch not in applied:
+            if upto_patch in crt_series.get_unapplied():
+                raise CmdException, 'Patch "%s" is not currently applied' \
+                      % upto_patch
+            else:
+                raise CmdException, 'Patch "%s" does not exist' % upto_patch
+        patches = applied[:applied.index(upto_patch)]
     else:
         patches = [applied[0]]
 
index 71fe100..a636ad2 100644 (file)
@@ -24,16 +24,16 @@ from stgit.utils import *
 from stgit import stack, git
 
 
-help = 'push a patch on top of the series'
-usage = """%prog [options] [<patch1> [<patch2>...]]
+help = 'push one or more patches onto of the stack'
+usage = """%prog [options] [<patch1>] [<patch2>] [<patch3>..<patch4>]
 
-Push a patch (defaulting to the first unapplied one) or range of
-patches to the stack. The 'push' operation allows patch reordering by
-commuting them with the three-way merge algorithm. If the result of
-the 'push' operation is not acceptable or if there are too many
-conflicts, the '--undo' option can be used to revert the patch and the
-tree to the state before the operation. Conflicts raised during the
-push operation have to be fixed and the 'resolved' command run.
+Push one or more patches (defaulting to the first unapplied one) onto
+the stack. The 'push' operation allows patch reordering by commuting
+them with the three-way merge algorithm. If the result of the 'push'
+operation is not acceptable or if there are too many conflicts, the
+'--undo' option can be used to revert the last pushed patch. Conflicts
+raised during the push operation have to be fixed and the 'resolved'
+command run.
 
 The command also notifies when the patch becomes empty (fully merged
 upstream) or is modified (three-way merged) by the 'push' operation."""
@@ -43,9 +43,6 @@ options = [make_option('-a', '--all',
                        action = 'store_true'),
            make_option('-n', '--number', type = 'int',
                        help = 'push the specified number of patches'),
-           make_option('-t', '--to', metavar = 'PATCH1[:PATCH2]',
-                       help = 'push all patches to PATCH1 or between '
-                       'PATCH1 and PATCH2'),
            make_option('--reverse',
                        help = 'push the patches in reverse order',
                        action = 'store_true'),
@@ -53,22 +50,13 @@ options = [make_option('-a', '--all',
                        help = 'check for patches merged upstream',
                        action = 'store_true'),
            make_option('--undo',
-                       help = 'undo the last push operation',
+                       help = 'undo the last patch pushing',
                        action = 'store_true')]
 
 
-def is_patch_appliable(p):
-    """See if patch exists, or is already applied.
-    """
-    if p in applied:
-        raise CmdException, 'Patch "%s" is already applied' % p
-    if p not in unapplied:
-        raise CmdException, 'Patch "%s" does not exist' % p
-
 def func(parser, options, args):
     """Pushes the given patch or all onto the series
     """
-    global applied, unapplied
 
     # If --undo is passed, do the work and exit
     if options.undo:
@@ -91,36 +79,18 @@ def func(parser, options, args):
     check_conflicts()
     check_head_top_equal()
 
-    applied = crt_series.get_applied()
     unapplied = crt_series.get_unapplied()
     if not unapplied:
         raise CmdException, 'No more patches to push'
 
-    if options.to:
-        boundaries = options.to.split(':')
-        if len(boundaries) == 1:
-            is_patch_appliable(boundaries[0])
-            patches = unapplied[:unapplied.index(boundaries[0])+1]
-        elif len(boundaries) == 2:
-            is_patch_appliable(boundaries[0])
-            is_patch_appliable(boundaries[1])
-            lb = unapplied.index(boundaries[0])
-            hb = unapplied.index(boundaries[1])
-            if lb > hb:
-                raise CmdException, 'Patch "%s" after "%s"' \
-                      % (boundaries[0], boundaries[1])
-            patches = unapplied[lb:hb+1]
-        else:
-            raise CmdException, 'incorrect parameters to "--to"'
-    elif options.number:
+    if options.number:
         patches = unapplied[:options.number]
     elif options.all:
         patches = unapplied
     elif len(args) == 0:
         patches = [unapplied[0]]
     else:
-        patches = args
-        map(is_patch_appliable, patches)
+        patches = parse_patches(args, unapplied)
 
     if patches == []:
         raise CmdException, 'No patches to push'