diff --git a/Cargo.toml b/Cargo.toml index f376766..900f0f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ termion = "3.0.0" thiserror = "1.0" tokio-listener = "0.3.1" tokio-native-tls = "0.3.1" -tokio-tar = "0.3.1" +tokio-tar = { git = "https://github.com/edera-dev/tokio-tar.git", branch = "edera" } tokio-tun = "0.11.2" tonic-build = "0.11.0" tower = "0.4.13" diff --git a/crates/kratart/src/image/compiler.rs b/crates/kratart/src/image/compiler.rs index cc3ca9a..45ef050 100644 --- a/crates/kratart/src/image/compiler.rs +++ b/crates/kratart/src/image/compiler.rs @@ -109,17 +109,16 @@ impl ImageCompiler<'_> { } let local = downloader.download(resolved).await?; - for layer in local.layers { + for layer in &local.layers { debug!( "process layer digest={} compression={:?}", - &layer.digest, layer.compression + &layer.digest, layer.compression, ); + self.process_layer_whiteout(layer, image_dir).await?; let mut archive = layer.archive().await?; - let mut entries = archive.entries()?; while let Some(entry) = entries.next().await { - let mut entry: Entry>>> = - entry?; + let mut entry = entry?; let path = entry.path()?; let Some(name) = path.file_name() else { return Err(anyhow!("unable to get file name")); @@ -129,14 +128,18 @@ impl ImageCompiler<'_> { }; if name.starts_with(".wh.") { - self.process_whiteout_entry(&entry, name, &layer, image_dir) - .await?; + continue; } else { - self.process_write_entry(&mut entry, &layer, image_dir) + self.process_write_entry(&mut entry, layer, image_dir) .await?; } } - fs::remove_file(&layer.path).await?; + } + + for layer in &local.layers { + if layer.path.exists() { + fs::remove_file(&layer.path).await?; + } } self.squash(image_dir, squash_file)?; @@ -148,6 +151,27 @@ impl ImageCompiler<'_> { self.cache.store(&cache_digest, &info).await } + async fn process_layer_whiteout(&self, layer: &OciImageLayer, image_dir: &Path) -> Result<()> { + let mut archive = layer.archive().await?; + let mut entries = archive.entries()?; + while let Some(entry) = entries.next().await { + let entry = entry?; + let path = entry.path()?; + let Some(name) = path.file_name() else { + return Err(anyhow!("unable to get file name")); + }; + let Some(name) = name.to_str() else { + return Err(anyhow!("unable to get file name as string")); + }; + + if name.starts_with(".wh.") { + self.process_whiteout_entry(&entry, name, layer, image_dir) + .await?; + } + } + Ok(()) + } + async fn process_whiteout_entry( &self, entry: &Entry>>>, @@ -162,7 +186,7 @@ impl ImageCompiler<'_> { let opaque = name == ".wh..wh..opq"; if !opaque { - dst.push(name); + dst.push(&name[4..]); self.check_safe_path(&dst, image_dir)?; } @@ -187,7 +211,7 @@ impl ImageCompiler<'_> { } } else { warn!( - "whiteout entry missing locally layer={} path={:?} local={:?}", + "whiteout opaque entry missing locally layer={} path={:?} local={:?}", &layer.digest, entry.path()?, dst, @@ -196,7 +220,7 @@ impl ImageCompiler<'_> { } else if dst.is_file() || dst.is_symlink() { fs::remove_file(&dst).await?; } else if dst.is_dir() { - fs::remove_dir(&dst).await?; + fs::remove_dir_all(&dst).await?; } else { warn!( "whiteout entry missing locally layer={} path={:?} local={:?}",