Repository navigation
extract: add -k/--keep-old-files #404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,8 @@ use std::io::{Cursor, Read, Write}; | |
| use std::path::{self, PathBuf}; | ||
|
|
||
| use tar_rs_crate::{Archive as TarRsArchive, Builder as TarRsBuilder, Header as TarRsHeader}; | ||
| use uutests::{at_and_ucmd, new_ucmd}; | ||
| use uutests::util::TestScenario; | ||
| use uutests::{at_and_ucmd, new_ucmd, util_name}; | ||
|
|
||
| /// Size of a single tar block in bytes (per POSIX specification). | ||
| // TODO: This should be exported from the tar crate instead of being redefined here. | ||
|
|
@@ -86,6 +87,96 @@ fn test_create_dir_verbose() { | |
| .stdout_contains(file2_path); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_extract_keep_old_files() { | ||
| let ts = TestScenario::new(util_name!()); | ||
| let at = &ts.fixtures; | ||
|
|
||
| at.write("a.txt", "from archive"); | ||
| at.write("b.txt", "also from archive"); | ||
| ts.ucmd() | ||
| .args(&["-cf", "archive.tar", "a.txt", "b.txt"]) | ||
| .succeeds(); | ||
| at.write("a.txt", "already here"); | ||
| at.remove("b.txt"); | ||
|
|
||
| ts.ucmd() | ||
| .args(&["-xkf", "archive.tar"]) | ||
| .fails() | ||
| .code_is(2) | ||
| .stderr_contains("tar: a.txt: Cannot open: File exists") | ||
| .stderr_contains("Exiting with failure status due to previous errors"); | ||
| assert_eq!(at.read("a.txt"), "already here"); | ||
| assert_eq!(at.read("b.txt"), "also from archive"); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please also add a test where the member is a directory that already exists (it should not be an error)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added test_extract_keep_old_files_existing_directory. |
||
|
|
||
| #[test] | ||
| fn test_extract_keep_old_files_existing_directory() { | ||
| let ts = TestScenario::new(util_name!()); | ||
| let at = &ts.fixtures; | ||
|
|
||
| at.mkdir("d"); | ||
| at.write("d/f.txt", "from archive"); | ||
| ts.ucmd().args(&["-cf", "archive.tar", "d"]).succeeds(); | ||
| at.remove("d/f.txt"); | ||
|
|
||
| ts.ucmd() | ||
| .args(&["-xkf", "archive.tar"]) | ||
| .succeeds() | ||
| .no_output(); | ||
| assert_eq!(at.read("d/f.txt"), "from archive"); | ||
| } | ||
|
|
||
| fn keep_old_members_tar(names: &[&str]) -> Vec<u8> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. almost the same code as in test_extract_reports_member_with_parent_dir_and_continues, could you please use this helper there too? |
||
| let mut tar_bytes = Vec::new(); | ||
| { | ||
| let mut builder = TarRsBuilder::new(&mut tar_bytes); | ||
| for name in names { | ||
| let mut header = TarRsHeader::new_gnu(); | ||
| header.as_old_mut().name[..name.len()].copy_from_slice(name.as_bytes()); | ||
| header.set_mode(0o644); | ||
| header.set_size(1); | ||
| header.set_cksum(); | ||
| builder.append(&header, Cursor::new("x")).unwrap(); | ||
| } | ||
| builder.finish().unwrap(); | ||
| } | ||
| tar_bytes | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_extract_keep_old_files_checks_the_unpacked_path() { | ||
| let (at, mut ucmd) = at_and_ucmd!(); | ||
| at.mkdir("out"); | ||
| at.write("out/kept.txt", "already here"); | ||
| // A leading `/` is dropped when extracting, so `/kept.txt` lands on | ||
| // out/kept.txt, which -k must keep. | ||
| at.write_bytes("members.tar", &keep_old_members_tar(&["/kept.txt"])); | ||
|
|
||
| ucmd.args(&["-xkf", "../members.tar"]) | ||
| .current_dir(at.plus("out")) | ||
| .fails() | ||
| .code_is(2) | ||
| .stderr_contains("tar: kept.txt: Cannot open: File exists"); | ||
| assert_eq!(at.read("out/kept.txt"), "already here"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_extract_keep_old_files_reports_parent_dir_member() { | ||
| let (at, mut ucmd) = at_and_ucmd!(); | ||
| at.mkdir("out"); | ||
| at.write("item", "outside"); | ||
| at.write_bytes("members.tar", &keep_old_members_tar(&["../item"])); | ||
|
|
||
| ucmd.args(&["-xkf", "../members.tar"]) | ||
| .current_dir(at.plus("out")) | ||
| .fails() | ||
| .code_is(2) | ||
| .stderr_contains("../item: Member name contains '..'") | ||
| .stderr_does_not_contain("File exists"); | ||
| assert_eq!(at.read("item"), "outside"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_create_no_recursion() { | ||
| let (at, mut ucmd) = at_and_ucmd!(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the asserts already say this, the comment can go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.