Add a --set-tree flag to stg push
authorDavid Kågedal <davidk@lysator.liu.se>
Fri, 22 May 2009 20:38:12 +0000 (22:38 +0200)
committerKarl Hasselström <kha@treskal.com>
Fri, 22 May 2009 20:42:06 +0000 (22:42 +0200)
This flag makes the push simply restore the tree that the patch used
before, rather than doing any kind of merge.

Signed-off-by: David Kågedal <davidk@lysator.liu.se>
Signed-off-by: Karl Hasselström <kha@treskal.com>
stgit/commands/push.py
stgit/lib/transaction.py
t/t1207-push-tree.sh [new file with mode: 0755]

index 0d25a65..84a93bd 100644 (file)
@@ -43,7 +43,18 @@ options = [
     opt('-n', '--number', type = 'int',
         short = 'Push the specified number of patches'),
     opt('--reverse', action = 'store_true',
-        short = 'Push the patches in reverse order')
+        short = 'Push the patches in reverse order'),
+    opt('--set-tree', action = 'store_true',
+        short = 'Push the patch with the original tree', long = """
+        Push the patches, but don't perform a merge. Instead, the
+        resulting tree will be identical to the tree that the patch
+        previously created.
+
+        This can be useful when splitting a patch by first popping the
+        patch and creating a new patch with some of the
+        changes. Pushing the original patch with '--set-tree' will
+        avoid conflicts and only the remaining changes will be in the
+        patch.""")
     ] + argparse.keep_option() + argparse.merged_option()
 
 directory = common.DirectoryHasRepositoryLib()
@@ -74,14 +85,18 @@ def func(parser, options, args):
     if options.reverse:
         patches.reverse()
 
-    try:
-        if options.merged:
-            merged = set(trans.check_merged(patches))
-        else:
-            merged = set()
+    if options.set_tree:
         for pn in patches:
-            trans.push_patch(pn, iw, allow_interactive = True,
-                             already_merged = pn in merged)
-    except transaction.TransactionHalted:
-        pass
+            trans.push_tree(pn)
+    else:
+        try:
+            if options.merged:
+                merged = set(trans.check_merged(patches))
+            else:
+                merged = set()
+            for pn in patches:
+                trans.push_patch(pn, iw, allow_interactive = True,
+                                 already_merged = pn in merged)
+        except transaction.TransactionHalted:
+            pass
     return trans.run(iw)
index 96c57b9..30a153b 100644 (file)
@@ -379,6 +379,28 @@ class StackTransaction(object):
             # Update immediately.
             update()
 
+    def push_tree(self, pn):
+        """Push the named patch without updating its tree."""
+        orig_cd = self.patches[pn].data
+        cd = orig_cd.set_committer(None).set_parent(self.top)
+
+        s = ''
+        if any(getattr(cd, a) != getattr(orig_cd, a) for a in
+               ['parent', 'tree', 'author', 'message']):
+            self.patches[pn] = self.__stack.repository.commit(cd)
+        else:
+            s = ' (unmodified)'
+        if cd.is_nochange():
+            s = ' (empty)'
+        out.info('Pushed %s%s' % (pn, s))
+
+        if pn in self.hidden:
+            x = self.hidden
+        else:
+            x = self.unapplied
+        del x[x.index(pn)]
+        self.applied.append(pn)
+
     def reorder_patches(self, applied, unapplied, hidden = None, iw = None):
         """Push and pop patches to attain the given ordering."""
         if hidden is None:
diff --git a/t/t1207-push-tree.sh b/t/t1207-push-tree.sh
new file mode 100755 (executable)
index 0000000..9d0b1cc
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 David Kågedal
+#
+
+test_description='Exercise pushing patches with --set-tree.'
+
+. ./test-lib.sh
+
+test_expect_success \
+    'Create initial patches' '
+    stg init &&
+    stg new A -m A &&
+    echo hello world > a &&
+    git add a &&
+    stg refresh
+    stg new B -m B &&
+    echo HELLO WORLD > a &&
+    stg refresh
+'
+
+test_expect_success \
+    'Back up and create a partial patch' '
+    stg pop &&
+    stg new C -m C &&
+    echo hello WORLD > a &&
+    stg refresh
+'
+
+test_expect_success \
+    'Reapply patch B' '
+    stg push --set-tree B
+'
+
+test_expect_success \
+    'Compare results' '
+    stg pop -a &&
+    stg push &&
+    test "$(echo $(cat a))" = "hello world" &&
+    stg push &&
+    test "$(echo $(cat a))" = "hello WORLD" &&
+    stg push &&
+    test "$(echo $(cat a))" = "HELLO WORLD"
+'
+
+test_done