Skip to content

Commit 838ef4f

Browse files
authored
Merge pull request #36 from joshi-monster/lstat
add `link_info`
2 parents 5193b3e + 86f502f commit 838ef4f

File tree

5 files changed

+63
-6
lines changed

5 files changed

+63
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

33
## Unreleased
4+
- Add `link_info` function to get `FileInfo` values without following symlinks
45

56
## v2.0.1 - 27 June 2024
67
- Internal refactoring and some added tests

src/simplifile.gleam

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,25 @@ pub type FileInfo {
211211
}
212212

213213
/// Get information about a file at a given path
214+
///
215+
/// When the given `filepath` points to a symlink, this function will follow
216+
/// the symlink and return information about the target file.
217+
///
218+
/// See `link_info` if you want to get information about a symlink instead.
214219
@external(erlang, "simplifile_erl", "file_info")
215220
@external(javascript, "./simplifile_js.mjs", "fileInfo")
216221
pub fn file_info(filepath: String) -> Result(FileInfo, FileError)
217222

223+
/// Get information about a file at a given path
224+
///
225+
/// When the given `filepath` is a symlink, this function will return
226+
/// infromation about the symlink itself.
227+
///
228+
/// See `file_info` if you want to follow symlinks instead.
229+
@external(erlang, "simplifile_erl", "link_info")
230+
@external(javascript, "./simplifile_js.mjs", "linkInfo")
231+
pub fn link_info(filepath: String) -> Result(FileInfo, FileError)
232+
218233
/// Read a files contents as a string
219234
/// ## Example
220235
/// ```gleam

src/simplifile_erl.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
delete/1,
1717
delete_directory/1,
1818
file_info/1,
19+
link_info/1,
1920
is_directory/1,
2021
is_file/1,
2122
is_symlink/1,
@@ -223,3 +224,6 @@ file_info_result(Result) ->
223224

224225
file_info(Filename) ->
225226
file_info_result(file:read_file_info(Filename, [{time, posix}])).
227+
228+
link_info(Filename) ->
229+
file_info_result(file:read_link_info(Filename, [{time, posix}])).

src/simplifile_js.mjs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,28 @@ export function currentDirectory() {
203203
* @returns {Ok | GError}
204204
*/
205205
export function fileInfo(filepath) {
206-
return gleamResult(() => new FileInfo(filepath));
206+
return gleamResult(() => {
207+
const stat = fs.statSync(path.normalize(filepath))
208+
return new FileInfo(stat)
209+
});
210+
}
211+
212+
/**
213+
* @param {string} filepath
214+
* @returns {Ok | GError}
215+
*/
216+
export function linkInfo(filepath) {
217+
return gleamResult(() => {
218+
const stat = fs.lstatSync(path.normalize(filepath))
219+
return new FileInfo(stat)
220+
})
207221
}
208222

209223
class FileInfo {
210-
constructor(filepath) {
211-
const stat = fs.statSync(path.normalize(filepath));
224+
/**
225+
* @param {fs.Stats} stat
226+
*/
227+
constructor(stat) {
212228
this.size = stat.size;
213229
this.mode = stat.mode;
214230
this.nlinks = stat.nlink;

test/simplifile_test.gleam

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import simplifile.{
1212
FilePermissions, NotUtf8, Read, Unknown, Write, append, append_bits,
1313
copy_directory, copy_file, create_directory, create_directory_all, create_file,
1414
create_symlink, delete, delete_all, file_info, file_permissions_to_octal,
15-
get_files, is_directory, is_file, is_symlink, read, read_bits, read_directory,
16-
rename_directory, rename_file, set_permissions, set_permissions_octal, write,
17-
write_bits,
15+
get_files, is_directory, is_file, is_symlink, link_info, read, read_bits,
16+
read_directory, rename_directory, rename_file, set_permissions,
17+
set_permissions_octal, write, write_bits,
1818
}
1919

2020
pub fn main() {
@@ -473,6 +473,27 @@ pub fn file_info_test() {
473473
let assert Ok(_info) = file_info("./test.sh")
474474
}
475475

476+
pub fn link_info_test() {
477+
let target_path = "./tmp/the_target"
478+
let symlink_path = "./tmp/the_symlink"
479+
let target_relative_to_symlink = "the_target"
480+
481+
let assert Ok(_) = write(to: target_path, contents: "Wibble")
482+
let assert Ok(_) = create_symlink(target_relative_to_symlink, symlink_path)
483+
484+
let assert Ok(lstat) = link_info(symlink_path)
485+
let assert Ok(stat) = file_info(symlink_path)
486+
487+
stat
488+
|> should.not_equal(lstat)
489+
490+
stat.size
491+
|> should.equal(6)
492+
493+
lstat.size
494+
|> should.not_equal(6)
495+
}
496+
476497
/// I visually inspected this info to make sure it matched on all targets.
477498
/// TODO: Add a better test setup for validating file info functionality.
478499
pub fn clear_directory_test() {

0 commit comments

Comments
 (0)