Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions benches/bench_tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ fn build_archive(archive_path: &Path, source_dir: &Path) {
&refs,
true,
false,
true,
CompressionMode::None,
)
.unwrap();
Expand Down Expand Up @@ -76,6 +77,7 @@ fn create_archive_10_files(bencher: divan::Bencher) {
&refs,
true,
false,
true,
CompressionMode::None,
)
.unwrap();
Expand All @@ -101,6 +103,7 @@ fn create_archive_100_files(bencher: divan::Bencher) {
&refs,
true,
false,
true,
CompressionMode::None,
)
.unwrap();
Expand All @@ -126,6 +129,7 @@ fn create_archive_directory(bencher: divan::Bencher) {
&[sub.as_path()],
true,
false,
true,
CompressionMode::None,
)
.unwrap();
Expand Down
30 changes: 21 additions & 9 deletions src/uu/tar/src/operations/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use uucore::error::UResult;
/// * `files` - Slice of file paths to add to the archive
/// * `allow_absolute` - Allow absolute paths while creating archive
/// * `verbose` - Whether to print verbose output during creation
/// * `recursive` - Whether to add the contents of directories, not only the directories themselves
///
/// # Errors
///
Expand All @@ -35,6 +36,7 @@ pub fn create_archive(
files: &[&Path],
allow_absolute: bool,
verbose: bool,
recursive: bool,
compression: CompressionMode,
) -> UResult<()> {
let output = BufWriter::new(output);
Expand All @@ -56,18 +58,23 @@ pub fn create_archive(
}

if verbose {
print_verbose_tree(&mut status_output, path)?;
print_verbose_tree(&mut status_output, path, recursive)?;
}

let normalized_name = get_normalized_path(path, allow_absolute)?;

// If it's a directory, recursively add all contents
if path.is_dir() {
builder.append_dir_all(normalized_name, path).map_err(|e| {
TarError::CannotAddDirectory {
path: path.to_path_buf(),
source: e,
}
if recursive {
// If it's a directory, recursively add all contents
builder.append_dir_all(normalized_name, path)
} else {
// --no-recursion: the directory entry only, named with a trailing
// slash like the top directory added by append_dir_all
builder.append_dir(normalized_name.join(""), path)
}
.map_err(|e| TarError::CannotAddDirectory {
path: path.to_path_buf(),
source: e,
})?;
} else {
// For files, add them directly
Expand All @@ -90,8 +97,13 @@ pub fn create_archive(
Ok(())
}

fn print_verbose_tree(status_output: &mut impl Write, path: &Path) -> UResult<()> {
let to_print = get_tree(path)?
fn print_verbose_tree(status_output: &mut impl Write, path: &Path, recursive: bool) -> UResult<()> {
let tree = if recursive {
get_tree(path)?
} else {
vec![path.to_path_buf()]
};
let to_print = tree
.iter()
.map(|p| (p.is_dir(), p.display().to_string()))
.map(|(is_dir, path)| {
Expand Down
4 changes: 4 additions & 0 deletions src/uu/tar/src/operations/create_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn test_create_archive_flush_failed() {
&[file_path.as_path()],
false,
false,
true,
CompressionMode::None,
);
assert!(res.is_err());
Expand All @@ -53,6 +54,7 @@ fn test_create_archive_gzip_flush_failed() {
&[file_path.as_path()],
false,
false,
true,
CompressionMode::Gzip,
);
assert!(res.is_err());
Expand All @@ -70,6 +72,7 @@ fn test_create_archive_with_zstd() {
&[Path::new("file.txt")],
false,
false,
true,
CompressionMode::Zstd,
)
.unwrap();
Expand All @@ -93,6 +96,7 @@ fn test_create_archive_missing_file_fails() {
&[missing_path.as_path()],
false,
false,
true,
CompressionMode::Zstd,
)
.unwrap_err();
Expand Down
4 changes: 4 additions & 0 deletions src/uu/tar/src/tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {

let verbose = matches.get_flag("verbose");
let allow_absolute = matches.get_flag("absolute-names");
let recursive = !matches.get_flag("no-recursion");
let explicit_compression = if matches.get_flag("gzip") {
Some(CompressionMode::Gzip)
} else if matches.get_flag("zstd") {
Expand Down Expand Up @@ -201,6 +202,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
&files,
allow_absolute,
verbose,
recursive,
compression,
)
}
Expand All @@ -216,6 +218,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
&files,
allow_absolute,
verbose,
recursive,
compression,
)
};
Expand Down Expand Up @@ -276,6 +279,7 @@ pub fn uu_app() -> Command {
arg!(--zstd "Filter through zstd").conflicts_with("gzip"),
// Common options
arg!(-v --verbose "Verbosely list files processed"),
arg!(--"no-recursion" "Avoid descending automatically in directories"),
// arg!(-h --dereference "Follow symlinks"),
// arg!(-p --"preserve-permissions" "Extract information about file permissions"),
// Help
Expand Down
30 changes: 30 additions & 0 deletions tests/by-util/test_tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,36 @@ fn test_create_dir_verbose() {
.stdout_contains(file2_path);
}

#[test]
fn test_create_no_recursion() {
let (at, mut ucmd) = at_and_ucmd!();
let separator = path::MAIN_SEPARATOR;

at.mkdir("dir1");
at.mkdir(format!("dir1{separator}dir2"));
at.write(&format!("dir1{separator}file1.txt"), "test content 1");
at.write(
&format!("dir1{separator}dir2{separator}file2.txt"),
"test content 2",
);

ucmd.args(&[
"--no-recursion",
"-cvf",
"archive.tar",
"dir1",
&format!("dir1{separator}file1.txt"),
])
.succeeds()
.stdout_is(format!("dir1{separator}\ndir1{separator}file1.txt\n"));

new_ucmd!()
.arg("-tf")
.arg(at.plus("archive.tar"))
.succeeds()
.stdout_is("dir1/\ndir1/file1.txt\n");
}

#[test]
fn test_create_single_file() {
let (at, mut ucmd) = at_and_ucmd!();
Expand Down
Loading