Skip to content

Commit 7577d1d

Browse files
committed
Support apple's container for docker lang
1 parent b48ee92 commit 7577d1d

File tree

3 files changed

+61
-19
lines changed

3 files changed

+61
-19
lines changed

crates/prek/src/languages/docker.rs

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ fn container_id_from_cgroup_v2(mount_info: impl AsRef<Path>) -> Result<String> {
111111
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
112112
enum RuntimeKind {
113113
Auto,
114+
AppleContainer,
114115
Docker,
115116
Podman,
116117
}
@@ -120,6 +121,7 @@ impl FromStr for RuntimeKind {
120121

121122
fn from_str(s: &str) -> Result<Self, Self::Err> {
122123
match s.to_ascii_lowercase().as_str() {
124+
"container" => Ok(RuntimeKind::AppleContainer),
123125
"docker" => Ok(RuntimeKind::Docker),
124126
"podman" => Ok(RuntimeKind::Podman),
125127
"auto" => Ok(RuntimeKind::Auto),
@@ -139,6 +141,7 @@ struct Mount {
139141
impl RuntimeKind {
140142
fn cmd(&self) -> &str {
141143
match self {
144+
RuntimeKind::AppleContainer => "container",
142145
RuntimeKind::Docker => "docker",
143146
RuntimeKind::Podman => "podman",
144147
RuntimeKind::Auto => unreachable!("Auto should be resolved before use"),
@@ -148,6 +151,7 @@ impl RuntimeKind {
148151
/// Detect if the current runtime is rootless.
149152
fn detect_rootless(self) -> Result<bool> {
150153
match self {
154+
RuntimeKind::AppleContainer => Ok(false),
151155
RuntimeKind::Docker => {
152156
let output = Command::new(self.cmd())
153157
.arg("info")
@@ -206,14 +210,16 @@ struct ContainerRuntimeInfo {
206210
impl ContainerRuntimeInfo {
207211
/// Detect container runtime provider, prioritise docker over podman if
208212
/// both are on the path, unless `PREK_CONTAINER_RUNTIME` is set to override detection.
209-
fn resolve_runtime_kind<DF, PF>(
213+
fn resolve_runtime_kind<DF, PF, CF>(
210214
env_override: Option<String>,
211215
docker_available: DF,
212216
podman_available: PF,
217+
apple_container_available: CF,
213218
) -> RuntimeKind
214219
where
215220
DF: Fn() -> bool,
216221
PF: Fn() -> bool,
222+
CF: Fn() -> bool,
217223
{
218224
if let Some(val) = env_override {
219225
match RuntimeKind::from_str(&val) {
@@ -243,6 +249,9 @@ impl ContainerRuntimeInfo {
243249
if podman_available() {
244250
return RuntimeKind::Podman;
245251
}
252+
if apple_container_available() {
253+
return RuntimeKind::AppleContainer;
254+
}
246255

247256
debug!("No container runtime found on PATH, defaulting to docker");
248257
RuntimeKind::Docker
@@ -253,6 +262,7 @@ impl ContainerRuntimeInfo {
253262
EnvVars::var(EnvVars::PREK_CONTAINER_RUNTIME).ok(),
254263
|| which::which("docker").is_ok(),
255264
|| which::which("podman").is_ok(),
265+
|| which::which("container").is_ok(),
256266
);
257267
let rootless = runtime.detect_rootless().unwrap_or_else(|e| {
258268
warn!("Failed to detect if container runtime is rootless: {e}, defaulting to rootful");
@@ -283,6 +293,10 @@ impl ContainerRuntimeInfo {
283293
self.runtime == RuntimeKind::Podman
284294
}
285295

296+
fn is_apple_container(&self) -> bool {
297+
self.runtime == RuntimeKind::AppleContainer
298+
}
299+
286300
/// Get the path of the current directory in the host.
287301
fn map_to_host_path<'a>(&self, path: &'a Path) -> Cow<'a, Path> {
288302
for mount in &self.mounts {
@@ -387,14 +401,21 @@ impl Docker {
387401
}
388402

389403
let work_dir = CONTAINER_RUNTIME.map_to_host_path(work_dir);
404+
let z = if CONTAINER_RUNTIME.is_apple_container() {
405+
"" // Not currently supported
406+
} else {
407+
",Z"
408+
};
409+
if !CONTAINER_RUNTIME.is_apple_container() {
410+
// Run an init inside the container that forwards signals and reaps processes
411+
command.arg("--init");
412+
}
390413
command
391-
// https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from
414+
// https://docs.docker.com/reference/cli/docker/container/run/#volumes-from
392415
// The `Z` option tells Docker to label the content with a private
393416
// unshared label. Only the current container can use a private volume.
394417
.arg("--volume")
395-
.arg(format!("{}:/src:rw,Z", work_dir.display()))
396-
// Run an init inside the container that forwards signals and reaps processes
397-
.arg("--init")
418+
.arg(format!("{}:/src:rw{}", work_dir.display(), z))
398419
.arg("--workdir")
399420
.arg("/src");
400421

@@ -673,52 +694,72 @@ mod tests {
673694
env_override: Option<&str>,
674695
docker_available: bool,
675696
podman_available: bool,
697+
apple_container_available: bool,
676698
) -> RuntimeKind {
677699
ContainerRuntimeInfo::resolve_runtime_kind(
678700
env_override.map(ToString::to_string),
679701
|| docker_available,
680702
|| podman_available,
703+
|| apple_container_available,
681704
)
682705
}
683706

684-
assert_eq!(runtime_with(None, true, false), RuntimeKind::Docker);
685-
assert_eq!(runtime_with(None, false, true), RuntimeKind::Podman);
686-
assert_eq!(runtime_with(None, false, false), RuntimeKind::Docker);
707+
assert_eq!(runtime_with(None, true, false, false), RuntimeKind::Docker);
708+
assert_eq!(runtime_with(None, false, true, false), RuntimeKind::Podman);
709+
assert_eq!(
710+
runtime_with(None, false, false, true),
711+
RuntimeKind::AppleContainer
712+
);
713+
assert_eq!(runtime_with(None, false, false, false), RuntimeKind::Docker);
687714

688-
assert_eq!(runtime_with(Some("auto"), true, false), RuntimeKind::Docker);
689-
assert_eq!(runtime_with(Some("auto"), false, true), RuntimeKind::Podman);
690715
assert_eq!(
691-
runtime_with(Some("auto"), false, false),
716+
runtime_with(Some("auto"), true, false, false),
717+
RuntimeKind::Docker
718+
);
719+
assert_eq!(
720+
runtime_with(Some("auto"), false, true, false),
721+
RuntimeKind::Podman
722+
);
723+
assert_eq!(
724+
runtime_with(Some("auto"), false, false, true),
725+
RuntimeKind::AppleContainer
726+
);
727+
assert_eq!(
728+
runtime_with(Some("auto"), false, false, false),
692729
RuntimeKind::Docker
693730
);
694731

695732
assert_eq!(
696-
runtime_with(Some("docker"), true, false),
733+
runtime_with(Some("docker"), true, false, false),
697734
RuntimeKind::Docker
698735
);
699736
assert_eq!(
700-
runtime_with(Some("docker"), false, true),
737+
runtime_with(Some("docker"), false, true, false),
701738
RuntimeKind::Docker
702739
);
703740
assert_eq!(
704-
runtime_with(Some("DOCKER"), false, false),
741+
runtime_with(Some("DOCKER"), false, false, false),
705742
RuntimeKind::Docker
706743
);
707744
assert_eq!(
708-
runtime_with(Some("podman"), true, false),
745+
runtime_with(Some("podman"), true, false, false),
709746
RuntimeKind::Podman
710747
);
711748
assert_eq!(
712-
runtime_with(Some("podman"), false, true),
749+
runtime_with(Some("podman"), false, true, false),
713750
RuntimeKind::Podman
714751
);
715752
assert_eq!(
716-
runtime_with(Some("podman"), false, false),
753+
runtime_with(Some("podman"), false, false, false),
717754
RuntimeKind::Podman
718755
);
756+
assert_eq!(
757+
runtime_with(Some("container"), true, true, false),
758+
RuntimeKind::AppleContainer
759+
);
719760

720761
assert_eq!(
721-
runtime_with(Some("invalid"), false, false),
762+
runtime_with(Some("invalid"), false, false, false),
722763
RuntimeKind::Docker
723764
);
724765
}

docs/configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ Prek supports the following environment variables:
221221
- `auto` (default, auto-detect available runtime)
222222
- `docker`
223223
- `podman`
224+
- `container`
224225

225226
Compatibility fallbacks:
226227

docs/diff.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Gems specified in hook gemspec files and `additional_dependencies` will be insta
7878

7979
### Docker & Docker Image
8080

81-
`prek` auto-detects the available container runtime on the system (Docker or Podman) and uses it to run container-based hooks. You can also explicitly specify the container runtime using the `PREK_CONTAINER_RUNTIME` environment variable.
81+
`prek` auto-detects the available container runtime on the system (Docker, Podman, or Container) and uses it to run container-based hooks. You can also explicitly specify the container runtime using the `PREK_CONTAINER_RUNTIME` environment variable.
8282

8383
## Command line interface
8484

0 commit comments

Comments
 (0)