diff --git a/dangerzone/cli.py b/dangerzone/cli.py
index 5e19fab..ca5b644 100644
--- a/dangerzone/cli.py
+++ b/dangerzone/cli.py
@@ -11,6 +11,7 @@ from .isolation_provider.container import Container
from .isolation_provider.dummy import Dummy
from .isolation_provider.qubes import Qubes, is_qubes_native_conversion
from .logic import DangerzoneCore
+from .settings import Settings
from .util import get_version, replace_control_chars
@@ -37,7 +38,7 @@ def print_header(s: str) -> None:
)
@click.argument(
"filenames",
- required=True,
+ required=False,
nargs=-1,
type=click.UNPROCESSED,
callback=args.validate_input_filenames,
@@ -48,17 +49,33 @@ def print_header(s: str) -> None:
flag_value=True,
help="Run Dangerzone in debug mode, to get logs from gVisor.",
)
+@click.option(
+ "--set-container-runtime",
+ required=False,
+ help="The path to the container runtime you want to set in the settings",
+)
@click.version_option(version=get_version(), message="%(version)s")
@errors.handle_document_errors
def cli_main(
output_filename: Optional[str],
ocr_lang: Optional[str],
- filenames: List[str],
+ filenames: Optional[List[str]],
archive: bool,
dummy_conversion: bool,
debug: bool,
+ set_container_runtime: Optional[str] = None,
) -> None:
setup_logging()
+ display_banner()
+ if set_container_runtime:
+ settings = Settings()
+ container_runtime = settings.set_custom_runtime(
+ set_container_runtime, autosave=True
+ )
+ click.echo(f"Set the settings container_runtime to {container_runtime}")
+ sys.exit(0)
+ elif not filenames:
+ raise click.UsageError("Missing argument 'FILENAMES...'")
if getattr(sys, "dangerzone_dev", False) and dummy_conversion:
dangerzone = DangerzoneCore(Dummy())
@@ -67,7 +84,6 @@ def cli_main(
else:
dangerzone = DangerzoneCore(Container(debug=debug))
- display_banner()
if len(filenames) == 1 and output_filename:
dangerzone.add_document_from_filename(filenames[0], output_filename, archive)
elif len(filenames) > 1 and output_filename:
diff --git a/dangerzone/container_utils.py b/dangerzone/container_utils.py
index 6101cdd..e7d60ff 100644
--- a/dangerzone/container_utils.py
+++ b/dangerzone/container_utils.py
@@ -16,6 +16,14 @@ log = logging.getLogger(__name__)
class Runtime(object):
+ """Represents the container runtime to use.
+
+ - It can be specified via the settings, using the "container_runtime" key,
+ which should point to the full path of the runtime;
+ - If the runtime is not specified via the settings, it defaults
+ to "podman" on Linux and "docker" on macOS and Windows.
+ """
+
def __init__(self) -> None:
settings = Settings()
@@ -26,14 +34,22 @@ class Runtime(object):
self.name = self.path.stem
else:
self.name = self.get_default_runtime_name()
- binary_path = shutil.which(self.name)
- if binary_path is None or not os.path.exists(binary_path):
- raise errors.NoContainerTechException(self.name)
- self.path = Path(binary_path)
+ self.path = Runtime.path_from_name(self.name)
if self.name not in ("podman", "docker"):
raise errors.UnsupportedContainerRuntime(self.name)
+ @staticmethod
+ def path_from_name(name: str) -> Path:
+ name_path = Path(name)
+ if name_path.is_file():
+ return name_path
+ else:
+ runtime = shutil.which(name_path)
+ if runtime is None:
+ raise errors.NoContainerTechException(name)
+ return Path(runtime)
+
@staticmethod
def get_default_runtime_name() -> str:
return "podman" if platform.system() == "Linux" else "docker"
diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py
index 3f6cbf3..38b871f 100644
--- a/dangerzone/gui/main_window.py
+++ b/dangerzone/gui/main_window.py
@@ -605,17 +605,18 @@ class WaitingWidgetContainer(WaitingWidget):
)
elif platform.system() == "Linux":
# "not_running" here means that the `podman image ls` command failed.
- message = (
+ self.show_error(
"Dangerzone requires Podman
"
- "Podman is installed but cannot run properly. See errors below"
+ "Podman is installed but cannot run properly. See errors below",
+ error,
)
else:
- message = (
+ self.show_error(
"Dangerzone requires Docker Desktop
"
"Docker is installed but isn't running.
"
- "Open Docker and make sure it's running in the background."
+ "Open Docker and make sure it's running in the background.",
+ error,
)
- self.show_error(message, error)
else:
self.show_message(
"Installing the Dangerzone container image.
"
diff --git a/dangerzone/settings.py b/dangerzone/settings.py
index a10ad6b..a95917b 100644
--- a/dangerzone/settings.py
+++ b/dangerzone/settings.py
@@ -1,6 +1,7 @@
import json
import logging
import os
+from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict
from packaging import version
@@ -42,6 +43,15 @@ class Settings:
def custom_runtime_specified(self) -> bool:
return "container_runtime" in self.settings
+ def set_custom_runtime(self, runtime: str, autosave: bool = False) -> Path:
+ from .container_utils import Runtime # Avoid circular import
+
+ container_runtime = Runtime.path_from_name(runtime)
+ self.settings["container_runtime"] = str(container_runtime)
+ if autosave:
+ self.save()
+ return container_runtime
+
def get(self, key: str) -> Any:
return self.settings[key]
diff --git a/tests/test_container_utils.py b/tests/test_container_utils.py
index e7ee07e..db47b5a 100644
--- a/tests/test_container_utils.py
+++ b/tests/test_container_utils.py
@@ -49,7 +49,7 @@ def test_get_runtime_name_non_linux(mocker: MockerFixture, tmp_path: Path) -> No
assert Runtime().name == "docker"
-def test_get_unsupported_runtime_name(mocker: MockerFixture, tmp_path: Path):
+def test_get_unsupported_runtime_name(mocker: MockerFixture, tmp_path: Path) -> None:
mocker.patch("dangerzone.settings.get_config_dir", return_value=tmp_path)
settings = Settings()
settings.set(