chiark / gitweb /
Add a "--clone" option to "stg branch"
authorChuck Lever <cel@netapp.com>
Sun, 4 Dec 2005 03:50:19 +0000 (22:50 -0500)
committerCatalin Marinas <catalin.marinas@gmail.com>
Wed, 7 Dec 2005 22:13:31 +0000 (22:13 +0000)
Cloning a branch means creating a new branch and copying all of the
original branch's patches and its base to it.  Like creating a tag,
but this also preserves all the StGIT patches as well.

Signed-off-by: Chuck Lever <cel@netapp.com>
stgit/commands/branch.py
stgit/stack.py

index ccf1f6baefafb0585a0ebfe0f1f8822b249f0dd6..860d7d5af2d89d1949642972c294e3594751b494 100644 (file)
@@ -18,7 +18,7 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
-import sys, os
+import sys, os, time
 from optparse import OptionParser, make_option
 
 from stgit.commands.common import *
 from optparse import OptionParser, make_option
 
 from stgit.commands.common import *
@@ -29,10 +29,10 @@ from stgit import stack, git
 help = 'manage development branches'
 usage = """%prog [options] branch-name [commit-id]
 
 help = 'manage development branches'
 usage = """%prog [options] branch-name [commit-id]
 
-Create, list, switch between, rename, or delete development branches
+Create, clone, switch between, rename, or delete development branches
 within a git repository.  By default, a single branch called 'master'
 is always created in a new repository.  This subcommand allows you to
 within a git repository.  By default, a single branch called 'master'
 is always created in a new repository.  This subcommand allows you to
-manage several patch series in the same repository.
+manage several patch series in the same repository via GIT branches.
 
 When displaying the branches, the names can be prefixed with
 's' (StGIT managed) or 'p' (protected)."""
 
 When displaying the branches, the names can be prefixed with
 's' (StGIT managed) or 'p' (protected)."""
@@ -40,6 +40,9 @@ When displaying the branches, the names can be prefixed with
 options = [make_option('-c', '--create',
                        help = 'create a new development branch',
                        action = 'store_true'),
 options = [make_option('-c', '--create',
                        help = 'create a new development branch',
                        action = 'store_true'),
+           make_option('--clone',
+                       help = 'clone the contents of the current branch',
+                       action = 'store_true'),
            make_option('--delete',
                        help = 'delete an existing development branch',
                        action = 'store_true'),
            make_option('--delete',
                        help = 'delete an existing development branch',
                        action = 'store_true'),
@@ -124,6 +127,27 @@ def func(parser, options, args):
         print 'Branch "%s" created.' % args[0]
         return
 
         print 'Branch "%s" created.' % args[0]
         return
 
+    elif options.clone:
+
+        if len(args) == 0:
+            clone = crt_series.get_branch() + \
+                    time.strftime('-%C%y%m%d-%H%M%S')
+        elif len(args) == 1:
+            clone = args[0]
+        else:
+            parser.error('incorrect number of arguments')
+
+        check_local_changes()
+        check_conflicts()
+        check_head_top_equal()
+
+        print 'Cloning current branch to "%s"...' % clone,
+        sys.stdout.flush()
+        crt_series.clone(clone)
+        print 'done'
+
+        return
+
     elif options.delete:
 
         if len(args) != 1:
     elif options.delete:
 
         if len(args) != 1:
index bc5915e727754bf26d61fc78e5a543885d0b9100..8b7c29620d6479299f065fd6237be6e754dafcd0 100644 (file)
@@ -420,6 +420,33 @@ class Series:
 
         self.__init__(to_name)
 
 
         self.__init__(to_name)
 
+    def clone(self, target_series):
+        """Clones a series
+        """
+        base = read_string(self.get_base_file())
+        git.create_branch(target_series, tree_id = base)
+        Series(target_series).init()
+        new_series = Series(target_series)
+
+        # generate an artificial description file
+        write_string(new_series.__descr_file, 'clone of "%s"' % self.__name)
+
+        # clone self's entire series as unapplied patches
+        patches = self.get_applied() + self.get_unapplied()
+        patches.reverse()
+        for p in patches:
+            patch = self.get_patch(p)
+            new_series.new_patch(p, message = patch.get_description(),
+                                 can_edit = False, unapplied = True,
+                                 bottom = patch.get_bottom(),
+                                 top = patch.get_top(),
+                                 author_name = patch.get_authname(),
+                                 author_email = patch.get_authemail(),
+                                 author_date = patch.get_authdate())
+
+        # fast forward the cloned series to self's top
+        new_series.forward_patches(self.get_applied())
+
     def delete(self, force = False):
         """Deletes an stgit series
         """
     def delete(self, force = False):
         """Deletes an stgit series
         """