diff --git a/pool_bin b/pool_bin index fbfd182..e3749df 100755 --- a/pool_bin +++ b/pool_bin @@ -393,10 +393,10 @@ def pool_info( pool_info(function, recursive, subpool) -def pool_init(buildroot: str) -> None: +def pool_init(buildroot: str | None) -> None: logger.debug(f"pool_init({buildroot=})") try: - Pool.init_create(os.path.abspath(buildroot)) + Pool.init_create(buildroot) except PoolError as e: if DEBUG: raise e @@ -464,7 +464,7 @@ def main() -> None: command = os.path.split(sys.argv[0])[-1] sys.argv[0] = PROG if command.startswith(PROG + "-"): - subcommand = command[len(PROG + "-") :] + subcommand = command[len(PROG + "-"):] sys.argv.insert(1, subcommand) env_vars = ( @@ -675,7 +675,20 @@ def main() -> None: formatter_class=argparse.RawDescriptionHelpFormatter, epilog=env_vars, ) - parser_init.add_argument("buildroot", help="/path/to/build-chroot") + parser_init_conflicts = parser_init.add_mutually_exclusive_group() + parser_init_conflicts.add_argument( + "buildroot", + nargs="?", + default=None, + help="/path/to/build-chroot", + ) + parser_init_conflicts.add_argument( + "-N", + "--no-buildroot", + action="store_true", + help="create pool with no buildroot (for pool of pools or pre-built" + " packages)" + ) parser_init.set_defaults(func=pool_init) # pool-list @@ -743,8 +756,18 @@ def main() -> None: if args.cmd: func = args.func args_dict = vars(args) + if args.cmd == "init": + # argparse handles error if both buildroot and --no-buildroot, but + # to force user to make explicit choice, error if neither set + if args.buildroot is None and not args.no_buildroot: + fatal( + "pool-init requires one of /path/to/buildroot or" + " --no-buildroot" + ) + # if no_buildroot == True then buildroot is None + del args_dict["no_buildroot"] # only pass debug for pool-get - if func.__name__ != "get" and "debug" in args: + if args.cmd != "get" and "debug" in args: del args_dict["debug"] del args_dict["cmd"] del args_dict["func"] @@ -753,7 +776,10 @@ def main() -> None: fatal(f"{args.outputdir} does not exist") elif not isdir(args.outputdir): fatal(f"{args.outputdir} exists, but is not a directory") - func(**args_dict) + try: + func(**args_dict) + except PoolError as e: + fatal(e) else: fatal("Subcommand required.", parser.print_help) diff --git a/pool_lib/__init__.py b/pool_lib/__init__.py index ac4ed44..ea06925 100644 --- a/pool_lib/__init__.py +++ b/pool_lib/__init__.py @@ -110,7 +110,7 @@ def parse_package_filename(filename: str) -> tuple[str, str]: return name, version -def set_deckdebuild_env(filename: str) -> dict[str, str]: +def read_pkg_deckdebuild_env(filename: str) -> dict[str, str]: """Read 'DECKDEBUILD_*' env vars from file. Return dict of 'DECKDEBUILD_*' values. Values are read from repo env file @@ -880,7 +880,12 @@ def __init__( if not exists(spath): raise PoolError(f"no pool found (POOL_DIR={self.path})") - self.buildroot = os.readlink(self.path_build_root) + self.buildroot: str | None + if islink(self.path_build_root): + self.buildroot = os.readlink(self.path_build_root) + else: + self.buildroot = None + self.pkgcache = PackageCache(self.path_pkgcache) self.stocks = Stocks( self.path_stocks, self.pkgcache, [*recursed_paths, self.path] @@ -1014,6 +1019,11 @@ def resolve(self, unresolved: RS) -> RS: def _build_package_source( self, source_path: str, name: str, version: str, source: bool = False ) -> None: + if self.buildroot is None: + raise PoolError( + "Cannot build a package in a pool without a buildroot" + " configured" + ) build_outputdir = tempfile.mkdtemp( dir=self.path_tmp, prefix=f"{name}-{version}." ) @@ -1032,7 +1042,9 @@ def _build_package_source( if source: args.append("--build-source") # read DECKDEBUILD_ENV if it exists, but existing env takes precidence - build_env = set_deckdebuild_env(join(source_path, "DECKDEBUILD_ENV")) + build_env = read_pkg_deckdebuild_env( + join(source_path, "DECKDEBUILD_ENV") + ) with in_dir(source_path): command = [ "/usr/bin/deckdebuild", @@ -1259,7 +1271,9 @@ def sort(self, key: Callable | None, reverse: bool = False) -> None: @classmethod def init_create( - cls: type["Pool"], buildroot: AnyPath, path: AnyPath | None = None + cls: type["Pool"], + buildroot: AnyPath | None, + path: AnyPath | None = None, ) -> "Pool": if path is None: cwd = os.getcwd() @@ -1280,7 +1294,7 @@ def init_create( if isdir(spath): raise PoolError("pool already initialized") - if not isdir(buildroot): + if buildroot is not None and not isdir(buildroot): raise PoolError(f"buildroot `{buildroot}' is not a directory") mkdir(path_stocks) @@ -1311,12 +1325,18 @@ def init_create( Git.set_gitignore(spath, ["tmp"]) - os.symlink(buildroot, path_build_root) + # if set, symlink path_build_root -> buildroot, otherwise touch + if buildroot is not None: + os.symlink(abspath(buildroot), path_build_root) + else: + open(path_build_root, "w").close() return cls(path) def __init__( - self, path: AnyPath | None = None, preserve_buildroot: str = "on-error" + self, + path: AnyPath | None = None, + preserve_buildroot: str | None = "on-error", ) -> None: kernel = PoolKernel(path, preserve_buildroot=preserve_buildroot) if kernel.drop_privileges(pretend=True):