mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 03:55:28 +00:00
101 lines
2.7 KiB
Rust
101 lines
2.7 KiB
Rust
//! Contains Tar-specific building and unpacking functions
|
|
|
|
use std::{
|
|
env,
|
|
io::prelude::*,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
use fs_err as fs;
|
|
use tar;
|
|
use walkdir::WalkDir;
|
|
|
|
use crate::{
|
|
error::FinalError,
|
|
info,
|
|
list::FileInArchive,
|
|
utils::{self, Bytes},
|
|
QuestionPolicy,
|
|
};
|
|
|
|
/// Unpacks the archive given by `archive` into the folder given by `into`.
|
|
pub fn unpack_archive(
|
|
reader: Box<dyn Read>,
|
|
output_folder: &Path,
|
|
question_policy: QuestionPolicy,
|
|
) -> crate::Result<Vec<PathBuf>> {
|
|
let mut archive = tar::Archive::new(reader);
|
|
|
|
let mut files_unpacked = vec![];
|
|
for file in archive.entries()? {
|
|
let mut file = file?;
|
|
|
|
let file_path = output_folder.join(file.path()?);
|
|
if utils::clear_path(&file_path, question_policy)?.is_none() {
|
|
// User doesn't want to overwrite
|
|
continue;
|
|
}
|
|
|
|
file.unpack_in(output_folder)?;
|
|
|
|
info!("{:?} extracted. ({})", output_folder.join(file.path()?), Bytes::new(file.size()));
|
|
|
|
files_unpacked.push(file_path);
|
|
}
|
|
|
|
Ok(files_unpacked)
|
|
}
|
|
|
|
/// List contents of `archive`, returning a vector of archive entries
|
|
pub fn list_archive(reader: Box<dyn Read>) -> crate::Result<Vec<FileInArchive>> {
|
|
let mut archive = tar::Archive::new(reader);
|
|
|
|
let mut files = vec![];
|
|
for file in archive.entries()? {
|
|
let file = file?;
|
|
|
|
let path = file.path()?.into_owned();
|
|
let is_dir = file.header().entry_type().is_dir();
|
|
|
|
files.push(FileInArchive { path, is_dir });
|
|
}
|
|
|
|
Ok(files)
|
|
}
|
|
|
|
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`.
|
|
pub fn build_archive_from_paths<W>(input_filenames: &[PathBuf], writer: W) -> crate::Result<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
let mut builder = tar::Builder::new(writer);
|
|
|
|
for filename in input_filenames {
|
|
let previous_location = utils::cd_into_same_dir_as(filename)?;
|
|
|
|
// Safe unwrap, input shall be treated before
|
|
let filename = filename.file_name().unwrap();
|
|
|
|
for entry in WalkDir::new(&filename) {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
|
|
info!("Compressing '{}'.", utils::to_utf(path));
|
|
|
|
if path.is_dir() {
|
|
builder.append_dir(path, path)?;
|
|
} else {
|
|
let mut file = fs::File::open(path)?;
|
|
builder.append_file(path, file.file_mut()).map_err(|err| {
|
|
FinalError::with_title("Could not create archive")
|
|
.detail("Unexpected error while trying to read file")
|
|
.detail(format!("Error: {}.", err))
|
|
})?;
|
|
}
|
|
}
|
|
env::set_current_dir(previous_location)?;
|
|
}
|
|
|
|
Ok(builder.into_inner()?)
|
|
}
|