Adjust permissions using umask in mkdir (#12207)

<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

With this change, `mkdir` mirrors coreutils works. Closes #12161

I referred to the implementation of `mkdir` in uutils/coreutils. I add
`uucore` required for implementation to dependencies. Since `uucore` is
already included in dependencies of `uu_mkdir`, I don't think there will
be any additional dependencies.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

- Directories are created according to `umask` except for Windows.

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

I add `mkdir` test considering permissions. The test assumes that the
default `umask` is `022`.

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
This commit is contained in:
sarubo 2024-03-15 06:43:42 +09:00 committed by GitHub
parent c950269575
commit 687fbc49c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 3 deletions

1
Cargo.lock generated
View File

@ -2940,6 +2940,7 @@ dependencies = [
"uu_mktemp", "uu_mktemp",
"uu_mv", "uu_mv",
"uu_whoami", "uu_whoami",
"uucore",
"uuid", "uuid",
"v_htmlescape", "v_htmlescape",
"wax", "wax",

View File

@ -100,6 +100,9 @@ chardetng = "0.1.17"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winreg = "0.52" winreg = "0.52"
[target.'cfg(not(windows))'.dependencies]
uucore = { version = "0.0.24", features = ["mode"] }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
libc = "0.2" libc = "0.2"
umask = "2.1" umask = "2.1"

View File

@ -5,15 +5,25 @@ use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type}; use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type};
use uu_mkdir::mkdir; use uu_mkdir::mkdir;
#[cfg(not(windows))]
use uucore::mode;
#[derive(Clone)] #[derive(Clone)]
pub struct UMkdir; pub struct UMkdir;
const IS_RECURSIVE: bool = true; const IS_RECURSIVE: bool = true;
// This is the same default as Rust's std uses:
// https://doc.rust-lang.org/nightly/std/os/unix/fs/trait.DirBuilderExt.html#tymethod.mode
const DEFAULT_MODE: u32 = 0o777; const DEFAULT_MODE: u32 = 0o777;
#[cfg(not(windows))]
fn get_mode() -> u32 {
DEFAULT_MODE - mode::get_umask()
}
#[cfg(windows)]
fn get_mode() -> u32 {
DEFAULT_MODE
}
impl Command for UMkdir { impl Command for UMkdir {
fn name(&self) -> &str { fn name(&self) -> &str {
"mkdir" "mkdir"
@ -67,7 +77,7 @@ impl Command for UMkdir {
} }
for dir in directories { for dir in directories {
if let Err(error) = mkdir(&dir, IS_RECURSIVE, DEFAULT_MODE, is_verbose) { if let Err(error) = mkdir(&dir, IS_RECURSIVE, get_mode(), is_verbose) {
return Err(ShellError::GenericError { return Err(ShellError::GenericError {
error: format!("{}", error), error: format!("{}", error),
msg: format!("{}", error), msg: format!("{}", error),

View File

@ -122,3 +122,26 @@ fn creates_directory_three_dots_quotation_marks() {
assert!(expected.exists()); assert!(expected.exists());
}) })
} }
#[cfg(not(windows))]
#[test]
fn mkdir_umask_permission() {
use std::{fs, os::unix::fs::PermissionsExt};
Playground::setup("mkdir_umask_permission", |dirs, _| {
nu!(
cwd: dirs.test(),
"mkdir test_umask_permission"
);
let actual = fs::metadata(dirs.test().join("test_umask_permission"))
.unwrap()
.permissions()
.mode();
assert_eq!(
actual, 0o40755,
"Most *nix systems have 0o00022 as the umask. \
So directory permission should be 0o40755 = 0o40777 - 0o00022"
);
})
}