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))
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")
page(text, args.pager)
return
+ for config in images:
+ check_workspace_directory(config)
+
images = finalize_tools(args, images)
last = images[-1]
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":
name="WorkspaceDirectory",
section="Output",
parse=config_make_path_parser(required=False),
- paths=("mkosi.workspace",),
help="Workspace directory",
),
MkosiConfigSetting(
: 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