use anyhow::{anyhow, Context, Result};
use std::path::PathBuf;
use std::process::Command;
use tempfile::TempDir;
use super::Source;
use crate::notifier::Notifier;
pub struct NerdctlSource;
impl NerdctlSource {
pub fn new() -> Result<Self> {
let output = Command::new("nerdctl")
.arg("--version")
.output()
.context("Failed to execute nerdctl command. Is nerdctl installed?")?;
if !output.status.success() {
return Err(anyhow!("nerdctl is not available"));
}
Ok(Self)
}
}
impl Source for NerdctlSource {
fn name(&self) -> &str {
"nerdctl"
}
fn get_image_tarball(
&self,
_image_name: &str,
_notifier: &Notifier,
) -> Result<(PathBuf, Option<TempDir>)> {
unimplemented!("nerdctl support is not yet implemented")
}
fn branch_name(&self, image_name: &str, os_arch: &str, image_digest: &str) -> String {
let normalized = if !image_name.contains(':') && !image_name.contains('@') {
format!("{image_name}:latest")
} else {
image_name.to_string()
};
let base_branch = normalized
.replace(":", "#")
.replace("/", "-")
.replace("@", "-");
if let Some(short_digest) = super::extract_short_digest(image_digest) {
format!("{base_branch}#{os_arch}#{short_digest}")
} else {
format!("{base_branch}#{os_arch}#{image_digest}")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nerdctl_source_branch_name() {
let source = NerdctlSource;
assert_eq!(
source.branch_name(
"hello-world:latest",
"linux-amd64",
"sha256:1234567890abcdef"
),
"hello-world#latest#linux-amd64#1234567890ab"
);
assert_eq!(
source.branch_name("hello-world", "linux-arm64", "sha256:1234567890abcdef"),
"hello-world#latest#linux-arm64#1234567890ab"
);
assert_eq!(
source.branch_name("nginx/nginx:1.21", "linux-amd64", "sha256:9876543210fedcba"),
"nginx-nginx#1.21#linux-amd64#9876543210fe"
);
assert_eq!(
source.branch_name("nginx", "windows-amd64", "sha256:abcdef123456789"),
"nginx#latest#windows-amd64#abcdef123456"
);
assert_eq!(
source.branch_name("nginx", "linux-amd64", "abcdef123456789"),
"nginx#latest#linux-amd64#abcdef123456789"
);
}
}