path.exists

This commit is contained in:
Francesco Mecca 2024-12-07 14:27:39 +01:00
parent 0055b8f6cb
commit 350cd98661
3 changed files with 32 additions and 18 deletions

View file

@ -2,6 +2,7 @@ module internal Pentole.Native
open System
open System.Runtime.InteropServices
open System.Runtime.CompilerServices
[<DllImport("libc", EntryPoint = "realpath", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)>]
@ -10,7 +11,6 @@ extern nativeint _realpath (string _path, nativeint _resolved_path)
[<DllImport("libc", EntryPoint = "strerror", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)>]
extern nativeint _strerror (int _errnum)
let realpath (path: string) =
let ptr = _realpath(path, IntPtr.Zero)
if ptr = IntPtr.Zero then

View file

@ -2,8 +2,8 @@ namespace Pentole
open System
module Internal =
/// don't use
module PathInternal =
let private invalid_chars = System.IO.Path.GetInvalidPathChars ()
let trim (a: string) =
@ -28,13 +28,20 @@ module Internal =
type IPath =
abstract member ToString: unit -> string
/// The string value of the path. Mainly useful for C# interop.
abstract member string_value: string
inherit IEquatable<IPath>
inherit IComparable
/// Specifies a location in the file system from the root
/// directory. It is not dependent on the current working directory
/// and provides a complete path to a file or directory. Note that an
/// `AbsolutePath` does not have to correspond to an actual file or
/// directory on the file system. To verify its existence or resolve
/// it to a real file, additional methods in the FileSystem module are provided
[<Struct>]
[<CustomEquality>]
[<CustomComparison>]
[<CustomComparison>]
type AbsolutePath internal (path: string) =
interface IPath with
member _.ToString () = $"AbsolutePath {path}"
@ -50,8 +57,15 @@ type AbsolutePath internal (path: string) =
interface IEquatable<IPath> with
member _.Equals (o: IPath) =
Internal.trim o.string_value = path
PathInternal.trim o.string_value = path
/// Specifies a location in the file system relative to the current
/// working directory. It does not provide a complete path and is
/// dependent on the context in which it is used. Similar to
/// `AbsolutePath`, a `RelativePath` does not have to correspond to an
/// actual file or directory. To verify its existence or resolve
/// it to a real file, additional methods in the FileSystem module are provided
/// should be used.
[<Struct>]
[<CustomEquality>]
[<CustomComparison>]
@ -69,11 +83,12 @@ type RelativePath internal (path: string) =
interface IEquatable<IPath> with
member _.Equals (o: IPath) =
Internal.trim o.string_value = path
PathInternal.trim o.string_value = path
module Path =
/// Construct a IPath object from the given path.
let of_string (path: string): Result<IPath, string> =
match Internal.construct path with
match PathInternal.construct path with
| Ok (path, true) -> AbsolutePath path :> IPath |> Ok
| Ok (path, false) -> RelativePath path :> IPath |> Ok
| Error e -> Error e
@ -121,13 +136,6 @@ module Path =
/// Returns the parent directory of the given path.
///
/// If the path is the root directory or does not have a parent, the original path is returned.
///
/// # Arguments
///
/// * `path`: The path to get the parent directory of.
///
/// # Returns
/// The parent directory of the given path, or the original path if it has no parent
let parent (path: IPath) =
let parent = IO.Path.GetDirectoryName path.string_value
if parent = null then
@ -135,12 +143,12 @@ module Path =
else
parent |> should_not_fail
// impure functions
// https://docs.python.org/3.8/library/pathlib.html
module FileSystem =
let resolve (path: IPath) =
Native.realpath path.string_value |> Result.bind Path.of_string
let exists (path: IPath) =
IO.Path.Exists path.string_value
(*
let relative_to (parent: Path) (child: Path) =

View file

@ -75,3 +75,9 @@ let parent_test () =
"/etc/conf" |> test |> Assert.are_equal (p "/etc")
"/etc/../etc" |> test |> Assert.are_equal (p "/etc/../")
"etc/../etc" |> test |> Assert.are_equal (p "etc/../")
[<Test>]
let exitsts_test () =
let p (n: string ) = Path.of_string n |> Result.Unsafe.get
FileSystem.exists (p "/tmp/") |> Assert.is_true
FileSystem.exists (p "/IHOPE_this_DOESNT_exist/") |> Assert.is_false