]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Scripts/SetupGit.py
MdePkg/DxeServicesLib: remove bogus cast
[mirror_edk2.git] / BaseTools / Scripts / SetupGit.py
CommitLineData
4eb0acb1
LL
1## @file\r
2# Set up the git configuration for contributing to TianoCore projects\r
3#\r
4# Copyright (c) 2019, Linaro Ltd. All rights reserved.<BR>\r
5#\r
6# SPDX-License-Identifier: BSD-2-Clause-Patent\r
7#\r
8\r
9from __future__ import print_function\r
10import argparse\r
11import os.path\r
12import re\r
13import sys\r
14\r
15try:\r
16 import git\r
17except ImportError:\r
18 print('Unable to load gitpython module - please install and try again.')\r
19 sys.exit(1)\r
20\r
21try:\r
22 # Try Python 2 'ConfigParser' module first since helpful lib2to3 will\r
23 # otherwise automagically load it with the name 'configparser'\r
24 import ConfigParser\r
25except ImportError:\r
26 # Otherwise, try loading the Python 3 'configparser' under an alias\r
27 try:\r
28 import configparser as ConfigParser\r
29 except ImportError:\r
30 print("Unable to load configparser/ConfigParser module - please install and try again!")\r
31 sys.exit(1)\r
32\r
33\r
34# Assumptions: Script is in edk2/BaseTools/Scripts,\r
35# templates in edk2/BaseTools/Conf\r
36CONFDIR = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))),\r
37 'Conf')\r
38\r
39UPSTREAMS = [\r
40 {'name': 'edk2',\r
41 'repo': 'https://github.com/tianocore/edk2.git',\r
42 'list': 'devel@edk2.groups.io'},\r
43 {'name': 'edk2-platforms',\r
44 'repo': 'https://github.com/tianocore/edk2-platforms.git',\r
45 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-platforms'},\r
46 {'name': 'edk2-non-osi',\r
47 'repo': 'https://github.com/tianocore/edk2-non-osi.git',\r
48 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-non-osi'}\r
49 ]\r
50\r
51# The minimum version required for all of the below options to work\r
52MIN_GIT_VERSION = (1, 9, 0)\r
53\r
54# Set of options to be set identically for all repositories\r
55OPTIONS = [\r
56 {'section': 'am', 'option': 'keepcr', 'value': True},\r
57 {'section': 'am', 'option': 'signoff', 'value': True},\r
58 {'section': 'cherry-pick', 'option': 'signoff', 'value': True},\r
59 {'section': 'color', 'option': 'diff', 'value': True},\r
60 {'section': 'color', 'option': 'grep', 'value': 'auto'},\r
61 {'section': 'commit', 'option': 'signoff', 'value': True},\r
62 {'section': 'core', 'option': 'abbrev', 'value': 12},\r
63 {'section': 'core', 'option': 'attributesFile',\r
64 'value': os.path.join(CONFDIR, 'gitattributes').replace('\\', '/')},\r
65 {'section': 'core', 'option': 'whitespace', 'value': 'cr-at-eol'},\r
66 {'section': 'diff', 'option': 'algorithm', 'value': 'patience'},\r
67 {'section': 'diff', 'option': 'orderFile',\r
68 'value': os.path.join(CONFDIR, 'diff.order').replace('\\', '/')},\r
69 {'section': 'diff', 'option': 'renames', 'value': 'copies'},\r
70 {'section': 'diff', 'option': 'statGraphWidth', 'value': '20'},\r
71 {'section': 'diff "ini"', 'option': 'xfuncname',\r
72 'value': '^\\\\[[A-Za-z0-9_., ]+]'},\r
73 {'section': 'format', 'option': 'coverLetter', 'value': True},\r
74 {'section': 'format', 'option': 'numbered', 'value': True},\r
75 {'section': 'format', 'option': 'signoff', 'value': False},\r
76 {'section': 'notes', 'option': 'rewriteRef', 'value': 'refs/notes/commits'},\r
77 {'section': 'sendemail', 'option': 'chainreplyto', 'value': False},\r
78 {'section': 'sendemail', 'option': 'thread', 'value': True},\r
79 ]\r
80\r
81\r
82def locate_repo():\r
83 """Opens a Repo object for the current tree, searching upwards in the directory hierarchy."""\r
84 try:\r
85 repo = git.Repo(path='.', search_parent_directories=True)\r
86 except (git.InvalidGitRepositoryError, git.NoSuchPathError):\r
87 print("It doesn't look like we're inside a git repository - aborting.")\r
88 sys.exit(2)\r
89 return repo\r
90\r
91\r
92def fuzzy_match_repo_url(one, other):\r
93 """Compares two repository URLs, ignoring protocol and optional trailing '.git'."""\r
94 oneresult = re.match(r'.*://(?P<oneresult>.*?)(\.git)*$', one)\r
95 otherresult = re.match(r'.*://(?P<otherresult>.*?)(\.git)*$', other)\r
96\r
97 if oneresult and otherresult:\r
98 onestring = oneresult.group('oneresult')\r
99 otherstring = otherresult.group('otherresult')\r
100 if onestring == otherstring:\r
101 return True\r
102\r
103 return False\r
104\r
105\r
106def get_upstream(url):\r
107 """Extracts the dict for the current repo origin."""\r
108 for upstream in UPSTREAMS:\r
109 if fuzzy_match_repo_url(upstream['repo'], url):\r
110 return upstream\r
111 print("Unknown upstream '%s' - aborting!" % url)\r
112 sys.exit(3)\r
113\r
114\r
115def check_versions():\r
116 """Checks versions of dependencies."""\r
117 version = git.cmd.Git().version_info\r
118\r
119 if version < MIN_GIT_VERSION:\r
120 print('Need git version %d.%d or later!' % (version[0], version[1]))\r
121 sys.exit(4)\r
122\r
123\r
124def write_config_value(repo, section, option, data):\r
125 """."""\r
126 with repo.config_writer(config_level='repository') as configwriter:\r
127 configwriter.set_value(section, option, data)\r
128\r
129\r
130if __name__ == '__main__':\r
131 check_versions()\r
132\r
133 PARSER = argparse.ArgumentParser(\r
134 description='Sets up a git repository according to TianoCore rules.')\r
135 PARSER.add_argument('-c', '--check',\r
136 help='check current config only, printing what would be changed',\r
137 action='store_true',\r
138 required=False)\r
139 PARSER.add_argument('-f', '--force',\r
140 help='overwrite existing settings conflicting with program defaults',\r
141 action='store_true',\r
142 required=False)\r
143 PARSER.add_argument('-v', '--verbose',\r
144 help='enable more detailed output',\r
145 action='store_true',\r
146 required=False)\r
147 ARGS = PARSER.parse_args()\r
148\r
149 REPO = locate_repo()\r
150 if REPO.bare:\r
151 print('Bare repo - please check out an upstream one!')\r
152 sys.exit(6)\r
153\r
154 URL = REPO.remotes.origin.url\r
155\r
156 UPSTREAM = get_upstream(URL)\r
157 if not UPSTREAM:\r
158 print("Upstream '%s' unknown, aborting!" % URL)\r
159 sys.exit(7)\r
160\r
161 # Set a list email address if our upstream wants it\r
162 if 'list' in UPSTREAM:\r
163 OPTIONS.append({'section': 'sendemail', 'option': 'to',\r
164 'value': UPSTREAM['list']})\r
165 # Append a subject prefix entry to OPTIONS if our upstream wants it\r
166 if 'prefix' in UPSTREAM:\r
167 OPTIONS.append({'section': 'format', 'option': 'subjectPrefix',\r
168 'value': "PATCH " + UPSTREAM['prefix']})\r
169\r
170 CONFIG = REPO.config_reader(config_level='repository')\r
171\r
172 for entry in OPTIONS:\r
173 exists = False\r
174 try:\r
175 # Make sure to read boolean/int settings as real type rather than strings\r
176 if isinstance(entry['value'], bool):\r
177 value = CONFIG.getboolean(entry['section'], entry['option'])\r
178 elif isinstance(entry['value'], int):\r
179 value = CONFIG.getint(entry['section'], entry['option'])\r
180 else:\r
181 value = CONFIG.get(entry['section'], entry['option'])\r
182\r
183 exists = True\r
184 # Don't bail out from options not already being set\r
185 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):\r
186 pass\r
187\r
188 if exists:\r
189 if value == entry['value']:\r
190 if ARGS.verbose:\r
191 print("%s.%s already set (to '%s')" % (entry['section'],\r
192 entry['option'], value))\r
193 else:\r
194 if ARGS.force:\r
195 write_config_value(REPO, entry['section'], entry['option'], entry['value'])\r
196 else:\r
197 print("Not overwriting existing %s.%s value:" % (entry['section'],\r
198 entry['option']))\r
199 print(" '%s' != '%s'" % (value, entry['value']))\r
200 print(" add '-f' to command line to force overwriting existing settings")\r
201 else:\r
202 print("%s.%s => '%s'" % (entry['section'], entry['option'], entry['value']))\r
203 if not ARGS.check:\r
204 write_config_value(REPO, entry['section'], entry['option'], entry['value'])\r