List command: print file immediatly after it iss processed

This commit is contained in:
Nbiba Bedis 2021-12-08 13:29:10 +01:00
parent 9c3446924c
commit 2adcfb364f
4 changed files with 40 additions and 27 deletions

View File

@ -47,20 +47,23 @@ pub fn unpack_archive(
} }
/// List contents of `archive`, returning a vector of archive entries /// List contents of `archive`, returning a vector of archive entries
pub fn list_archive(reader: Box<dyn Read>) -> crate::Result<Vec<FileInArchive>> { pub fn list_archive(
let mut archive = tar::Archive::new(reader); archive: tar::Archive<impl Read + 'static>,
) -> crate::Result<impl Iterator<Item = crate::Result<FileInArchive>>> {
// NOTE: tar::Archive::entries takes a &mut self
// This makes returning an iterator impossible
// Current workaround is just to leak the archive
// This can be replaced when upstream add `into_entries` function that consumes the archive
let archive = Box::leak(Box::new(archive));
let mut files = vec![]; Ok(archive.entries()?.map(|file| {
for file in archive.entries()? {
let file = file?; let file = file?;
let path = file.path()?.into_owned(); let path = file.path()?.into_owned();
let is_dir = file.header().entry_type().is_dir(); let is_dir = file.header().entry_type().is_dir();
files.push(FileInArchive { path, is_dir }); Ok(FileInArchive { path, is_dir })
} }))
Ok(files)
} }
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`. /// Compresses the archives given by `input_filenames` into the file given previously to `writer`.

View File

@ -80,23 +80,24 @@ where
} }
/// List contents of `archive`, returning a vector of archive entries /// List contents of `archive`, returning a vector of archive entries
pub fn list_archive<R>(mut archive: ZipArchive<R>) -> crate::Result<Vec<FileInArchive>> pub fn list_archive<R>(mut archive: ZipArchive<R>) -> impl Iterator<Item = crate::Result<FileInArchive>>
where where
R: Read + Seek, R: Read + Seek + 'static,
{ {
let mut files = vec![]; (0..archive.len()).filter_map(move |idx| {
for idx in 0..archive.len() { let file = match archive.by_index(idx) {
let file = archive.by_index(idx)?; Ok(f) => f,
Err(e) => return Some(Err(e.into())),
};
let path = match file.enclosed_name() { let path = match file.enclosed_name() {
Some(path) => path.to_owned(), Some(path) => path.to_owned(),
None => continue, None => return None,
}; };
let is_dir = file.is_dir(); let is_dir = file.is_dir();
files.push(FileInArchive { path, is_dir }); Some(Ok(FileInArchive { path, is_dir }))
} })
Ok(files)
} }
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`. /// Compresses the archives given by `input_filenames` into the file given previously to `writer`.

View File

@ -20,7 +20,7 @@ use crate::{
Extension, Extension,
}, },
info, info,
list::{self, ListOptions}, list::{self, FileInArchive, ListOptions},
progress::Progress, progress::Progress,
utils::{ utils::{
self, concatenate_os_str_list, dir_is_empty, nice_directory_display, to_utf, try_infer_extension, self, concatenate_os_str_list, dir_is_empty, nice_directory_display, to_utf, try_infer_extension,
@ -580,8 +580,9 @@ fn list_archive_contents(
// Any other Zip decompression done can take up the whole RAM and freeze ouch. // Any other Zip decompression done can take up the whole RAM and freeze ouch.
if let [Zip] = *formats.as_slice() { if let [Zip] = *formats.as_slice() {
let zip_archive = zip::ZipArchive::new(reader)?; let zip_archive = zip::ZipArchive::new(reader)?;
let files = crate::archive::zip::list_archive(zip_archive)?; let files = crate::archive::zip::list_archive(zip_archive);
list::list_files(archive_path, files, list_options); list::list_files(archive_path, files, list_options)?;
return Ok(()); return Ok(());
} }
@ -607,8 +608,8 @@ fn list_archive_contents(
reader = chain_reader_decoder(format, reader)?; reader = chain_reader_decoder(format, reader)?;
} }
let files = match formats[0] { let files: Box<dyn Iterator<Item = crate::Result<FileInArchive>>> = match formats[0] {
Tar => crate::archive::tar::list_archive(reader)?, Tar => Box::new(crate::archive::tar::list_archive(tar::Archive::new(reader))?),
Zip => { Zip => {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET); eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!( eprintln!(
@ -626,13 +627,13 @@ fn list_archive_contents(
io::copy(&mut reader, &mut vec)?; io::copy(&mut reader, &mut vec)?;
let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?; let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?;
crate::archive::zip::list_archive(zip_archive)? Box::new(crate::archive::zip::list_archive(zip_archive))
} }
Gzip | Bzip | Lz4 | Lzma | Snappy | Zstd => { Gzip | Bzip | Lz4 | Lzma | Snappy | Zstd => {
panic!("Not an archive! This should never happen, if it does, something is wrong with `CompressionFormat::is_archive()`. Please report this error!"); panic!("Not an archive! This should never happen, if it does, something is wrong with `CompressionFormat::is_archive()`. Please report this error!");
} }
}; };
list::list_files(archive_path, files, list_options); list::list_files(archive_path, files, list_options)?;
Ok(()) Ok(())
} }

View File

@ -22,16 +22,24 @@ pub struct FileInArchive {
} }
/// Actually print the files /// Actually print the files
pub fn list_files(archive: &Path, files: Vec<FileInArchive>, list_options: ListOptions) { /// Returns an Error, if one of the files can't be read
pub fn list_files(
archive: &Path,
files: impl IntoIterator<Item = crate::Result<FileInArchive>>,
list_options: ListOptions,
) -> crate::Result<()> {
println!("Archive: {}", archive.display()); println!("Archive: {}", archive.display());
if list_options.tree { if list_options.tree {
let tree: Tree = files.into_iter().collect(); let tree: Tree = files.into_iter().collect::<crate::Result<Tree>>()?;
tree.print(); tree.print();
} else { } else {
for FileInArchive { path, is_dir } in files { for file in files {
let FileInArchive { path, is_dir } = file?;
print_entry(path.display(), is_dir); print_entry(path.display(), is_dir);
} }
} }
Ok(())
} }
/// Print an entry and highlight directories, either by coloring them /// Print an entry and highlight directories, either by coloring them