Cache the HEAD value
[stgit] / stgit / stack.py
index 55c49a8..d411725 100644 (file)
@@ -249,8 +249,7 @@ class Series:
     """Class including the operations on series
     """
     def __init__(self, name = None):
-        """Takes a series name as the parameter. A valid .git/patches/name
-        directory should exist
+        """Takes a series name as the parameter.
         """
         if name:
             self.__name = name
@@ -297,12 +296,16 @@ class Series:
             return name
 
     def get_applied(self):
+        if not os.path.isfile(self.__applied_file):
+            raise StackException, 'Branch "%s" not initialised' % self.__name
         f = file(self.__applied_file)
         names = [line.strip() for line in f.readlines()]
         f.close()
         return names
 
     def get_unapplied(self):
+        if not os.path.isfile(self.__unapplied_file):
+            raise StackException, 'Branch "%s" not initialised' % self.__name
         f = file(self.__unapplied_file)
         names = [line.strip() for line in f.readlines()]
         f.close()
@@ -517,13 +520,40 @@ class Series:
             # top != bottom always since we have a commit for each patch
             if head == bottom:
                 # reset the backup information
-                patch.set_bottom(bottom, backup = True)
+                patch.set_bottom(head, backup = True)
                 patch.set_top(top, backup = True)
 
             else:
-                top = head
-                # stop the fast-forwarding, must do a real merge
-                break
+                head_tree = git.get_commit(head).get_tree()
+                bottom_tree = git.get_commit(bottom).get_tree()
+                if head_tree == bottom_tree:
+                    # We must just reparent this patch and create a new commit
+                    # for it
+                    descr = patch.get_description()
+                    author_name = patch.get_authname()
+                    author_email = patch.get_authemail()
+                    author_date = patch.get_authdate()
+                    committer_name = patch.get_commname()
+                    committer_email = patch.get_commemail()
+
+                    top_tree = git.get_commit(top).get_tree()
+
+                    top = git.commit(message = descr, parents = [head],
+                                     cache_update = False,
+                                     tree_id = top_tree,
+                                     allowempty = True,
+                                     author_name = author_name,
+                                     author_email = author_email,
+                                     author_date = author_date,
+                                     committer_name = committer_name,
+                                     committer_email = committer_email)
+
+                    patch.set_bottom(head, backup = True)
+                    patch.set_top(top, backup = True)
+                else:
+                    top = head
+                    # stop the fast-forwarding, must do a real merge
+                    break
 
             forwarded+=1
             unapplied.remove(name)
@@ -568,14 +598,17 @@ class Series:
             # The current patch is empty after merge.
             patch.set_bottom(head, backup = True)
             patch.set_top(head, backup = True)
-            # merge/refresh can fail but the patch needs to be pushed
-            try:
-                git.merge(bottom, head, top)
-            except git.GitException, ex:
-                print >> sys.stderr, \
-                      'The merge failed during "push". ' \
-                      'Use "refresh" after fixing the conflicts'
-                pass
+
+            # Try the fast applying first. If this fails, fall back to the
+            # three-way merge
+            if not git.apply_diff(bottom, top):
+                # merge can fail but the patch needs to be pushed
+                try:
+                    git.merge(bottom, head, top)
+                except git.GitException, ex:
+                    print >> sys.stderr, \
+                          'The merge failed during "push". ' \
+                          'Use "refresh" after fixing the conflicts'
 
         append_string(self.__applied_file, name)