Add a --set-tree flag to stg push
[stgit] / stgit / lib / transaction.py
index 4148ff3..30a153b 100644 (file)
@@ -302,6 +302,7 @@ class StackTransaction(object):
         """Attempt to push the named patch. If this results in conflicts,
         halts the transaction. If index+worktree are given, spill any
         conflicts to them."""
+        out.start('Pushing patch "%s"' % pn)
         orig_cd = self.patches[pn].data
         cd = orig_cd.set_committer(None)
         oldparent = cd.parent
@@ -330,27 +331,33 @@ class StackTransaction(object):
                 iw.merge(base, ours, theirs, interactive = interactive)
                 tree = iw.index.write_tree()
                 self.__current_tree = tree
-                s = ' (modified)'
+                s = 'modified'
             except git.MergeConflictException, e:
                 tree = ours
                 merge_conflict = True
                 self.__conflicts = e.conflicts
-                s = ' (conflict)'
+                s = 'conflict'
             except git.MergeException, e:
                 self.__halt(str(e))
         cd = cd.set_tree(tree)
         if any(getattr(cd, a) != getattr(orig_cd, a) for a in
                ['parent', 'tree', 'author', 'message']):
             comm = self.__stack.repository.commit(cd)
-            self.head = comm
+            if merge_conflict:
+                # When we produce a conflict, we'll run the update()
+                # function defined below _after_ having done the
+                # checkout in run(). To make sure that we check out
+                # the real stack top (as it will look after update()
+                # has been run), set it hard here.
+                self.head = comm
         else:
             comm = None
-            s = ' (unmodified)'
+            s = 'unmodified'
         if already_merged:
-            s = ' (merged)'
+            s = 'merged'
         elif not merge_conflict and cd.is_nochange():
-            s = ' (empty)'
-        out.info('Pushed %s%s' % (pn, s))
+            s = 'empty'
+        out.done(s)
         def update():
             if comm:
                 self.patches[pn] = comm
@@ -372,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:
@@ -389,6 +418,7 @@ class StackTransaction(object):
 
     def check_merged(self, patches):
         """Return a subset of patches already merged."""
+        out.start('Checking for patches merged upstream')
         merged = []
         if self.temp_index_tree != self.stack.head.data.tree:
             self.temp_index.read_tree(self.stack.head.data.tree)
@@ -407,4 +437,5 @@ class StackTransaction(object):
                 self.temp_index_tree = None
             except git.MergeException:
                 pass
+        out.done('%d found' % len(merged))
         return merged