patman: additionally honor a local .patman config file

This enables versioning a project specific patman configuration file.
It also makes it possible to declare the project name, which is not a
useful thing to do in $HOME/.patman.  A new test is added, along
updated documentation.

Signed-off-by: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Maxim Cournoyer 2022-12-20 00:38:41 -05:00 committed by Simon Glass
parent db16edd8ce
commit 8f8d3f72f2
3 changed files with 94 additions and 5 deletions

View file

@ -74,7 +74,7 @@ out where to send patches pretty well.
During the first run patman creates a config file for you by taking the default During the first run patman creates a config file for you by taking the default
user name and email address from the global .gitconfig file. user name and email address from the global .gitconfig file.
To add your own, create a file ~/.patman like this:: To add your own, create a file `~/.patman` like this::
# patman alias file # patman alias file
@ -85,6 +85,12 @@ To add your own, create a file ~/.patman like this::
wolfgang: Wolfgang Denk <wd@denx.de> wolfgang: Wolfgang Denk <wd@denx.de>
others: Mike Frysinger <vapier@gentoo.org>, Fred Bloggs <f.bloggs@napier.net> others: Mike Frysinger <vapier@gentoo.org>, Fred Bloggs <f.bloggs@napier.net>
Patman will also look for a `.patman` configuration file at the root
of the current project git repository, which makes it possible to
override the `project` settings variable or anything else in a
project-specific way. The values of this "local" configuration file
take precedence over those of the "global" one.
Aliases are recursive. Aliases are recursive.
The checkpatch.pl in the U-Boot tools/ subdirectory will be located and The checkpatch.pl in the U-Boot tools/ subdirectory will be located and

View file

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+ # SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2011 The Chromium OS Authors. # Copyright (c) 2011 The Chromium OS Authors.
# Copyright (c) 2022 Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
# #
try: try:
@ -336,6 +337,12 @@ def GetItems(config, section):
def Setup(parser, project_name, config_fname=None): def Setup(parser, project_name, config_fname=None):
"""Set up the settings module by reading config files. """Set up the settings module by reading config files.
Unless `config_fname` is specified, a `.patman` config file local
to the git repository is consulted, followed by the global
`$HOME/.patman`. If none exists, the later is created. Values
defined in the local config file take precedence over those
defined in the global one.
Args: Args:
parser: The parser to update. parser: The parser to update.
project_name: Name of project that we're working on; we'll look project_name: Name of project that we're working on; we'll look
@ -352,13 +359,22 @@ def Setup(parser, project_name, config_fname=None):
if not config_fname: if not config_fname:
config_fname = '%s/.patman' % os.getenv('HOME') config_fname = '%s/.patman' % os.getenv('HOME')
has_config = os.path.exists(config_fname)
if not os.path.exists(config_fname): git_local_config_fname = os.path.join(gitutil.get_top_level(), '.patman')
print("No config file found ~/.patman\nCreating one...\n") has_git_local_config = os.path.exists(git_local_config_fname)
# Read the git local config last, so that its values override
# those of the global config, if any.
if has_config:
config.read(config_fname)
if has_git_local_config:
config.read(git_local_config_fname)
if not (has_config or has_git_local_config):
print("No config file found.\nCreating ~/.patman...\n")
CreatePatmanConfigFile(config_fname) CreatePatmanConfigFile(config_fname)
config.read(config_fname)
for name, value in GetItems(config, 'alias'): for name, value in GetItems(config, 'alias'):
alias[name] = value.split(',') alias[name] = value.split(',')

View file

@ -0,0 +1,67 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2022 Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
#
import argparse
import contextlib
import os
import sys
import tempfile
from patman import settings
from patman import tools
@contextlib.contextmanager
def empty_git_repository():
with tempfile.TemporaryDirectory() as tmpdir:
os.chdir(tmpdir)
tools.run('git', 'init', raise_on_error=True)
yield tmpdir
@contextlib.contextmanager
def cleared_command_line_args():
old_value = sys.argv[:]
sys.argv = [sys.argv[0]]
try:
yield
finally:
sys.argv = old_value
def test_git_local_config():
# Clearing the command line arguments is required, otherwise
# arguments passed to the test running such as in 'pytest -k
# filter' would be processed by _UpdateDefaults and fail.
with cleared_command_line_args():
with empty_git_repository():
with tempfile.NamedTemporaryFile() as global_config:
global_config.write(b'[settings]\n'
b'project=u-boot\n')
global_config.flush()
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--project', default='unknown')
subparsers = parser.add_subparsers(dest='cmd')
send = subparsers.add_parser('send')
send.add_argument('--no-check', action='store_false',
dest='check_patch', default=True)
# Test "global" config is used.
settings.Setup(parser, 'unknown', global_config.name)
args, _ = parser.parse_known_args([])
assert args.project == 'u-boot'
send_args, _ = send.parse_known_args([])
assert send_args.check_patch
# Test local config can shadow it.
with open('.patman', 'w', buffering=1) as f:
f.write('[settings]\n'
'project: guix-patches\n'
'check_patch: False\n')
settings.Setup(parser, 'unknown', global_config.name)
args, _ = parser.parse_known_args([])
assert args.project == 'guix-patches'
send_args, _ = send.parse_known_args([])
assert not send_args.check_patch