From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=vOFGJLPS; spf=pass (domain: linaro.org, ip: 209.85.128.68, mailfrom: leif.lindholm@linaro.org) Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by groups.io with SMTP; Thu, 30 May 2019 08:59:41 -0700 Received: by mail-wm1-f68.google.com with SMTP id d17so4300391wmb.3 for ; Thu, 30 May 2019 08:59:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=M0RLjbtEZO3y+yVo0K+2V2tgAV/oRWuwxpqh6SK+DiI=; b=vOFGJLPSIEHZZMSeQB83nbGoM6AeRpTmm5i36L/mzz4ooqCHMprjO20aZmNyHy0Q6h 5Lg/1d4z+bg+5EMwF9rIcL59Nxs5yjhSnJnkGGvmnMSSdRF/ffY2tdUO/pLxJT8L6fuS 58ftqXXX92j5lj8gWg5j/jCcJanipJoYCvXc3y7qpdMGgki01BNvQ+1bkYEOUiiR1JlN aYmQJ3gXq1/LI03Ugvvx2J6/Kf68/RNxHD83LjcWv7MdRzOrEyZmK/qSRyLNqsAD6JvI kmSTv8W7TmfBklX0JMvlJG9L4vxhj55lycaoY2cQLfBW7gFNTLUnghk9wIABCjXicW4K 33Qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=M0RLjbtEZO3y+yVo0K+2V2tgAV/oRWuwxpqh6SK+DiI=; b=DLHDIkkrDoArGYmMoPuCk48eo7j2iSVErgWi/JGqKKUeU4A37uUHL6aBZCWmh4CdxS jstg3EnVAnYQuIUdjgh9rGjLR6ir8ZSmDMHfF0dSsnwqhcWlBaEzYUYX0h7lugkP7Djb k6bZLIW3J8gpb9hmF69OojO83OB+/HqYMQViEvou3VFTakzMKShJdrLoShE+QzvXcV8s rMloHFSO4oyNzauqOz+Tm3L74WK9qSBqTU24M/DOV0A6Lj6eND1MwxJCrQmv2xoxkQev N8adi8dmKLPtCvIRmcgBzFzni2JLBOoRZ8P83oguF7qw9Mzb3L5KsCXhPJcZbIg+XO1J JmLQ== X-Gm-Message-State: APjAAAVxecERIAe7FL/KlteOP1WS+Tk1WeaVIx1Hd9vL4Go2HkzWOBGi OV59j6iWHqr8WN5aL2Lbb4JgN1v/k2U1ng== X-Google-Smtp-Source: APXvYqyftzKJXSjwMaA/289WjM32QQM1EO8KPrUxbDNVYfiPw2WELkBpBj/H7UUreG0xi5E3Tkjj4w== X-Received: by 2002:a1c:44d4:: with SMTP id r203mr755562wma.158.1559231978998; Thu, 30 May 2019 08:59:38 -0700 (PDT) Return-Path: Received: from vanye.hemma.eciton.net (cpc92302-cmbg19-2-0-cust304.5-4.cable.virginm.net. [82.1.209.49]) by smtp.gmail.com with ESMTPSA id o21sm3748705wmc.46.2019.05.30.08.59.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 May 2019 08:59:38 -0700 (PDT) From: "Leif Lindholm" To: devel@edk2.groups.io Cc: Bob Feng , Liming Gao , Yonghong Zhu , Andrew Fish , Laszlo Ersek , Michael D Kinney Subject: [RFC PATCH 2/2] BaseTools: add script to configure local git options Date: Thu, 30 May 2019 16:59:33 +0100 Message-Id: <20190530155933.25588-3-leif.lindholm@linaro.org> X-Mailer: git-send-email 2.11.0 Patch contribution and review is greatly simplified by following the steps described in "Laszlo's unkempt guide": https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers but there are a lot of tedious manual steps in there, so here is a python script that configures all options I am aware of *for the repository the script is executed from*. Signed-off-by: Leif Lindholm --- BaseTools/Scripts/SetupGit.py | 187 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 BaseTools/Scripts/SetupGit.py diff --git a/BaseTools/Scripts/SetupGit.py b/BaseTools/Scripts/SetupGit.py new file mode 100644 index 0000000000..3b199f08b2 --- /dev/null +++ b/BaseTools/Scripts/SetupGit.py @@ -0,0 +1,187 @@ +## @file +# Set up the git configuration for contributing to TianoCore projects +# +# Copyright (c) 2019, Linaro Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +from __future__ import print_function +import argparse +import os.path +import sys + +try: + import git +except ImportError: + print('Unable to load gitpython module - please install and try again.') + sys.exit(1) + +try: + # Try Python 2 'ConfigParser' module first since helpful lib2to3 will + # otherwise automagically load it with the name 'configparser' + import ConfigParser +except ImportError: + # Otherwise, try loading the Python 3 'configparser' uner an alias + try: + import configparser as ConfigParser + except ImportError: + print("Unable to load configparser/ConfigParser module - please install and try again!") + sys.exit(1) + + +# Assumptions: Script is in edk2/BaseTools/Scripts, +# templates in edk2/BaseTools/Conf +CONFDIR = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), + 'Conf') + +UPSTREAMS = [ + {'name': 'edk2', + 'repo': 'https://github.com/tianocore/edk2.git', + 'list': 'devel@edk2.groups.io'}, + {'name': 'edk2-platforms', + 'repo': 'https://github.com/tianocore/edk2-platforms.git', + 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-platforms'}, + {'name': 'edk2-non-osi', + 'repo': 'https://github.com/tianocore/edk2-non-osi.git', + 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-non-osi'} + ] + +# The minimum version required for all of the below options to work +MIN_GIT_VERSION = (1, 9, 0) + +# Set of options to be set identically for all repositories +OPTIONS = [ + {'section': 'am', 'option': 'keepcr', 'value': True}, + {'section': 'am', 'option': 'signoff', 'value': True}, + {'section': 'cherry-pick', 'option': 'signoff', 'value': True}, + {'section': 'color', 'option': 'diff', 'value': True}, + {'section': 'color', 'option': 'grep', 'value': 'auto'}, + {'section': 'commit', 'option': 'signoff', 'value': True}, + {'section': 'core', 'option': 'abbrev', 'value': 12}, + {'section': 'core', 'option': 'attributesFile', + 'value': os.path.join(CONFDIR, 'gitattributes').replace('\\', '/')}, + {'section': 'core', 'option': 'whitespace', 'value': 'cr-at-eol'}, + {'section': 'diff', 'option': 'algorithm', 'value': 'patience'}, + {'section': 'diff', 'option': 'orderFile', + 'value': os.path.join(CONFDIR, 'diff.order').replace('\\', '/')}, + {'section': 'diff', 'option': 'renames', 'value': 'copies'}, + {'section': 'diff', 'option': 'statGraphWidth', 'value': '20'}, + {'section': 'diff "ini"', 'option': 'xfuncname', + 'value': '^\\\\[[A-Za-z0-9_., ]+]'}, # or 'diff "ini"'? + {'section': 'format', 'option': 'coverLetter', 'value': True}, + {'section': 'format', 'option': 'numbered', 'value': True}, + {'section': 'format', 'option': 'signoff', 'value': False}, + {'section': 'notes', 'option': 'rewriteRef', 'value': 'refs/notes/commits'}, + {'section': 'sendemail', 'option': 'chainreplyto', 'value': False}, + {'section': 'sendemail', 'option': 'thread', 'value': True}, + ] + + +def locate_repo(): + """Opens a Repo object for the current tree, searching upwards in the directory hierarchy.""" + try: + repo = git.Repo(path='.', search_parent_directories=True) + except (git.InvalidGitRepositoryError, git.NoSuchPathError): + print("It doesn't look like we're inside a git repository - aborting.") + sys.exit(2) + return repo + + +def get_upstream(url): + """Extracts the dict for the current repo origin.""" + for upstream in UPSTREAMS: + if upstream['repo'] == url: + return upstream + print("Unknown upstream '%s' - aborting!" % url) + sys.exit(3) + + +def check_versions(): + """Checks versions of dependencies.""" + version = git.cmd.Git().version_info + + if version < MIN_GIT_VERSION: + print('Need git version %d.%d or later!' % (version[0], version[1])) + sys.exit(4) + + +def write_config_value(repo, section, option, data): + """.""" + with repo.config_writer(config_level='repository') as configwriter: + configwriter.set_value(section, option, data) + + +if __name__ == '__main__': + check_versions() + + PARSER = argparse.ArgumentParser( + description='Sets up a git repository according to TianoCore rules.') + PARSER.add_argument('-c', '--check', + help='check current config only, printing what would be changed', + action='store_true', + required=False) + PARSER.add_argument('-f', '--force', + help='overwrite existing settings conflicting with program defaults', + action='store_true', + required=False) + PARSER.add_argument('-v', '--verbose', + help='enable more detailed output', + action='store_true', + required=False) + ARGS = PARSER.parse_args() + + REPO = locate_repo() + if REPO.bare: + print('Bare repo - please check out an upstream one!') + sys.exit(6) + + URL = REPO.remotes.origin.url + + UPSTREAM = get_upstream(URL) + if not UPSTREAM: + print("Upstream '%s' unknown, aborting!" % URL) + sys.exit(7) + + # Set a list email address if our upstream wants it + if 'list' in UPSTREAM: + OPTIONS.append({'section': 'sendemail', 'option': 'to', + 'value': UPSTREAM['list']}) + # Append a subject prefix entry to OPTIONS if our upstream wants it + if 'prefix' in UPSTREAM: + OPTIONS.append({'section': 'format', 'option': 'subjectPrefix', + 'value': "PATCH " + UPSTREAM['prefix']}) + + CONFIG = REPO.config_reader(config_level='repository') + + for entry in OPTIONS: + exists = False + try: + # Make sure to read boolean/int settings as real type rather than strings + if isinstance(entry['value'], bool): + value = CONFIG.getboolean(entry['section'], entry['option']) + elif isinstance(entry['value'], int): + value = CONFIG.getint(entry['section'], entry['option']) + else: + value = CONFIG.get(entry['section'], entry['option']) + + exists = True + # Don't bail out from options not already being set + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + pass + + if exists: + if value == entry['value']: + if ARGS.verbose: + print("%s.%s already set (to '%s')" % (entry['section'], entry['option'], value)) + else: + if ARGS.force: + write_config_value(REPO, entry['section'], entry['option'], entry['value']) + else: + print("Not overwriting existing %s.%s value:" % (entry['section'], entry['option'])) + print(" '%s' != '%s'" % (value, entry['value'])) + print(" add '-f' to command line to force overwriting existing settings") + else: + print("%s.%s => '%s'" % (entry['section'], entry['option'], entry['value'])) + if not ARGS.check: + write_config_value(REPO, entry['section'], entry['option'], entry['value']) -- 2.11.0