Allow git.apply_patch() to take a base revision
authorCatalin Marinas <catalin.marinas@gmail.com>
Wed, 5 Oct 2005 15:58:18 +0000 (16:58 +0100)
committerCatalin Marinas <catalin.marinas@gmail.com>
Wed, 5 Oct 2005 15:58:18 +0000 (16:58 +0100)
This option is useful for import --base and fold commands. Both these
commands were modified to take advantage of it. The fold commands also
supports a --base option, similar to the import one.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
stgit/commands/fold.py
stgit/commands/imprt.py
stgit/git.py
stgit/stack.py

index 9542fa6..963c196 100644 (file)
@@ -29,14 +29,15 @@ usage = """%prog [options] [<file>]
 Apply the given GNU diff file (or the standard input) onto the top of
 the current patch. With the '--threeway' option, the patch is applied
 onto the bottom of the current patch and a three-way merge is
-performed with the current top."""
+performed with the current top. With the --base option, the patch is
+applied onto the specified base and a three-way merged is performed
+with the current top."""
 
 options = [make_option('-t', '--threeway',
                        help = 'perform a three-way merge with the current patch',
                        action = 'store_true'),
-           make_option('-n', '--norefresh',
-                       help = 'do not refresh the current patch',
-                       action = 'store_true')]
+           make_option('-b', '--base',
+                       help = 'use BASE instead of HEAD applying the patch')]
 
 
 def func(parser, options, args):
@@ -67,24 +68,10 @@ def func(parser, options, args):
     if options.threeway:
         crt_patch = crt_series.get_patch(current)
         bottom = crt_patch.get_bottom()
-        top = crt_patch.get_top()
-
-        git.switch(bottom)
-        git.apply_patch(filename)
-        fold_head = crt_series.refresh_patch(commit_only = True)
-        git.switch(top)
-
-        git.merge(bottom, top, fold_head)
+        git.apply_patch(filename, bottom)
+    elif options.base:
+        git.apply_patch(filename, git.rev_parse(options.base))
     else:
         git.apply_patch(filename)
 
-    # no merge conflicts at this point, exception would have been raised
-    modified = git.local_changes()
-
-    if not options.norefresh and modified:
-        crt_series.refresh_patch()
-
-    if modified:
-        print 'done'
-    else:
-        print 'done (unchanged)'
+    print 'done'
index 0afe00f..96ba0a1 100644 (file)
@@ -220,19 +220,7 @@ def func(parser, options, args):
     sys.stdout.flush()
 
     if options.base:
-        orig_head = git.get_head()
-        git.switch(options.base)
-
-        try:
-            git.apply_patch(filename)
-        except git.GitException, ex:
-            print >> sys.stderr, '"git apply" failed'
-            git.switch(orig_head)
-            raise
-
-        top = crt_series.refresh_patch(commit_only = True)
-        git.switch(orig_head)
-        git.merge(options.base, orig_head, top)
+        git.apply_patch(filename, git.rev_parse(options.base))
     else:
         git.apply_patch(filename)
 
index 083e97f..c57063b 100644 (file)
@@ -245,7 +245,10 @@ def __set_head(val):
 def rev_parse(git_id):
     """Parse the string and return a verified SHA1 id
     """
-    return _output_one_line(['git-rev-parse', '--verify', git_id])
+    try:
+        return _output_one_line(['git-rev-parse', '--verify', git_id])
+    except GitException:
+        raise GitException, 'Unknown revision: %s' % git_id
 
 def add(names):
     """Add the files or recursively add the directory contents
@@ -511,17 +514,35 @@ def pull(repository = 'origin', refspec = None):
     if __run('git pull', args) != 0:
         raise GitException, 'Failed "git pull %s"' % repository
 
-def apply_patch(filename = None):
-    """Apply a patch onto the current index. There must not be any
-    local changes in the tree, otherwise the command fails
+def apply_patch(filename = None, base = None):
+    """Apply a patch onto the current or given index. There must not
+    be any local changes in the tree, otherwise the command fails
     """
+    def __apply_patch():
+        if filename:
+            return __run('git-apply --index', [filename]) == 0
+        else:
+            try:
+                _input('git-apply --index', sys.stdin)
+            except GitException:
+                return False
+            return True
+
     os.system('git-update-index --refresh > /dev/null')
 
-    if filename:
-        if __run('git-apply --index', [filename]) != 0:
-            raise GitException, 'Patch does not apply cleanly'
-    else:
-        _input('git-apply --index', sys.stdin)
+    if base:
+        orig_head = get_head()
+        switch(base)
+
+    if not __apply_patch():
+        if base:
+            switch(orig_head)
+        raise GitException, 'Patch does not apply cleanly'
+    elif base:
+        top = commit(message = 'temporary commit used for applying a patch',
+                     parents = [base])
+        switch(orig_head)
+        merge(base, orig_head, top)
 
 def clone(repository, local_dir):
     """Clone a remote repository. At the moment, just use the
index d411725..76da21a 100644 (file)
@@ -372,8 +372,7 @@ class Series:
                       cache_update = True,
                       author_name = None, author_email = None,
                       author_date = None,
-                      committer_name = None, committer_email = None,
-                      commit_only = False):
+                      committer_name = None, committer_email = None):
         """Generates a new commit for the given patch
         """
         name = self.get_current()
@@ -414,14 +413,13 @@ class Series:
                                committer_name = committer_name,
                                committer_email = committer_email)
 
-        if not commit_only:
-            patch.set_top(commit_id)
-            patch.set_description(descr)
-            patch.set_authname(author_name)
-            patch.set_authemail(author_email)
-            patch.set_authdate(author_date)
-            patch.set_commname(committer_name)
-            patch.set_commemail(committer_email)
+        patch.set_top(commit_id)
+        patch.set_description(descr)
+        patch.set_authname(author_name)
+        patch.set_authemail(author_email)
+        patch.set_authdate(author_date)
+        patch.set_commname(committer_name)
+        patch.set_commemail(committer_email)
 
         return commit_id