Skip to content

Commit c610e58

Browse files
authored
Add File.exists! (#380)
* added File.exists! * small correction * investigate check_all_exposed_funs_tested * try linker legacy for debug info * workaround + cleanup * try altering codegen units
1 parent dcc7070 commit c610e58

File tree

8 files changed

+79
-11
lines changed

8 files changed

+79
-11
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ lto = true
2525
strip = "debuginfo"
2626
# You can comment this out if you hit a segmentation fault similar to the one in see issue github.com/roc-lang/roc/issues/6121
2727
# Setting this to 1 should improve execution speed by making things easier to optimize for LLVM.
28-
codegen-units = 1
28+
# codegen-units = 1
2929

3030
[workspace.dependencies]
3131
roc_std = { git = "https://github.com/roc-lang/roc.git" }

ci/expect_scripts/file.exp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,22 @@ expect "Testing some File functions..." {
5959
expect "✓ Renamed file test_rename_new.txt exists" {
6060
expect "✓ Renamed file has correct content" {
6161

62-
# Cleanup phase
63-
expect "Cleaning up test files..." {
64-
expect "✓ Deleted all files." {
65-
66-
# Final completion message
67-
expect "I ran all file function tests." {
68-
expect eof {
69-
check_exit_and_segfault
62+
# Test File.exists!
63+
expect "Testing File.exists!:" {
64+
expect "✓ File.exists! returns true for a file that exists" {
65+
expect "✓ File.exists! returns false for a file that does not exist" {
66+
67+
# Cleanup phase
68+
expect "Cleaning up test files..." {
69+
expect "✓ Deleted all files." {
70+
71+
# Final completion message
72+
expect "I ran all file function tests." {
73+
expect eof {
74+
check_exit_and_segfault
75+
}
76+
}
77+
}
7078
}
7179
}
7280
}

crates/roc_file/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,14 @@ pub fn file_time_created(roc_path: &RocList<u8>) -> RocResult<roc_std::U128, IOE
343343
}
344344
}
345345

346+
pub fn file_exists(roc_path: &RocList<u8>) -> RocResult<bool, IOErr> {
347+
let path = path_from_roc_path(roc_path);
348+
match path.try_exists() {
349+
Ok(exists) => RocResult::ok(exists),
350+
Err(err) => RocResult::err(err.into()),
351+
}
352+
}
353+
346354
pub fn file_rename(from_path: &RocList<u8>, to_path: &RocList<u8>) -> RocResult<(), IOErr> {
347355
let rust_from_path = path_from_roc_path(from_path);
348356
let rust_to_path = path_from_roc_path(to_path);

crates/roc_host/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ pub fn init() {
324324
roc_fx_file_time_accessed as _,
325325
roc_fx_file_time_modified as _,
326326
roc_fx_file_time_created as _,
327+
roc_fx_file_exists as _,
327328
roc_fx_file_rename as _,
328329
roc_fx_hard_link as _,
329330
roc_fx_cwd as _,
@@ -569,6 +570,11 @@ pub extern "C" fn roc_fx_file_time_created(
569570
roc_file::file_time_created(roc_path)
570571
}
571572

573+
#[no_mangle]
574+
pub extern "C" fn roc_fx_file_exists(roc_path: &RocList<u8>) -> RocResult<bool, roc_io_error::IOErr> {
575+
roc_file::file_exists(roc_path)
576+
}
577+
572578
#[no_mangle]
573579
pub extern "C" fn roc_fx_file_rename(
574580
from_path: &RocList<u8>,

flake.nix

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
pkgs.rust-bin.fromRustupToolchainFile "${toString ./rust-toolchain.toml}";
3232

3333
aliases = ''
34+
alias buildcmd='bash jump-start.sh && roc ./build.roc -- --roc roc'
3435
alias testcmd='export ROC=roc && export EXAMPLES_DIR=./examples/ && ./ci/all_tests.sh'
3536
'';
3637

@@ -72,9 +73,13 @@
7273

7374
shellHook = ''
7475
${aliases}
76+
77+
echo "Some convenient command aliases:"
78+
echo "${aliases}" | grep -E "alias [^=]+" -o | sed 's/alias / /' | sort
79+
echo ""
7580
'';
7681
};
7782

7883
formatter = pkgs.nixpkgs-fmt;
7984
});
80-
}
85+
}

platform/File.roc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module [
1010
is_dir!,
1111
is_file!,
1212
is_sym_link!,
13+
exists!,
1314
is_executable!,
1415
is_readable!,
1516
is_writable!,
@@ -213,6 +214,14 @@ is_sym_link! : Str => Result Bool [PathErr IOErr]
213214
is_sym_link! = |path_str|
214215
Path.is_sym_link!(Path.from_str(path_str))
215216

217+
## Returns true if the path exists on disk.
218+
##
219+
## This uses [rust's std::path::try_exists](https://doc.rust-lang.org/std/path/struct.Path.html#method.try_exists).
220+
exists! : Str => Result Bool [PathErr IOErr]
221+
exists! = |path_str|
222+
Host.file_exists!(InternalPath.to_bytes(Path.from_str(path_str)))
223+
|> Result.map_err(|err| PathErr(InternalIOErr.handle_err(err)))
224+
216225
## Checks if the file has the execute permission for the current process.
217226
##
218227
## This uses rust [std::fs::Metadata](https://doc.rust-lang.org/std/fs/struct.Metadata.html).

platform/Host.roc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ hosted [
1414
env_var!,
1515
exe_path!,
1616
file_delete!,
17+
file_exists!,
1718
file_read_bytes!,
1819
file_reader!,
1920
file_read_line!,
@@ -75,6 +76,7 @@ file_write_utf8! : List U8, Str => Result {} InternalIOErr.IOErrFromHost
7576
file_delete! : List U8 => Result {} InternalIOErr.IOErrFromHost
7677
file_read_bytes! : List U8 => Result (List U8) InternalIOErr.IOErrFromHost
7778
file_size_in_bytes! : List U8 => Result U64 InternalIOErr.IOErrFromHost
79+
file_exists! : List U8 => Result Bool InternalIOErr.IOErrFromHost
7880
file_is_executable! : List U8 => Result Bool InternalIOErr.IOErrFromHost
7981
file_is_readable! : List U8 => Result Bool InternalIOErr.IOErrFromHost
8082
file_is_writable! : List U8 => Result Bool InternalIOErr.IOErrFromHost

tests/file.roc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ main! = |_args|
3131
# Test file rename
3232
test_file_rename!({})?
3333
34+
# Test file exists
35+
test_file_exists!({})?
36+
3437
# Clean up test files
3538
cleanup_test_files!({})?
3639
@@ -206,6 +209,33 @@ test_file_rename! = |{}|
206209

207210
Ok({})
208211

212+
test_file_exists! : {} => Result {} _
213+
test_file_exists! = |{}|
214+
Stdout.line!("\nTesting File.exists!:")?
215+
216+
# Test that a file that exists returns true
217+
filename = "test_exists.txt"
218+
File.write_utf8!("", filename)?
219+
220+
test_file_exists = File.exists!(filename) ? |err| FileExistsCheckFailed(err)
221+
222+
if test_file_exists then
223+
Stdout.line!("✓ File.exists! returns true for a file that exists")?
224+
else
225+
Stderr.line!("File.exists! returned false for a file that exists")?
226+
227+
# Test that a file that does not exist returns false
228+
File.delete!(filename)?
229+
230+
test_file_exists_after_delete = File.exists!(filename) ? |err| FileExistsCheckAfterDeleteFailed(err)
231+
232+
if test_file_exists_after_delete then
233+
Stderr.line!("File.exists! returned true for a file that does not exist")?
234+
else
235+
Stdout.line!("File.exists! returns false for a file that does not exist")?
236+
237+
Ok({})
238+
209239
cleanup_test_files! : {} => Result {} _
210240
cleanup_test_files! = |{}|
211241
Stdout.line!("\nCleaning up test files...")?
@@ -217,7 +247,7 @@ cleanup_test_files! = |{}|
217247
"test_multiline.txt",
218248
"test_original_file.txt",
219249
"test_link_to_original.txt",
220-
"test_rename_new.txt"
250+
"test_rename_new.txt",
221251
]
222252
223253
List.for_each_try!(test_files, |filename| File.delete!(filename)) ? |err| FileDeletionFailed(err)

0 commit comments

Comments
 (0)