chiark / gitweb /
Add --sign and --ack options to "stg import"
[stgit] / stgit / stack.py
index c7569b21ee4cd2029cad8b1541f3cd550c9e80de..b19ff4d059c7d373e6478ca338a05ab2747d411f 100644 (file)
@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 import sys, os, re
 
 from stgit.utils import *
+from stgit.out import *
 from stgit import git, basedir, templates
 from stgit.config import config
 from shutil import copyfile
@@ -86,7 +87,8 @@ def edit_file(series, line, comment, show_patch = True):
     if show_patch:
        print >> f, __patch_prefix
        # series.get_patch(series.get_current()).get_top()
-       git.diff([], series.get_patch(series.get_current()).get_bottom(), None, f)
+       diff_str = git.diff(rev1 = series.get_patch(series.get_current()).get_bottom())
+       f.write(diff_str)
 
     #Vim modeline must be near the end.
     print >> f, __comment_prefix, 'vi: set textwidth=75 filetype=diff nobackup:'
@@ -142,14 +144,16 @@ class StgitObject:
 class Patch(StgitObject):
     """Basic patch implementation
     """
-    def __init__(self, name, series_dir, refs_dir):
+    def __init_refs(self):
+        self.__top_ref = self.__refs_base + '/' + self.__name
+        self.__log_ref = self.__top_ref + '.log'
+
+    def __init__(self, name, series_dir, refs_base):
         self.__series_dir = series_dir
         self.__name = name
         self._set_dir(os.path.join(self.__series_dir, self.__name))
-        self.__refs_dir = refs_dir
-        self.__top_ref_file = os.path.join(self.__refs_dir, self.__name)
-        self.__log_ref_file = os.path.join(self.__refs_dir,
-                                           self.__name + '.log')
+        self.__refs_base = refs_base
+        self.__init_refs()
 
     def create(self):
         os.mkdir(self._dir())
@@ -160,33 +164,31 @@ class Patch(StgitObject):
         for f in os.listdir(self._dir()):
             os.remove(os.path.join(self._dir(), f))
         os.rmdir(self._dir())
-        os.remove(self.__top_ref_file)
-        if os.path.exists(self.__log_ref_file):
-            os.remove(self.__log_ref_file)
+        git.delete_ref(self.__top_ref)
+        if git.ref_exists(self.__log_ref):
+            git.delete_ref(self.__log_ref)
 
     def get_name(self):
         return self.__name
 
     def rename(self, newname):
         olddir = self._dir()
-        old_top_ref_file = self.__top_ref_file
-        old_log_ref_file = self.__log_ref_file
+        old_top_ref = self.__top_ref
+        old_log_ref = self.__log_ref
         self.__name = newname
         self._set_dir(os.path.join(self.__series_dir, self.__name))
-        self.__top_ref_file = os.path.join(self.__refs_dir, self.__name)
-        self.__log_ref_file = os.path.join(self.__refs_dir,
-                                           self.__name + '.log')
+        self.__init_refs()
 
+        git.rename_ref(old_top_ref, self.__top_ref)
+        if git.ref_exists(old_log_ref):
+            git.rename_ref(old_log_ref, self.__log_ref)
         os.rename(olddir, self._dir())
-        os.rename(old_top_ref_file, self.__top_ref_file)
-        if os.path.exists(old_log_ref_file):
-            os.rename(old_log_ref_file, self.__log_ref_file)
 
     def __update_top_ref(self, ref):
-        write_string(self.__top_ref_file, ref)
+        git.set_ref(self.__top_ref, ref)
 
     def __update_log_ref(self, ref):
-        write_string(self.__log_ref_file, ref)
+        git.set_ref(self.__log_ref, ref)
 
     def update_top_ref(self):
         top = self.get_top()
@@ -358,8 +360,7 @@ class Series(PatchSet):
         # initialized, but don't touch it if it isn't.
         self.update_to_current_format_version()
 
-        self.__refs_dir = os.path.join(self._basedir(), 'refs', 'patches',
-                                       self.get_name())
+        self.__refs_base = 'refs/patches/%s' % self.get_name()
 
         self.__applied_file = os.path.join(self._dir(), 'applied')
         self.__unapplied_file = os.path.join(self._dir(), 'unapplied')
@@ -416,20 +417,22 @@ class Series(PatchSet):
         def rm(f):
             if os.path.exists(f):
                 os.remove(f)
+        def rm_ref(ref):
+            if git.ref_exists(ref):
+                git.delete_ref(ref)
 
         # Update 0 -> 1.
         if get_format_version() == 0:
             mkdir(os.path.join(branch_dir, 'trash'))
             patch_dir = os.path.join(branch_dir, 'patches')
             mkdir(patch_dir)
-            refs_dir = os.path.join(self._basedir(), 'refs', 'patches', self.get_name())
-            mkdir(refs_dir)
+            refs_base = 'refs/patches/%s' % self.get_name()
             for patch in (file(os.path.join(branch_dir, 'unapplied')).readlines()
                           + file(os.path.join(branch_dir, 'applied')).readlines()):
                 patch = patch.strip()
                 os.rename(os.path.join(branch_dir, patch),
                           os.path.join(patch_dir, patch))
-                Patch(patch, patch_dir, refs_dir).update_top_ref()
+                Patch(patch, patch_dir, refs_base).update_top_ref()
             set_format_version(1)
 
         # Update 1 -> 2.
@@ -441,7 +444,7 @@ class Series(PatchSet):
                     config.set('branch.%s.description' % self.get_name(), desc)
                 rm(desc_file)
             rm(os.path.join(branch_dir, 'current'))
-            rm(os.path.join(self._basedir(), 'refs', 'bases', self.get_name()))
+            rm_ref('refs/bases/%s' % self.get_name())
             set_format_version(2)
 
         # Make sure we're at the latest version.
@@ -458,7 +461,7 @@ class Series(PatchSet):
     def get_patch(self, name):
         """Return a Patch object for the given name
         """
-        return Patch(name, self.__patch_dir, self.__refs_dir)
+        return Patch(name, self.__patch_dir, self.__refs_base)
 
     def get_current_patch(self):
         """Return a Patch object representing the topmost patch, or
@@ -514,7 +517,7 @@ class Series(PatchSet):
             out.note(('No parent remote declared for stack "%s",'
                       ' defaulting to "origin".' % self.get_name()),
                      ('Consider setting "branch.%s.remote" and'
-                      ' "branch.%s.merge" with "git repo-config".'
+                      ' "branch.%s.merge" with "git config".'
                       % (self.get_name(), self.get_name())))
             return 'origin'
         else:
@@ -531,7 +534,7 @@ class Series(PatchSet):
             out.note(('No parent branch declared for stack "%s",'
                       ' defaulting to "heads/origin".' % self.get_name()),
                      ('Consider setting "branch.%s.stgit.parentbranch"'
-                      ' with "git repo-config".' % self.get_name()))
+                      ' with "git config".' % self.get_name()))
             return 'heads/origin'
         else:
             raise StackException, 'Cannot find a parent branch for "%s"' % self.get_name()
@@ -545,7 +548,8 @@ class Series(PatchSet):
 
     def set_parent(self, remote, localbranch):
         if localbranch:
-            self.__set_parent_remote(remote)
+            if remote:
+                self.__set_parent_remote(remote)
             self.__set_parent_branch(localbranch)
         # We'll enforce this later
 #         else:
@@ -580,7 +584,7 @@ class Series(PatchSet):
         """
         if self.is_initialised():
             raise StackException, '%s already initialized' % self.get_name()
-        for d in [self._dir(), self.__refs_dir]:
+        for d in [self._dir()]:
             if os.path.exists(d):
                 raise StackException, '%s already exists' % d
 
@@ -593,7 +597,6 @@ class Series(PatchSet):
 
         self.create_empty_field('applied')
         self.create_empty_field('unapplied')
-        os.makedirs(self.__refs_dir)
         self._set_field('orig-base', git.get_head())
 
         config.set(self.format_version_key(), str(FORMAT_VERSION))
@@ -606,14 +609,18 @@ class Series(PatchSet):
         if to_stack.is_initialised():
             raise StackException, '"%s" already exists' % to_stack.get_name()
 
+        patches = self.get_applied() + self.get_unapplied()
+
         git.rename_branch(self.get_name(), to_name)
 
+        for patch in patches:
+            git.rename_ref('refs/patches/%s/%s' % (self.get_name(), patch),
+                           'refs/patches/%s/%s' % (to_name, patch))
+            git.rename_ref('refs/patches/%s/%s.log' % (self.get_name(), patch),
+                           'refs/patches/%s/%s.log' % (to_name, patch))
         if os.path.isdir(self._dir()):
             rename(os.path.join(self._basedir(), 'patches'),
                    self.get_name(), to_stack.get_name())
-        if os.path.exists(self.__refs_dir):
-            rename(os.path.join(self._basedir(), 'refs', 'patches'),
-                   self.get_name(), to_stack.get_name())
 
         # Rename the config section
         for k in ['branch.%s', 'branch.%s.stgit']:
@@ -715,9 +722,9 @@ class Series(PatchSet):
                                      % self._dir())
 
             try:
-                os.removedirs(self.__refs_dir)
-            except OSError:
-                out.warn('Refs directory %s is not empty' % self.__refs_dir)
+                git.delete_branch(self.get_name())
+            except GitException:
+                out.warn('Could not delete branch "%s"' % self.get_name())
 
         # Cleanup parent informations
         # FIXME: should one day make use of git-config --section-remove,
@@ -766,14 +773,7 @@ class Series(PatchSet):
         if not committer_email:
             committer_email = patch.get_commemail()
 
-        if sign_str:
-            descr = descr.rstrip()
-            if descr.find("\nSigned-off-by:") < 0 \
-               and descr.find("\nAcked-by:") < 0:
-                descr = descr + "\n"
-
-            descr = '%s\n%s: %s <%s>\n' % (descr, sign_str,
-                                           committer_name, committer_email)
+        descr = add_sign_line(descr, sign_str, committer_name, committer_email)
 
         bottom = patch.get_bottom()