-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
mpremote: Add rm -r
recursive remove functionality to filesystem commands.
#16994
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
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #16994 +/- ##
=======================================
Coverage 98.54% 98.54%
=======================================
Files 169 169
Lines 21890 21890
=======================================
Hits 21571 21571
Misses 319 319 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code size report:
|
8025729
to
f79ba18
Compare
can someone give this a testrun on a Host OS + physical device just to make sure ?
|
I'll test run this in my environment tomorrow -- it's WSL that I've mounted my devices into with usbipd, but that's still linux enough to count lol. |
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 tests need to be fixed; the test runner crashes on one of them, and even the parts that are run aren't properly reflected in the .exp file.
My own preference is to split this into two separate commits for test code vs implementation code, with the implementation commit coming after the test commit. That way, it's easy to do proper verification, i.e. not just that the tests pass with the implementation, but that they also fail without the implementation.
You don't have to specifically do it that way, but I do expect tests with both properties, and right now your tests only manage the 'fail' part.
45827a0
to
5f1d5ce
Compare
8f4a998
to
71ab5b3
Compare
I needed to add a special case to avoid confusing errors:
split in multiple commits ( code / tests / docs ) |
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.
There could be some merit to using vfs.mount()
output to skip failing on mountpounts, but special-casing it based on the directory name really isn't appropriate.
One other detail; with the |
magic is never nice. A Try / Except - continue is somewhat better, but has a risk hide other special cases. I do not want the CLI to terminate on hitting a mountpoint , as that requires knowledge that a user cannot have with current firmwares. Raising a Exception is useful in an API , not to send information to a user in a CLI.
That already works en is part of the tests
that would not be consistent with
|
Sure; the main point is that the way to detect this EPERM error is to add it to the code that detects the rest of the device-side errors, and raise the appropriate exception that follows the pattern. Then in
Oh, indeed? IMO it'd be good to make both subcommands' behavior more closely resemble GNU coreutils, rsync, etc -- but you're right that that's out of scope for this PR; that can be the subject of a separate PR and discussion later. |
71ab5b3
to
d66a498
Compare
Regarding EINVAL vs EPERM, per the vfs source code EPERM is the error that theoretically should be happening for invalid operations on or between mountpoints (including https://github.com/micropython/micropython/blob/master/extmod/vfs.c#L120-L121 EINVAL does happen, but only for trying to unmount a path that's not a mountpoint: https://github.com/micropython/micropython/blob/master/extmod/vfs.c#L303-L305 So I'm quite curious to hear what port/board you're using. I know some ports include their own filesystem components, perhaps there's another issue here to be fixed later. In the mean time though, for portability it seems reasonable to just generically catch |
Tested on 5 different ports, all raise the same error. |
It seems you're correct; I've misunderstood the error code here. The EPERM happens when attempting to remove the filesystem root |
Thanks for confirming. That clears up all review comments AFAIKT. The CI error on Mac appears to be a flakey build that I can't re-run |
One thing I'd consider still mandatory to fix, is the dead code introduced in the latest push at tools/mpremote/mpremote/transport.py:68, per this comment. (There's also the choice of python exception type mapping for EINVAL, per these comments; but that's a more minor nitpick.) For regularity sake, I also think that there should be an error message on failing to remove the root directory, even when the path filtering on the host side avoids actually executing the command on the device. i.e.
And should have an error exit code, not 0. |
You have a point on OSError. As I indicated before : I disagree that trying to remove all files and folder down from root should result in an error, as that would reduce usability too much. @peterhinch , @mattytrentini, |
d66a498
to
d75ea08
Compare
I would prefer no error: clearing the filesystem is a normal thing to do, and users of |
The point of reporting that error isn't to error in a way that fails to remove the contents of What I'm describing is the standard behavior for GNU coreutils 9.1
BusyBox v1.37.0
POSIX: IEEE Std 1003.1-2024, Shells & Utilities, Part 3: rm — remove directory entries
|
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.
I've tested this from WSL2 on both my rp2040 and rp2350.
Assuming the exit-0 behavior is what the maintainers prefer, this PR is ready to merge.
I think @AJMansfield presents a pretty compelling argument why there should be an error - and I think it also satisfies @peterhinch's expectation that the folders contents will be removed (just not the directory itself). Personally I'm not particularly invested, as long as I can delete the contents! |
Regarding errors when trying to remove the root: some boards/ports have the internal filesystem mounted at Maybe one way to support boards with
which would use the current directory as the target and remove everything from it, but crucially it would not attempt to remove the directory itself. So that's kind of like Then it would still support |
I like this approach as it will allow users to do cleanup in a single command without throwing errors. WRT raising error on root deletion: on ubuntu in docker ( I now find a desire for a |
Interesting! It looks like coreutils rm skips trying to remove a parent directory if it errored trying to remove any of its children. This happens with any directory, not just
Note that there was never an attempt to remove Using a chroot without any mounted filesystems to avoid this error (as in my demonstrations), does result in an attempt and error with removing |
Note that this seems to be implementation-specific. BusyBox's behavior is somewhat different:
It still exits nonzero -- but curiously, it log a success at removing the parent directories even though they still exist afterward. I've reported this potential issue to BusyBox here: https://bugs.busybox.net/show_bug.cgi?id=16330 |
Current iteration works :
Also supports -v , and exit = 1 on attempt to remove root. (not yet pushed, waiting for feedback as I want to limit churn ) |
I have an alternative implementation of
This restructures it to specifically only catch the OSError generated by the recursive child calls, and intentionally allows any error generated by This doesn't implement the |
indeed, it has it merits, and can stand on its own.
I'll await Damien's comments.
mpremote does not (yet) CLI to expose these mountpoints to users without writing code to a new and therefore mostly unknown API. Thus I see very clear merits. |
8e011bd
to
1de0223
Compare
Yes, I was also thinking that |
Clearing out an entire mount point / filesystem is probably one of the main uses of Since |
df2547d
to
3a159bd
Compare
The failing CI test is unrelated. |
mpremote now supports `mpremote rm -r`. Addresses micropython#9802 and micropython#16845. Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
3a159bd
to
064bfda
Compare
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.
Tested on stm32 and rp2 boards. Works well!
The implementation is also very clean. Thanks @Josverl for doing multiple passes to get it right, and @AJMansfield for testing/review/feedback.
Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
Signed-off-by: Jos Verlinde <Jos_Verlinde@hotmail.com>
064bfda
to
ef8282c
Compare
It's been a worthwhile effort getting this into a shape we can all be glad to see land! |
Summary
Recursive remove functionality for mpremote is frequently requested by users.
Testing
On Windows
On Linux
Trade-offs and Alternatives
rm -rf :foo
and therefore should be used with caution.If desired such a check, and its override '-rf' could be added
/rom
or/sd
Fixes : 16845