diff --git a/README.md b/README.md index 864cc8e..f847679 100644 --- a/README.md +++ b/README.md @@ -116,12 +116,12 @@ That's it! ### Commands -`stack-pr` has four main commands: +`stack-pr` has five main commands: - `submit` (or `export`) - create a new stack of PRs from the given set of - commits. One can think of this as “push my local changes to the corresponding + commits. One can think of this as "push my local changes to the corresponding remote branches and update the corresponding PRs (or create new PRs if they - don’t exist yet)”. + don't exist yet)". - `view` - inspect the given set of commits and find the linked PRs. This command does not push any changes anywhere and does not change any commits. It can be used to examine what other commands did or will do. @@ -130,6 +130,9 @@ That's it! the corresponding local and remote branches and closes the PRs. - `land` - merge the bottom-most PR in the current stack and rebase the rest of the stack on the latest main. +- `config` - set configuration values in the config file. Similar to `git config`, + it takes a setting in the format `
.=` and updates the + config file (`.stack-pr.cfg` by default). A usual workflow is the following: @@ -372,6 +375,32 @@ Inspect the current stack Takes no additional arguments beyond common ones. +#### config + +Set a configuration value in the config file. + +Arguments: + +- `setting` (required): Configuration setting in format `
.=` + +Examples: + +```bash +# Set verbose mode +stack-pr config common.verbose=True + +# Set target branch +stack-pr config repo.target=master + +# Set default reviewer(s) +stack-pr config repo.reviewer=user1,user2 + +# Set custom branch name template +stack-pr config repo.branch_name_template=$USERNAME/stack +``` + +The config command modifies the config file (`.stack-pr.cfg` by default, or the path specified by `STACKPR_CONFIG` environment variable). If the file doesn't exist, it will be created. If a setting already exists, it will be updated. + ### Config files Default values for command line options can be specified via a config file. diff --git a/src/stack_pr/cli.py b/src/stack_pr/cli.py index 32afe35..ff9c801 100755 --- a/src/stack_pr/cli.py +++ b/src/stack_pr/cli.py @@ -175,6 +175,15 @@ Please complete or abort the current rebase first. """ +ERROR_CONFIG_INVALID_FORMAT = """Invalid config format. + +Usage: stack-pr config
.= + +Examples: + stack-pr config common.verbose=True + stack-pr config repo.target=main + stack-pr config repo.reviewer=user1,user2 +""" UPDATE_STACK_TIP = """ If you'd like to push your local changes first, you can use the following command to update the stack: $ stack-pr export -B {top_commit}~{stack_size} -H {top_commit}""" @@ -1364,6 +1373,43 @@ def command_view(args: CommonArgs) -> None: log(h(blue("SUCCESS!"))) +# ===----------------------------------------------------------------------=== # +# CONFIG +# ===----------------------------------------------------------------------=== # +def command_config(config_file: str, setting: str) -> None: + """Set a configuration value in the config file. + + Args: + config_file: Path to the config file + setting: Setting in the format "section.key=value" + """ + if "=" not in setting: + error(ERROR_CONFIG_INVALID_FORMAT) + sys.exit(1) + + key_path, value = setting.split("=", 1) + + if "." not in key_path: + error(ERROR_CONFIG_INVALID_FORMAT) + sys.exit(1) + + section, key = key_path.split(".", 1) + + config = configparser.ConfigParser() + if Path(config_file).is_file(): + config.read(config_file) + + if not config.has_section(section): + config.add_section(section) + + config.set(section, key, value) + + with Path(config_file).open("w") as f: + config.write(f) + + print(f"Set {section}.{key} = {value}") + + # ===----------------------------------------------------------------------=== # # Main entry point # ===----------------------------------------------------------------------=== # @@ -1467,6 +1513,15 @@ def create_argparser( parents=[common_parser], ) + parser_config = subparsers.add_parser( + "config", + help="Set a configuration value", + ) + parser_config.add_argument( + "setting", + help="Configuration setting in format
.=", + ) + return parser @@ -1489,6 +1544,11 @@ def main() -> None: # noqa: PLR0912 parser.print_help() return + # Handle config command early since it doesn't need git repo setup + if args.command == "config": + command_config(config_file, args.setting) + return + # Make sure "$ID" is present in the branch name template and append it if not args.branch_name_template = fix_branch_name_template(args.branch_name_template) common_args = CommonArgs.from_args(args)