use async_bagit::{Algorithm, BagIt, ChecksumAlgorithm};
use async_compression::tokio::bufread::ZstdDecoder;
use sha2::Sha256;
use tokio::{
fs::File,
io::{AsyncBufReadExt, BufReader},
};
use tokio_tar::Archive;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let archive_path = args
.get(1)
.expect("CLI argument representing path to archive contaning bag");
let temp_directory = async_tempfile::TempDir::new().await.unwrap();
let temp_directory = temp_directory.to_path_buf();
println!("Reading archive `{}`", archive_path);
let archive_file = File::open(archive_path).await?;
let archive_reader = BufReader::new(archive_file);
let archive_decoder = ZstdDecoder::new(archive_reader);
Archive::new(archive_decoder)
.unpack(&temp_directory)
.await?;
let algorithm = ChecksumAlgorithm::<Sha256>::new(Algorithm::Sha256);
let bag_it = BagIt::read_existing(temp_directory.join("sample-bag"), &algorithm).await?;
for payload in bag_it.payload_items() {
println!(
"Payload `{}` is in the bag with hash `{}`",
payload.relative_path().display(),
payload.checksum()
);
}
println!("Finding file `bagit.md` and showing its first 5 lines\n===============");
let bagit_dot_md = bag_it
.payload_items()
.find(|payload| {
payload
.relative_path()
.file_name()
.and_then(|file_name| file_name.to_str())
== Some("bagit.md")
})
.ok_or(Box::<dyn std::error::Error>::from(
"failed to find payload named `bagit.md` in bag",
))?;
let markdown_file = File::open(bagit_dot_md.absolute_path(&bag_it)).await?;
let markdown_reader = BufReader::new(markdown_file);
let mut lines = markdown_reader.lines();
let mut display = String::new();
for _ in 0..5 {
if let Some(line) = lines.next_line().await? {
display.push_str(&line);
display.push('\n');
} else {
break;
}
}
print!("{}", display);
println!("===============\nBye!");
Ok(())
}