From e4f613c1bc6392b6db96d374fe8f620d58f510d0 Mon Sep 17 00:00:00 2001 From: Joshua Reusch Date: Mon, 26 Aug 2024 20:13:33 +0200 Subject: [PATCH 1/3] add `link_info` --- src/simplifile.gleam | 15 +++++++++++++++ src/simplifile_erl.erl | 4 ++++ src/simplifile_js.mjs | 22 +++++++++++++++++++--- test/simplifile_test.gleam | 22 +++++++++++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/simplifile.gleam b/src/simplifile.gleam index 2bd43d5..29161e9 100644 --- a/src/simplifile.gleam +++ b/src/simplifile.gleam @@ -211,10 +211,25 @@ pub type FileInfo { } /// Get information about a file at a given path +/// +/// When the given `filepath` points to a symlink, this function will follow +/// the symlink and return information about the target file. +/// +/// See `link_info` if you want to get information about a symlink instead. @external(erlang, "simplifile_erl", "file_info") @external(javascript, "./simplifile_js.mjs", "fileInfo") pub fn file_info(filepath: String) -> Result(FileInfo, FileError) +/// Get information about a file at a given path +/// +/// When the given `filepath` is a symlink, this function will return +/// infromation about the symlink itself. +/// +/// See `file_info` if you want to follow symlinks instead. +@external(erlang, "simplifile_erl", "link_info") +@external(javascript, "./simplifile_js.mjs", "linkInfo") +pub fn link_info(filepath: String) -> Result(FileInfo, FileError) + /// Read a files contents as a string /// ## Example /// ```gleam diff --git a/src/simplifile_erl.erl b/src/simplifile_erl.erl index 3d7e3ca..f554560 100644 --- a/src/simplifile_erl.erl +++ b/src/simplifile_erl.erl @@ -16,6 +16,7 @@ delete/1, delete_directory/1, file_info/1, + link_info/1, is_directory/1, is_file/1, is_symlink/1, @@ -223,3 +224,6 @@ file_info_result(Result) -> file_info(Filename) -> file_info_result(file:read_file_info(Filename, [{time, posix}])). + +link_info(Filename) -> + file_info_result(file:read_link_info(Filename, [{time, posix}])). diff --git a/src/simplifile_js.mjs b/src/simplifile_js.mjs index 0d28136..0de01a5 100644 --- a/src/simplifile_js.mjs +++ b/src/simplifile_js.mjs @@ -203,12 +203,28 @@ export function currentDirectory() { * @returns {Ok | GError} */ export function fileInfo(filepath) { - return gleamResult(() => new FileInfo(filepath)); + return gleamResult(() => { + const stat = fs.statSync(path.normalize(filepath)) + return new FileInfo(stat) + }); +} + +/** + * @param {string} filepath + * @returns {Ok | GError} + */ +export function linkInfo(filepath) { + return gleamResult(() => { + const stat = fs.lstatSync(path.normalize(filepath)) + return new FileInfo(stat) + }) } class FileInfo { - constructor(filepath) { - const stat = fs.statSync(path.normalize(filepath)); + /** + * @param {fs.Stats} stat + */ + constructor(stat) { this.size = stat.size; this.mode = stat.mode; this.nlinks = stat.nlink; diff --git a/test/simplifile_test.gleam b/test/simplifile_test.gleam index f33b18f..396f5a4 100644 --- a/test/simplifile_test.gleam +++ b/test/simplifile_test.gleam @@ -12,9 +12,9 @@ import simplifile.{ FilePermissions, NotUtf8, Read, Unknown, Write, append, append_bits, copy_directory, copy_file, create_directory, create_directory_all, create_file, create_symlink, delete, delete_all, file_info, file_permissions_to_octal, - get_files, is_directory, is_file, is_symlink, read, read_bits, read_directory, - rename_directory, rename_file, set_permissions, set_permissions_octal, write, - write_bits, + get_files, is_directory, is_file, is_symlink, link_info, read, read_bits, + read_directory, rename_directory, rename_file, set_permissions, + set_permissions_octal, write, write_bits, } pub fn main() { @@ -473,6 +473,22 @@ pub fn file_info_test() { let assert Ok(_info) = file_info("./test.sh") } +pub fn link_info_test() { + let target_path = "./tmp/the_target" + let symlink_path = "./tmp/the_symlink" + let target_relative_to_symlink = "the_target" + + let assert Ok(_) = write(to: target_path, contents: "Wibble") + let assert Ok(_) = create_symlink(target_relative_to_symlink, symlink_path) + + let assert Ok(lstat) = link_info(symlink_path) + let assert Ok(stat) = file_info(symlink_path) + + let assert False = stat == lstat + let assert True = stat.size == 6 + let assert False = lstat.size == 6 +} + /// I visually inspected this info to make sure it matched on all targets. /// TODO: Add a better test setup for validating file info functionality. pub fn clear_directory_test() { From 8c1fb10cc9e6a0312ae14a31b7cc7f665cd75ac1 Mon Sep 17 00:00:00 2001 From: Joshua Reusch Date: Tue, 27 Aug 2024 18:36:51 +0200 Subject: [PATCH 2/3] switch to gleeunit --- test/simplifile_test.gleam | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/simplifile_test.gleam b/test/simplifile_test.gleam index 396f5a4..6ad80f4 100644 --- a/test/simplifile_test.gleam +++ b/test/simplifile_test.gleam @@ -484,9 +484,14 @@ pub fn link_info_test() { let assert Ok(lstat) = link_info(symlink_path) let assert Ok(stat) = file_info(symlink_path) - let assert False = stat == lstat - let assert True = stat.size == 6 - let assert False = lstat.size == 6 + stat + |> should.not_equal(lstat) + + stat.size + |> should.equal(6) + + lstat.size + |> should.not_equal(6) } /// I visually inspected this info to make sure it matched on all targets. From 86f502f5cd19afb0e2a3462b0052850333bc2024 Mon Sep 17 00:00:00 2001 From: Joshua Reusch Date: Wed, 28 Aug 2024 09:35:06 +0200 Subject: [PATCH 3/3] update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 692aa18..4bd6942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- Add `link_info` function to get `FileInfo` values without following symlinks ## v2.0.1 - 27 June 2024 - Internal refactoring and some added tests