diff --git a/README.md b/README.md index e5c6e5c9..a4443df3 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,14 @@ Wrapper for managing custom repository inspired by [repo-scripts](https://github * Create `/var/lib/ahriman/.makepkg.conf` with `makepkg.conf` overrides if required (at least you might want to set `PACKAGER`): ```shell - echo 'PACKAGES="John Doe "' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf + echo 'PACKAGER="John Doe "' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf ``` * Configure build tools (it is required for correct dependency management system): * create build command, e.g. `ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build` (you can choose any name for command, basically it should be `{name}-{arch}-build`); * create configuration file, e.g. `cp /usr/share/devtools/pacman-{extra,ahriman}.conf` (same as previous `pacman-{name}.conf`); - * change configuration file, add your own repository, add multilib repository etc. Hint: you can use `Include` option as well; + * change configuration file, add your own repository, add multilib repository etc; * set `build_command` option to point to your command; * configure `/etc/sudoers.d/ahriman` to allow running command without a password. @@ -66,3 +66,5 @@ Wrapper for managing custom repository inspired by [repo-scripts](https://github ```shell sudo -u ahriman ahriman -a x86_64 add yay ``` + +Note that initial service configuration can be done by running `ahriman setup` with specific arguments. diff --git a/src/ahriman/application/ahriman.py b/src/ahriman/application/ahriman.py index 0d1e48d6..4b8f07e0 100644 --- a/src/ahriman/application/ahriman.py +++ b/src/ahriman/application/ahriman.py @@ -40,6 +40,7 @@ def _parser() -> argparse.ArgumentParser: parser.add_argument("--no-report", help="force disable reporting to web service", action="store_true") parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user", action="store_true") parser.add_argument("-v", "--version", action="version", version=version.__version__) + subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True) add_parser = subparsers.add_parser("add", description="add package") @@ -113,8 +114,8 @@ def _parser() -> argparse.ArgumentParser: if __name__ == "__main__": - arg_parser = _parser() - args = arg_parser.parse_args() + args_parser = _parser() + args = args_parser.parse_args() handler: handlers.Handler = args.handler status = handler.execute(args) diff --git a/src/ahriman/application/handlers/setup.py b/src/ahriman/application/handlers/setup.py index 4cfcfb7a..a168310c 100644 --- a/src/ahriman/application/handlers/setup.py +++ b/src/ahriman/application/handlers/setup.py @@ -55,8 +55,8 @@ class Setup(Handler): Setup.create_makepkg_configuration(args.packager, application.repository.paths) Setup.create_executable(args.build_command, architecture) Setup.create_devtools_configuration(args.build_command, architecture, Path(args.from_config), args.no_multilib, - application.repository.name, application.repository.paths) - Setup.create_ahriman_configuration(args.build_command, architecture, config.include) + args.repository, application.repository.paths) + Setup.create_ahriman_configuration(args.build_command, architecture, args.repository, config.include) Setup.create_sudo_configuration(args.build_command, architecture) @staticmethod @@ -70,18 +70,23 @@ class Setup(Handler): return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build" @staticmethod - def create_ahriman_configuration(prefix: str, architecture: str, include_path: Path) -> None: + def create_ahriman_configuration(prefix: str, architecture: str, repository: str, include_path: Path) -> None: """ create service specific configuration :param prefix: command prefix in {prefix}-{architecture}-build :param architecture: repository architecture + :param repository: repository name :param include_path: path to directory with configuration includes """ - config = configparser.RawConfigParser() + config = configparser.ConfigParser() + config.add_section("build") config.set("build", "build_command", str(Setup.build_command(prefix, architecture))) - target = include_path / "build.ini" + config.add_section("repository") + config.set("repository", "name", repository) + + target = include_path / "build-overrides.ini" with target.open("w") as ahriman_config: config.write(ahriman_config) @@ -97,11 +102,16 @@ class Setup(Handler): :param repository: repository name :param paths: repository paths instance """ - config = configparser.RawConfigParser() + config = configparser.ConfigParser() + # preserve case + # stupid mypy thinks that it is impossible + config.optionxform = lambda key: key # type: ignore - # include base configuration - config.add_section("options") - config.set("options", "Include", str(source)) + # load default configuration first + # we cannot use Include here because it will be copied to new chroot, thus no includes there + config.read(source) + + # set our architecture now config.set("options", "Architecture", architecture) # add multilib @@ -145,4 +155,6 @@ class Setup(Handler): :param prefix: command prefix in {prefix}-{architecture}-build :param architecture: repository architecture """ - Setup.build_command(prefix, architecture).symlink_to(Setup.BIN_DIR_PATH) + command = Setup.build_command(prefix, architecture) + command.unlink(missing_ok=True) + command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH) diff --git a/tests/ahriman/application/handlers/test_handler_setup.py b/tests/ahriman/application/handlers/test_handler_setup.py index 0203fc79..686b85ee 100644 --- a/tests/ahriman/application/handlers/test_handler_setup.py +++ b/tests/ahriman/application/handlers/test_handler_setup.py @@ -58,16 +58,22 @@ def test_create_ahriman_configuration(args: argparse.Namespace, configuration: C write_mock = mocker.patch("configparser.RawConfigParser.write") command = Setup.build_command(args.build_command, "x86_64") - Setup.create_ahriman_configuration(args.build_command, "x86_64", configuration.include) - add_section_mock.assert_called_once() - set_mock.assert_called_with("build", "build_command", str(command)) + Setup.create_ahriman_configuration(args.build_command, "x86_64", args.repository, configuration.include) + add_section_mock.assert_has_calls([ + mock.call("build"), + mock.call("repository"), + ]) + set_mock.assert_has_calls([ + mock.call("build", "build_command", str(command)), + mock.call("repository", "name", args.repository), + ]) write_mock.assert_called_once() def test_create_devtools_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: """ - must create configuration for the service + must create configuration for the devtools """ args = _default_args(args) mocker.patch("pathlib.Path.open") @@ -78,13 +84,29 @@ def test_create_devtools_configuration(args: argparse.Namespace, repository_path Setup.create_devtools_configuration(args.build_command, "x86_64", Path(args.from_config), args.no_multilib, args.repository, repository_paths) add_section_mock.assert_has_calls([ - mock.call("options"), mock.call("multilib"), mock.call(args.repository) ]) write_mock.assert_called_once() +def test_create_devtools_configuration_no_multilib(args: argparse.Namespace, repository_paths: RepositoryPaths, + mocker: MockerFixture) -> None: + """ + must create configuration for the devtools without multilib + """ + args = _default_args(args) + mocker.patch("pathlib.Path.open") + mocker.patch("configparser.RawConfigParser.set") + add_section_mock = mocker.patch("configparser.RawConfigParser.add_section") + write_mock = mocker.patch("configparser.RawConfigParser.write") + + Setup.create_devtools_configuration(args.build_command, "x86_64", Path(args.from_config), True, + args.repository, repository_paths) + add_section_mock.assert_called_once() + write_mock.assert_called_once() + + def test_create_makepkg_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: """ @@ -112,10 +134,12 @@ def test_create_sudo_configuration(args: argparse.Namespace, mocker: MockerFixtu def test_create_executable(args: argparse.Namespace, mocker: MockerFixture) -> None: """ - must create sudo configuration + must create executable """ args = _default_args(args) symlink_text_mock = mocker.patch("pathlib.Path.symlink_to") + unlink_text_mock = mocker.patch("pathlib.Path.unlink") Setup.create_executable(args.build_command, "x86_64") symlink_text_mock.assert_called_once() + unlink_text_mock.assert_called_once()