summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/patman/gitutil.py65
-rwxr-xr-xtools/patman/patman.py10
-rw-r--r--tools/patman/series.py10
3 files changed, 61 insertions, 24 deletions
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index 4e21d4c..f485750 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -273,7 +273,7 @@ def ApplyPatches(verbose, args, start_point):
print stdout, stderr
return error_count == 0
-def BuildEmailList(in_list, tag=None, alias=None):
+def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
"""Build a list of email addresses based on an input list.
Takes a list of email addresses and aliases, and turns this into a list
@@ -286,6 +286,9 @@ def BuildEmailList(in_list, tag=None, alias=None):
Args:
in_list: List of aliases/email addresses
tag: Text to put before each address
+ alias: Alias dictionary
+ raise_on_error: True to raise an error when an alias fails to match,
+ False to just print a message.
Returns:
List of email addresses
@@ -307,7 +310,7 @@ def BuildEmailList(in_list, tag=None, alias=None):
quote = '"' if tag and tag[0] == '-' else ''
raw = []
for item in in_list:
- raw += LookupEmail(item, alias)
+ raw += LookupEmail(item, alias, raise_on_error=raise_on_error)
result = []
for item in raw:
if not item in result:
@@ -316,7 +319,7 @@ def BuildEmailList(in_list, tag=None, alias=None):
return ['%s %s%s%s' % (tag, quote, email, quote) for email in result]
return result
-def EmailPatches(series, cover_fname, args, dry_run, cc_fname,
+def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
self_only=False, alias=None, in_reply_to=None):
"""Email a patch series.
@@ -325,6 +328,8 @@ def EmailPatches(series, cover_fname, args, dry_run, cc_fname,
cover_fname: filename of cover letter
args: list of filenames of patch files
dry_run: Just return the command that would be run
+ raise_on_error: True to raise an error when an alias fails to match,
+ False to just print a message.
cc_fname: Filename of Cc file for per-commit Cc
self_only: True to just email to yourself as a test
in_reply_to: If set we'll pass this to git as --in-reply-to.
@@ -347,20 +352,21 @@ def EmailPatches(series, cover_fname, args, dry_run, cc_fname,
>>> series = series.Series()
>>> series.to = ['fred']
>>> series.cc = ['mary']
- >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \
- alias)
+ >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
+ False, alias)
'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
- >>> EmailPatches(series, None, ['p1'], True, 'cc-fname', False, alias)
+ >>> EmailPatches(series, None, ['p1'], True, True, 'cc-fname', False, \
+ alias)
'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1'
>>> series.cc = ['all']
- >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', True, \
- alias)
+ >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
+ True, alias)
'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \
--cc-cmd cc-fname" cover p1 p2'
- >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \
- alias)
+ >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
+ False, alias)
'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
"f.bloggs@napier.co.nz" --cc "j.bloggs@napier.co.nz" --cc \
"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
@@ -368,14 +374,14 @@ def EmailPatches(series, cover_fname, args, dry_run, cc_fname,
# Restore argv[0] since we clobbered it.
>>> sys.argv[0] = _old_argv0
"""
- to = BuildEmailList(series.get('to'), '--to', alias)
+ to = BuildEmailList(series.get('to'), '--to', alias, raise_on_error)
if not to:
print ("No recipient, please add something like this to a commit\n"
"Series-to: Fred Bloggs <f.blogs@napier.co.nz>")
return
- cc = BuildEmailList(series.get('cc'), '--cc', alias)
+ cc = BuildEmailList(series.get('cc'), '--cc', alias, raise_on_error)
if self_only:
- to = BuildEmailList([os.getenv('USER')], '--to', alias)
+ to = BuildEmailList([os.getenv('USER')], '--to', alias, raise_on_error)
cc = []
cmd = ['git', 'send-email', '--annotate']
if in_reply_to:
@@ -393,13 +399,16 @@ def EmailPatches(series, cover_fname, args, dry_run, cc_fname,
return str
-def LookupEmail(lookup_name, alias=None, level=0):
+def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
"""If an email address is an alias, look it up and return the full name
TODO: Why not just use git's own alias feature?
Args:
lookup_name: Alias or email address to look up
+ alias: Dictionary containing aliases (None to use settings default)
+ raise_on_error: True to raise an error when an alias fails to match,
+ False to just print a message.
Returns:
tuple:
@@ -433,6 +442,15 @@ def LookupEmail(lookup_name, alias=None, level=0):
Traceback (most recent call last):
...
OSError: Recursive email alias at 'other'
+ >>> LookupEmail('odd', alias, raise_on_error=False)
+ \033[1;31mAlias 'odd' not found\033[0m
+ []
+ >>> # In this case the loop part will effectively be ignored.
+ >>> LookupEmail('loop', alias, raise_on_error=False)
+ \033[1;31mRecursive email alias at 'other'\033[0m
+ \033[1;31mRecursive email alias at 'john'\033[0m
+ \033[1;31mRecursive email alias at 'mary'\033[0m
+ ['j.bloggs@napier.co.nz', 'm.poppins@cloud.net']
"""
if not alias:
alias = settings.alias
@@ -441,16 +459,27 @@ def LookupEmail(lookup_name, alias=None, level=0):
return [lookup_name]
lookup_name = lookup_name.lower()
+ col = terminal.Color()
+ out_list = []
if level > 10:
- raise OSError, "Recursive email alias at '%s'" % lookup_name
+ msg = "Recursive email alias at '%s'" % lookup_name
+ if raise_on_error:
+ raise OSError, msg
+ else:
+ print col.Color(col.RED, msg)
+ return out_list
- out_list = []
if lookup_name:
if not lookup_name in alias:
- raise ValueError, "Alias '%s' not found" % lookup_name
+ msg = "Alias '%s' not found" % lookup_name
+ if raise_on_error:
+ raise ValueError, msg
+ else:
+ print col.Color(col.RED, msg)
+ return out_list
for item in alias[lookup_name]:
- todo = LookupEmail(item, alias, level + 1)
+ todo = LookupEmail(item, alias, raise_on_error, level + 1)
for new_item in todo:
if not new_item in out_list:
out_list.append(new_item)
diff --git a/tools/patman/patman.py b/tools/patman/patman.py
index 5000b7d..23026be 100755
--- a/tools/patman/patman.py
+++ b/tools/patman/patman.py
@@ -57,7 +57,9 @@ parser.add_option('-r', '--in-reply-to', type='string', action='store',
help="Message ID that this series is in reply to")
parser.add_option('-s', '--start', dest='start', type='int',
default=0, help='Commit to start creating patches from (0 = HEAD)')
-parser.add_option('-t', '--test', action='store_true', dest='test',
+parser.add_option('-t', '--ignore-bad-tags', action='store_true',
+ default=False, help='Ignore bad tags / aliases')
+parser.add_option('--test', action='store_true', dest='test',
default=False, help='run tests')
parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
default=False, help='Verbose output of errors and warnings')
@@ -159,13 +161,15 @@ else:
options.count + options.start):
ok = False
- cc_file = series.MakeCcFile(options.process_tags, cover_fname)
+ cc_file = series.MakeCcFile(options.process_tags, cover_fname,
+ not options.ignore_bad_tags)
# Email the patches out (giving the user time to check / cancel)
cmd = ''
if ok or options.ignore_errors:
cmd = gitutil.EmailPatches(series, cover_fname, args,
- options.dry_run, cc_file, in_reply_to=options.in_reply_to)
+ options.dry_run, not options.ignore_bad_tags, cc_file,
+ in_reply_to=options.in_reply_to)
# For a dry run, just show our actions as a sanity check
if options.dry_run:
diff --git a/tools/patman/series.py b/tools/patman/series.py
index 44ad931..eb5a00c 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -210,7 +210,7 @@ class Series(dict):
str = 'Change log exists, but no version is set'
print col.Color(col.RED, str)
- def MakeCcFile(self, process_tags, cover_fname):
+ def MakeCcFile(self, process_tags, cover_fname, raise_on_error):
"""Make a cc file for us to use for per-commit Cc automation
Also stores in self._generated_cc to make ShowActions() faster.
@@ -218,6 +218,8 @@ class Series(dict):
Args:
process_tags: Process tags as if they were aliases
cover_fname: If non-None the name of the cover letter.
+ raise_on_error: True to raise an error when an alias fails to match,
+ False to just print a message.
Return:
Filename of temp file created
"""
@@ -228,8 +230,10 @@ class Series(dict):
for commit in self.commits:
list = []
if process_tags:
- list += gitutil.BuildEmailList(commit.tags)
- list += gitutil.BuildEmailList(commit.cc_list)
+ list += gitutil.BuildEmailList(commit.tags,
+ raise_on_error=raise_on_error)
+ list += gitutil.BuildEmailList(commit.cc_list,
+ raise_on_error=raise_on_error)
list += get_maintainer.GetMaintainer(commit.patch)
all_ccs += list
print >>fd, commit.patch, ', '.join(list)