allow loading multiple from archives
All checks were successful
CI / build (push) Successful in 44s
CI / checks (push) Successful in 1m11s
CI / build-nixpkgs (push) Successful in 36s

This commit is contained in:
Robin Appelman 2025-09-27 14:31:55 +02:00
commit b62b0a8d8e
2 changed files with 35 additions and 30 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@ result
*.log
profile.*
*.out.*
/logs

View file

@ -7,7 +7,7 @@ use crate::logfile::archive::RarArchive;
use crate::logfile::archive::{Archive, ArchiveEntry, SevenZipArchive, TarArchive, ZipArchive};
use bzip2_rs::DecoderReader;
use csv::Reader;
use dialoguer::Select;
use dialoguer::MultiSelect;
use flate2::read::GzDecoder;
pub use logline::{LineNumber, LogLine};
use ruzstd::decoding::StreamingDecoder;
@ -44,15 +44,15 @@ impl LogFile {
pub fn open<R: Read + Seek>(path: &str, file: R) -> Result<LogFile, ReadError> {
if path.ends_with(".zip") {
let mut zip = ZipArchive::new(file)?;
return select_file(&mut zip);
return select_files(&mut zip);
} else if path.ends_with(".7z") {
let mut zip = SevenZipArchive::new(file)?;
return select_file(&mut zip);
return select_files(&mut zip);
} else if path.ends_with(".rar") {
#[cfg(all(unix, not(target_env = "musl")))]
{
let mut rar = RarArchive::new(path)?;
return select_file(&mut rar);
return select_files(&mut rar);
}
#[cfg(target_env = "musl")]
return Err(ReadError::UnSupportedFormat {
@ -100,7 +100,7 @@ impl LogFile {
fn open_no_seek<R: Read>(path: &str, mut file: R) -> Result<LogFile, ReadError> {
if path.ends_with(".tar") {
let mut zip = TarArchive::new(file)?;
select_file(&mut zip)
select_files(&mut zip)
} else {
let mut content = String::new();
file.read_to_string(&mut content)?;
@ -132,32 +132,36 @@ impl LogFile {
}
}
fn select_file<A: Archive>(archive: &mut A) -> Result<LogFile, ReadError> {
let entry = {
let mut entries = archive
.entries()
.filter(|entry| !entry.name().starts_with("__MACOSX") && !entry.name().ends_with('/'))
.collect::<Vec<_>>();
fn select_files<A: Archive>(archive: &mut A) -> Result<LogFile, ReadError> {
let entries = archive
.entries()
.filter(|entry| !entry.name().starts_with("__MACOSX") && !entry.name().ends_with('/'))
.collect::<Vec<_>>();
if entries.is_empty() {
return Err(ReadError::NoFiles);
}
if entries.is_empty() {
return Err(ReadError::NoFiles);
}
let index = if entries.len() == 1 {
0usize
} else {
let names = entries.iter().map(A::Entry::name).collect::<Vec<_>>();
Select::new()
.with_prompt("Select file to load?")
.items(&names)
.interact()
.unwrap()
};
entries.remove(index)
let indices = if entries.len() == 1 {
vec![0usize]
} else {
let names = entries.iter().map(A::Entry::name).collect::<Vec<_>>();
MultiSelect::new()
.with_prompt("Select file(s) to load?")
.items(&names)
.interact()
.unwrap()
};
let name = entry.name().to_string();
let raw = entry.extract()?;
LogFile::open(&name, Cursor::new(raw))
let mut files = Vec::new();
for (index, entry) in entries.into_iter().enumerate() {
if indices.contains(&index) {
let name = entry.name().to_string();
let raw = entry.extract()?;
files.push(LogFile::open(&name, Cursor::new(raw))?);
}
}
Ok(LogFile::merge(files))
}