"""Common utility functions
"""
-import errno, os, os.path, re, sys
+import errno, optparse, os, os.path, re, sys
from stgit.config import config
+from stgit.out import *
__copyright__ = """
Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
create_dirs(os.path.dirname(filename))
return file(filename, mode)
+def read_strings(filename):
+ """Reads the lines from a file
+ """
+ f = file(filename, 'r')
+ lines = [line.strip() for line in f.readlines()]
+ f.close()
+ return lines
+
def read_string(filename, multiline = False):
"""Reads the first line from a file
"""
f.close()
return result
+def write_strings(filename, lines):
+ """Write 'lines' sequence to file
+ """
+ f = file(filename, 'w+')
+ f.writelines([line + '\n' for line in lines])
+ f.close()
+
def write_string(filename, line, multiline = False):
"""Writes 'line' to file and truncates it
"""
editor = 'vi'
editor += ' %s' % filename
- print 'Invoking the editor: "%s"...' % editor,
- sys.stdout.flush()
+ out.start('Invoking the editor: "%s"' % editor)
err = os.system(editor)
if err:
raise EditorException, 'editor failed, exit code: %d' % err
- print 'done'
+ out.done()
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',
- alternative = True):
+def make_patch_name(msg, unacceptable, default_name = 'patch'):
"""Return a patch name generated from the given commit message,
guaranteed to make unacceptable(name) be false. If the commit
message is empty, base the name on default_name instead."""
patchname = patch_name_from_msg(msg)
if not patchname:
patchname = default_name
- if alternative and unacceptable(patchname):
+ if unacceptable(patchname):
suffix = 0
while unacceptable('%s-%d' % (patchname, suffix)):
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)