From: Daan De Meyer Date: Mon, 6 Nov 2023 12:58:56 +0000 (+0100) Subject: Stop using workspace directories in source directories X-Git-Tag: v19~26^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94c1e78a496713e006fc576f56e62216eb70ea57;p=thirdparty%2Fmkosi.git Stop using workspace directories in source directories Preparation for making source directories volatile while running scripts. Overlapping overlayfs directories cause massive mayhem so to keep our sanity, let's make sure the workspace directory is never a subdirectory of any source directories. XDG doesn't provide an equivalent of /var/tmp but when running in /home we really want the workspace to be located in /home as well so we can use reflinks if /home is a separate partition so we opt to use XDG_CACHE_HOME or $HOME/.cache instead. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 10891ae72..abb214961 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -2101,7 +2101,7 @@ def normalize_mtime(root: Path, mtime: Optional[int], directory: Optional[Path] def build_image(args: MkosiArgs, config: MkosiConfig) -> None: manifest = Manifest(config) if config.manifest_format else None - workspace = tempfile.TemporaryDirectory(dir=config.workspace_dir_or_cwd(), prefix=".mkosi-tmp") + workspace = tempfile.TemporaryDirectory(dir=config.workspace_dir_or_default(), prefix=".mkosi-tmp") with workspace, scopedenv({"TMPDIR" : workspace.name}): state = MkosiState(args, config, Path(workspace.name)) @@ -2599,6 +2599,19 @@ def mount_tools(tree: Optional[Path]) -> Iterator[None]: yield +def check_workspace_directory(config: MkosiConfig) -> None: + wd = config.workspace_dir_or_default() + + if wd.is_relative_to(Path.cwd()): + die(f"The workspace directory ({wd}) cannot be located in the current working directory ({Path.cwd()})", + hint="Use WorkspaceDirectory= to configure a different workspace directory") + + for src, _ in config.build_sources: + if wd.is_relative_to(src): + die(f"The workspace directory ({wd}) cannot be a subdirectory of any source directory ({src})", + hint="Use WorkspaceDirectory= to configure a different workspace directory") + + def run_verb(args: MkosiArgs, images: Sequence[MkosiConfig]) -> None: if args.verb.needs_root() and os.getuid() != 0: die(f"Must be root to run the {args.verb} command") @@ -2630,6 +2643,9 @@ def run_verb(args: MkosiArgs, images: Sequence[MkosiConfig]) -> None: page(text, args.pager) return + for config in images: + check_workspace_directory(config) + images = finalize_tools(args, images) last = images[-1] diff --git a/mkosi/config.py b/mkosi/config.py index 8d5456db3..c4a01ee6b 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -848,8 +848,26 @@ class MkosiConfig: def output_dir_or_cwd(self) -> Path: return self.output_dir or Path.cwd() - def workspace_dir_or_cwd(self) -> Path: - return self.workspace_dir or Path.cwd() + def workspace_dir_or_default(self) -> Path: + if self.workspace_dir: + return self.workspace_dir + + if (cache := os.getenv("XDG_CACHE_HOME")) and Path(cache).exists(): + return Path(cache) + + # If there's a cache directory and we're running from /home, we want to use a workspace directory in /home as + # well as /home might be on a separate partition or subvolume which means that to take advantage of reflinks + # and such, the workspace directory has to be on the same partition/subvolume. + if ( + (home := os.getenv("HOME")) and + "/home" in home and + self.cache_dir and + self.cache_dir.is_relative_to(home) and + (Path(home) / ".cache").exists() + ): + return Path(home) / ".cache" + + return Path("/var/tmp") @classmethod def default(cls) -> "MkosiConfig": @@ -1218,7 +1236,6 @@ SETTINGS = ( name="WorkspaceDirectory", section="Output", parse=config_make_path_parser(required=False), - paths=("mkosi.workspace",), help="Workspace directory", ), MkosiConfigSetting( diff --git a/mkosi/resources/mkosi.md b/mkosi/resources/mkosi.md index 35c606e39..9c3dc5ecc 100644 --- a/mkosi/resources/mkosi.md +++ b/mkosi/resources/mkosi.md @@ -602,9 +602,8 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`, : Path to a directory where to store data required temporarily while building the image. This directory should have enough space to store the full OS image, though in most modes the actually used disk space - is smaller. If not specified, and `mkosi.workspace/` exists in the - local directory, it is used for this purpose. Otherwise, hidden - subdirectories of the current working directory are used. + is smaller. If not specified, a subdirectory of `$XDG_CACHE_HOME` (if + set), `$HOME/.cache` (if set) or `/var/tmp` is used. : The data in this directory is removed automatically after each build. It's safe to manually remove the contents of this directory