Skip to content
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

Use iterative algorithms for mkdir_recursive and rmdir_recursive #12573

Merged
merged 3 commits into from
Mar 13, 2014

Conversation

lbonn
Copy link
Contributor

@lbonn lbonn commented Feb 26, 2014

As mentioned in #6109, mkdir_recursive doesn't really need to use recursive calls, so here is an iterative version.
The other points of the proposed overhaul (renaming and existing permissions) still need to be resolved.

I also bundled an iterative rmdir_recursive, for the same reason.

Please do not hesitate to provide feedback on style as this is my first code change in rust.

@adrientetar
Copy link
Contributor

These functions should be renamed if they are not recursive anymore, the doc comments before them also.

@huonw
Copy link
Member

huonw commented Feb 26, 2014

@adrientetar: I don't think the names correspond to their implementations, but rather their behaviour (making nested directories, etc.).

@lbonn
Copy link
Contributor Author

lbonn commented Feb 26, 2014

Yes, they serve the same purposes as mkdir -p and rm -r, the latter being an alias for rm --recursive.
However, I agree that mkdir_recursive, is somehow confusing.

I voluntarily left the original functions names pending for discussion.
As for the doc comments, they describe the functions' intended behaviours which haven't changed.

let mut curpath = match path.is_absolute() {
true => Path::new("/"),
false => Path::new("./")
};
Copy link
Member

Choose a reason for hiding this comment

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

I've found recently that as soon as you look at a path you've probably forgotten one thing or another. This may need to change to something like path.root_path().unwrap_or(Path::new(".")) to take into account drives on windows.

cc @kballard, you know lots about windows paths.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's absolutely correct. That takes into account the multitude of possible path prefixes on Windows.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also wonder if this takes into account symlinks and whatnot.

@lbonn
Copy link
Contributor Author

lbonn commented Feb 27, 2014

Here are some corrections for the root problem and is_dir usage.

Still need to be worked on :

  • spatial complexity
  • rm a non-directory directly ?
  • use vec_ng

@alexcrichton
Copy link
Member

@lbonn, if you want, you can defer the semantics fixes until later. I think that the change to non-recursion is worth merging regardless of changing what exactly the function does.

To that end, I would recommend dealing with the spatial complexity and using vec_ng for now.

@kud1ing
Copy link

kud1ing commented Feb 27, 2014

Nice.

@lbonn
Copy link
Contributor Author

lbonn commented Feb 27, 2014

This one is more space efficient and uses vec_ng.

However, it calls readdir each time it falls back on a directory, I'm not sure if this is a big deal.
The alternative would be to keep a state of to-be-deleted children for each directory in the stack.

Also it looks like vec! cannot be used inside std itself, because of ::std::vec_ng::Vec in the macro expansion.


// delete all regular files in the way and push subdirs
// on the stack
for child in children.iter() {
Copy link
Member

Choose a reason for hiding this comment

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

If you use .move_iter() here, the .clone() will be unnecessary.

@lbonn
Copy link
Contributor Author

lbonn commented Feb 27, 2014

Thanks for the re-read, it should look better.

This turned out to be a good learning exercice :).

match unlink(&child) {
Ok(()) => (),
Err(ref e) if e.kind == io::FileNotFound => (),
Err(e) => return Err(e)
Copy link
Member

Choose a reason for hiding this comment

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

I don't personally understand why io::FileNotFound is ignored. Can you add a comment explaining why?

Copy link

Choose a reason for hiding this comment

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

I guess, because there is no harm done if the file you want to remove is not there in the first place. But i agree: this constellation/reasoning should be documented.

@alexcrichton
Copy link
Member

I would also like to see some tests for all the new functionality. I'm a little uncomfortable adding in the lstat calls without tests asserting that you're calling lstat.

You'll find a bunch of tests at the end of this module, and if you wrap them in the iotest! macro it will test it for both the native and green implementations.

@lbonn
Copy link
Contributor Author

lbonn commented Feb 28, 2014

It turns out the functions were not really tested, except for the somewhat odd recursive_mkdir_slash.

Here are some tests which check for basic functionnality and ensure that symlinks to other directories are not explored during deletion.

let testdir = tmpdir().join("d1/d2");
check!(mkdir_recursive(&testdir, io::UserRWX));
assert!(testdir.is_dir())
})
Copy link
Member

Choose a reason for hiding this comment

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

This test should have tmpdir alive for the entire test. Otherwise it leaves around temporary directories.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I see. This is pretty subtle because the test still passes.

@alexcrichton
Copy link
Member

This failed on windows, likely because lstat is not implemented on windows.

@lbonn
Copy link
Contributor Author

lbonn commented Mar 7, 2014

Yes, it makes sense :).

I'll try to set up a build on my windows machine and work on lstat soon.

@alexcrichton
Copy link
Member

It's ok to ignore the tests on windows for now though. I had difficulty figuring out how to implement lstat on windows, so it's fine if we don't get it for now.

lbonn added 2 commits March 10, 2014 19:27
For now, the windows version uses stat, just as before.
We should switch back to lstat as soon as rust-lang#12795 is closed.
bors added a commit that referenced this pull request Mar 13, 2014
As mentioned in #6109, ```mkdir_recursive``` doesn't really need to use recursive calls, so here is an iterative version.
The other points of the proposed overhaul (renaming and existing permissions) still need to be resolved.

I also bundled an iterative ```rmdir_recursive```, for the same reason.

Please do not hesitate to provide feedback on style as this is my first code change in rust.
@bors bors merged commit 164b7c2 into rust-lang:master Mar 13, 2014
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 25, 2022
internal: Split flyimport into its 3 applicable contexts
flip1995 pushed a commit to flip1995/rust that referenced this pull request Apr 18, 2024
…ns-in-module-name-repetitions, r=Jarcho

[`module_name_repetition`] Recognize common prepositions

Fixes rust-lang#12544

changelog: [`module_name_repetition`]: don't report an item name if it consists only of a prefix from `allowed-prefixes` list and a module name (e.g. `AsFoo` in module `foo`). Prefixes allowed by default: [`to`, `from`, `into`, `as`, `try_into`, `try_from`]
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.

7 participants