tools.linux.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] b4: Add support for setting config on the command-line
@ 2024-01-18 20:25 Jani Nikula
  2024-01-18 20:25 ` [PATCH 1/2] init: separate config setup from access Jani Nikula
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jani Nikula @ 2024-01-18 20:25 UTC (permalink / raw)
  To: tools; +Cc: Konstantin Ryabitsev, jani.nikula

Add -c/--config name=value option to set and override config options on
the command-line.

Only very lightly tested.


BR,
Jani.

Jani Nikula (2):
  init: separate config setup from access
  b4: add --config option to set config options on the command-line

 b4/__init__.py  | 152 ++++++++++++++++++++++++++++++------------------
 b4/command.py   |  26 +++++++++
 docs/config.rst |   5 ++
 3 files changed, 127 insertions(+), 56 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] init: separate config setup from access
  2024-01-18 20:25 [PATCH 0/2] b4: Add support for setting config on the command-line Jani Nikula
@ 2024-01-18 20:25 ` Jani Nikula
  2024-01-18 20:25 ` [PATCH 2/2] b4: add --config option to set config options on the command-line Jani Nikula
  2024-01-23 23:00 ` [PATCH 0/2] b4: Add support for setting config " Konstantin Ryabitsev
  2 siblings, 0 replies; 4+ messages in thread
From: Jani Nikula @ 2024-01-18 20:25 UTC (permalink / raw)
  To: tools; +Cc: Konstantin Ryabitsev, jani.nikula

In preparation for adding support for setting config options on the
command-line, separate the config setup from regular access.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>

---

Note: 'git show -w' helps review the indentation changes.
---
 b4/__init__.py | 129 ++++++++++++++++++++++++++++---------------------
 b4/command.py  |   2 +
 2 files changed, 75 insertions(+), 56 deletions(-)

diff --git a/b4/__init__.py b/b4/__init__.py
index 5b692a1e0ef7..f62ec11f965b 100644
--- a/b4/__init__.py
+++ b/b4/__init__.py
@@ -2719,6 +2719,16 @@ def in_directory(dirname):
         os.chdir(cdir)
 
 
+def setup_config(cmdargs: argparse.Namespace):
+    """Setup configuration options. Needs to be called before accessing any of
+    the config options."""
+    _setup_main_config(cmdargs)
+    _setup_user_config(cmdargs)
+
+    # Depends on main config!
+    _setup_sendemail_config(cmdargs)
+
+
 def git_set_config(fullpath: Optional[str], param: str, value: str, operation: str = '--replace-all'):
     args = ['config', operation, param, value]
     ecode, out = git_run_command(fullpath, args)
@@ -2759,39 +2769,41 @@ def get_config_from_git(regexp: str, defaults: Optional[dict] = None,
     return gitconfig
 
 
-def get_main_config() -> dict:
+def _setup_main_config(cmdargs: argparse.Namespace):
     global MAIN_CONFIG
-    if MAIN_CONFIG is None:
-        defcfg = copy.deepcopy(DEFAULT_CONFIG)
-        # some options can be provided via the toplevel .b4-config file,
-        # so load them up and use as defaults
-        topdir = git_get_toplevel()
-        wtglobs = ['send-*', '*mask', '*template*', 'trailer*', 'pw-*']
-        if topdir:
-            wtcfg = os.path.join(topdir, '.b4-config')
-            if os.access(wtcfg, os.R_OK):
-                logger.debug('Loading worktree configs from %s', wtcfg)
-                wtconfig = get_config_from_git(r'b4\..*', source=wtcfg)
-                logger.debug('wtcfg=%s', wtconfig)
-                for key, val in wtconfig.items():
-                    if val.startswith('./'):
-                        # replace it with full topdir path
-                        val = os.path.abspath(os.path.join(topdir, val))
-                    for wtglob in wtglobs:
-                        if fnmatch.fnmatch(key, wtglob):
-                            logger.debug('wtcfg: %s=%s', key, val)
-                            defcfg[key] = val
-                            break
-        config = get_config_from_git(r'b4\..*', defaults=defcfg, multivals=['keyringsrc'])
-        config['listid-preference'] = config['listid-preference'].split(',')
-        config['listid-preference'].remove('*')
-        config['listid-preference'].append('*')
-        if config['gpgbin'] is None:
-            gpgcfg = get_config_from_git(r'gpg\..*', {'program': 'gpg'})
-            config['gpgbin'] = gpgcfg['program']
 
-        MAIN_CONFIG = config
+    defcfg = copy.deepcopy(DEFAULT_CONFIG)
+    # some options can be provided via the toplevel .b4-config file,
+    # so load them up and use as defaults
+    topdir = git_get_toplevel()
+    wtglobs = ['send-*', '*mask', '*template*', 'trailer*', 'pw-*']
+    if topdir:
+        wtcfg = os.path.join(topdir, '.b4-config')
+        if os.access(wtcfg, os.R_OK):
+            logger.debug('Loading worktree configs from %s', wtcfg)
+            wtconfig = get_config_from_git(r'b4\..*', source=wtcfg)
+            logger.debug('wtcfg=%s', wtconfig)
+            for key, val in wtconfig.items():
+                if val.startswith('./'):
+                    # replace it with full topdir path
+                    val = os.path.abspath(os.path.join(topdir, val))
+                for wtglob in wtglobs:
+                    if fnmatch.fnmatch(key, wtglob):
+                        logger.debug('wtcfg: %s=%s', key, val)
+                        defcfg[key] = val
+                        break
+    config = get_config_from_git(r'b4\..*', defaults=defcfg, multivals=['keyringsrc'])
+    config['listid-preference'] = config['listid-preference'].split(',')
+    config['listid-preference'].remove('*')
+    config['listid-preference'].append('*')
+    if config['gpgbin'] is None:
+        gpgcfg = get_config_from_git(r'gpg\..*', {'program': 'gpg'})
+        config['gpgbin'] = gpgcfg['program']
+
+    MAIN_CONFIG = config
+
 
+def get_main_config() -> dict:
     return MAIN_CONFIG
 
 
@@ -2874,16 +2886,18 @@ def save_cache(contents: str, identifier: str, suffix: Optional[str] = None, mod
     except FileNotFoundError:
         logger.debug('Could not write cache %s for %s', fullpath, identifier)
 
-
-def get_user_config():
+def _setup_user_config(cmdargs: argparse.Namespace):
     global USER_CONFIG
-    if USER_CONFIG is None:
-        USER_CONFIG = get_config_from_git(r'user\..*')
-        if 'name' not in USER_CONFIG:
-            udata = pwd.getpwuid(os.getuid())
-            USER_CONFIG['name'] = udata.pw_gecos
-        if 'email' not in USER_CONFIG:
-            USER_CONFIG['email'] = os.environ['EMAIL']
+
+    USER_CONFIG = get_config_from_git(r'user\..*')
+    if 'name' not in USER_CONFIG:
+        udata = pwd.getpwuid(os.getuid())
+        USER_CONFIG['name'] = udata.pw_gecos
+    if 'email' not in USER_CONFIG:
+        USER_CONFIG['email'] = os.environ['EMAIL']
+
+
+def get_user_config() -> dict:
     return USER_CONFIG
 
 
@@ -3500,25 +3514,28 @@ def read_template(tptfile):
     return tpt
 
 
-def get_sendemail_config() -> dict:
+def _setup_sendemail_config(cmdargs: argparse.Namespace):
     global SENDEMAIL_CONFIG
-    if SENDEMAIL_CONFIG is None:
-        # Get the default settings first
-        config = get_main_config()
-        identity = config.get('sendemail-identity')
-        _basecfg = get_config_from_git(r'sendemail\.[^.]+$')
-        if identity:
-            # Use this identity to override what we got from the default one
-            sconfig = get_config_from_git(rf'sendemail\.{identity}\..*', defaults=_basecfg)
-            sectname = f'sendemail.{identity}'
-            if not len(sconfig):
-                raise smtplib.SMTPException('Unable to find %s settings in any applicable git config' % sectname)
-        else:
-            sconfig = _basecfg
-            sectname = 'sendemail'
-        logger.debug('Using values from %s', sectname)
-        SENDEMAIL_CONFIG = sconfig
 
+    # Get the default settings first
+    config = get_main_config()
+    identity = config.get('sendemail-identity')
+    _basecfg = get_config_from_git(r'sendemail\.[^.]+$')
+    if identity:
+        # Use this identity to override what we got from the default one
+        sconfig = get_config_from_git(rf'sendemail\.{identity}\..*', defaults=_basecfg)
+        sectname = f'sendemail.{identity}'
+        if not len(sconfig):
+            raise smtplib.SMTPException('Unable to find %s settings in any applicable git config' % sectname)
+    else:
+        sconfig = _basecfg
+        sectname = 'sendemail'
+    logger.debug('Using values from %s', sectname)
+
+    SENDEMAIL_CONFIG = sconfig
+
+
+def get_sendemail_config() -> dict:
     return SENDEMAIL_CONFIG
 
 
diff --git a/b4/command.py b/b4/command.py
index d1046375c97c..07b6d67735dc 100644
--- a/b4/command.py
+++ b/b4/command.py
@@ -362,6 +362,8 @@ def cmd():
         parser.print_help()
         sys.exit(1)
 
+    b4.setup_config(cmdargs)
+
     if cmdargs.offline_mode:
         logger.info('Running in OFFLINE mode')
         b4.can_network = False
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] b4: add --config option to set config options on the command-line
  2024-01-18 20:25 [PATCH 0/2] b4: Add support for setting config on the command-line Jani Nikula
  2024-01-18 20:25 ` [PATCH 1/2] init: separate config setup from access Jani Nikula
@ 2024-01-18 20:25 ` Jani Nikula
  2024-01-23 23:00 ` [PATCH 0/2] b4: Add support for setting config " Konstantin Ryabitsev
  2 siblings, 0 replies; 4+ messages in thread
From: Jani Nikula @ 2024-01-18 20:25 UTC (permalink / raw)
  To: tools; +Cc: Konstantin Ryabitsev, jani.nikula

It's useful to be able to set and override configuration options on the
command-line. Add the --config and -c options to do this. This is
similar to the git -c option.

The basic form is 'b4 -c name=value'. Mimic git -c option for the 'b4 -c
name' and 'b4 -c name=' forms to set the value to 'true' and the empty
string, respectively. The name is also the same section.key dotted
format as in git -c. For example, 'b4 -c
b4.midmask=https://some.host/%s'.

The argparse action class is handy for special parsing. For details, see
[1] and [2]. This stores a dict of the config options set on the command
line to cmdargs.config, mapping the full dotted keys to values. Relevant
parts for main, user and sendemail configs will be set using
_cmdline_config_override().

[1] https://docs.python.org/3/library/argparse.html#action
[2] https://docs.python.org/3/library/argparse.html#action-classes

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 b4/__init__.py  | 23 +++++++++++++++++++++++
 b4/command.py   | 24 ++++++++++++++++++++++++
 docs/config.rst |  5 +++++
 3 files changed, 52 insertions(+)

diff --git a/b4/__init__.py b/b4/__init__.py
index f62ec11f965b..38a248aa8ca4 100644
--- a/b4/__init__.py
+++ b/b4/__init__.py
@@ -2729,6 +2729,22 @@ def setup_config(cmdargs: argparse.Namespace):
     _setup_sendemail_config(cmdargs)
 
 
+def _cmdline_config_override(cmdargs: argparse.Namespace, config: dict, section: str):
+    """Use cmdline.config to set and override config values for section."""
+    if not cmdargs.config:
+        return
+
+    section += '.'
+
+    config_override = {
+        key[len(section):]: val
+        for key, val in cmdargs.config.items()
+        if key.startswith(section)
+    }
+
+    config.update(config_override)
+
+
 def git_set_config(fullpath: Optional[str], param: str, value: str, operation: str = '--replace-all'):
     args = ['config', operation, param, value]
     ecode, out = git_run_command(fullpath, args)
@@ -2800,6 +2816,8 @@ def _setup_main_config(cmdargs: argparse.Namespace):
         gpgcfg = get_config_from_git(r'gpg\..*', {'program': 'gpg'})
         config['gpgbin'] = gpgcfg['program']
 
+    _cmdline_config_override(cmdargs, config, 'b4')
+
     MAIN_CONFIG = config
 
 
@@ -2896,6 +2914,8 @@ def _setup_user_config(cmdargs: argparse.Namespace):
     if 'email' not in USER_CONFIG:
         USER_CONFIG['email'] = os.environ['EMAIL']
 
+    _cmdline_config_override(cmdargs, USER_CONFIG, 'user')
+
 
 def get_user_config() -> dict:
     return USER_CONFIG
@@ -3532,6 +3552,9 @@ def _setup_sendemail_config(cmdargs: argparse.Namespace):
         sectname = 'sendemail'
     logger.debug('Using values from %s', sectname)
 
+    # Note: This can't handle identity, need to use sendemail.key directly
+    _cmdline_config_override(cmdargs, sconfig, 'sendemail')
+
     SENDEMAIL_CONFIG = sconfig
 
 
diff --git a/b4/command.py b/b4/command.py
index 07b6d67735dc..96d585f6983e 100644
--- a/b4/command.py
+++ b/b4/command.py
@@ -111,6 +111,24 @@ def cmd_diff(cmdargs):
     b4.diff.main(cmdargs)
 
 
+class ConfigOption(argparse.Action):
+    """Action class for storing key=value arguments in a dict."""
+    def __call__(self, parser, namespace, keyval, option_string=None):
+        config = getattr(namespace, self.dest, None)
+
+        if config is None:
+            config = dict()
+            setattr(namespace, self.dest, config)
+
+        if '=' in keyval:
+            key, value = keyval.split('=', maxsplit=1)
+        else:
+            # mimic git -c option
+            key, value = keyval, 'true'
+
+        config[key] = value
+
+
 def setup_parser() -> argparse.ArgumentParser:
     # noinspection PyTypeChecker
     parser = argparse.ArgumentParser(
@@ -132,6 +150,12 @@ def setup_parser() -> argparse.ArgumentParser:
                         help='Disable TTY detection for stdin')
     parser.add_argument('--use-web-endpoint', dest='send_web', action='store_true', default=False,
                         help="Force going through the web endpoint")
+    parser.add_argument('-c', '--config', metavar='NAME=VALUE', action=ConfigOption,
+                        help='''Set config option NAME to VALUE. Override value
+                        from config files. NAME is in dotted section.key
+                        format. Using NAME= and omitting VALUE will set the
+                        value to the empty string. Using NAME and omitting
+                        =VALUE will set the value to "true".''')
 
     subparsers = parser.add_subparsers(help='sub-command help', dest='subcmd')
 
diff --git a/docs/config.rst b/docs/config.rst
index 8936d2274734..c46d43a16ac0 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -12,6 +12,11 @@ Since the purpose of b4 is to work with git repositories, this allows
 the usual fall-through configuration that can be overridden by more
 local settings on the repository level.
 
+Additionally, you can set and override configuration options on the command-line
+using the ``--config`` (or ``-c``) option, for example::
+
+    b4 --config b4.midmask=https://some.host/%s
+
 Per-project defaults
 ~~~~~~~~~~~~~~~~~~~~
 .. note::
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] b4: Add support for setting config on the command-line
  2024-01-18 20:25 [PATCH 0/2] b4: Add support for setting config on the command-line Jani Nikula
  2024-01-18 20:25 ` [PATCH 1/2] init: separate config setup from access Jani Nikula
  2024-01-18 20:25 ` [PATCH 2/2] b4: add --config option to set config options on the command-line Jani Nikula
@ 2024-01-23 23:00 ` Konstantin Ryabitsev
  2 siblings, 0 replies; 4+ messages in thread
From: Konstantin Ryabitsev @ 2024-01-23 23:00 UTC (permalink / raw)
  To: tools, Jani Nikula


On Thu, 18 Jan 2024 22:25:42 +0200, Jani Nikula wrote:
> Add -c/--config name=value option to set and override config options on
> the command-line.
> 
> Only very lightly tested.
> 
> 
> BR,
> Jani.
> 
> [...]

Applied, thanks!

[1/2] init: separate config setup from access
      commit: ccdafeadb856095132b28929519d835802509e21
[2/2] b4: add --config option to set config options on the command-line
      commit: a8b915060228e594b76989211adf1a8e96fe58de

Best regards,
-- 
Konstantin Ryabitsev <konstantin@linuxfoundation.org>


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-01-23 23:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-18 20:25 [PATCH 0/2] b4: Add support for setting config on the command-line Jani Nikula
2024-01-18 20:25 ` [PATCH 1/2] init: separate config setup from access Jani Nikula
2024-01-18 20:25 ` [PATCH 2/2] b4: add --config option to set config options on the command-line Jani Nikula
2024-01-23 23:00 ` [PATCH 0/2] b4: Add support for setting config " Konstantin Ryabitsev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).