Skip to content

Commit

Permalink
Merge pull request #30 from giacomocavalieri/perf-optimisation
Browse files Browse the repository at this point in the history
Improve performance of `get_files`
  • Loading branch information
bcpeinhardt authored May 14, 2024
2 parents 1deee71 + 8545e5e commit 22ae565
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 34 deletions.
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

0 comments on commit 22ae565

Please sign in to comment.