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