Don't always use git-merge-recursive because of speed
[stgit] / stgit / commands / pick.py
index e8f4dfa..400e4eb 100644 (file)
@@ -28,7 +28,7 @@ usage = """%prog [options] [<patch@branch>|<commit>]
 
 Import a patch from a different branch or a commit object into the
 current series. By default, the name of the imported patch is used as
-the name of the current patch. It can be overriden with the '--name'
+the name of the current patch. It can be overridden with the '--name'
 option. A commit object can be reverted with the '--reverse'
 option. The log and author information are those of the commit object."""
 
@@ -36,6 +36,14 @@ options = [make_option('-n', '--name',
                        help = 'use NAME as the patch name'),
            make_option('-r', '--reverse',
                        help = 'reverse the commit object before importing',
+                       action = 'store_true'),
+           make_option('-p', '--parent', metavar = 'COMMITID',
+                       help = 'use COMMITID as parent'),
+           make_option('--fold',
+                       help = 'fold the commit object into the current patch',
+                       action = 'store_true'),
+           make_option('--update',
+                       help = 'like fold but only update the current patch files',
                        action = 'store_true')]
 
 
@@ -50,38 +58,74 @@ def func(parser, options, args):
     check_head_top_equal()
 
     commit_str = args[0]
-    patch_branch = commit_str.split('@')
-
-    if len(patch_branch) == 2:
-        patch = patch_branch[0]
-    elif options.name:
-        patch = options.name
-    else:
-        raise CmdException, 'Unkown patch name'
-
     commit_id = git_id(commit_str)
     commit = git.Commit(commit_id)
 
+    if options.fold or options.update:
+        if not crt_series.get_current():
+            raise CmdException, 'No patches applied'
+    else:
+        patch_branch = commit_str.split('@')
+        if options.name:
+            patch = options.name
+        elif len(patch_branch) == 2:
+            patch = patch_branch[0]
+        else:
+            patch = make_patch_name(commit.get_log(), crt_series.patch_exists)
+
+    if options.parent:
+        parent = git_id(options.parent)
+    else:
+        parent = commit.get_parent()
+
     if not options.reverse:
-        bottom = commit.get_parent()
+        bottom = parent
         top = commit_id
     else:
         bottom = commit_id
-        top = commit.get_parent()
+        top = parent
+
+    if options.fold:
+        print 'Folding commit %s...' % commit_id,
+        sys.stdout.flush()
 
-    message = commit.get_log()
-    author_name, author_email, author_date = \
-                 name_email_date(commit.get_author())
+        # try a direct git-apply first
+        if not git.apply_diff(bottom, top):
+            git.merge(bottom, git.get_head(), top, recursive = True)
 
-    print 'Importing commit %s...' % commit_id,
-    sys.stdout.flush()
+        print 'done'
+    elif options.update:
+        rev1 = git_id('//bottom')
+        rev2 = git_id('//top')
+        files = git.barefiles(rev1, rev2).split('\n')
 
-    crt_series.new_patch(patch, message = message, can_edit = False,
-                         unapplied = True, bottom = bottom, top = top,
-                         author_name = author_name,
-                         author_email = author_email,
-                         author_date = author_date)
-    crt_series.push_patch(patch)
+        print 'Updating with commit %s...' % commit_id,
+        sys.stdout.flush()
 
-    print 'done'
+        if not git.apply_diff(bottom, top, files = files):
+            raise CmdException, 'Patch updating failed'
+
+        print 'done'
+    else:
+        message = commit.get_log()
+        author_name, author_email, author_date = \
+                     name_email_date(commit.get_author())
+
+        print 'Importing commit %s...' % commit_id,
+        sys.stdout.flush()
+
+        crt_series.new_patch(patch, message = message, can_edit = False,
+                             unapplied = True, bottom = bottom, top = top,
+                             author_name = author_name,
+                             author_email = author_email,
+                             author_date = author_date)
+        modified = crt_series.push_patch(patch)
+
+        if crt_series.empty_patch(patch):
+            print 'done (empty patch)'
+        elif modified:
+            print 'done (modified)'
+        else:
+            print 'done'
+        
     print_crt_patch()