Repository navigation
fix(mkdir): don't report an existing directory as created in --verbose - #19017
Merged
fdncred merged 1 commit intoSep 13, 2026
Merged
Conversation
`mkdir` passes `recursive: true` to uutils, which makes it succeed silently when the path is already there. The verbose output did not account for that and reported `created: true` for every path it did not fail on, including ones that already existed before the call. Record whether the path existed before calling `mkdir` and report that instead. This does not change the exit code or the error behavior discussed in nushell#19003 — whether `mkdir` should fail on an existing directory is a separate decision. The `created` column is wrong under any answer to it, since nothing was created. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2 tasks done
Contributor
|
Thanks |
This was referenced Sep 14, 2026
fdncred
pushed a commit
that referenced
this pull request
Sep 14, 2026
…19023) ## Description `help mkdir` shows this for the `--verbose` example: | path | created | error | | --- | --- | --- | | foo/bar | true | | | foo2 | true | | `mkdir` never produces that. Every argument goes through `nu_path::expand_path_with(..)` before it reaches the output, so the reported paths are absolute: ``` > mkdir -v foo/bar foo2 | get 0.path /tmp/.tmpHDMTuH/mkdir_verbose_absolute/foo/bar ``` Since the value depends on the working directory, it cannot be written down as a literal at all — so this drops the declared `result`, the way the first example in the same command already does, and says in the description that the paths are absolute. Why it went unnoticed: `umkdir.rs` has no `test_examples()`, unlike the commands in `crates/nu-command/src/path/`, so the declared result was never compared against what the command actually returns. ## User-facing changes (Release notes) n/a — documentation only. The `help mkdir` example no longer shows output that the command cannot produce. ## Tests + Formatting Added `verbose_reports_the_expanded_path`, which asserts the reported path equals the expanded path rather than the argument as typed. It is not vacuous: pointing it at the value the example used to claim produces ``` assertion `left == right` failed left: "foo/bar" right: "/tmp/.tmpHDMTuH/mkdir_verbose_absolute/foo/bar" ``` which is the bug this PR fixes. All 18 `umkdir` tests pass; `cargo fmt --all -- --check` and `cargo clippy --all-targets` are clean. I did not add `test_examples()` for this command: its examples create directories as a side effect, which is presumably why it has none. ## Additional notes Follow-up to #19017, same command, unrelated bug. Co-authored-by: Prajwal Narayana <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
fdncred
pushed a commit
that referenced
this pull request
Sep 14, 2026
…9024) ## Description `view source` renders a rest parameter without a space after the colon, unlike every other parameter kind: ```nu > def test [a?:any --b:int ...rest:string] { echo 'test' }; view source test def test [ a?: any --b: int ...rest:string] { echo 'test' } ``` `a?: any` and `--b: int` are spaced; `...rest:string` is not. In `render_def` the branches are: | kind | format | | --- | --- | | required positional | `"{}: {} "` | | optional positional | `"{}?: {} "` | | flag with an argument | `": {arg}"` | | rest | `"...{}:{}"` | The rest branch is the only one missing the space. The command's own examples already show `...rest: string`, in two of them, so the documented form was the right one and the code disagreed with it. Why it was not caught: `view_source.rs` declares eight example results and had no test running them. Adding `test_examples` for `ViewSource` is what surfaced this, and it also caught a second, smaller mismatch — the module example claimed ``` " export-env { $env.FOO_ENV = 'BAZ' }" ``` while `view source` returns the source between the module's braces verbatim, so the real value has the trailing space too. That one is the example being wrong rather than the code, so the example is corrected. ## User-facing changes (Release notes) `view source` now renders a rest parameter as `...rest: string` rather than `...rest:string`, matching how it already renders every other parameter. ## Tests + Formatting Added `test_examples` for `ViewSource`, which runs all eight declared example results. It is not vacuous — it is what found both mismatches, failing first on ``` expected: "def --env --wrapped foo [ ...rest: string] { print $rest }" got: "def --env --wrapped foo [ ...rest:string] { print $rest }" ``` and then on the module example. Both are green now. The full `nu-command` lib suite (815 tests) and the existing `view_source` integration tests pass. I checked nothing asserted the old spelling: the only other `...name:type` in the tree is input source in an unrelated parser test, not an assertion on `view source` output. `cargo fmt --all -- --check` and `cargo clippy --all-targets` are clean. ## Additional notes Third small `nu-command` fix from me after #19017 and #19023, same theme: a declared example result that nothing was checking. Co-authored-by: Prajwal Narayana <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
fdncred
pushed a commit
that referenced
this pull request
Sep 16, 2026
…#19021) # Description Follow-up to #19003. The default `mkdir` behavior (idempotent, `-p`-like) stays exactly as-is — #19006 tried making it error by default and was reverted in #19008, since people rely on `mkdir foo` to just ensure a directory exists (and `^mkdir -p` doesn't error either). Per @fdncred's suggestion in the thread, this instead adds an **opt-in** flag. With `--fail-if-exists`, `mkdir` errors on a target that already exists (message `<path>: File exists`, matching coreutils), while still creating any non-existing targets passed in the same call. Without the flag, nothing changes. The `--verbose` `created: true` half of the issue was already fixed in #19017, so this covers the remaining piece. # User-Facing Changes New opt-in switch: `mkdir --fail-if-exists <dir>` (short: none) errors if the directory already exists instead of silently succeeding. Default `mkdir` is unchanged. # Tests + Formatting Added `commands::umkdir` tests: errors on an existing dir with the flag, still creates new dirs with the flag, and `-v --fail-if-exists` reports `created: false`. Existing default-behavior tests (idempotent mkdir, intermediary dirs) still pass. `cargo fmt --all --check`, `cargo clippy -p nu-command`, and the `nu-command` test suite are clean. # After Submitting Nothing needed (no doc/`std` changes). --- _Disclosure: I use AI assistance for code review and for drafting text (English isn't my first language); I review and verify every change myself before sending it._ --------- Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
mkdir --verbosereportscreated: truefor directories that already existed.mkdirbuilds its uutils config withrecursive: true(theIS_RECURSIVEconstant), and in that mode
uu_mkdirreturnsOk(())for a path that isalready there rather than raising "File exists" — that check is guarded by
!config.recursive. The verbose branch treated every non-error as a creation,so an existing directory came back as
created: true.This records whether the path existed before the call and reports that instead:
Previously that same row said
created: true.Scope: this touches only the
createdcolumn. Whethermkdirshould fail onan existing directory is the open question in #19003, and I have deliberately
not answered it here — that one is a behavior change worth deciding separately,
since
mkdirin Nushell is alwaysmkdir -pand POSIX has-psuppress theerror. The
createdfield is wrong under any answer to it, because nothing wascreated either way.
User-facing changes (Release notes)
mkdir --verboseno longer reports existing directories as newly createdFixed
mkdir --verbosereportingcreated: truefor directories that alreadyexisted. Such rows now report
created: false. Directories that are actuallycreated are unaffected.
Tests + Formatting
Two tests in
crates/nu-command/tests/commands/umkdir.rs:verbose_does_not_report_existing_directory_as_createdverbose_reports_newly_created_directory_as_created— the control, so thefirst cannot pass by inverting the field
I checked these are not vacuous: reverting the one-line change makes the first
fail while the control still passes. The other 15 existing
umkdirtests passunchanged.
cargo fmt --all -- --checkandcargo clippy --all-targetsare clean.Additional notes
Related to #19003 — this fixes one part of that report and deliberately leaves
the exit-code question open. See my comment there for the trade-offs.