Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of get_files #30

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- improve performance of `get_files`

## v1.7.0 - 5 April 2024
- add `create_symlink` function to create a symbolic link
- add `verify_is_symlink` function to check if a file is a symbolic link
Expand All @@ -12,7 +14,7 @@
relative.

## v1.6.0 - 26 March 2024
- add the `clear_directory` function to make it easy to delete the
- add the `clear_directory` function to make it easy to delete the
contents of a directory while leaving the top level directory in place.
- add the `filepath` dependency to clean up some code.

Expand Down Expand Up @@ -90,8 +92,8 @@
- Small refactor to remove js functions `writeFile` and `appendFile`

## v0.1.7 - 31 July 2023
- Fix bug where `read` was incorrectly returning non utf8 content for string on
javascript target. Now returns correct `NonUtf8` error
- Fix bug where `read` was incorrectly returning non utf8 content for string on
javascript target. Now returns correct `NonUtf8` error

## v0.1.6 - 19 July 2023
- Add `make_directory` and `delete_directory` functions for working with directories.
Expand All @@ -110,4 +112,4 @@

## v0.1.1 - 31 May 2023
- Refactored to match gleam idiom of ffi "do" functions and single signature.
- Added documentation about the utf8 issue with the read function.
- Added documentation about the utf8 issue with the read function.
65 changes: 35 additions & 30 deletions src/simplifile.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ pub type FileInfo {
FileInfo(
/// File size in bytes.
size: Int,
/// File mode that indicates the file type and its permissions.
/// For example, in Unix and Linux, a mode value of 33188 indicates
/// a regular file and the permissions associated with it
/// (read and write for the owner, and read-only for others, in
/// File mode that indicates the file type and its permissions.
/// For example, in Unix and Linux, a mode value of 33188 indicates
/// a regular file and the permissions associated with it
/// (read and write for the owner, and read-only for others, in
/// this case).
mode: Int,
/// Number of hard links that exist for the file.
Expand Down Expand Up @@ -265,9 +265,9 @@ pub fn delete(file_or_dir_at path: String) -> Result(Nil, FileError) {

/// Delete all files/directories specified in a list of paths.
/// Recursively deletes provided directories.
/// Does not return an error if one or more of the provided paths
/// do not exist.
///
/// Does not return an error if one or more of the provided paths
/// do not exist.
///
pub fn delete_all(paths paths: List(String)) -> Result(Nil, FileError) {
case paths {
[] -> Ok(Nil)
Expand Down Expand Up @@ -338,15 +338,15 @@ pub fn append_bits(
/// ```gleam
/// let assert True = is_directory("./test")
/// ```
///
///
@deprecated("Use `verify_is_directory` instead")
pub fn is_directory(filepath: String) -> Bool {
do_is_directory(filepath)
}

/// Checks if the provided filepath exists and is a directory.
/// Returns an error if it lacks permissions to read the directory.
///
///
/// ## Example
/// ```gleam
/// let assert Ok(True) = verify_is_directory("./test")
Expand Down Expand Up @@ -392,27 +392,27 @@ pub fn create_symlink(

/// Lists the contents of a directory.
/// The list contains directory and file names, and is not recursive.
///
///
/// ## Example
/// ```gleam
/// let assert Ok(files_and_folders) = read_directory(at: "./Folder1")
/// ```
///
///
pub fn read_directory(at path: String) -> Result(List(String), FileError) {
do_read_directory(path)
|> cast_error
}

/// Returns `True` if there is a file at the given path, false otherwise.
///
///
@deprecated("Use `verify_is_file` instead")
pub fn is_file(filepath: String) -> Bool {
do_is_file(filepath)
}

/// Checks if the file at the provided filepath exists and is a file.
/// Returns an Error if it lacks permissions to read the file.
///
///
/// ## Example
/// ```gleam
/// let assert Ok(True) = verify_is_file("./test.txt")
Expand Down Expand Up @@ -454,7 +454,7 @@ fn do_verify_is_symlink(filepath: String) -> Result(Bool, FileError)

/// Creates an empty file at the given filepath. Returns an `Error(Eexist)`
/// if the file already exists.
///
///
pub fn create_file(at filepath: String) -> Result(Nil, FileError) {
case
filepath
Expand Down Expand Up @@ -502,8 +502,8 @@ pub fn rename_file(at src: String, to dest: String) -> Result(Nil, FileError) {

/// Copy a directory recursively
pub fn copy_directory(at src: String, to dest: String) -> Result(Nil, FileError) {
// Erlang does not provide a built in `copy_dir` function,
// and Deno doesn't support Node's `fs.cpSync`, so we'll just roll
// Erlang does not provide a built in `copy_dir` function,
// and Deno doesn't support Node's `fs.cpSync`, so we'll just roll
// our own for now.
use _ <- result.try(create_directory_all(dest))
do_copy_directory(src, dest)
Expand Down Expand Up @@ -561,19 +561,24 @@ pub fn clear_directory(at path: String) -> Result(Nil, FileError) {

/// Returns a list of filepaths for every file in the directory, including nested
/// files.
///
///
pub fn get_files(in directory: String) -> Result(List(String), FileError) {
use contents <- result.try(read_directory(directory))
let paths =
contents
|> list.map(filepath.join(directory, _))
let files = list.filter(paths, fn(path) { verify_is_file(path) == Ok(True) })
case list.filter(paths, fn(path) { verify_is_directory(path) == Ok(True) }) {
[] -> Ok(files)
directories -> {
use nested_files <- result.try(list.try_map(directories, get_files))
Ok(list.append(files, list.flatten(nested_files)))
}
use acc, content <- list.try_fold(over: contents, from: [])
let path = filepath.join(directory, content)

case verify_is_file(path) {
Error(e) -> Error(e)
Ok(True) -> Ok([path, ..acc])
Ok(False) ->
case verify_is_directory(path) {
Error(e) -> Error(e)
Ok(False) -> Ok(acc)
Ok(True) -> {
use nested_files <- result.try(get_files(path))
Ok(list.append(acc, nested_files))
}
}
}
}

Expand Down Expand Up @@ -617,7 +622,7 @@ pub fn file_permissions_to_octal(permissions: FilePermissions) -> Int {
}

/// Sets the permissions for a given file
///
///
/// # Example
/// ```gleam
/// let all = set.from_list([Read, Write, Execute])
Expand All @@ -632,7 +637,7 @@ pub fn set_permissions(
}

/// Sets the permissions for a given file using an octal representation
///
///
/// # Example
/// ```gleam
/// set_permissions_octal("./script.sh", 0o777)
Expand All @@ -646,7 +651,7 @@ pub fn set_permissions_octal(
}

/// Returns the current working directory
///
///
pub fn current_directory() -> Result(String, FileError) {
do_current_directory()
|> cast_error
Expand Down
Loading