xref: /rk3399_rockchip-uboot/tools/patman/patman.py (revision 27067a46c56cdaa0f8a2ef433f0aed4376834c44)
1e8570757SMichal Simek#!/usr/bin/env python
20d24de9dSSimon Glass#
30d24de9dSSimon Glass# Copyright (c) 2011 The Chromium OS Authors.
40d24de9dSSimon Glass#
51a459660SWolfgang Denk# SPDX-License-Identifier:	GPL-2.0+
60d24de9dSSimon Glass#
70d24de9dSSimon Glass
80d24de9dSSimon Glass"""See README for more information"""
90d24de9dSSimon Glass
100d24de9dSSimon Glassfrom optparse import OptionParser
110d24de9dSSimon Glassimport os
120d24de9dSSimon Glassimport re
130d24de9dSSimon Glassimport sys
140d24de9dSSimon Glassimport unittest
150d24de9dSSimon Glass
160d24de9dSSimon Glass# Our modules
17488d19cbSChris Packhamtry:
18488d19cbSChris Packham    from patman import checkpatch, command, gitutil, patchstream, \
19488d19cbSChris Packham        project, settings, terminal, test
20488d19cbSChris Packhamexcept ImportError:
210d24de9dSSimon Glass    import checkpatch
220d24de9dSSimon Glass    import command
230d24de9dSSimon Glass    import gitutil
240d24de9dSSimon Glass    import patchstream
25a1dcee84SDoug Anderson    import project
268568baedSDoug Anderson    import settings
270d24de9dSSimon Glass    import terminal
280d24de9dSSimon Glass    import test
290d24de9dSSimon Glass
300d24de9dSSimon Glass
310d24de9dSSimon Glassparser = OptionParser()
320d24de9dSSimon Glassparser.add_option('-H', '--full-help', action='store_true', dest='full_help',
330d24de9dSSimon Glass       default=False, help='Display the README file')
340d24de9dSSimon Glassparser.add_option('-c', '--count', dest='count', type='int',
350d24de9dSSimon Glass       default=-1, help='Automatically create patches from top n commits')
360d24de9dSSimon Glassparser.add_option('-i', '--ignore-errors', action='store_true',
370d24de9dSSimon Glass       dest='ignore_errors', default=False,
380d24de9dSSimon Glass       help='Send patches email even if patch errors are found')
39983a2749SSimon Glassparser.add_option('-m', '--no-maintainers', action='store_false',
40983a2749SSimon Glass       dest='add_maintainers', default=True,
41983a2749SSimon Glass       help="Don't cc the file maintainers automatically")
420d24de9dSSimon Glassparser.add_option('-n', '--dry-run', action='store_true', dest='dry_run',
43ca706e76SSimon Glass       default=False, help="Do a dry run (create but don't email patches)")
4499adf6edSVadim Bendeburyparser.add_option('-p', '--project', default=project.DetectProject(),
4599adf6edSVadim Bendebury                  help="Project name; affects default option values and "
4699adf6edSVadim Bendebury                  "aliases [default: %default]")
476d819925SDoug Andersonparser.add_option('-r', '--in-reply-to', type='string', action='store',
486d819925SDoug Anderson                  help="Message ID that this series is in reply to")
490d24de9dSSimon Glassparser.add_option('-s', '--start', dest='start', type='int',
500d24de9dSSimon Glass       default=0, help='Commit to start creating patches from (0 = HEAD)')
51a1318f7cSSimon Glassparser.add_option('-t', '--ignore-bad-tags', action='store_true',
52a1318f7cSSimon Glass                  default=False, help='Ignore bad tags / aliases')
53a1318f7cSSimon Glassparser.add_option('--test', action='store_true', dest='test',
540d24de9dSSimon Glass                  default=False, help='run tests')
550d24de9dSSimon Glassparser.add_option('-v', '--verbose', action='store_true', dest='verbose',
560d24de9dSSimon Glass       default=False, help='Verbose output of errors and warnings')
570d24de9dSSimon Glassparser.add_option('--cc-cmd', dest='cc_cmd', type='string', action='store',
580d24de9dSSimon Glass       default=None, help='Output cc list for patch file (used by git)')
5999adf6edSVadim Bendeburyparser.add_option('--no-check', action='store_false', dest='check_patch',
6099adf6edSVadim Bendebury                  default=True,
6199adf6edSVadim Bendebury                  help="Don't check for patch compliance")
620d24de9dSSimon Glassparser.add_option('--no-tags', action='store_false', dest='process_tags',
630d24de9dSSimon Glass                  default=True, help="Don't process subject tags as aliaes")
64*27067a46SMateusz Kulikowskiparser.add_option('-T', '--thread', action='store_true', dest='thread',
65*27067a46SMateusz Kulikowski                  default=False, help='Create patches as a single thread')
660d24de9dSSimon Glass
67e0a4d06aSMasahiro Yamadaparser.usage += """
680d24de9dSSimon Glass
690d24de9dSSimon GlassCreate patches from commits in a branch, check them and email them as
70ca706e76SSimon Glassspecified by tags you place in the commits. Use -n to do a dry run first."""
710d24de9dSSimon Glass
728568baedSDoug Anderson
73a1dcee84SDoug Anderson# Parse options twice: first to get the project and second to handle
74a1dcee84SDoug Anderson# defaults properly (which depends on project).
75a1dcee84SDoug Anderson(options, args) = parser.parse_args()
76a1dcee84SDoug Andersonsettings.Setup(parser, options.project, '')
770d24de9dSSimon Glass(options, args) = parser.parse_args()
780d24de9dSSimon Glass
799649e152SSimon Glassif __name__ != "__main__":
809649e152SSimon Glass    pass
819649e152SSimon Glass
820d24de9dSSimon Glass# Run our meagre tests
839649e152SSimon Glasselif options.test:
840d24de9dSSimon Glass    import doctest
850d24de9dSSimon Glass
860d24de9dSSimon Glass    sys.argv = [sys.argv[0]]
870d24de9dSSimon Glass    suite = unittest.TestLoader().loadTestsFromTestCase(test.TestPatch)
880d24de9dSSimon Glass    result = unittest.TestResult()
890d24de9dSSimon Glass    suite.run(result)
900d24de9dSSimon Glass
91656cffebSDoug Anderson    for module in ['gitutil', 'settings']:
92656cffebSDoug Anderson        suite = doctest.DocTestSuite(module)
930d24de9dSSimon Glass        suite.run(result)
940d24de9dSSimon Glass
950d24de9dSSimon Glass    # TODO: Surely we can just 'print' result?
960d24de9dSSimon Glass    print result
970d24de9dSSimon Glass    for test, err in result.errors:
980d24de9dSSimon Glass        print err
990d24de9dSSimon Glass    for test, err in result.failures:
1000d24de9dSSimon Glass        print err
1010d24de9dSSimon Glass
1020d24de9dSSimon Glass# Called from git with a patch filename as argument
1030d24de9dSSimon Glass# Printout a list of additional CC recipients for this patch
1040d24de9dSSimon Glasselif options.cc_cmd:
1050d24de9dSSimon Glass    fd = open(options.cc_cmd, 'r')
1060d24de9dSSimon Glass    re_line = re.compile('(\S*) (.*)')
1070d24de9dSSimon Glass    for line in fd.readlines():
1080d24de9dSSimon Glass        match = re_line.match(line)
1090d24de9dSSimon Glass        if match and match.group(1) == args[0]:
1100d24de9dSSimon Glass            for cc in match.group(2).split(', '):
1110d24de9dSSimon Glass                cc = cc.strip()
1120d24de9dSSimon Glass                if cc:
1130d24de9dSSimon Glass                    print cc
1140d24de9dSSimon Glass    fd.close()
1150d24de9dSSimon Glass
1160d24de9dSSimon Glasselif options.full_help:
1170d24de9dSSimon Glass    pager = os.getenv('PAGER')
1180d24de9dSSimon Glass    if not pager:
1190d24de9dSSimon Glass        pager = 'more'
1200d24de9dSSimon Glass    fname = os.path.join(os.path.dirname(sys.argv[0]), 'README')
1210d24de9dSSimon Glass    command.Run(pager, fname)
1220d24de9dSSimon Glass
1230d24de9dSSimon Glass# Process commits, produce patches files, check them, email them
1240d24de9dSSimon Glasselse:
1250d24de9dSSimon Glass    gitutil.Setup()
1260d24de9dSSimon Glass
1270d24de9dSSimon Glass    if options.count == -1:
1280d24de9dSSimon Glass        # Work out how many patches to send if we can
1290d24de9dSSimon Glass        options.count = gitutil.CountCommitsToBranch() - options.start
1300d24de9dSSimon Glass
1310d24de9dSSimon Glass    col = terminal.Color()
1320d24de9dSSimon Glass    if not options.count:
1330d24de9dSSimon Glass        str = 'No commits found to process - please use -c flag'
13431e2141dSMasahiro Yamada        sys.exit(col.Color(col.RED, str))
1350d24de9dSSimon Glass
1360d24de9dSSimon Glass    # Read the metadata from the commits
1370d24de9dSSimon Glass    if options.count:
1380d24de9dSSimon Glass        series = patchstream.GetMetaData(options.start, options.count)
1390d24de9dSSimon Glass        cover_fname, args = gitutil.CreatePatches(options.start, options.count,
1400d24de9dSSimon Glass                series)
1410d24de9dSSimon Glass
1420d24de9dSSimon Glass    # Fix up the patch files to our liking, and insert the cover letter
1430d24de9dSSimon Glass    series = patchstream.FixPatches(series, args)
1440d24de9dSSimon Glass    if series and cover_fname and series.get('cover'):
1450d24de9dSSimon Glass        patchstream.InsertCoverLetter(cover_fname, series, options.count)
1460d24de9dSSimon Glass
1470d24de9dSSimon Glass    # Do a few checks on the series
1480d24de9dSSimon Glass    series.DoChecks()
1490d24de9dSSimon Glass
1500d24de9dSSimon Glass    # Check the patches, and run them through 'git am' just to be sure
15199adf6edSVadim Bendebury    if options.check_patch:
1520d24de9dSSimon Glass        ok = checkpatch.CheckPatches(options.verbose, args)
15399adf6edSVadim Bendebury    else:
15499adf6edSVadim Bendebury        ok = True
1550d24de9dSSimon Glass
156a1318f7cSSimon Glass    cc_file = series.MakeCcFile(options.process_tags, cover_fname,
157983a2749SSimon Glass                                not options.ignore_bad_tags,
158983a2749SSimon Glass                                options.add_maintainers)
159d94566a1SDoug Anderson
1600d24de9dSSimon Glass    # Email the patches out (giving the user time to check / cancel)
1610d24de9dSSimon Glass    cmd = ''
1621f727885SVadim Bendebury    its_a_go = ok or options.ignore_errors
1631f727885SVadim Bendebury    if its_a_go:
1640d24de9dSSimon Glass        cmd = gitutil.EmailPatches(series, cover_fname, args,
165a1318f7cSSimon Glass                options.dry_run, not options.ignore_bad_tags, cc_file,
166*27067a46SMateusz Kulikowski                in_reply_to=options.in_reply_to, thread=options.thread)
1671f727885SVadim Bendebury    else:
1681f727885SVadim Bendebury        print col.Color(col.RED, "Not sending emails due to errors/warnings")
1690d24de9dSSimon Glass
1700d24de9dSSimon Glass    # For a dry run, just show our actions as a sanity check
1710d24de9dSSimon Glass    if options.dry_run:
1720d24de9dSSimon Glass        series.ShowActions(args, cmd, options.process_tags)
1731f727885SVadim Bendebury        if not its_a_go:
1741f727885SVadim Bendebury            print col.Color(col.RED, "Email would not be sent")
175d94566a1SDoug Anderson
176d94566a1SDoug Anderson    os.remove(cc_file)
177