From 3537f8e1d174f2ce422c9024a9e0d6df87ad9207 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 12 Apr 2021 18:43:04 +0200 Subject: Filter out the /outputs/ directory The issue here is that we copy all build results (packages) in the container to /outputs and then butido uses that directory to fetch the outputs of the build. But, because how the docker API works, we get a TAR stream from docker that _contains_ the /outputs directory. But of course, we don't want that. Until now, that was no issue. But it has become one now that we start adopting butido for our real-world scenarios. This patch adds filtering out that /outputs portion of the pathes from the tar archive when writing all the things to disc. Signed-off-by: Matthias Beyer Tested-by: Matthias Beyer --- doc/containers.md | 2 +- src/consts.rs | 1 + src/filestore/path.rs | 30 +++++++++++++++++++++++++++++- src/filestore/staging.rs | 29 +++++++++++++++++++++-------- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/doc/containers.md b/doc/containers.md index cbb62a0..52f4b4a 100644 --- a/doc/containers.md +++ b/doc/containers.md @@ -15,7 +15,7 @@ on. Those are listed here. 1. Dependencies are named `/inputs/-.pkg` inside the container 2. Sources are named `/inputs/src-.source` -3. Outputs are expected to be named `/outputs/-.pkg` +3. Outputs are expected to be written to the `/outputs` directory The reason for the names lies in the artifact parsing mechanism. If the package is named differently, the artifact parsing mechanism is not able diff --git a/src/consts.rs b/src/consts.rs index 8891f81..5c6dbc4 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -16,6 +16,7 @@ pub const INPUTS_DIR_PATH: &str = "/inputs"; /// The path to the directory inside the container where the outputs of a compile job must be /// located after the script was run pub const OUTPUTS_DIR_PATH: &str = "/outputs"; +pub const OUTPUTS_DIR_NAME: &str = "outputs"; /// The path where the script that is executed inside the container is copied to. pub const SCRIPT_PATH: &str = "/script"; diff --git a/src/filestore/path.rs b/src/filestore/path.rs index e8c7a26..3d74992 100644 --- a/src/filestore/path.rs +++ b/src/filestore/path.rs @@ -92,7 +92,35 @@ impl StoreRoot { where R: std::io::Read, { - ar.unpack(&self.0).map_err(Error::from) + ar.entries()? + .into_iter() + .map_err(Error::from) + .filter_ok(|entry| entry.header().entry_type() == tar::EntryType::Regular) + .and_then_ok(|mut entry| -> Result<_> { + let path = entry + .path() + .context("Getting path from entry in Archive")? + .components() + .filter(|comp| { + log::trace!("Filtering path component: '{:?}'", comp); + let osstr = std::ffi::OsStr::new(crate::consts::OUTPUTS_DIR_NAME); + match comp { + std::path::Component::Normal(s) => *s != osstr, + _ => true, + } + }) + .collect::(); + + log::trace!("Path = '{:?}'", path); + let unpack_dest = self.0.join(path); + log::trace!("Unpack to = '{:?}'", unpack_dest); + + entry.unpack(unpack_dest) + .map(|_| ()) + .map_err(Error::from) + }) + .collect::>>() + .map(|_| ()) } } diff --git a/src/filestore/staging.rs b/src/filestore/staging.rs index 73701cd..9f60d32 100644 --- a/src/filestore/staging.rs +++ b/src/filestore/staging.rs @@ -17,6 +17,9 @@ use anyhow::anyhow; use futures::stream::Stream; use indicatif::ProgressBar; use log::trace; +use resiter::AndThen; +use resiter::Filter; +use resiter::Map; use result_inspect::ResultInspect; use crate::filestore::path::ArtifactPath; @@ -54,15 +57,25 @@ impl StagingStore { .and_then(|bytes| { let mut archive = tar::Archive::new(&bytes[..]); - let outputs = archive - .entries() - .context("Fetching entries from tar archive")? - .map(|ent| { - let p = ent? + let outputs = archive.entries()? + .map_err(Error::from) + .filter_ok(|entry| entry.header().entry_type() == tar::EntryType::Regular) + .and_then_ok(|entry| { + let entry = entry .path() - .context("Getting path of TAR entry")? - .into_owned(); - Ok(p) + .context("Getting path from entry in Archive")? + .components() + .filter(|comp| { + log::trace!("Filtering path component: '{:?}'", comp); + let osstr = std::ffi::OsStr::new(crate::consts::OUTPUTS_DIR_NAME); + match comp { + std::path::Component::Normal(s) => *s != osstr, + _ => true, + } + }) + .collect::(); + + Ok(entry) }) .inspect(|p| trace!("Path in tar archive: {:?}", p)) .collect::>>() -- cgit v1.2.3