Skip to content

Fix for #7455: cp -r <directory> -T <target> throws a StripPrefixError #7465

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Carreau
Copy link
Contributor

@Carreau Carreau commented Mar 16, 2025

This fixes the usage of the --no-target-dir then the target dir does not exists.

This also adds a test when the target dir ends with a trailing slash, which is for me the expected behavior fo gnu cp, but i'd like someone else to confirm this.

$ mkdir temp
$ touch temp/x
$ rm -rf new_temp; ...gnubin/cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; ...gnubin/cp -r temp -T new_temp/; tree new_temp;
rm -rf new_temp; mkdir new_temp; ...gnubin/cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; mkdir new_temp; ...gnubin/cp -r temp -T new_temp/; tree new_temp;

new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

$ rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file

Some(root_path)
};
let root_parent =
if (target.exists() || no_target_dir) && !root.to_str().unwrap().ends_with("/.") {
Copy link
Contributor Author

@Carreau Carreau Mar 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not confident about this. The following also works.

Suggested change
if (target.exists() || no_target_dir) && !root.to_str().unwrap().ends_with("/.") {
if (target.exists() && !root.to_str().unwrap().ends_with("/.")) || no_target_dir {

}
descendant = descendant.strip_prefix(context.root)?.to_path_buf();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this is a bit a shot in the dark, I'm not sure I 100% get it.

@Carreau Carreau changed the title Fix for #7455 Fix for #7455: cp -r <directory> -T <target> throws a StripPrefixError Mar 16, 2025
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)

@cakebaker cakebaker linked an issue Mar 17, 2025 that may be closed by this pull request
@sylvestre sylvestre requested a review from Copilot March 19, 2025 10:18
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue with the cp command when using the --no-target-dir flag and the target directory does not exist, and it adds a new test to validate trailing slash behavior to align with GNU cp.

  • Re-enables a previously ignored test for the no-target-dir case.
  • Adds a new test to ensure correct behavior when the target directory path has a trailing slash.
  • Updates the Context::new function documentation and logic to support the no_target_dir flag.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
tests/by-util/test_cp.rs Adds a new test to check cp behavior with a trailing slash on the target directory.
src/uu/cp/src/copydir.rs Updates Context::new documentation and adjusts logic to correctly handle the no_target_dir flag.

Copy link

GNU testsuite comparison:

Congrats! The gnu test misc/stdbuf.log is no longer failing!
Congrats! The gnu test timeout/timeout.log is no longer failing!

Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

Copy link

github-actions bot commented Apr 8, 2025

GNU testsuite comparison:

Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)

@Carreau
Copy link
Contributor Author

Carreau commented Apr 27, 2025

gentle nudge

/// - `root`: The source path from which the directory will be copied.
/// - `target`: The target path to which the directory will be copied.
/// - `no_target_dir`: A boolean indicating whether the root parent
/// should consider whether or not the target directory exists.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please fix this clippy warning? thanks

@sylvestre
Copy link
Contributor

you have a few jobs failing

This fixes the usage of the `--no-target-dir` then the target dir does
not exists.

This also adds a test when the target dir ends with a trailing slash, which is for me the expected behavior fo gnu cp,
but i'd like someone else to confirm this.

```
$ mkdir temp
$ touch temp/x
```

```
$ rm -rf new_temp; ...gnubin/cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; ...gnubin/cp -r temp -T new_temp/; tree new_temp;
rm -rf new_temp; mkdir new_temp; ...gnubin/cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; mkdir new_temp; ...gnubin/cp -r temp -T new_temp/; tree new_temp;

new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

```

```
$ rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;

$ rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp; tree new_temp;
rm -rf new_temp; mkdir new_temp; target/debug/coreutils cp -r temp -T new_temp/; tree new_temp;
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
new_temp
└── x

1 directory, 1 file
```
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/tail/inotify-dir-recreate (passes in this run but fails in the 'main' branch)

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/tail/inotify-dir-recreate (passes in this run but fails in the 'main' branch)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cp -r <directory> -T <target> throws a StripPrefixError
2 participants