diff options
-rw-r--r-- | b4/__init__.py | 20 | ||||
-rw-r--r-- | b4/command.py | 2 | ||||
-rw-r--r-- | b4/mbox.py | 12 | ||||
-rw-r--r-- | b4/pr.py | 8 | ||||
-rw-r--r-- | b4/ty.py | 137 |
5 files changed, 120 insertions, 59 deletions
diff --git a/b4/__init__.py b/b4/__init__.py index 54cc42b..a49f439 100644 --- a/b4/__init__.py +++ b/b4/__init__.py @@ -93,6 +93,12 @@ DEFAULT_CONFIG = { 'attestation-checkmarks': 'fancy', # How long to keep things in cache before expiring (minutes)? 'cache-expire': '10', + # Used when creating summaries for b4 ty + 'thanks-commit-url-mask': None, + # See thanks-pr-template.example + 'thanks-pr-template': None, + # See thanks-am-template.example + 'thanks-am-template': None, # If this is not set, we'll use what we find in # git-config for gpg.program, and if that's not set, # we'll use "gpg" and hope for the better @@ -1673,3 +1679,17 @@ def format_addrs(pairs): # Remove any quoted-printable header junk from the name addrs.add(email.utils.formataddr((LoreMessage.clean_header(pair[0]), LoreMessage.clean_header(pair[1])))) return ', '.join(addrs) + + +def make_quote(body, maxlines=5): + quotelines = list() + qcount = 0 + for line in body.split('\n'): + # Quote the first paragraph only and then [snip] if we quoted more than maxlines + if qcount > maxlines and (not len(line.strip()) or line.strip().find('---') == 0): + quotelines.append('> ') + quotelines.append('> [...]') + break + quotelines.append('> %s' % line.strip('\r\n')) + qcount += 1 + return '\n'.join(quotelines) diff --git a/b4/command.py b/b4/command.py index d1b43e8..6d5e054 100644 --- a/b4/command.py +++ b/b4/command.py @@ -153,7 +153,7 @@ def cmd(): sp_ty.add_argument('-a', '--auto', action='store_true', default=False, help='Use the Auto-Thankanator to figure out what got applied/merged') sp_ty.add_argument('-b', '--branch', default=None, - help='The branch to check against, instead of current (use with -a)') + help='The branch to check against, instead of current') sp_ty.add_argument('--since', default='1.week', help='The --since option to use when auto-matching patches (default=1.week)') sp_ty.set_defaults(func=cmd_ty) @@ -169,16 +169,6 @@ def thanks_record_am(lser): allto = email.utils.getaddresses([str(x) for x in lmsg.msg.get_all('to', [])]) allcc = email.utils.getaddresses([str(x) for x in lmsg.msg.get_all('cc', [])]) - quotelines = list() - qcount = 0 - for line in lmsg.body.split('\n'): - # Quote the first paragraph only and then [snip] if we quoted more than 5 lines - if qcount > 5 and (not len(line.strip()) or line.strip().find('---') == 0): - quotelines.append('> ') - quotelines.append('> [...]') - break - quotelines.append('> %s' % line.strip('\r\n')) - qcount += 1 out = { 'msgid': lmsg.msgid, @@ -189,7 +179,7 @@ def thanks_record_am(lser): 'cc': b4.format_addrs(allcc), 'references': b4.LoreMessage.clean_header(lmsg.msg['References']), 'sentdate': b4.LoreMessage.clean_header(lmsg.msg['Date']), - 'quote': '\n'.join(quotelines), + 'quote': b4.make_quote(lmsg.body, maxlines=5), 'patches': patches, } fullpath = os.path.join(datadir, filename) @@ -206,12 +206,6 @@ def thanks_record_pr(lmsg): return allto = utils.getaddresses([str(x) for x in lmsg.msg.get_all('to', [])]) allcc = utils.getaddresses([str(x) for x in lmsg.msg.get_all('cc', [])]) - quotelines = list() - for line in lmsg.body.split('\n'): - if line.find('---') == 0: - break - quotelines.append('> %s' % line.strip('\r\n')) - out = { 'msgid': lmsg.msgid, 'subject': lmsg.full_subject, @@ -223,7 +217,7 @@ def thanks_record_pr(lmsg): 'remote': lmsg.pr_repo, 'ref': lmsg.pr_ref, 'sentdate': b4.LoreMessage.clean_header(lmsg.msg['Date']), - 'quote': '\n'.join(quotelines), + 'quote': b4.make_quote(lmsg.body, maxlines=6) } fullpath = os.path.join(datadir, filename) with open(fullpath, 'w', encoding='utf-8') as fh: @@ -25,6 +25,8 @@ ${quote} Merged, thanks! +${summary} + Best regards, -- ${myname} <${myemail}> @@ -36,6 +38,8 @@ ${quote} Applied, thanks! +${summary} + Best regards, -- ${myname} <${myemail}> @@ -148,7 +152,7 @@ def get_all_commits(gitdir, branch, since='1.week', committer=None): logger.debug('No new commits from the current user --since=%s', since) return MY_COMMITS - logger.info('Found %s of your comits since %s', len(lines), since) + logger.info('Found %s of your commits since %s', len(lines), since) logger.info('Calculating patch hashes, may take a moment...') # Get patch hash of each commit for line in lines: @@ -160,7 +164,7 @@ def get_all_commits(gitdir, branch, since='1.week', committer=None): return MY_COMMITS -def auto_locate_series(gitdir, jsondata, branch, since='1.week'): +def auto_locate_series(gitdir, jsondata, branch, since='1.week', loose=False): commits = get_all_commits(gitdir, branch, since) patchids = set(commits.keys()) @@ -170,6 +174,12 @@ def auto_locate_series(gitdir, jsondata, branch, since='1.week'): if patch[1] in patchids: logger.debug('Found: %s', patch[0]) found.append(commits[patch[1]]) + elif loose: + # try to locate by subject + for pwhash, commit in commits.items(): + if commit[1] == patch[0]: + found.append(commits[patch[1]]) + break if len(found) == len(jsondata['patches']): return found @@ -177,35 +187,73 @@ def auto_locate_series(gitdir, jsondata, branch, since='1.week'): return None -def generate_pr_thanks(jsondata): +def read_template(tptfile): + # bubbles up FileNotFound + tpt = '' + with open(tptfile, 'r', encoding='utf-8') as fh: + for line in fh: + if len(line) and line[0] == '#': + continue + tpt += line + return tpt + + +def generate_pr_thanks(gitdir, jsondata): config = b4.get_main_config() thanks_template = DEFAULT_PR_TEMPLATE - if 'thanks-pr-template' in config: + if config['thanks-pr-template']: # Try to load this template instead try: - with open(config['thanks-pr-template'], 'r', encoding='utf-8') as fh: - thanks_template = fh.read() + thanks_template = read_template(config['thanks-pr-template']) except FileNotFoundError: logger.critical('ERROR: thanks-pr-template says to use %s, but it does not exist', config['thanks-pr-template']) sys.exit(2) + if 'merge_commit_id' not in jsondata: + merge_commit_id = git_get_merge_id(gitdir, jsondata['pr_commit_id']) + if not merge_commit_id: + logger.critical('Could not get merge commit id for %s', jsondata['subject']) + logger.critical('Was it actually merged?') + sys.exit(1) + jsondata['merge_commit_id'] = merge_commit_id + # Make a summary + cidmask = config['thanks-commit-url-mask'] + if not cidmask: + cidmask = 'merge commit: %s' + jsondata['summary'] = cidmask % jsondata['merge_commit_id'] msg = make_reply(thanks_template, jsondata) return msg -def generate_am_thanks(jsondata): +def generate_am_thanks(gitdir, jsondata, branch, since): config = b4.get_main_config() thanks_template = DEFAULT_AM_TEMPLATE - if 'thanks-am-template' in config: + if config['thanks-am-template']: # Try to load this template instead try: - with open(config['thanks-am-template'], 'r', encoding='utf-8') as fh: - thanks_template = fh.read() + thanks_template = read_template(config['thanks-am-template']) except FileNotFoundError: logger.critical('ERROR: thanks-am-template says to use %s, but it does not exist', config['thanks-am-template']) sys.exit(2) + if 'commits' not in jsondata: + commits = auto_locate_series(gitdir, jsondata, branch, since, loose=True) + else: + commits = jsondata['commits'] + + if commits is None: + logger.critical('Could not identify all commits for: %s', jsondata['subject']) + logger.critical('Cowardly refusing to run') + sys.exit(1) + cidmask = config['thanks-commit-url-mask'] + if not cidmask: + cidmask = 'commit: %s' + slines = list() + for commit in commits: + slines.append('- %s' % commit[1]) + slines.append(' %s' % (cidmask % commit[0])) + jsondata['summary'] = '\n'.join(slines) msg = make_reply(thanks_template, jsondata) return msg @@ -213,27 +261,8 @@ def generate_am_thanks(jsondata): def auto_thankanator(cmdargs): gitdir = cmdargs.gitdir - if not cmdargs.branch: - # Find out our current branch - gitargs = ['branch', '--show-current'] - ecode, out = b4.git_run_command(gitdir, gitargs) - if ecode > 0: - logger.critical('Not able to get current branch (git branch --show-current)') - sys.exit(1) - wantbranch = out.strip() - else: - # Make sure it's a real branch - gitargs = ['branch', '--format=%(refname:short)', '--list'] - lines = b4.git_get_command_lines(gitdir, gitargs) - if not len(lines): - logger.critical('Not able to get a list of branches (git branch --list)') - sys.exit(1) - if cmdargs.branch not in lines: - logger.critical('Requested branch %s not found in git branch --list', cmdargs.branch) - sys.exit(1) - wantbranch = cmdargs.branch - - logger.info('Auto-thankinating commits in %s', wantbranch) + wantbranch = get_wanted_branch(cmdargs) + logger.info('Auto-thankanating commits in %s', wantbranch) tracked = list_tracked() if not len(tracked): logger.info('Nothing to do') @@ -249,9 +278,10 @@ def auto_thankanator(cmdargs): jsondata['merge_commit_id'] = merge_commit_id else: # This is a patch series - patches = auto_locate_series(gitdir, jsondata, wantbranch, since=cmdargs.since) - if patches is None: + commits = auto_locate_series(gitdir, jsondata, wantbranch, since=cmdargs.since) + if commits is None: continue + jsondata['commits'] = commits applied.append(jsondata) logger.info(' Located: %s', jsondata['subject']) @@ -260,11 +290,11 @@ def auto_thankanator(cmdargs): sys.exit(0) logger.info('---') - send_messages(applied, cmdargs.outdir) + send_messages(applied, cmdargs.gitdir, cmdargs.outdir, wantbranch, since=cmdargs.since) sys.exit(0) -def send_messages(listing, outdir): +def send_messages(listing, gitdir, outdir, branch, since='1.week'): # Not really sending, but writing them out to be sent on your own # We'll probably gain ability to send these once the feature is # more mature and we're less likely to mess things up @@ -281,10 +311,10 @@ def send_messages(listing, outdir): slug = re.sub(r'_+', '_', slug) if 'pr_commit_id' in jsondata: # This is a pull request - msg = generate_pr_thanks(jsondata) + msg = generate_pr_thanks(gitdir, jsondata) else: # This is a patch series - msg = generate_am_thanks(jsondata) + msg = generate_am_thanks(gitdir, jsondata, branch, since) outfile = os.path.join(outdir, '%s.thanks' % slug) logger.info(' Writing: %s', outfile) @@ -355,7 +385,9 @@ def send_selected(cmdargs): logger.info('Nothing to do') sys.exit(0) - send_messages(listing, cmdargs.outdir) + wantbranch = get_wanted_branch(cmdargs) + send_messages(listing, cmdargs.gitdir, cmdargs.outdir, wantbranch, cmdargs.since) + sys.exit(0) def discard_selected(cmdargs): @@ -407,6 +439,31 @@ def check_stale_thanks(outdir): sys.exit(1) +def get_wanted_branch(cmdargs): + gitdir = cmdargs.gitdir + if not cmdargs.branch: + # Find out our current branch + gitargs = ['branch', '--show-current'] + ecode, out = b4.git_run_command(gitdir, gitargs) + if ecode > 0: + logger.critical('Not able to get current branch (git branch --show-current)') + sys.exit(1) + wantbranch = out.strip() + else: + # Make sure it's a real branch + gitargs = ['branch', '--format=%(refname:short)', '--list'] + lines = b4.git_get_command_lines(gitdir, gitargs) + if not len(lines): + logger.critical('Not able to get a list of branches (git branch --list)') + sys.exit(1) + if cmdargs.branch not in lines: + logger.critical('Requested branch %s not found in git branch --list', cmdargs.branch) + sys.exit(1) + wantbranch = cmdargs.branch + + return wantbranch + + def main(cmdargs): usercfg = b4.get_user_config() if 'email' not in usercfg: @@ -414,11 +471,11 @@ def main(cmdargs): sys.exit(1) if cmdargs.auto: - auto_thankanator(cmdargs) check_stale_thanks(cmdargs.outdir) + auto_thankanator(cmdargs) elif cmdargs.send: - send_selected(cmdargs) check_stale_thanks(cmdargs.outdir) + send_selected(cmdargs) elif cmdargs.discard: discard_selected(cmdargs) else: |