]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add --debug-workspace
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 6 Nov 2023 19:47:17 +0000 (20:47 +0100)
committerJörg Behrmann <behrmann@physik.fu-berlin.de>
Tue, 7 Nov 2023 08:13:31 +0000 (09:13 +0100)
Fixes #2036

mkosi/__init__.py
mkosi/config.py
mkosi/log.py
mkosi/resources/mkosi.md
tests/test_json.py

index dc976b2d64609770afe3977adfd91ee815e7df2e..857acdae4fe390639f6c983dd5c05e54656818b0 100644 (file)
@@ -44,7 +44,7 @@ from mkosi.config import (
 from mkosi.distributions import Distribution
 from mkosi.installer import clean_package_manager_metadata, package_manager_scripts
 from mkosi.kmod import gen_required_kernel_modules, process_kernel_modules
-from mkosi.log import ARG_DEBUG, complete_step, die, log_step
+from mkosi.log import ARG_DEBUG, complete_step, die, log_notice, log_step
 from mkosi.manifest import Manifest
 from mkosi.mounts import mount, mount_overlay, mount_passwd, mount_usr
 from mkosi.pager import page
@@ -2113,12 +2113,27 @@ def normalize_mtime(root: Path, mtime: Optional[int], directory: Optional[Path]
             os.utime(p, (mtime, mtime), follow_symlinks=False)
 
 
+@contextlib.contextmanager
+def setup_workspace(args: MkosiArgs, config: MkosiConfig) -> Iterator[Path]:
+    with contextlib.ExitStack() as stack:
+        workspace = Path(tempfile.mkdtemp(dir=config.workspace_dir_or_default(), prefix="mkosi-workspace"))
+        stack.callback(lambda: rmtree(workspace))
+
+        with scopedenv({"TMPDIR" : os.fspath(workspace)}):
+            try:
+                yield Path(workspace)
+            except BaseException:
+                if args.debug_workspace:
+                    stack.pop_all()
+                    log_notice(f"Workspace: {workspace}")
+                    workspace.chmod(0o755)
+
+
 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_default(), prefix=".mkosi-tmp")
 
-    with workspace, scopedenv({"TMPDIR" : workspace.name}):
-        state = MkosiState(args, config, Path(workspace.name))
+    with setup_workspace(args, config) as workspace:
+        state = MkosiState(args, config, workspace)
         install_package_manager_trees(state)
 
         with mount_base_trees(state):
index c4a01ee6b8a8e0acc56eaa42378749f718f81018..d2f620d09a9d99767e8b6c0f477e132eebe03908 100644 (file)
@@ -648,6 +648,7 @@ class MkosiArgs:
     directory: Optional[Path]
     debug: bool
     debug_shell: bool
+    debug_workspace: bool
     pager: bool
     genkey_valid_days: str
     genkey_common_name: str
@@ -2020,6 +2021,12 @@ def create_argument_parser(action: type[argparse.Action]) -> argparse.ArgumentPa
         action="store_true",
         default=False,
     )
+    parser.add_argument(
+        "--debug-workspace",
+        help="When an error occurs, the workspace directory will not be deleted",
+        action="store_true",
+        default=False,
+    )
     parser.add_argument(
         "--no-pager",
         action="store_false",
@@ -2772,8 +2779,8 @@ def summary(config: MkosiConfig) -> str:
               Manifest Formats: {maniformats}
                         Output: {bold(config.output_with_compression)}
                    Compression: {config.compress_output}
-              Output Directory: {none_to_default(config.output_dir)}
-           Workspace Directory: {none_to_default(config.workspace_dir)}
+              Output Directory: {config.output_dir_or_cwd()}
+           Workspace Directory: {config.workspace_dir_or_default()}
                Cache Directory: {none_to_none(config.cache_dir)}
                Build Directory: {none_to_none(config.build_dir)}
                       Image ID: {config.image_id}
index a03a9a3cdfd4e63caa314366aaf66be37c9e8e53..4c9fc9c15239832a723b667fdb0cafff5d2c61f1 100644 (file)
@@ -44,6 +44,10 @@ def log_step(text: str) -> None:
         logging.info(f"{prefix}{Style.bold}{text}{Style.reset}")
 
 
+def log_notice(text: str) -> None:
+    logging.info(f"{Style.bold}{text}{Style.reset}")
+
+
 @contextlib.contextmanager
 def complete_step(text: str, text2: Optional[str] = None) -> Iterator[list[Any]]:
     global LEVEL
index 2c185f14040f0cd239c4f643e1835f4a98e3b92b..9c93c76fcc9d6d5aea184995aa809be5c20277d0 100644 (file)
@@ -193,6 +193,10 @@ Those settings cannot be configured in the configuration files.
 : When executing a command in the image fails, mkosi will start an interactive
   shell in the image allowing further debugging.
 
+`--debug-workspace=`
+
+: When an error occurs, the workspace directory will not be deleted.
+
 `--version`
 
 : Show package version.
index d0c1663f34ac68dd2a294a8b92f3acd46ed1557d..7a80b539c3bcdb1b37578e7a0644785406d6462b 100644 (file)
@@ -39,6 +39,7 @@ def test_args(path: Optional[Path]) -> None:
             ],
             "Debug": false,
             "DebugShell": false,
+            "DebugWorkspace": false,
             "Directory": {f'"{os.fspath(path)}"' if path is not None else 'null'},
             "DocFormat": "auto",
             "Force": 9001,
@@ -56,6 +57,7 @@ def test_args(path: Optional[Path]) -> None:
         cmdline = ["foo", "bar"],
         debug = False,
         debug_shell = False,
+        debug_workspace = False,
         directory = Path(path) if path is not None else None,
         doc_format = DocFormat.auto,
         force = 9001,