Skip to content

Commit

Permalink
ok it might even run correctly now?
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Aug 26, 2024
1 parent 93c3bb9 commit d4b1b13
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 104 deletions.
31 changes: 26 additions & 5 deletions cli/src/extract.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
borrow::Cow,
cell::RefCell,
io::{self, Read, Write},
io::{Read, Write},
rc::Rc,
};

Expand All @@ -13,7 +13,7 @@ mod receiver;
mod transform;
use entries::IterateEntries;
use matcher::EntryMatcher;
use receiver::{CompiledEntrySpec, ConcatEntry, EntryData, EntryReceiver, ExtractEntry};
use receiver::{CompiledEntrySpec, ConcatEntry, EntryData, EntryKind, EntryReceiver, ExtractEntry};
use transform::NameTransformer;

pub fn execute_extract(mut err: impl Write, extract: Extract) -> Result<(), CommandError> {
Expand All @@ -29,6 +29,22 @@ pub fn execute_extract(mut err: impl Write, extract: Extract) -> Result<(), Comm
let mut copy_buf: Vec<u8> = vec![0u8; 1024 * 16];

while let Some(mut entry) = entry_iterator.next_entry()? {
let symlink_target: Option<Vec<u8>> = {
let (kind, size) = {
let data = EntryData::from_entry(&entry);
(data.kind, data.size)
};
match kind {
EntryKind::Symlink => {
let mut target: Vec<u8> = Vec::with_capacity(size.try_into().unwrap());
entry
.read_to_end(&mut target)
.wrap_err("failed to read symlink target from zip archive entry")?;
Some(target)
}
_ => None,
}
};
let data = EntryData::from_entry(&entry);

let mut matching_concats: Vec<Rc<RefCell<dyn Write>>> = Vec::new();
Expand Down Expand Up @@ -86,10 +102,15 @@ pub fn execute_extract(mut err: impl Write, extract: Extract) -> Result<(), Comm

let mut matching_handles: Vec<Box<dyn Write>> = deduped_matching_extracts
.into_iter()
.map(|(name, recv)| recv.generate_entry_handle(name))
.collect::<Result<_, _>>()?;
.map(|(name, recv)| {
recv.generate_entry_handle(data, symlink_target.as_ref().map(|t| t.as_ref()), name)
})
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect();

let mut read_len: usize = 0;
let mut read_len: usize;
loop {
read_len = entry.read(&mut copy_buf).wrap_err("read of entry failed")?;
if read_len == 0 {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/extract/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::Path;
use glob;
use regex;

use zip::{read::ZipFile, CompressionMethod};
use zip::CompressionMethod;

use super::receiver::{EntryData, EntryKind};
use crate::{args::extract::*, CommandError};
Expand Down
181 changes: 90 additions & 91 deletions cli/src/extract/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::{
borrow::Cow,
cell::RefCell,
collections::{HashMap, HashSet},
env, fs,
io::{self, Read, Seek, Write},
fs,
io::{self, Seek, Write},
mem,
path::PathBuf,
rc::Rc,
Expand Down Expand Up @@ -60,9 +60,9 @@ impl OutputName {
}

pub struct ParsedEntrySpecArg {
matcher: Option<CompiledMatcher>,
transforms: Option<CompiledTransformer>,
output_name: OutputName,
pub matcher: Option<CompiledMatcher>,
pub transforms: Option<CompiledTransformer>,
pub output_name: OutputName,
}

impl ParsedEntrySpecArg {
Expand Down Expand Up @@ -119,11 +119,17 @@ pub fn process_entry_and_output_specs(
entry_specs: impl IntoIterator<Item = EntrySpec>,
output_specs: OutputSpecs,
) -> Result<Vec<CompiledEntrySpec>, CommandError> {
let entry_specs: Vec<ParsedEntrySpecArg> = entry_specs
let mut entry_specs: Vec<ParsedEntrySpecArg> = entry_specs
.into_iter()
.map(ParsedEntrySpecArg::from_entry_spec)
.collect::<Result<_, _>>()?;
assert!(!entry_specs.is_empty());
if entry_specs.is_empty() {
entry_specs.push(ParsedEntrySpecArg {
matcher: None,
transforms: None,
output_name: OutputName::default_name(),
});
}
let parsed_outputs = ParsedNamedOutputs::from_output_specs(output_specs)?;
parsed_outputs.process_entry_specs_for_outputs(entry_specs)
}
Expand Down Expand Up @@ -357,8 +363,12 @@ impl ParsedNamedOutputs {
}

pub trait EntryReceiver {
fn generate_entry_handle<'s>(&self, name: Cow<'s, str>)
-> Result<Box<dyn Write>, CommandError>;
fn generate_entry_handle<'s>(
&self,
data: EntryData<'s>,
symlink_target: Option<&[u8]>,
name: Cow<'s, str>,
) -> Result<Option<Box<dyn Write>>, CommandError>;

fn finalize_entries(&self) -> Result<(), CommandError>;
}
Expand All @@ -382,90 +392,79 @@ impl FilesystemReceiver {
impl EntryReceiver for FilesystemReceiver {
fn generate_entry_handle<'s>(
&self,
data: EntryData<'s>,
symlink_target: Option<&[u8]>,
name: Cow<'s, str>,
) -> Result<Box<dyn Write>, CommandError> {
todo!("wow!")
}
) -> Result<Option<Box<dyn Write>>, CommandError> {
/* let mut err = self.err.borrow_mut(); */
let full_output_path = self.output_dir.join(name.as_ref());
/* writeln!( */
/* err, */
/* "receiving entry {} with name {name} and writing to path {full_output_path:?}", */
/* entry.name() */
/* ) */
/* .unwrap(); */

#[cfg(unix)]
if let Some(mode) = data.unix_mode {
/* writeln!( */
/* err, */
/* "storing unix mode {mode} for path {full_output_path:?}" */
/* ) */
/* .unwrap(); */
self.perms_to_set
.borrow_mut()
.push((full_output_path.clone(), mode));
}

/* fn receive_entry<'a>( */
/* &mut self, */
/* entry: &mut ZipFile<'a>, */
/* name: &str, */
/* ) -> Result<(), CommandError> { */
/* let mut err = self.err.borrow_mut(); */
/* let full_output_path = self.output_dir.join(name); */
/* writeln!( */
/* err, */
/* "receiving entry {} with name {name} and writing to path {full_output_path:?}", */
/* entry.name() */
/* ) */
/* .unwrap(); */

/* #[cfg(unix)] */
/* if let Some(mode) = entry.unix_mode() { */
/* writeln!( */
/* err, */
/* "storing unix mode {mode} for path {full_output_path:?}" */
/* ) */
/* .unwrap(); */
/* self.perms_to_set */
/* .borrow_mut() */
/* .push((full_output_path.clone(), mode)); */
/* } */

/* if entry.is_dir() { */
/* writeln!(err, "entry is directory, creating").unwrap(); */
/* fs::create_dir_all(&full_output_path).wrap_err_with(|| { */
/* format!("failed to create directory entry at {full_output_path:?}") */
/* })?; */
/* } else if entry.is_symlink() { */
/* let mut target: Vec<u8> = Vec::with_capacity(entry.size().try_into().unwrap()); */
/* entry.read_to_end(&mut target).wrap_err_with(|| { */
/* format!( */
/* "failed to read symlink target from zip archive entry {}", */
/* entry.name() */
/* ) */
/* })?; */

/* #[cfg(unix)] */
/* { */
/* use std::{ */
/* ffi::OsString, */
/* os::unix::{ffi::OsStringExt, fs::symlink}, */
/* }; */
/* let target = OsString::from_vec(target); */
/* writeln!(err, "entry is symlink to {target:?}, creating").unwrap(); */
/* symlink(&target, &full_output_path).wrap_err_with(|| { */
/* format!( */
/* "failed to create symlink at {full_output_path:?} with target {target:?}" */
/* ) */
/* })?; */
/* } */
/* #[cfg(not(unix))] */
/* { */
/* /\* FIXME: non-unix symlink extraction not yet supported! *\/ */
/* todo!("TODO: cannot create symlink for entry {name} on non-unix yet!"); */
/* } */
/* } else { */
/* writeln!(err, "entry is file, creating").unwrap(); */
/* if let Some(containing_dir) = full_output_path.parent() { */
/* fs::create_dir_all(containing_dir).wrap_err_with(|| { */
/* format!("failed to create parent dirs for file at {full_output_path:?}") */
/* })?; */
/* } else { */
/* writeln!(err, "entry had no parent dir (in root dir?)").unwrap(); */
/* } */
/* let mut outfile = fs::File::create(&full_output_path) */
/* .wrap_err_with(|| format!("failed to create file at {full_output_path:?}"))?; */
/* io::copy(entry, &mut outfile).wrap_err_with(|| { */
/* format!( */
/* "failed to copy file contents from {} to {full_output_path:?}", */
/* entry.name() */
/* ) */
/* })?; */
/* } */
/* Ok(()) */
/* } */
match data.kind {
EntryKind::Dir => {
/* writeln!(err, "entry is directory, creating").unwrap(); */
fs::create_dir_all(&full_output_path).wrap_err_with(|| {
format!("failed to create directory entry at {full_output_path:?}")
})?;
}
EntryKind::Symlink => {
let target: Vec<u8> = symlink_target
.expect("we should have generated this")
.to_vec();

#[cfg(unix)]
{
use std::{
ffi::OsString,
os::unix::{ffi::OsStringExt, fs::symlink},
};
let target = OsString::from_vec(target);
/* writeln!(err, "entry is symlink to {target:?}, creating").unwrap(); */
symlink(&target, &full_output_path).wrap_err_with(|| {
format!(
"failed to create symlink at {full_output_path:?} with target {target:?}"
)
})?;
}
#[cfg(not(unix))]
{
/* FIXME: non-unix symlink extraction not yet supported! */

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
todo!("TODO: cannot create symlink for entry {name} on non-unix yet!");

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
}
}
EntryKind::File => {
/* writeln!(err, "entry is file, creating").unwrap(); */
if let Some(containing_dir) = full_output_path.parent() {
fs::create_dir_all(containing_dir).wrap_err_with(|| {
format!("failed to create parent dirs for file at {full_output_path:?}")
})?;
} else {
/* writeln!(err, "entry had no parent dir (in root dir?)").unwrap(); */
}
let outfile = fs::File::create(&full_output_path)
.wrap_err_with(|| format!("failed to create file at {full_output_path:?}"))?;
return Ok(Some(Box::new(outfile)));
}
}
Ok(None)
}

fn finalize_entries(&self) -> Result<(), CommandError> {
#[cfg(unix)]
Expand Down
7 changes: 0 additions & 7 deletions cli/src/extract/transform.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
use std::{borrow::Cow, collections::VecDeque};

use zip::read::ZipFile;

use crate::{args::extract::*, CommandError};

use super::{
matcher::process_component_selector,
receiver::{EntryData, EntryReceiver},
};

pub trait NameTransformer {
type Arg
where
Expand Down

0 comments on commit d4b1b13

Please sign in to comment.