path: Force-remove files in unlink() - #130
Conversation
Path.unlink() removes a file with a plain `rm`. If the file is write-protected (e.g. -r--r--r--) but the containing directory still permits deletion, GNU rm asks an interactive confirmation question before removing it. Since tbot's channel has no way to answer that question, exec0() never sees a shell prompt again and hangs indefinitely instead of raising an error. unlink() already resolves existence/missing_ok itself before running rm, so nothing is lost by making the actual removal non-interactive as well, via -f. Fixes: Rahix#128 Signed-off-by: Martin Jocic <martin.jocic@kvaser.com>
|
Hi, thanks for the contribution! I just confirmed, Python The I just checked, busybox |
What were those about? I cannot reproduce them here and CI also seems happy... Can you open a new issue for this topic, please? |
rm -f self could misinterpret a filename that happens to start with a dash as a flag instead of a path. Add a `--` before the path argument to make sure it is always treated as the operand, not an option. busybox's rm also supports `--`, so this works across the rm implementations tbot might run against. Signed-off-by: Martin Jocic <martin.jocic@kvaser.com>
Add a testcase that creates a 0400 (write-protected) file and then unlinks it, to cover the fix for unlink() hanging on such files (rm -f in path.py's unlink()). Matches the behavior of Python's pathlib, which also removes a write-protected file without complaining as long as the containing directory permits it. Signed-off-by: Martin Jocic <martin.jocic@kvaser.com>
|
Good points, thanks! I've pushed two commits addressing both:
Ran the selftest suite locally ( |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #130 +/- ##
==========================================
+ Coverage 62.44% 62.47% +0.02%
==========================================
Files 53 53
Lines 3762 3765 +3
==========================================
+ Hits 2349 2352 +3
Misses 1413 1413 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
It's an assertion in result = list(path.rglob("cpu"))
assert len(result) > 3On my machine, I haven't been able to confirm this against the actual CI runner's cgroup mode directly, so take it as a plausible explanation rather than a confirmed one — but it would fit why CI and your own machine are happy while mine isn't. Given that, do you still want me to open a new issue for this or do you prefer to do it yourself? |
Damn, I see, made too many assumptions about Linux systems again. Yes, please do open a new issue anyway to track it. Or alternatively, if you want, you can also send a PR to fix it: it's fine if we just reduce the >3 to >2 or more ideally, create a synthetic structure inside the testdir and rglob() against that. |
|
Issue #132 opened. |
Fixes #128.
Path.unlink()removes a file with a plainrm:If the file is write-protected (e.g.
-r--r--r--) but the containingdirectory still permits deletion, GNU
rmasks an interactiveconfirmation question before removing it:
Since tbot's channel has no way to answer that question,
exec0()never sees a shell prompt again and hangs indefinitely instead of
raising an error.
unlink()already resolves existence/missing_okitself beforerunning
rm, so nothing is lost by making the actual removalnon-interactive as well, via
-f.Testing
pre-commit's pinnedblack,flake8, andmypyall pass on thechanged file.
selftest/tests/test_path.pyhas the same pass/fail counts beforeand after this change (two pre-existing, unrelated failures in
test_rglob_errorreproduce identically on unmodifiedmaster).chmod 400file hangs(confirmed via timeout) on unmodified
master, and completes cleanlyon this branch.