2 # Set up the git configuration for contributing to TianoCore projects
4 # Copyright (c) 2019, Linaro Ltd. All rights reserved.<BR>
5 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
10 from __future__
import print_function
19 print('Unable to load gitpython module - please install and try again.')
23 # Try Python 2 'ConfigParser' module first since helpful lib2to3 will
24 # otherwise automagically load it with the name 'configparser'
27 # Otherwise, try loading the Python 3 'configparser' under an alias
29 import configparser
as ConfigParser
31 print("Unable to load configparser/ConfigParser module - please install and try again!")
35 # Assumptions: Script is in edk2/BaseTools/Scripts,
36 # templates in edk2/BaseTools/Conf
37 CONFDIR
= os
.path
.join(os
.path
.dirname(os
.path
.dirname(os
.path
.realpath(__file__
))),
42 'repo': 'https://github.com/tianocore/edk2.git',
43 'list': 'devel@edk2.groups.io'},
44 {'name': 'edk2-platforms',
45 'repo': 'https://github.com/tianocore/edk2-platforms.git',
46 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-platforms'},
47 {'name': 'edk2-non-osi',
48 'repo': 'https://github.com/tianocore/edk2-non-osi.git',
49 'list': 'devel@edk2.groups.io', 'prefix': 'edk2-non-osi'}
52 # The minimum version required for all of the below options to work
53 MIN_GIT_VERSION
= (1, 9, 0)
55 # Set of options to be set identically for all repositories
57 {'section': 'am', 'option': 'keepcr', 'value': True},
58 {'section': 'am', 'option': 'signoff', 'value': True},
59 {'section': 'cherry-pick', 'option': 'signoff', 'value': True},
60 {'section': 'color', 'option': 'diff', 'value': True},
61 {'section': 'color', 'option': 'grep', 'value': 'auto'},
62 {'section': 'commit', 'option': 'signoff', 'value': True},
63 {'section': 'core', 'option': 'abbrev', 'value': 12},
64 {'section': 'core', 'option': 'attributesFile',
65 'value': os
.path
.join(CONFDIR
, 'gitattributes').replace('\\', '/')},
66 {'section': 'core', 'option': 'whitespace', 'value': 'cr-at-eol'},
67 {'section': 'diff', 'option': 'algorithm', 'value': 'patience'},
68 {'section': 'diff', 'option': 'orderFile',
69 'value': os
.path
.join(CONFDIR
, 'diff.order').replace('\\', '/')},
70 {'section': 'diff', 'option': 'renames', 'value': 'copies'},
71 {'section': 'diff', 'option': 'statGraphWidth', 'value': '20'},
72 {'section': 'diff "ini"', 'option': 'xfuncname',
73 'value': '^\\\\[[A-Za-z0-9_., ]+]'},
74 {'section': 'format', 'option': 'coverLetter', 'value': True},
75 {'section': 'format', 'option': 'numbered', 'value': True},
76 {'section': 'format', 'option': 'signoff', 'value': False},
77 {'section': 'log', 'option': 'mailmap', 'value': True},
78 {'section': 'notes', 'option': 'rewriteRef', 'value': 'refs/notes/commits'},
79 {'section': 'sendemail', 'option': 'chainreplyto', 'value': False},
80 {'section': 'sendemail', 'option': 'thread', 'value': True},
81 {'section': 'sendemail', 'option': 'transferEncoding', 'value': '8bit'},
86 """Opens a Repo object for the current tree, searching upwards in the directory hierarchy."""
88 repo
= git
.Repo(path
='.', search_parent_directories
=True)
89 except (git
.InvalidGitRepositoryError
, git
.NoSuchPathError
):
90 print("It doesn't look like we're inside a git repository - aborting.")
95 def fuzzy_match_repo_url(one
, other
):
96 """Compares two repository URLs, ignoring protocol and optional trailing '.git'."""
97 oneresult
= re
.match(r
'.*://(?P<oneresult>.*?)(\.git)*$', one
)
98 otherresult
= re
.match(r
'.*://(?P<otherresult>.*?)(\.git)*$', other
)
100 if oneresult
and otherresult
:
101 onestring
= oneresult
.group('oneresult')
102 otherstring
= otherresult
.group('otherresult')
103 if onestring
== otherstring
:
109 def get_upstream(url
):
110 """Extracts the dict for the current repo origin."""
111 for upstream
in UPSTREAMS
:
112 if fuzzy_match_repo_url(upstream
['repo'], url
):
114 print("Unknown upstream '%s' - aborting!" % url
)
118 def check_versions():
119 """Checks versions of dependencies."""
120 version
= git
.cmd
.Git().version_info
122 if version
< MIN_GIT_VERSION
:
123 print('Need git version %d.%d or later!' % (version
[0], version
[1]))
127 def write_config_value(repo
, section
, option
, data
):
129 with repo
.config_writer(config_level
='repository') as configwriter
:
130 configwriter
.set_value(section
, option
, data
)
133 if __name__
== '__main__':
136 PARSER
= argparse
.ArgumentParser(
137 description
='Sets up a git repository according to TianoCore rules.')
138 PARSER
.add_argument('-c', '--check',
139 help='check current config only, printing what would be changed',
142 PARSER
.add_argument('-f', '--force',
143 help='overwrite existing settings conflicting with program defaults',
146 PARSER
.add_argument('-v', '--verbose',
147 help='enable more detailed output',
150 ARGS
= PARSER
.parse_args()
154 print('Bare repo - please check out an upstream one!')
157 URL
= REPO
.remotes
.origin
.url
159 UPSTREAM
= get_upstream(URL
)
161 print("Upstream '%s' unknown, aborting!" % URL
)
164 # Set a list email address if our upstream wants it
165 if 'list' in UPSTREAM
:
166 OPTIONS
.append({'section': 'sendemail', 'option': 'to',
167 'value': UPSTREAM
['list']})
168 # Append a subject prefix entry to OPTIONS if our upstream wants it
169 if 'prefix' in UPSTREAM
:
170 OPTIONS
.append({'section': 'format', 'option': 'subjectPrefix',
171 'value': "PATCH " + UPSTREAM
['prefix']})
173 CONFIG
= REPO
.config_reader(config_level
='repository')
175 for entry
in OPTIONS
:
178 # Make sure to read boolean/int settings as real type rather than strings
179 if isinstance(entry
['value'], bool):
180 value
= CONFIG
.getboolean(entry
['section'], entry
['option'])
181 elif isinstance(entry
['value'], int):
182 value
= CONFIG
.getint(entry
['section'], entry
['option'])
184 value
= CONFIG
.get(entry
['section'], entry
['option'])
187 # Don't bail out from options not already being set
188 except (ConfigParser
.NoSectionError
, ConfigParser
.NoOptionError
):
192 if value
== entry
['value']:
194 print("%s.%s already set (to '%s')" % (entry
['section'],
195 entry
['option'], value
))
198 write_config_value(REPO
, entry
['section'], entry
['option'], entry
['value'])
200 print("Not overwriting existing %s.%s value:" % (entry
['section'],
202 print(" '%s' != '%s'" % (value
, entry
['value']))
203 print(" add '-f' to command line to force overwriting existing settings")
205 print("%s.%s => '%s'" % (entry
['section'], entry
['option'], entry
['value']))
207 write_config_value(REPO
, entry
['section'], entry
['option'], entry
['value'])