1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Helper script for committing data to git and pushing upstream 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Copyright (c) 2017, Intel Corporation. 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunimport argparse 11*4882a593Smuzhiyunimport logging 12*4882a593Smuzhiyunimport os 13*4882a593Smuzhiyunimport re 14*4882a593Smuzhiyunimport sys 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun# Import oe and bitbake libs 17*4882a593Smuzhiyunscripts_path = os.path.dirname(os.path.realpath(__file__)) 18*4882a593Smuzhiyunsys.path.append(os.path.join(scripts_path, 'lib')) 19*4882a593Smuzhiyunimport scriptpath 20*4882a593Smuzhiyunscriptpath.add_bitbake_lib_path() 21*4882a593Smuzhiyunscriptpath.add_oe_lib_path() 22*4882a593Smuzhiyun 23*4882a593Smuzhiyunfrom oeqa.utils.git import GitRepo, GitError 24*4882a593Smuzhiyunfrom oeqa.utils.metadata import metadata_from_bb 25*4882a593Smuzhiyunimport oeqa.utils.gitarchive as gitarchive 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun# Setup logging 28*4882a593Smuzhiyunlogging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") 29*4882a593Smuzhiyunlog = logging.getLogger() 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun 32*4882a593Smuzhiyundef parse_args(argv): 33*4882a593Smuzhiyun """Parse command line arguments""" 34*4882a593Smuzhiyun parser = argparse.ArgumentParser( 35*4882a593Smuzhiyun description="Commit data to git and push upstream", 36*4882a593Smuzhiyun formatter_class=argparse.ArgumentDefaultsHelpFormatter) 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun parser.add_argument('--debug', '-D', action='store_true', 39*4882a593Smuzhiyun help="Verbose logging") 40*4882a593Smuzhiyun parser.add_argument('--git-dir', '-g', required=True, 41*4882a593Smuzhiyun help="Local git directory to use") 42*4882a593Smuzhiyun parser.add_argument('--no-create', action='store_true', 43*4882a593Smuzhiyun help="If GIT_DIR is not a valid Git repository, do not " 44*4882a593Smuzhiyun "try to create one") 45*4882a593Smuzhiyun parser.add_argument('--bare', action='store_true', 46*4882a593Smuzhiyun help="Initialize a bare repository when creating a " 47*4882a593Smuzhiyun "new one") 48*4882a593Smuzhiyun parser.add_argument('--push', '-p', nargs='?', default=False, const=True, 49*4882a593Smuzhiyun help="Push to remote") 50*4882a593Smuzhiyun parser.add_argument('--branch-name', '-b', 51*4882a593Smuzhiyun default='{hostname}/{branch}/{machine}', 52*4882a593Smuzhiyun help="Git branch name (pattern) to use") 53*4882a593Smuzhiyun parser.add_argument('--no-tag', action='store_true', 54*4882a593Smuzhiyun help="Do not create Git tag") 55*4882a593Smuzhiyun parser.add_argument('--tag-name', '-t', 56*4882a593Smuzhiyun default='{hostname}/{branch}/{machine}/{commit_count}-g{commit}/{tag_number}', 57*4882a593Smuzhiyun help="Tag name (pattern) to use") 58*4882a593Smuzhiyun parser.add_argument('--commit-msg-subject', 59*4882a593Smuzhiyun default='Results of {branch}:{commit} on {hostname}', 60*4882a593Smuzhiyun help="Subject line (pattern) to use in the commit message") 61*4882a593Smuzhiyun parser.add_argument('--commit-msg-body', 62*4882a593Smuzhiyun default='branch: {branch}\ncommit: {commit}\nhostname: {hostname}', 63*4882a593Smuzhiyun help="Commit message body (pattern)") 64*4882a593Smuzhiyun parser.add_argument('--tag-msg-subject', 65*4882a593Smuzhiyun default='Test run #{tag_number} of {branch}:{commit} on {hostname}', 66*4882a593Smuzhiyun help="Subject line (pattern) of the tag message") 67*4882a593Smuzhiyun parser.add_argument('--tag-msg-body', 68*4882a593Smuzhiyun default='', 69*4882a593Smuzhiyun help="Tag message body (pattern)") 70*4882a593Smuzhiyun parser.add_argument('--exclude', action='append', default=[], 71*4882a593Smuzhiyun help="Glob to exclude files from the commit. Relative " 72*4882a593Smuzhiyun "to DATA_DIR. May be specified multiple times") 73*4882a593Smuzhiyun parser.add_argument('--notes', nargs=2, action='append', default=[], 74*4882a593Smuzhiyun metavar=('GIT_REF', 'FILE'), 75*4882a593Smuzhiyun help="Add a file as a note under refs/notes/GIT_REF. " 76*4882a593Smuzhiyun "{branch_name} in GIT_REF will be expanded to the " 77*4882a593Smuzhiyun "actual target branch name (specified by " 78*4882a593Smuzhiyun "--branch-name). This option may be specified " 79*4882a593Smuzhiyun "multiple times.") 80*4882a593Smuzhiyun parser.add_argument('data_dir', metavar='DATA_DIR', 81*4882a593Smuzhiyun help="Data to commit") 82*4882a593Smuzhiyun return parser.parse_args(argv) 83*4882a593Smuzhiyun 84*4882a593Smuzhiyundef get_nested(d, list_of_keys): 85*4882a593Smuzhiyun try: 86*4882a593Smuzhiyun for k in list_of_keys: 87*4882a593Smuzhiyun d = d[k] 88*4882a593Smuzhiyun return d 89*4882a593Smuzhiyun except KeyError: 90*4882a593Smuzhiyun return "" 91*4882a593Smuzhiyun 92*4882a593Smuzhiyundef main(argv=None): 93*4882a593Smuzhiyun args = parse_args(argv) 94*4882a593Smuzhiyun if args.debug: 95*4882a593Smuzhiyun log.setLevel(logging.DEBUG) 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun try: 98*4882a593Smuzhiyun # Get keywords to be used in tag and branch names and messages 99*4882a593Smuzhiyun metadata = metadata_from_bb() 100*4882a593Smuzhiyun keywords = {'hostname': get_nested(metadata, ['hostname']), 101*4882a593Smuzhiyun 'branch': get_nested(metadata, ['layers', 'meta', 'branch']), 102*4882a593Smuzhiyun 'commit': get_nested(metadata, ['layers', 'meta', 'commit']), 103*4882a593Smuzhiyun 'commit_count': get_nested(metadata, ['layers', 'meta', 'commit_count']), 104*4882a593Smuzhiyun 'machine': get_nested(metadata, ['config', 'MACHINE'])} 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun gitarchive.gitarchive(args.data_dir, args.git_dir, args.no_create, args.bare, 107*4882a593Smuzhiyun args.commit_msg_subject.strip(), args.commit_msg_body, args.branch_name, 108*4882a593Smuzhiyun args.no_tag, args.tag_name, args.tag_msg_subject, args.tag_msg_body, 109*4882a593Smuzhiyun args.exclude, args.notes, args.push, keywords, log) 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun except gitarchive.ArchiveError as err: 112*4882a593Smuzhiyun log.error(str(err)) 113*4882a593Smuzhiyun return 1 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun return 0 116*4882a593Smuzhiyun 117*4882a593Smuzhiyunif __name__ == "__main__": 118*4882a593Smuzhiyun sys.exit(main()) 119