Update file path API and docs
This commit is contained in:
parent
88ab24c133
commit
b0b2504a94
314
docs/paths.md
314
docs/paths.md
@ -37,33 +37,68 @@ intended. Paths can be created from text with slashes using
|
|||||||
|
|
||||||
## Path Methods
|
## Path Methods
|
||||||
|
|
||||||
|
- [`func accessed(path:Path, follow_symlinks=yes -> Moment?)`](#accessed)
|
||||||
- [`func append(path: Path, text: Text, permissions: Int32 = 0o644[32] -> Void)`](#append)
|
- [`func append(path: Path, text: Text, permissions: Int32 = 0o644[32] -> Void)`](#append)
|
||||||
- [`func append_bytes(path: Path, bytes: [Byte], permissions: Int32 = 0o644[32] -> Void)`](#append_bytes)
|
- [`func append_bytes(path: Path, bytes: [Byte], permissions: Int32 = 0o644[32] -> Void)`](#append_bytes)
|
||||||
- [`func base_name(path: Path -> Text)`](#base_name)
|
- [`func base_name(path: Path -> Text)`](#base_name)
|
||||||
- [`func by_line(path: Path -> func(->Text?)?)`](#by_line)
|
- [`func by_line(path: Path -> func(->Text?)?)`](#by_line)
|
||||||
|
- [`func can_execute(path:Path -> Bool)`](#can_execute)
|
||||||
|
- [`func can_read(path:Path -> Bool)`](#can_read)
|
||||||
|
- [`func can_write(path:Path -> Bool)`](#can_write)
|
||||||
|
- [`func changed(path:Path, follow_symlinks=yes -> Moment?)`](#changed)
|
||||||
|
- [`func child(path: Path, child:Text -> Path)`](#child)
|
||||||
- [`func children(path: Path, include_hidden=no -> [Path])`](#children)
|
- [`func children(path: Path, include_hidden=no -> [Path])`](#children)
|
||||||
- [`func create_directory(path: Path, permissions=0o755[32] -> Void)`](#create_directory)
|
- [`func create_directory(path: Path, permissions=0o755[32] -> Void)`](#create_directory)
|
||||||
- [`func exists(path: Path -> Bool)`](#exists)
|
- [`func exists(path: Path -> Bool)`](#exists)
|
||||||
- [`func extension(path: Path, full=yes -> Text)`](#extension)
|
- [`func extension(path: Path, full=yes -> Text)`](#extension)
|
||||||
- [`func files(path: Path, include_hidden=no -> [Path])`](#files)
|
- [`func files(path: Path, include_hidden=no -> [Path])`](#files)
|
||||||
|
- [`func from_components(components:[Text] -> Path)`](#from_components)
|
||||||
- [`func glob(path: Path -> [Path])`](#glob)
|
- [`func glob(path: Path -> [Path])`](#glob)
|
||||||
|
- [`func group(path: Path, follow_symlinks=yes -> Text?)`](#group)
|
||||||
- [`func is_directory(path: Path, follow_symlinks=yes -> Bool)`](#is_directory)
|
- [`func is_directory(path: Path, follow_symlinks=yes -> Bool)`](#is_directory)
|
||||||
- [`func is_file(path: Path, follow_symlinks=yes -> Bool)`](#is_file)
|
- [`func is_file(path: Path, follow_symlinks=yes -> Bool)`](#is_file)
|
||||||
- [`func is_socket(path: Path, follow_symlinks=yes -> Bool)`](#is_socket)
|
- [`func is_socket(path: Path, follow_symlinks=yes -> Bool)`](#is_socket)
|
||||||
- [`func is_symlink(path: Path -> Bool)`](#is_symlink)
|
- [`func is_symlink(path: Path -> Bool)`](#is_symlink)
|
||||||
|
- [`func modified(path:Path, follow_symlinks=yes -> Moment?)`](#modified)
|
||||||
|
- [`func owner(path: Path, follow_symlinks=yes -> Text?)`](#owner)
|
||||||
- [`func parent(path: Path -> Path)`](#parent)
|
- [`func parent(path: Path -> Path)`](#parent)
|
||||||
- [`func read(path: Path -> Text?)`](#read)
|
- [`func read(path: Path -> Text?)`](#read)
|
||||||
- [`func read_bytes(path: Path -> [Byte]?)`](#read_bytes)
|
- [`func read_bytes(path: Path -> [Byte]?)`](#read_bytes)
|
||||||
- [`func relative(path: Path, relative_to=(./) -> Path)`](#relative)
|
- [`func relative_to(path: Path, relative_to=(./) -> Path)`](#relative_to)
|
||||||
- [`func remove(path: Path, ignore_missing=no -> Void)`](#remove)
|
- [`func remove(path: Path, ignore_missing=no -> Void)`](#remove)
|
||||||
- [`func resolved(path: Path, relative_to=(./) -> Path)`](#resolved)
|
- [`func resolved(path: Path, relative_to=(./) -> Path)`](#resolved)
|
||||||
|
- [`func set_owner(path:Path, owner=none:Text, group=none:Text, follow_symlinks=yes)`](#set_owner)
|
||||||
- [`func subdirectories(path: Path, include_hidden=no -> [Path])`](#subdirectories)
|
- [`func subdirectories(path: Path, include_hidden=no -> [Path])`](#subdirectories)
|
||||||
- [`func unique_directory(path: Path -> Path)`](#unique_directory)
|
- [`func unique_directory(path: Path -> Path)`](#unique_directory)
|
||||||
- [`func write(path: Path, text: Text, permissions=0o644[32] -> Void)`](#write)
|
- [`func write(path: Path, text: Text, permissions=0o644[32] -> Void)`](#write)
|
||||||
- [`func write(path: Path, bytes: [Byte], permissions=0o644[32] -> Void)`](#write_bytes)
|
- [`func write_bytes(path: Path, bytes: [Byte], permissions=0o644[32] -> Void)`](#write_bytes)
|
||||||
- [`func write_unique(path: Path, text: Text -> Path)`](#write_unique)
|
- [`func write_unique(path: Path, text: Text -> Path)`](#write_unique)
|
||||||
- [`func write_unique_bytes(path: Path, bytes: [Byte] -> Path)`](#write_unique_bytes)
|
- [`func write_unique_bytes(path: Path, bytes: [Byte] -> Path)`](#write_unique_bytes)
|
||||||
|
|
||||||
|
### `accessed`
|
||||||
|
Gets the file access time of a file.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func accessed(path:Path, follow_symlinks: Bool = yes -> Moment?)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file whose access time you want.
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
A [Moment](moments.md) representing when the file or directory was last
|
||||||
|
accessed, or `none` if no such file or directory exists.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (./file.txt):accessed()
|
||||||
|
= Sun 16 Mar 2025 03:43:53 PM EDT EDT : Moment?
|
||||||
|
>> (./not-a-file):accessed()
|
||||||
|
= none : Moment?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `append`
|
### `append`
|
||||||
Appends the given text to the file at the specified path, creating the file if
|
Appends the given text to the file at the specified path, creating the file if
|
||||||
it doesn't already exist. Failure to write will result in a runtime error.
|
it doesn't already exist. Failure to write will result in a runtime error.
|
||||||
@ -74,7 +109,7 @@ func append(path: Path, text: Text, permissions: Int32 = 0o644[32] -> Void)
|
|||||||
|
|
||||||
- `path`: The path of the file to append to.
|
- `path`: The path of the file to append to.
|
||||||
- `text`: The text to append to the file.
|
- `text`: The text to append to the file.
|
||||||
- `permissions` (optional): The permissions to set on the file if it is being created (default is `0o644`).
|
- `permissions`: The permissions to set on the file if it is being created (default is `0o644`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
@ -96,7 +131,7 @@ func append_bytes(path: Path, bytes: [Byte], permissions: Int32 = 0o644[32] -> V
|
|||||||
|
|
||||||
- `path`: The path of the file to append to.
|
- `path`: The path of the file to append to.
|
||||||
- `bytes`: The bytes to append to the file.
|
- `bytes`: The bytes to append to the file.
|
||||||
- `permissions` (optional): The permissions to set on the file if it is being created (default is `0o644`).
|
- `permissions`: The permissions to set on the file if it is being created (default is `0o644`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
@ -158,6 +193,127 @@ for line in (/dev/stdin):by_line()!:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `can_execute`
|
||||||
|
Returns whether or not a file can be executed by the current user/group.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func can_execute(path: Path -> Bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file to check.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
`yes` if the file or directory exists and the current user has execute permissions, otherwise `no`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (/bin/sh):can_execute()
|
||||||
|
= yes
|
||||||
|
>> (/usr/include/stdlib.h):can_execute()
|
||||||
|
= no
|
||||||
|
>> (/non/existant/file):can_execute()
|
||||||
|
= no
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `can_read`
|
||||||
|
Returns whether or not a file can be read by the current user/group.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func can_read(path: Path -> Bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file to check.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
`yes` if the file or directory exists and the current user has read permissions, otherwise `no`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (/usr/include/stdlib.h):can_read()
|
||||||
|
= yes
|
||||||
|
>> (/etc/shadow):can_read()
|
||||||
|
= no
|
||||||
|
>> (/non/existant/file):can_read()
|
||||||
|
= no
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `can_write`
|
||||||
|
Returns whether or not a file can be written by the current user/group.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func can_write(path: Path -> Bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file to check.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
`yes` if the file or directory exists and the current user has write permissions, otherwise `no`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (/tmp):can_write()
|
||||||
|
= yes
|
||||||
|
>> (/etc/passwd):can_write()
|
||||||
|
= no
|
||||||
|
>> (/non/existant/file):can_write()
|
||||||
|
= no
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `changed`
|
||||||
|
Gets the file change time of a file.
|
||||||
|
|
||||||
|
**Note:** this is the
|
||||||
|
["ctime"](https://en.wikipedia.org/wiki/Stat_(system_call)#ctime) of a file,
|
||||||
|
which is _not_ the file creation time.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func changed(path:Path, follow_symlinks: Bool = yes -> Moment?)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file whose change time you want.
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
A [Moment](moments.md) representing when the file or directory was last
|
||||||
|
changed, or `none` if no such file or directory exists.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (./file.txt):changed()
|
||||||
|
= Sun 16 Mar 2025 03:43:53 PM EDT EDT : Moment?
|
||||||
|
>> (./not-a-file):changed()
|
||||||
|
= none : Moment?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `child`
|
||||||
|
Return a path that is a child of another path.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func child(path: Path, child: Text -> [Path])
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of a directory.
|
||||||
|
- `child`: The name of a child file or directory.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
A new path representing the child.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (./directory):child("file.txt")
|
||||||
|
= (./directory/file.txt)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `children`
|
### `children`
|
||||||
Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files.
|
Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files.
|
||||||
|
|
||||||
@ -166,7 +322,7 @@ func children(path: Path, include_hidden=no -> [Path])
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path of the directory.
|
- `path`: The path of the directory.
|
||||||
- `include_hidden` (optional): Whether to include hidden files, which start with a `.` (default is `no`).
|
- `include_hidden`: Whether to include hidden files, which start with a `.` (default is `no`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
A list of paths for the children.
|
A list of paths for the children.
|
||||||
@ -188,7 +344,7 @@ func create_directory(path: Path, permissions=0o755[32] -> Void)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path of the directory to create.
|
- `path`: The path of the directory to create.
|
||||||
- `permissions` (optional): The permissions to set on the new directory (default is `0o644`).
|
- `permissions`: The permissions to set on the new directory (default is `0o644`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
@ -224,11 +380,11 @@ func exists(path: Path -> Bool)
|
|||||||
Returns the file extension of the file at the specified path. Optionally returns the full extension.
|
Returns the file extension of the file at the specified path. Optionally returns the full extension.
|
||||||
|
|
||||||
```tomo
|
```tomo
|
||||||
func extension(path: Path, full=yes -> Text)
|
func extension(path: Path, full:Bool = yes -> Text)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path of the file.
|
- `path`: The path of the file.
|
||||||
- `full` (optional): Whether to return everything after the first `.` in the
|
- `full`: Whether to return everything after the first `.` in the
|
||||||
base name, or only the last part of the extension (default is `yes`).
|
base name, or only the last part of the extension (default is `yes`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
@ -253,11 +409,11 @@ no file extension.
|
|||||||
Returns a list of files within the directory at the specified path. Optionally includes hidden files.
|
Returns a list of files within the directory at the specified path. Optionally includes hidden files.
|
||||||
|
|
||||||
```tomo
|
```tomo
|
||||||
func files(path: Path, include_hidden=no -> [Path])
|
func files(path: Path, include_hidden: Bool = no -> [Path])
|
||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path of the directory.
|
- `path`: The path of the directory.
|
||||||
- `include_hidden` (optional): Whether to include hidden files (default is `no`).
|
- `include_hidden`: Whether to include hidden files (default is `no`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
A list of file paths.
|
A list of file paths.
|
||||||
@ -270,6 +426,30 @@ A list of file paths.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `from_components`
|
||||||
|
Returns a path built from an array of path components.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func from_components(components: [Text] -> Path)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `components`: An array of path components.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
A path representing the given components.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> Path.from_components(["/", "usr", "include"])
|
||||||
|
= /usr/include
|
||||||
|
>> Path.from_components(["foo.txt"])
|
||||||
|
= ./foo.txt
|
||||||
|
>> Path.from_components(["~", ".local"])
|
||||||
|
= ~/.local
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `glob`
|
### `glob`
|
||||||
Perform a globbing operation and return an array of matching paths. Some glob
|
Perform a globbing operation and return an array of matching paths. Some glob
|
||||||
specific details:
|
specific details:
|
||||||
@ -312,6 +492,29 @@ A list of file paths that match the glob.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `group`
|
||||||
|
Get the owning group of a file or directory.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func group(path: Path, follow_symlinks: Bool = yes -> Text?)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path whose owning group to get.
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
The name of the group which owns the file or directory, or `none` if the path does not exist.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (/bin):group()
|
||||||
|
= "root"
|
||||||
|
>> (/non/existent/file):group()
|
||||||
|
= none:Text
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `is_directory`
|
### `is_directory`
|
||||||
Checks if the path represents a directory. Optionally follows symbolic links.
|
Checks if the path represents a directory. Optionally follows symbolic links.
|
||||||
|
|
||||||
@ -320,7 +523,7 @@ func is_directory(path: Path, follow_symlinks=yes -> Bool)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to check.
|
- `path`: The path to check.
|
||||||
- `follow_symlinks` (optional): Whether to follow symbolic links (default is `yes`).
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
`True` if the path is a directory, `False` otherwise.
|
`True` if the path is a directory, `False` otherwise.
|
||||||
@ -344,7 +547,7 @@ func is_file(path: Path, follow_symlinks=yes -> Bool)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to check.
|
- `path`: The path to check.
|
||||||
- `follow_symlinks` (optional): Whether to follow symbolic links (default is `yes`).
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
`True` if the path is a file, `False` otherwise.
|
`True` if the path is a file, `False` otherwise.
|
||||||
@ -368,7 +571,7 @@ func is_socket(path: Path, follow_symlinks=yes -> Bool)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to check.
|
- `path`: The path to check.
|
||||||
- `follow_symlinks` (optional): Whether to follow symbolic links (default is `yes`).
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
`True` if the path is a socket, `False` otherwise.
|
`True` if the path is a socket, `False` otherwise.
|
||||||
@ -401,6 +604,53 @@ func is_symlink(path: Path -> Bool)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `modified`
|
||||||
|
Gets the file modification time of a file.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func modified(path:Path, follow_symlinks: Bool = yes -> Moment?)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path of the file whose modification time you want.
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
A [Moment](moments.md) representing when the file or directory was last
|
||||||
|
modified, or `none` if no such file or directory exists.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (./file.txt):modified()
|
||||||
|
= Sun 16 Mar 2025 03:43:53 PM EDT EDT : Moment?
|
||||||
|
>> (./not-a-file):modified()
|
||||||
|
= none : Moment?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `owner`
|
||||||
|
Get the owning user of a file or directory.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func owner(path: Path, follow_symlinks: Bool = yes -> Text?)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path whose owner to get.
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
The name of the user who owns the file or directory, or `none` if the path does not exist.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> (/bin):owner()
|
||||||
|
= "root"
|
||||||
|
>> (/non/existent/file):owner()
|
||||||
|
= none:Text
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `parent`
|
### `parent`
|
||||||
Returns the parent directory of the file or directory at the specified path.
|
Returns the parent directory of the file or directory at the specified path.
|
||||||
|
|
||||||
@ -471,15 +721,15 @@ returned.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `relative`
|
### `relative_to`
|
||||||
Returns the path relative to a given base path. By default, the base path is the current directory.
|
Returns the path relative to a given base path. By default, the base path is the current directory.
|
||||||
|
|
||||||
```tomo
|
```tomo
|
||||||
func relative(path: Path, relative_to=(./) -> Path)
|
func relative_to(path: Path, relative_to=(./) -> Path)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to convert.
|
- `path`: The path to convert.
|
||||||
- `relative_to` (optional): The base path for the relative path (default is `./`).
|
- `relative_to`: The base path for the relative path (default is `./`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
The relative path.
|
The relative path.
|
||||||
@ -500,7 +750,7 @@ func remove(path: Path, ignore_missing=no -> Void)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to remove.
|
- `path`: The path to remove.
|
||||||
- `ignore_missing` (optional): Whether to ignore errors if the file or directory does not exist (default is `no`).
|
- `ignore_missing`: Whether to ignore errors if the file or directory does not exist (default is `no`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
@ -520,7 +770,7 @@ func resolved(path: Path, relative_to=(./) -> Path)
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path to resolve.
|
- `path`: The path to resolve.
|
||||||
- `relative_to` (optional): The base path for resolution (default is `./`).
|
- `relative_to`: The base path for resolution (default is `./`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
The resolved absolute path.
|
The resolved absolute path.
|
||||||
@ -536,6 +786,28 @@ The resolved absolute path.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `set_owner`
|
||||||
|
Set the owning user and/or group for a path.
|
||||||
|
|
||||||
|
```tomo
|
||||||
|
func set_owner(path:Path, owner: Text? = none:Text, group: Text? = none:Text, follow_symlinks: Bool = yes)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `path`: The path to change the permissions for.
|
||||||
|
- `owner`: If non-none, the new user to assign to be the owner of the file (default: `none`).
|
||||||
|
- `group`: If non-none, the new group to assign to be the owner of the file (default: `none`).
|
||||||
|
- `follow_symlinks`: Whether to follow symbolic links (default is `yes`).
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
Nothing. If a path does not exist, a failure will be raised.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
(./file.txt):set_owner(owner="root", group="wheel")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `subdirectories`
|
### `subdirectories`
|
||||||
Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.
|
Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.
|
||||||
|
|
||||||
@ -544,7 +816,7 @@ func subdirectories(path: Path, include_hidden=no -> [Path])
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `path`: The path of the directory.
|
- `path`: The path of the directory.
|
||||||
- `include_hidden` (optional): Whether to include hidden subdirectories (default is `no`).
|
- `include_hidden`: Whether to include hidden subdirectories (default is `no`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
A list of subdirectory paths.
|
A list of subdirectory paths.
|
||||||
@ -595,7 +867,7 @@ func write(path: Path, text: Text, permissions=0o644[32] -> Void)
|
|||||||
|
|
||||||
- `path`: The path of the file to write to.
|
- `path`: The path of the file to write to.
|
||||||
- `text`: The text to write to the file.
|
- `text`: The text to write to the file.
|
||||||
- `permissions` (optional): The permissions to set on the file if it is created (default is `0o644`).
|
- `permissions`: The permissions to set on the file if it is created (default is `0o644`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
@ -618,7 +890,7 @@ func write(path: Path, bytes: [Byte], permissions=0o644[32] -> Void)
|
|||||||
|
|
||||||
- `path`: The path of the file to write to.
|
- `path`: The path of the file to write to.
|
||||||
- `bytes`: An array of bytes to write to the file.
|
- `bytes`: An array of bytes to write to the file.
|
||||||
- `permissions` (optional): The permissions to set on the file if it is created (default is `0o644`).
|
- `permissions`: The permissions to set on the file if it is created (default is `0o644`).
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
Nothing.
|
Nothing.
|
||||||
|
@ -334,45 +334,45 @@ env_t *new_compilation_unit(CORD libname)
|
|||||||
{"year", "Moment$year", "func(moment:Moment,timezone=none:Text -> Int)"},
|
{"year", "Moment$year", "func(moment:Moment,timezone=none:Text -> Int)"},
|
||||||
)},
|
)},
|
||||||
{"Path", PATH_TYPE, "Path_t", "Path$info", TypedArray(ns_entry_t,
|
{"Path", PATH_TYPE, "Path_t", "Path$info", TypedArray(ns_entry_t,
|
||||||
|
{"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
||||||
{"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"},
|
{"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"},
|
||||||
{"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"},
|
{"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"},
|
||||||
{"base_name", "Path$base_name", "func(path:Path -> Text)"},
|
{"base_name", "Path$base_name", "func(path:Path -> Text)"},
|
||||||
{"by_line", "Path$by_line", "func(path:Path -> func(->Text?)?)"},
|
{"by_line", "Path$by_line", "func(path:Path -> func(->Text?)?)"},
|
||||||
|
{"can_execute", "Path$can_execute", "func(path:Path -> Bool)"},
|
||||||
|
{"can_read", "Path$can_read", "func(path:Path -> Bool)"},
|
||||||
|
{"can_write", "Path$can_write", "func(path:Path -> Bool)"},
|
||||||
|
{"changed", "Path$changed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
||||||
{"child", "Path$with_component", "func(path:Path, child:Text -> Path)"},
|
{"child", "Path$with_component", "func(path:Path, child:Text -> Path)"},
|
||||||
{"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
{"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
||||||
{"components", "Path$components", "func(path:Path -> [Text])"},
|
|
||||||
{"concatenated_with", "Path$concat", "func(a,b:Path -> 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))"},
|
||||||
{"escape_int", "Int$value_as_text", "func(i:Int -> Path)"},
|
|
||||||
{"escape_path", "Path$escape_path", "func(path:Path -> Path)"},
|
|
||||||
{"escape_text", "Path$escape_text", "func(text:Text -> Path)"},
|
|
||||||
{"exists", "Path$exists", "func(path:Path -> Bool)"},
|
{"exists", "Path$exists", "func(path:Path -> Bool)"},
|
||||||
{"extension", "Path$extension", "func(path:Path, full=yes -> Text)"},
|
{"extension", "Path$extension", "func(path:Path, full=yes -> Text)"},
|
||||||
{"files", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
{"files", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
||||||
{"from_components", "Path$from_components", "func(components:[Text] -> Path)"},
|
{"from_components", "Path$from_components", "func(components:[Text] -> Path)"},
|
||||||
{"glob", "Path$glob", "func(path:Path -> [Path])"},
|
{"glob", "Path$glob", "func(path:Path -> [Path])"},
|
||||||
|
{"group", "Path$group", "func(path:Path, follow_symlinks=yes -> Text?)"},
|
||||||
{"is_directory", "Path$is_directory", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
{"is_directory", "Path$is_directory", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||||
{"is_file", "Path$is_file", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
{"is_file", "Path$is_file", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||||
{"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
{"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||||
{"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
{"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||||
{"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"},
|
{"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"},
|
||||||
|
{"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
||||||
|
{"owner", "Path$owner", "func(path:Path, follow_symlinks=yes -> Text?)"},
|
||||||
{"parent", "Path$parent", "func(path:Path -> Path)"},
|
{"parent", "Path$parent", "func(path:Path -> Path)"},
|
||||||
{"read", "Path$read", "func(path:Path -> Text?)"},
|
{"read", "Path$read", "func(path:Path -> Text?)"},
|
||||||
{"read_bytes", "Path$read_bytes", "func(path:Path, limit=none:Int -> [Byte]?)"},
|
{"read_bytes", "Path$read_bytes", "func(path:Path, limit=none:Int -> [Byte]?)"},
|
||||||
{"relative", "Path$relative", "func(path:Path, relative_to=(./) -> Path)"},
|
|
||||||
{"relative_to", "Path$relative_to", "func(path:Path, relative_to:Path -> Path)"},
|
{"relative_to", "Path$relative_to", "func(path:Path, relative_to:Path -> Path)"},
|
||||||
{"remove", "Path$remove", "func(path:Path, ignore_missing=no)"},
|
{"remove", "Path$remove", "func(path:Path, ignore_missing=no)"},
|
||||||
{"resolved", "Path$resolved", "func(path:Path, relative_to=(./) -> Path)"},
|
{"resolved", "Path$resolved", "func(path:Path, relative_to=(./) -> Path)"},
|
||||||
|
{"set_owner", "Path$set_owner", "func(path:Path, owner=none:Text, group=none:Text, follow_symlinks=yes)"},
|
||||||
{"subdirectories", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
{"subdirectories", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
||||||
{"unique_directory", "Path$unique_directory", "func(path:Path -> Path)"},
|
{"unique_directory", "Path$unique_directory", "func(path:Path -> Path)"},
|
||||||
{"write", "Path$write", "func(path:Path, text:Text, permissions=Int32(0o644))"},
|
{"write", "Path$write", "func(path:Path, text:Text, permissions=Int32(0o644))"},
|
||||||
{"write_bytes", "Path$write_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"},
|
{"write_bytes", "Path$write_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"},
|
||||||
{"write_unique", "Path$write_unique", "func(path:Path, text:Text -> Path)"},
|
{"write_unique", "Path$write_unique", "func(path:Path, text:Text -> Path)"},
|
||||||
{"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte] -> Path)"},
|
{"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte] -> Path)"},
|
||||||
|
|
||||||
{"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
|
||||||
{"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
|
||||||
{"changed", "Path$changed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
|
||||||
)},
|
)},
|
||||||
// RNG must come after Path so we can read bytes from /dev/urandom
|
// RNG must come after Path so we can read bytes from /dev/urandom
|
||||||
{"RNG", RNG_TYPE, "RNG_t", "RNG", TypedArray(ns_entry_t,
|
{"RNG", RNG_TYPE, "RNG_t", "RNG", TypedArray(ns_entry_t,
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <gc.h>
|
#include <gc.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -215,6 +217,27 @@ public bool Path$is_symlink(Path_t path)
|
|||||||
return (sb.st_mode & S_IFMT) == S_IFLNK;
|
return (sb.st_mode & S_IFMT) == S_IFLNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Path$can_read(Path_t path)
|
||||||
|
{
|
||||||
|
path = Path$_expand_home(path);
|
||||||
|
const char *path_str = Path$as_c_string(path);
|
||||||
|
return (euidaccess(path_str, R_OK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Path$can_write(Path_t path)
|
||||||
|
{
|
||||||
|
path = Path$_expand_home(path);
|
||||||
|
const char *path_str = Path$as_c_string(path);
|
||||||
|
return (euidaccess(path_str, W_OK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Path$can_execute(Path_t path)
|
||||||
|
{
|
||||||
|
path = Path$_expand_home(path);
|
||||||
|
const char *path_str = Path$as_c_string(path);
|
||||||
|
return (euidaccess(path_str, X_OK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks)
|
public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@ -340,6 +363,45 @@ public OptionalText_t Path$read(Path_t path)
|
|||||||
return Text$from_bytes(bytes);
|
return Text$from_bytes(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OptionalText_t Path$owner(Path_t path, bool follow_symlinks)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int status = path_stat(path, follow_symlinks, &sb);
|
||||||
|
if (status != 0) return NONE_TEXT;
|
||||||
|
struct passwd *pw = getpwuid(sb.st_uid);
|
||||||
|
return pw ? Text$from_str(pw->pw_name) : NONE_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionalText_t Path$group(Path_t path, bool follow_symlinks)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int status = path_stat(path, follow_symlinks, &sb);
|
||||||
|
if (status != 0) return NONE_TEXT;
|
||||||
|
struct group *gr = getgrgid(sb.st_uid);
|
||||||
|
return gr ? Text$from_str(gr->gr_name) : NONE_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks)
|
||||||
|
{
|
||||||
|
uid_t owner_id = (uid_t)-1;
|
||||||
|
if (owner.length >= 0) {
|
||||||
|
struct passwd *pwd = getpwnam(Text$as_c_string(owner));
|
||||||
|
if (pwd == NULL) fail("Not a valid user: %k", &owner);
|
||||||
|
owner_id = pwd->pw_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
gid_t group_id = (gid_t)-1;
|
||||||
|
if (group.length >= 0) {
|
||||||
|
struct group *grp = getgrnam(Text$as_c_string(group));
|
||||||
|
if (grp == NULL) fail("Not a valid group: %k", &group);
|
||||||
|
group_id = grp->gr_gid;
|
||||||
|
}
|
||||||
|
const char *path_str = Path$as_c_string(path);
|
||||||
|
int result = follow_symlinks ? chown(path_str, owner_id, group_id) : lchown(path_str, owner_id, group_id);
|
||||||
|
if (result < 0)
|
||||||
|
fail("Could not set owner!");
|
||||||
|
}
|
||||||
|
|
||||||
public void Path$remove(Path_t path, bool ignore_missing)
|
public void Path$remove(Path_t path, bool ignore_missing)
|
||||||
{
|
{
|
||||||
path = Path$_expand_home(path);
|
path = Path$_expand_home(path);
|
||||||
@ -515,6 +577,7 @@ public Path_t Path$with_component(Path_t path, Text_t component)
|
|||||||
};
|
};
|
||||||
ARRAY_INCREF(result.components);
|
ARRAY_INCREF(result.components);
|
||||||
Array$insert(&result.components, &component, I(0), sizeof(Text_t));
|
Array$insert(&result.components, &component, I(0), sizeof(Text_t));
|
||||||
|
clean_components(&result.components);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +753,7 @@ public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type)
|
|||||||
text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text);
|
text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text);
|
||||||
else if (path->type == PATH_ABSOLUTE)
|
else if (path->type == PATH_ABSOLUTE)
|
||||||
text = Text$concat(Text("/"), text);
|
text = Text$concat(Text("/"), text);
|
||||||
else if (path->type == PATH_RELATIVE && path->components.length > 0 && !Text$equal_values(*(Text_t*)(path->components.data), Text("..")))
|
else if (path->type == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text(".."))))
|
||||||
text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text);
|
text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text);
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
|
@ -24,6 +24,9 @@ bool Path$is_directory(Path_t path, bool follow_symlinks);
|
|||||||
bool Path$is_pipe(Path_t path, bool follow_symlinks);
|
bool Path$is_pipe(Path_t path, bool follow_symlinks);
|
||||||
bool Path$is_socket(Path_t path, bool follow_symlinks);
|
bool Path$is_socket(Path_t path, bool follow_symlinks);
|
||||||
bool Path$is_symlink(Path_t path);
|
bool Path$is_symlink(Path_t path);
|
||||||
|
bool Path$can_read(Path_t path);
|
||||||
|
bool Path$can_write(Path_t path);
|
||||||
|
bool Path$can_execute(Path_t path);
|
||||||
OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks);
|
OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks);
|
||||||
OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks);
|
OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks);
|
||||||
OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks);
|
OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks);
|
||||||
@ -33,6 +36,9 @@ void Path$append(Path_t path, Text_t text, int permissions);
|
|||||||
void Path$append_bytes(Path_t path, Array_t bytes, int permissions);
|
void Path$append_bytes(Path_t path, Array_t bytes, int permissions);
|
||||||
OptionalText_t Path$read(Path_t path);
|
OptionalText_t Path$read(Path_t path);
|
||||||
OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t limit);
|
OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t limit);
|
||||||
|
void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks);
|
||||||
|
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$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);
|
||||||
Array_t Path$children(Path_t path, bool include_hidden);
|
Array_t Path$children(Path_t path, bool include_hidden);
|
||||||
|
Loading…
Reference in New Issue
Block a user