"""Common utility functions
"""
-import errno, os, os.path, re, sys
+import errno, optparse, os, os.path, re, sys
+from stgit.exception import *
from stgit.config import config
+from stgit.out import *
__copyright__ = """
Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-class MessagePrinter(object):
- def __init__(self):
- class Output(object):
- def __init__(self, write, flush):
- self.write = write
- self.flush = flush
- self.at_start_of_line = True
- self.level = 0
- def new_line(self):
- """Ensure that we're at the beginning of a line."""
- if not self.at_start_of_line:
- self.write('\n')
- self.at_start_of_line = True
- def single_line(self, msg, print_newline = True,
- need_newline = True):
- """Write a single line. Newline before and after are
- separately configurable."""
- if need_newline:
- self.new_line()
- if self.at_start_of_line:
- self.write(' '*self.level)
- self.write(msg)
- if print_newline:
- self.write('\n')
- self.at_start_of_line = True
- else:
- self.flush()
- self.at_start_of_line = False
- def tagged_lines(self, tag, lines):
- tag += ': '
- for line in lines:
- self.single_line(tag + line)
- tag = ' '*len(tag)
- def write_line(self, line):
- """Write one line of text on a lines of its own, not
- indented."""
- self.new_line()
- self.write('%s\n' % line)
- self.at_start_of_line = True
- def write_raw(self, string):
- """Write an arbitrary string, possibly containing
- newlines."""
- self.new_line()
- self.write(string)
- self.at_start_of_line = string.endswith('\n')
- self.__stdout = Output(sys.stdout.write, sys.stdout.flush)
- if sys.stdout.isatty():
- self.__out = self.__stdout
- else:
- self.__out = Output(lambda msg: None, lambda: None)
- def stdout(self, line):
- """Write a line to stdout."""
- self.__stdout.write_line(line)
- def stdout_raw(self, string):
- """Write a string possibly containing newlines to stdout."""
- self.__stdout.write_raw(string)
- def info(self, *msgs):
- for msg in msgs:
- self.__out.single_line(msg)
- def note(self, *msgs):
- self.__out.tagged_lines('Notice', msgs)
- def warn(self, *msgs):
- self.__out.tagged_lines('Warning', msgs)
- def error(self, *msgs):
- self.__out.tagged_lines('Error', msgs)
- def start(self, msg):
- """Start a long-running operation."""
- self.__out.single_line('%s ... ' % msg, print_newline = False)
- self.__out.level += 1
- def done(self, extramsg = None):
- """Finish long-running operation."""
- self.__out.level -= 1
- if extramsg:
- msg = 'done (%s)' % extramsg
- else:
- msg = 'done'
- self.__out.single_line(msg, need_newline = False)
-
-out = MessagePrinter()
-
def mkdir_file(filename, mode):
"""Opens filename with the given mode, creating the directory it's
in if it doesn't already exist."""
# file1's parent dir may not be empty after move
pass
-class EditorException(Exception):
+class EditorException(StgException):
pass
def call_editor(filename):
def patch_name_from_msg(msg):
"""Return a string to be used as a patch name. This is generated
- from the top line of the string passed as argument, and is at most
- 30 characters long."""
+ from the top line of the string passed as argument."""
if not msg:
return None
+ name_len = config.get('stgit.namelength')
+ if not name_len:
+ name_len = 30
+
subject_line = msg.split('\n', 1)[0].lstrip().lower()
- return re.sub('[\W]+', '-', subject_line).strip('-')[:30]
+ return re.sub('[\W]+', '-', subject_line).strip('-')[:name_len]
def make_patch_name(msg, unacceptable, default_name = 'patch'):
"""Return a patch name generated from the given commit message,
suffix += 1
patchname = '%s-%d' % (patchname, suffix)
return patchname
+
+# any and all functions are builtin in Python 2.5 and higher, but not
+# in 2.4.
+if not 'any' in dir(__builtins__):
+ def any(bools):
+ for b in bools:
+ if b:
+ return True
+ return False
+if not 'all' in dir(__builtins__):
+ def all(bools):
+ for b in bools:
+ if not b:
+ return False
+ return True
+
+def make_sign_options():
+ def callback(option, opt_str, value, parser, sign_str):
+ if parser.values.sign_str not in [None, sign_str]:
+ raise optparse.OptionValueError(
+ '--ack and --sign were both specified')
+ parser.values.sign_str = sign_str
+ return [optparse.make_option('--sign', action = 'callback',
+ callback = callback, dest = 'sign_str',
+ callback_args = ('Signed-off-by',),
+ help = 'add Signed-off-by line'),
+ optparse.make_option('--ack', action = 'callback',
+ callback = callback, dest = 'sign_str',
+ callback_args = ('Acked-by',),
+ help = 'add Acked-by line')]
+
+def add_sign_line(desc, sign_str, name, email):
+ if not sign_str:
+ return desc
+ sign_str = '%s: %s <%s>' % (sign_str, name, email)
+ if sign_str in desc:
+ return desc
+ desc = desc.rstrip()
+ if not any(s in desc for s in ['\nSigned-off-by:', '\nAcked-by:']):
+ desc = desc + '\n'
+ return '%s\n%s\n' % (desc, sign_str)