Skip to content

Commit e1e277a

Browse files
authored
Update ImageName::as_path escaping for digest reference case (#134)
Add escape rule of image name into path for #128 case: ```text quay.io/jitesoft/alpine:sha256:6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c ``` will escape into ``` quay.io/jitesoft/alpine/__sha256__6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c ```
1 parent 060155a commit e1e277a

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

ocipkg/src/distribution/reference.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::fmt;
66
/// Reference of container image stored in the repository
77
///
88
/// In [OCI distribution spec](https://github.com/opencontainers/distribution-spec/blob/main/spec.md):
9-
/// > `<reference>` MUST be either (a) the digest of the manifest or (b) a tag
9+
/// > `<reference>` MUST be either (a) the digest of the manifest or (b) a tag
1010
/// > `<reference>` as a tag MUST be at most 128 characters
1111
/// > in length and MUST match the following regular expression:
1212
/// > ```text

ocipkg/src/image_name.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@ use url::Url;
7474
/// # Ok::<(), anyhow::Error>(())
7575
/// ```
7676
///
77+
/// [Reference] can be a digest:
78+
///
79+
/// ```text
80+
/// quay.io/jitesoft/alpine:sha256:6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c
81+
/// ^^^^^^^-------------------- hostname
82+
/// ^^^^^^^^^^^^^^^---- name
83+
/// reference ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
/// ```
85+
///
86+
/// ```
87+
/// use ocipkg::{ImageName, distribution::{Name, Reference}};
88+
/// let name = ImageName::parse("quay.io/jitesoft/alpine:sha256:6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c")?;
89+
/// assert_eq!(
90+
/// name,
91+
/// ImageName {
92+
/// hostname: "quay.io".to_string(),
93+
/// port: None,
94+
/// name: Name::new("jitesoft/alpine")?,
95+
/// reference: Reference::new("sha256:6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c")?,
96+
/// }
97+
/// );
98+
/// # Ok::<(), anyhow::Error>(())
99+
/// ```
100+
///
77101
/// Default values
78102
/// ---------------
79103
/// If `hostname` is absent, use `registry-1.docker.io` for docker compatibility:
@@ -175,13 +199,11 @@ impl ImageName {
175199

176200
/// Encode image name into a path by `{hostname}/{name}/__{reference}` or `{hostname}__{port}/{name}/__{reference}` if port is specified.
177201
pub fn as_path(&self) -> PathBuf {
202+
let reference = self.reference.replace(':', "__");
178203
PathBuf::from(if let Some(port) = self.port {
179-
format!(
180-
"{}__{}/{}/__{}",
181-
self.hostname, port, self.name, self.reference
182-
)
204+
format!("{}__{}/{}/__{}", self.hostname, port, self.name, reference)
183205
} else {
184-
format!("{}/{}/__{}", self.hostname, self.name, self.reference)
206+
format!("{}/{}/__{}", self.hostname, self.name, reference)
185207
})
186208
}
187209

@@ -217,9 +239,10 @@ impl ImageName {
217239
let name = Name::new(&components[1..n - 1].join("/"))?;
218240

219241
let reference = Reference::new(
220-
components[n - 1]
242+
&components[n - 1]
221243
.strip_prefix("__")
222-
.with_context(|| anyhow!("Missing tag in path: {}", path.display()))?,
244+
.with_context(|| anyhow!("Missing tag in path: {}", path.display()))?
245+
.replace("__", ":"),
223246
)?;
224247

225248
Ok(ImageName {
@@ -266,6 +289,10 @@ mod test {
266289
"registry-1.docker.io/ubuntu/__20.04".as_ref(),
267290
)?;
268291
test_as_path("alpine", "registry-1.docker.io/alpine/__latest".as_ref())?;
292+
test_as_path(
293+
"quay.io/jitesoft/alpine:sha256:6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c",
294+
"quay.io/jitesoft/alpine/__sha256__6755355f801f8e3694bffb1a925786813462cea16f1ce2b0290b6a48acf2500c".as_ref()
295+
)?;
269296
Ok(())
270297
}
271298
}

0 commit comments

Comments
 (0)