Add support to hide and unhide patches
authorCatalin Marinas <catalin.marinas@gmail.com>
Fri, 26 Jan 2007 22:29:10 +0000 (22:29 +0000)
committerCatalin Marinas <catalin.marinas@gmail.com>
Fri, 26 Jan 2007 22:29:10 +0000 (22:29 +0000)
Hidden patches are only listed with 'series' -a or -i options.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
contrib/stgit-completion.bash
stgit/commands/hide.py [new file with mode: 0644]
stgit/commands/series.py
stgit/commands/unhide.py [new file with mode: 0644]
stgit/main.py
stgit/stack.py

index 6454ab1..8a027bf 100644 (file)
@@ -25,6 +25,7 @@ _stg_commands="
     float
     fold
     goto
     float
     fold
     goto
+    hide
     id
     import
     init
     id
     import
     init
@@ -48,6 +49,7 @@ _stg_commands="
     top
     unapplied
     uncommit
     top
     unapplied
     uncommit
+    unhide
 "
 
 # The path to .git, or empty if we're not in a repository.
 "
 
 # The path to .git, or empty if we're not in a repository.
@@ -188,9 +190,11 @@ _stg ()
         # stack commands
         float)  _stg_patches $command _all_patches ;;
         goto)   _stg_patches $command _all_other_patches ;;
         # stack commands
         float)  _stg_patches $command _all_patches ;;
         goto)   _stg_patches $command _all_other_patches ;;
+        hide)   _stg_patches $command _all_patches ;;
         pop)    _stg_patches $command _applied_patches ;;
         push)   _stg_patches $command _unapplied_patches ;;
         series) _stg_patches $command _all_patches ;;
         pop)    _stg_patches $command _applied_patches ;;
         push)   _stg_patches $command _unapplied_patches ;;
         series) _stg_patches $command _all_patches ;;
+        unhide) _stg_patches $command _all_patches ;;
         # patch commands
         delete) _stg_patches $command _all_patches ;;
         export) _stg_patches $command _applied_patches ;;
         # patch commands
         delete) _stg_patches $command _all_patches ;;
         export) _stg_patches $command _applied_patches ;;
diff --git a/stgit/commands/hide.py b/stgit/commands/hide.py
new file mode 100644 (file)
index 0000000..9ef948d
--- /dev/null
@@ -0,0 +1,49 @@
+__copyright__ = """
+Copyright (C) 2007, Catalin Marinas <catalin.marinas@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+import sys, os
+from optparse import OptionParser, make_option
+
+from stgit.commands.common import *
+from stgit.utils import *
+from stgit import stack, git
+
+
+help = 'hide a patch in the series'
+usage = """%prog [options] [<patch-range>]
+
+Hide a range of patches or the current one so that they are no longer
+shown in the plain 'series' command output."""
+
+options = [make_option('-b', '--branch',
+                       help = 'use BRANCH instead of the default one')]
+
+def func(parser, options, args):
+    """Hide a range of patch in the series
+    """
+    if not args:
+        patches = [crt_series.get_current()]
+    else:
+        applied = crt_series.get_applied()
+        unapplied = crt_series.get_unapplied()
+        patches = parse_patches(args, applied + unapplied, len(applied))
+
+    patches = [p for p in patches if p not in crt_series.get_hidden()]
+
+    for patch in patches:
+        crt_series.hide_patch(patch)
+        print 'Patch "%s" hidden' % patch
index 788e57b..4f372ff 100644 (file)
@@ -31,10 +31,17 @@ usage = """%prog [options] [<patch-range>]
 Show all the patches in the series or just those in the given
 range. The applied patches are prefixed with a '+' and the unapplied
 ones with a '-'. The current patch is prefixed with a '>'. Empty
 Show all the patches in the series or just those in the given
 range. The applied patches are prefixed with a '+' and the unapplied
 ones with a '-'. The current patch is prefixed with a '>'. Empty
-patches are prefixed with a '0'."""
+patches are prefixed with a '0'. The '*' postfix is appended to hidden
+patches."""
 
 options = [make_option('-b', '--branch',
                        help = 'use BRANCH instead of the default one'),
 
 options = [make_option('-b', '--branch',
                        help = 'use BRANCH instead of the default one'),
+           make_option('-a', '--all',
+                       help = 'show all patches, including the hidden ones',
+                       action = 'store_true'),
+           make_option('-i', '--invisible',
+                       help = 'show the hidden patches only',
+                       action = 'store_true'),
            make_option('-m', '--missing', metavar = 'BRANCH',
                        help = 'show patches in BRANCH missing in current'),
            make_option('-c', '--count',
            make_option('-m', '--missing', metavar = 'BRANCH',
                        help = 'show patches in BRANCH missing in current'),
            make_option('-c', '--count',
@@ -69,16 +76,21 @@ def __get_description(patch):
     descr_lines = descr.split('\n')
     return descr_lines[0].rstrip()
 
     descr_lines = descr.split('\n')
     return descr_lines[0].rstrip()
 
-def __print_patch(patch, branch_str, prefix, empty_prefix, length, options):
+def __print_patch(patch, hidden, branch_str, prefix, empty_prefix, length,
+                  options):
+    """Print a patch name, description and various markers.
+    """
     if options.noprefix:
         prefix = ''
     elif options.empty and crt_series.empty_patch(patch):
         prefix = empty_prefix
 
     patch_str = patch + branch_str
     if options.noprefix:
         prefix = ''
     elif options.empty and crt_series.empty_patch(patch):
         prefix = empty_prefix
 
     patch_str = patch + branch_str
+    if not options.noprefix and patch in hidden:
+        patch_str += '*'
 
     if options.description:
 
     if options.description:
-        print prefix + patch_str.ljust(length) + '  | ' \
+        print prefix + patch_str.ljust(length) + ' | ' \
               + __get_description(patch)
     else:
         print prefix + patch_str
               + __get_description(patch)
     else:
         print prefix + patch_str
@@ -108,11 +120,19 @@ def func(parser, options, args):
     else:
         show_patches = applied + unapplied
 
     else:
         show_patches = applied + unapplied
 
+    # missing filtering
+    show_patches = [p for p in show_patches if p not in cmp_patches]
+
+    # hidden patches filtering
+    hidden = crt_series.get_hidden()
+    if options.invisible:
+        show_patches = [p for p in show_patches if p in hidden]
+    elif not options.all:
+        show_patches = [p for p in show_patches if p not in hidden]
+
     # filter the patches
     # filter the patches
-    applied = [p for p in applied
-               if p in show_patches and p not in cmp_patches]
-    unapplied = [p for p in unapplied
-                 if p in show_patches and p not in cmp_patches]
+    applied = [p for p in applied if p in show_patches]
+    unapplied = [p for p in unapplied if p in show_patches]
 
     if options.short:
         if len(applied) > 5:
 
     if options.short:
         if len(applied) > 5:
@@ -153,13 +173,22 @@ def func(parser, options, args):
         max_len = 0
         if len(patches) > 0:
             max_len = max([len(i + branch_str) for i in patches])
         max_len = 0
         if len(patches) > 0:
             max_len = max([len(i + branch_str) for i in patches])
+            max_len += 1
 
         if len(applied) > 0:
 
         if len(applied) > 0:
-            for p in applied [0:-1]:
-                __print_patch(p, branch_str, '+ ', '0 ', max_len, options)
+            current = crt_series.get_current()
+            if applied[-1] == current:
+                del applied[-1]
+            else:
+                current = None
+
+            for p in applied:
+                __print_patch(p, hidden, branch_str, '+ ', '0 ', max_len,
+                              options)
 
 
-            __print_patch(applied[-1], branch_str, '> ', '0>', max_len,
-                          options)
+            if current:
+                __print_patch(current, hidden, branch_str, '> ', '0>', max_len,
+                              options)
 
         for p in unapplied:
 
         for p in unapplied:
-            __print_patch(p, branch_str, '- ', '0 ', max_len, options)
+            __print_patch(p, hidden, branch_str, '- ', '0 ', max_len, options)
diff --git a/stgit/commands/unhide.py b/stgit/commands/unhide.py
new file mode 100644 (file)
index 0000000..f2db05f
--- /dev/null
@@ -0,0 +1,49 @@
+__copyright__ = """
+Copyright (C) 2007, Catalin Marinas <catalin.marinas@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+import sys, os
+from optparse import OptionParser, make_option
+
+from stgit.commands.common import *
+from stgit.utils import *
+from stgit import stack, git
+
+
+help = 'unhide a hidden patch in the series'
+usage = """%prog [options] [<patch-range>]
+
+Unhide a hidden range of patches or the current one if hidden so that
+they are shown in the plain 'series' command output."""
+
+options = [make_option('-b', '--branch',
+                       help = 'use BRANCH instead of the default one')]
+
+def func(parser, options, args):
+    """Unhide a range of patches in the series
+    """
+    if not args:
+        patches = [crt_series.get_current()]
+    else:
+        applied = crt_series.get_applied()
+        unapplied = crt_series.get_unapplied()
+        patches = parse_patches(args, applied + unapplied, len(applied))
+
+    patches = [p for p in patches if p in crt_series.get_hidden()]
+
+    for patch in patches:
+        crt_series.unhide_patch(patch)
+        print 'Patch "%s" unhidden' % patch
index f9b07d7..8694acd 100644 (file)
@@ -69,6 +69,7 @@ commands = Commands({
     'float':            'float',
     'fold':             'fold',
     'goto':             'goto',
     'float':            'float',
     'fold':             'fold',
     'goto':             'goto',
+    'hide':             'hide',
     'id':               'id',
     'import':           'imprt',
     'init':             'init',
     'id':               'id',
     'import':           'imprt',
     'init':             'init',
@@ -91,7 +92,8 @@ commands = Commands({
     'sync':             'sync',
     'top':              'top',
     'unapplied':        'unapplied',
     'sync':             'sync',
     'top':              'top',
     'unapplied':        'unapplied',
-    'uncommit':         'uncommit'
+    'uncommit':         'uncommit',
+    'unhide':           'unhide'
     })
 
 # classification: repository, stack, patch, working copy
     })
 
 # classification: repository, stack, patch, working copy
@@ -108,6 +110,7 @@ stackcommands = (
     'commit',
     'float',
     'goto',
     'commit',
     'float',
     'goto',
+    'hide',
     'init',
     'pop',
     'push',
     'init',
     'pop',
     'push',
@@ -115,7 +118,8 @@ stackcommands = (
     'series',
     'top',
     'unapplied',
     'series',
     'top',
     'unapplied',
-    'uncommit'
+    'uncommit',
+    'unhide'
     )
 patchcommands = (
     'delete',
     )
 patchcommands = (
     'delete',
index 2ae4dd5..5237084 100644 (file)
@@ -307,6 +307,7 @@ class Series(StgitObject):
 
         self.__applied_file = os.path.join(self._dir(), 'applied')
         self.__unapplied_file = os.path.join(self._dir(), 'unapplied')
 
         self.__applied_file = os.path.join(self._dir(), 'applied')
         self.__unapplied_file = os.path.join(self._dir(), 'unapplied')
+        self.__hidden_file = os.path.join(self._dir(), 'hidden')
         self.__current_file = os.path.join(self._dir(), 'current')
         self.__descr_file = os.path.join(self._dir(), 'description')
 
         self.__current_file = os.path.join(self._dir(), 'current')
         self.__descr_file = os.path.join(self._dir(), 'description')
 
@@ -374,6 +375,14 @@ class Series(StgitObject):
         f.close()
         return names
 
         f.close()
         return names
 
+    def get_hidden(self):
+        if not os.path.isfile(self.__hidden_file):
+            return []
+        f = file(self.__hidden_file)
+        names = [line.strip() for line in f.readlines()]
+        f.close()
+        return names
+
     def get_base_file(self):
         self.__begin_stack_check()
         return self.__base_file
     def get_base_file(self):
         self.__begin_stack_check()
         return self.__base_file
@@ -410,6 +419,11 @@ class Series(StgitObject):
         """
         return name in self.get_unapplied()
 
         """
         return name in self.get_unapplied()
 
+    def patch_hidden(self, name):
+        """Return true if the patch is hidden.
+        """
+        return name in self.get_hidden()
+
     def patch_exists(self, name):
         """Return true if there is a patch with the given name, false
         otherwise."""
     def patch_exists(self, name):
         """Return true if there is a patch with the given name, false
         otherwise."""
@@ -589,6 +603,8 @@ class Series(StgitObject):
                 os.remove(self.__applied_file)
             if os.path.exists(self.__unapplied_file):
                 os.remove(self.__unapplied_file)
                 os.remove(self.__applied_file)
             if os.path.exists(self.__unapplied_file):
                 os.remove(self.__unapplied_file)
+            if os.path.exists(self.__hidden_file):
+                os.remove(self.__hidden_file)
             if os.path.exists(self.__current_file):
                 os.remove(self.__current_file)
             if os.path.exists(self.__descr_file):
             if os.path.exists(self.__current_file):
                 os.remove(self.__current_file)
             if os.path.exists(self.__descr_file):
@@ -784,6 +800,10 @@ class Series(StgitObject):
         f = file(self.__unapplied_file, 'w+')
         f.writelines([line + '\n' for line in unapplied])
         f.close()
         f = file(self.__unapplied_file, 'w+')
         f.writelines([line + '\n' for line in unapplied])
         f.close()
+
+        if self.patch_hidden(name):
+            self.unhide_patch(name)
+
         self.__begin_stack_check()
 
     def forward_patches(self, names):
         self.__begin_stack_check()
 
     def forward_patches(self, names):
@@ -1057,6 +1077,10 @@ class Series(StgitObject):
         if newname in applied or newname in unapplied:
             raise StackException, 'Patch "%s" already exists' % newname
 
         if newname in applied or newname in unapplied:
             raise StackException, 'Patch "%s" already exists' % newname
 
+        if self.patch_hidden(oldname):
+            self.unhide_patch(oldname)
+            self.hide_patch(newname)
+
         if oldname in unapplied:
             Patch(oldname, self.__patch_dir, self.__refs_dir).rename(newname)
             unapplied[unapplied.index(oldname)] = newname
         if oldname in unapplied:
             Patch(oldname, self.__patch_dir, self.__refs_dir).rename(newname)
             unapplied[unapplied.index(oldname)] = newname
@@ -1093,3 +1117,28 @@ class Series(StgitObject):
                          cache_update = False, tree_id = top.get_tree(),
                          allowempty = True)
         patch.set_log(log)
                          cache_update = False, tree_id = top.get_tree(),
                          allowempty = True)
         patch.set_log(log)
+
+    def hide_patch(self, name):
+        """Add the patch to the hidden list.
+        """
+        if not self.patch_exists(name):
+            raise StackException, 'Unknown patch "%s"' % name
+        elif self.patch_hidden(name):
+            raise StackException, 'Patch "%s" already hidden' % name
+
+        append_string(self.__hidden_file, name)
+
+    def unhide_patch(self, name):
+        """Add the patch to the hidden list.
+        """
+        if not self.patch_exists(name):
+            raise StackException, 'Unknown patch "%s"' % name
+        hidden = self.get_hidden()
+        if not name in hidden:
+            raise StackException, 'Patch "%s" not hidden' % name
+
+        hidden.remove(name)
+
+        f = file(self.__hidden_file, 'w+')
+        f.writelines([line + '\n' for line in hidden])
+        f.close()