diff options
| -rw-r--r-- | CHANGES.md | 2 | ||||
| -rw-r--r-- | api/api.md | 4 | ||||
| -rw-r--r-- | api/paths.md | 4 | ||||
| -rw-r--r-- | api/paths.yaml | 7 | ||||
| -rw-r--r-- | man/man3/tomo-Path.create_directory.3 | 7 | ||||
| -rw-r--r-- | src/environment.c | 3 | ||||
| -rw-r--r-- | src/modules.c | 4 | ||||
| -rw-r--r-- | src/stdlib/paths.c | 12 | ||||
| -rw-r--r-- | src/stdlib/paths.h | 2 |
9 files changed, 35 insertions, 10 deletions
@@ -22,6 +22,8 @@ - Added `Path.lines()`. - Added `Text.find(text, target, start=1)`. - Added `at_cleanup()` to register cleanup functions. +- Added `recursive` argument to `Path.create_directory()` to create parent + directories if needed. - Deprecated: - Sets are no longer a separate type with separate methods. - Instead of sets, use tables with a value type of `{KeyType:Empty}`. @@ -2777,15 +2777,17 @@ assert (./directory).children(include_hidden=yes) == [".git", "foo.txt"] ## Path.create_directory ```tomo -Path.create_directory : func(path: Path, permissions = Int32(0o755) -> Void) +Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Void) ``` Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed. + Argument | Type | Description | Default ---------|------|-------------|--------- path | `Path` | The path of the directory to create. | - permissions | `` | The permissions to set on the new directory. | `Int32(0o755)` +recursive | `` | If set to `yes`, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to `yes`, this function behaves like `mkdir -p`. | `yes` **Return:** Nothing. diff --git a/api/paths.md b/api/paths.md index 07f0560b..4beabdc2 100644 --- a/api/paths.md +++ b/api/paths.md @@ -253,15 +253,17 @@ assert (./directory).children(include_hidden=yes) == [".git", "foo.txt"] ## Path.create_directory ```tomo -Path.create_directory : func(path: Path, permissions = Int32(0o755) -> Void) +Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Void) ``` Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed. + Argument | Type | Description | Default ---------|------|-------------|--------- path | `Path` | The path of the directory to create. | - permissions | `` | The permissions to set on the new directory. | `Int32(0o755)` +recursive | `` | If set to `yes`, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to `yes`, this function behaves like `mkdir -p`. | `yes` **Return:** Nothing. diff --git a/api/paths.yaml b/api/paths.yaml index 8fbd18dc..65d63671 100644 --- a/api/paths.yaml +++ b/api/paths.yaml @@ -258,6 +258,7 @@ Path.create_directory: description: > Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed. + note: > return: type: 'Void' description: > @@ -271,6 +272,12 @@ Path.create_directory: default: 'Int32(0o755)' description: > The permissions to set on the new directory. + recursive: + default: 'yes' + description: > + If set to `yes`, then recursively create any parent directories if they + don't exist, otherwise fail if the parent directory does not exist. When + set to `yes`, this function behaves like `mkdir -p`. example: | (./new_directory).create_directory() diff --git a/man/man3/tomo-Path.create_directory.3 b/man/man3/tomo-Path.create_directory.3 index adfe7e97..db50d468 100644 --- a/man/man3/tomo-Path.create_directory.3 +++ b/man/man3/tomo-Path.create_directory.3 @@ -2,14 +2,14 @@ .\" Copyright (c) 2025 Bruce Hill .\" All rights reserved. .\" -.TH Path.create_directory 3 2025-05-17 "Tomo man-pages" +.TH Path.create_directory 3 2025-11-27 "Tomo man-pages" .SH NAME Path.create_directory \- make a directory .SH LIBRARY Tomo Standard Library .SH SYNOPSIS .nf -.BI Path.create_directory\ :\ func(path:\ Path,\ permissions\ =\ Int32(0o755)\ ->\ Void) +.BI Path.create_directory\ :\ func(path:\ Path,\ permissions\ =\ Int32(0o755),\ recursive\ =\ yes\ ->\ Void) .fi .SH DESCRIPTION Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed. @@ -24,10 +24,13 @@ l l l l. Name Type Description Default path Path The path of the directory to create. - permissions The permissions to set on the new directory. Int32(0o755) +recursive If set to `yes`, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to `yes`, this function behaves like `mkdir -p`. yes .TE .SH RETURN Nothing. +.SH NOTES + .SH EXAMPLES .EX (./new_directory).create_directory() diff --git a/src/environment.c b/src/environment.c index 6075ce49..88a15bb5 100644 --- a/src/environment.c +++ b/src/environment.c @@ -310,7 +310,8 @@ env_t *global_env(bool source_mapping) { {"child", "Path$child", "func(path:Path, child:Text -> Path)"}, // {"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, // {"concatenated_with", "Path$concat", "func(a,b:Path -> Path)"}, // - {"create_directory", "Path$create_directory", "func(path:Path, permissions=Int32(0o755))"}, // + {"create_directory", "Path$create_directory", + "func(path:Path, permissions=Int32(0o755), recursive=yes)"}, // {"current_dir", "Path$current_dir", "func(->Path)"}, // {"exists", "Path$exists", "func(path:Path -> Bool)"}, // {"expand_home", "Path$expand_home", "func(path:Path -> Path)"}, // diff --git a/src/modules.c b/src/modules.c index 23b8a0a0..df6bade3 100644 --- a/src/modules.c +++ b/src/modules.c @@ -153,10 +153,10 @@ bool try_install_module(module_info_t mod, bool ask_confirmation) { const char *extension = p + 1; Path_t tmpdir = Path$unique_directory(Path("/tmp/tomo-module-XXXXXX")); tmpdir = Path$child(tmpdir, Text$from_str(mod.name)); - Path$create_directory(tmpdir, 0755); + Path$create_directory(tmpdir, 0755, true); xsystem("curl ", mod.url, " -o ", tmpdir); - Path$create_directory(dest, 0755); + Path$create_directory(dest, 0755, true); if (streq(extension, ".zip")) xsystem("unzip ", tmpdir, "/", filename, " -d ", dest); else if (streq(extension, ".tar.gz") || streq(extension, ".tar")) xsystem("tar xf ", tmpdir, "/", filename, " -C ", dest); diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c index 22effad7..6c99cf0b 100644 --- a/src/stdlib/paths.c +++ b/src/stdlib/paths.c @@ -468,11 +468,19 @@ void Path$remove(Path_t path, bool ignore_missing) { } public -void Path$create_directory(Path_t path, int permissions) { +void Path$create_directory(Path_t path, int permissions, bool recursive) { +retry: path = Path$expand_home(path); const char *c_path = Path$as_c_string(path); int status = mkdir(c_path, (mode_t)permissions); - if (status != 0 && errno != EEXIST) fail("Could not create directory: ", c_path, " (", strerror(errno), ")"); + if (status != 0) { + if (recursive && errno == ENOENT) { + Path$create_directory(Path$parent(path), permissions, recursive); + goto retry; + } else if (errno != EEXIST) { + fail("Could not create directory: ", c_path, " (", strerror(errno), ")"); + } + } } static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter) { diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h index 3b1f3ce6..677631b2 100644 --- a/src/stdlib/paths.h +++ b/src/stdlib/paths.h @@ -41,7 +41,7 @@ void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, boo OptionalText_t Path$owner(Path_t path, bool follow_symlinks); OptionalText_t Path$group(Path_t path, bool follow_symlinks); void Path$remove(Path_t path, bool ignore_missing); -void Path$create_directory(Path_t path, int permissions); +void Path$create_directory(Path_t path, int permissions, bool recursive); List_t Path$children(Path_t path, bool include_hidden); List_t Path$files(Path_t path, bool include_hidden); List_t Path$subdirectories(Path_t path, bool include_hidden); |
