1 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright 2020 Google LLC
5 """Handles the main control logic of patman
7 This module provides various functions called by the main program to implement
8 the features of patman.
14 from patman import checkpatch
15 from patman import gitutil
16 from patman import patchstream
17 from patman import terminal
20 """Do required setup before doing anything"""
23 def prepare_patches(col, branch, count, start, end, ignore_binary):
24 """Figure out what patches to generate, then generate them
26 The patch files are written to the current directory, e.g. 0001_xxx.patch
30 col (terminal.Color): Colour output object
31 branch (str): Branch to create patches from (None = current)
32 count (int): Number of patches to produce, or -1 to produce patches for
33 the current branch back to the upstream commit
34 start (int): Start partch to use (0=first / top of branch)
35 end (int): End patch to use (0=last one in series, 1=one before that,
37 ignore_binary (bool): Don't generate patches for binary files
41 Series object for this series (set of patches)
42 Filename of the cover letter as a string (None if none)
43 patch_files: List of patch filenames, each a string, e.g.
44 ['0001_xxx.patch', '0002_yyy.patch']
47 # Work out how many patches to send if we can
48 count = (gitutil.CountCommitsToBranch(branch) - start)
51 str = 'No commits found to process - please use -c flag, or run:\n' \
52 ' git branch --set-upstream-to remote/branch'
53 sys.exit(col.Color(col.RED, str))
55 # Read the metadata from the commits
57 series = patchstream.GetMetaData(branch, start, to_do)
58 cover_fname, patch_files = gitutil.CreatePatches(
59 branch, start, to_do, ignore_binary, series)
61 # Fix up the patch files to our liking, and insert the cover letter
62 patchstream.FixPatches(series, patch_files)
63 if cover_fname and series.get('cover'):
64 patchstream.InsertCoverLetter(cover_fname, series, to_do)
65 return series, cover_fname, patch_files
67 def check_patches(series, patch_files, run_checkpatch, verbose):
68 """Run some checks on a set of patches
70 This santiy-checks the patman tags like Series-version and runs the patches
74 series (Series): Series object for this series (set of patches)
75 patch_files (list): List of patch filenames, each a string, e.g.
76 ['0001_xxx.patch', '0002_yyy.patch']
77 run_checkpatch (bool): True to run checkpatch.pl
78 verbose (bool): True to print out every line of the checkpatch output as
82 bool: True if the patches had no errors, False if they did
84 # Do a few checks on the series
87 # Check the patches, and run them through 'git am' just to be sure
89 ok = checkpatch.CheckPatches(verbose, patch_files)
95 def email_patches(col, series, cover_fname, patch_files, process_tags, its_a_go,
96 ignore_bad_tags, add_maintainers, limit, dry_run, in_reply_to,
98 """Email patches to the recipients
100 This emails out the patches and cover letter using 'git send-email'. Each
101 patch is copied to recipients identified by the patch tag and output from
102 the get_maintainer.pl script. The cover letter is copied to all recipients
105 To make this work a CC file is created holding the recipients for each patch
106 and the cover letter. See the main program 'cc_cmd' for this logic.
109 col (terminal.Color): Colour output object
110 series (Series): Series object for this series (set of patches)
111 cover_fname (str): Filename of the cover letter as a string (None if
113 patch_files (list): List of patch filenames, each a string, e.g.
114 ['0001_xxx.patch', '0002_yyy.patch']
115 process_tags (bool): True to process subject tags in each patch, e.g.
116 for 'dm: spi: Add SPI support' this would be 'dm' and 'spi'. The
117 tags are looked up in the configured sendemail.aliasesfile and also
118 in ~/.patman (see README)
119 its_a_go (bool): True if we are going to actually send the patches,
120 False if the patches have errors and will not be sent unless
122 ignore_bad_tags (bool): True to just print a warning for unknown tags,
123 False to halt with an error
124 add_maintainers (bool): Run the get_maintainer.pl script for each patch
125 limit (int): Limit on the number of people that can be cc'd on a single
126 patch or the cover letter (None if no limit)
127 dry_run (bool): Don't actually email the patches, just print out what
129 in_reply_to (str): If not None we'll pass this to git as --in-reply-to.
130 Should be a message ID that this is in reply to.
131 thread (bool): True to add --thread to git send-email (make all patches
132 reply to cover-letter or first patch in series)
133 smtp_server (str): SMTP server to use to send patches (None for default)
135 cc_file = series.MakeCcFile(process_tags, cover_fname, not ignore_bad_tags,
136 add_maintainers, limit)
138 # Email the patches out (giving the user time to check / cancel)
141 cmd = gitutil.EmailPatches(
142 series, cover_fname, patch_files, dry_run, not ignore_bad_tags,
143 cc_file, in_reply_to=in_reply_to, thread=thread,
144 smtp_server=smtp_server)
146 print(col.Color(col.RED, "Not sending emails due to errors/warnings"))
148 # For a dry run, just show our actions as a sanity check
150 series.ShowActions(patch_files, cmd, process_tags)
152 print(col.Color(col.RED, "Email would not be sent"))
157 """Create, check and send patches by email
160 args (argparse.Namespace): Arguments to patman
163 col = terminal.Color()
164 series, cover_fname, patch_files = prepare_patches(
165 col, args.branch, args.count, args.start, args.end,
167 ok = check_patches(series, patch_files, args.check_patch,
170 ok = ok and gitutil.CheckSuppressCCConfig()
172 its_a_go = ok or args.ignore_errors
175 col, series, cover_fname, patch_files, args.process_tags,
176 its_a_go, args.ignore_bad_tags, args.add_maintainers,
177 args.limit, args.dry_run, args.in_reply_to, args.thread,