Tidy Eio interface

Instead of passing in an FS capability and a path, the interface now
only takes an _ Eio.Path.t.

+6 -3
bin/mlgpx_cli.ml
··· 3 3 open Cmdliner 4 4 open Gpx 5 5 6 + let ( / ) = Eio.Path.( / ) 7 + 6 8 (* Terminal and formatting setup *) 7 9 let setup_fmt style_renderer = 8 10 Fmt_tty.setup_std_outputs ?style_renderer (); ··· 67 69 log_info "Reading GPX file: %a" (bold_style Fmt.string) input_file; 68 70 69 71 (* Read input GPX *) 70 - let gpx = Gpx_eio.read ~fs input_file in 72 + let gpx = Gpx_eio.read (fs / input_file) in 71 73 72 74 if verbose then 73 75 log_info "Found %d waypoints and %d existing tracks" ··· 140 142 log_info "Writing output to: %a" (bold_style Fmt.string) output_file; 141 143 142 144 (* Write output GPX *) 143 - Gpx_eio.write ~fs output_file output_gpx; 145 + Gpx_eio.write (fs / output_file) output_gpx; 144 146 145 147 if verbose then ( 146 148 Fmt.pf Format.std_formatter "%a\n" (success_style Fmt.string) "Conversion completed successfully!"; ··· 215 217 if verbose then 216 218 log_info "Analyzing GPX file: %a" (bold_style Fmt.string) input_file; 217 219 218 - let gpx = Gpx_eio.read ~fs input_file in 220 + let gpx = Gpx_eio.read (fs / input_file) in 219 221 220 222 (* Header *) 221 223 Fmt.pf Format.std_formatter "%a\n" (bold_style Fmt.string) "GPX File Information"; ··· 255 257 let duration_span = Ptime.diff stop_time start_time in 256 258 match Ptime.Span.to_int_s duration_span with 257 259 | Some seconds -> 260 + let ( / ) = Int.div in 258 261 let days = seconds / 86400 in 259 262 let hours = (seconds mod 86400) / 3600 in 260 263 let minutes = (seconds mod 3600) / 60 in
+3 -3
lib/gpx_eio/gpx_eio.ml
··· 3 3 module IO = Gpx_io 4 4 5 5 (** Read and parse GPX file *) 6 - let read ?(validate=false) ~fs path = IO.read_file ~validate ~fs path 6 + let read ?(validate=false) path = IO.read_file ~validate path 7 7 8 8 (** Write GPX to file *) 9 - let write ?(validate=false) ~fs path gpx = IO.write_file ~validate ~fs path gpx 9 + let write ?(validate=false) path gpx = IO.write_file ~validate path gpx 10 10 11 11 (** Write GPX to file with backup *) 12 - let write_with_backup ?(validate=false) ~fs path gpx = IO.write_file_with_backup ~validate ~fs path gpx 12 + let write_with_backup ?(validate=false) path gpx = IO.write_file_with_backup ~validate path gpx 13 13 14 14 (** Read GPX from Eio source *) 15 15 let from_source ?(validate=false) source = IO.read_source ~validate source
+7 -10
lib/gpx_eio/gpx_eio.mli
··· 38 38 These functions provide simple file I/O with the filesystem from {!Eio.Stdenv.fs}. *) 39 39 40 40 (** Read and parse GPX file. 41 - @param fs Filesystem capability 42 41 @param path File path to read 43 42 @param ?validate Optional validation flag (default: false) 44 43 @return GPX document 45 44 @raises Gpx.Gpx_error on read or parse failure *) 46 - val read : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t 45 + val read : ?validate:bool -> _ Eio.Path.t -> Gpx.t 47 46 48 47 (** Write GPX to file. 49 - @param fs Filesystem capability 50 48 @param path File path to write 51 49 @param gpx GPX document to write 52 50 @param ?validate Optional validation flag (default: false) 53 51 @raises Gpx.Gpx_error on write failure *) 54 - val write : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> unit 52 + val write : ?validate:bool -> _ Eio.Path.t -> Gpx.t -> unit 55 53 56 54 (** Write GPX to file with automatic backup. 57 - @param fs Filesystem capability 58 55 @param path File path to write 59 56 @param gpx GPX document to write 60 57 @param ?validate Optional validation flag (default: false) 61 - @return Backup file path (empty if no backup created) 58 + @return Backup file path ([None] if no backup created) 62 59 @raises Gpx.Gpx_error on failure *) 63 - val write_with_backup : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> string 60 + val write_with_backup : ?validate:bool -> 'a Eio.Path.t -> Gpx.t -> 'a Eio.Path.t option 64 61 65 62 (** {2 Stream Operations} 66 63 ··· 71 68 @param ?validate Optional validation flag (default: false) 72 69 @return GPX document 73 70 @raises Gpx.Gpx_error on read or parse failure *) 74 - val from_source : ?validate:bool -> [> Eio.Flow.source_ty ] Eio.Resource.t -> Gpx.t 71 + val from_source : ?validate:bool -> _ Eio.Flow.source -> Gpx.t 75 72 76 73 (** Write GPX to Eio sink. 77 74 @param sink Output flow 78 75 @param gpx GPX document 79 76 @param ?validate Optional validation flag (default: false) 80 77 @raises Gpx.Gpx_error on write failure *) 81 - val to_sink : ?validate:bool -> [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit 78 + val to_sink : ?validate:bool -> _ Eio.Flow.sink -> Gpx.t -> unit 82 79 83 80 (** Print GPX statistics to sink. 84 81 @param sink Output sink 85 82 @param gpx GPX document *) 86 - val print_stats : [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit 83 + val print_stats : _ Eio.Flow.sink -> Gpx.t -> unit
+27 -29
lib/gpx_eio/gpx_io.ml
··· 1 1 (** GPX Eio I/O operations *) 2 2 3 3 (** Read GPX from file path *) 4 - let read_file ?(validate=false) ~fs path = 5 - let content = Eio.Path.load Eio.Path.(fs / path) in 4 + let read_file ?(validate=false) path = 5 + let content = Eio.Path.load path in 6 6 match Gpx.parse_string ~validate content with 7 7 | Ok gpx -> gpx 8 8 | Error err -> raise (Gpx.Gpx_error err) 9 9 10 10 (** Write GPX to file path *) 11 - let write_file ?(validate=false) ~fs path gpx = 11 + let write_file ?(validate=false) path gpx = 12 12 match Gpx.write_string ~validate gpx with 13 13 | Ok xml_string -> 14 - Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) xml_string 14 + Eio.Path.save ~create:(`Or_truncate 0o644) path xml_string 15 15 | Error err -> raise (Gpx.Gpx_error err) 16 16 17 17 (** Read GPX from Eio source *) ··· 29 29 | Error err -> raise (Gpx.Gpx_error err) 30 30 31 31 (** Check if file exists *) 32 - let file_exists ~fs path = 33 - try 34 - let _stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in 35 - true 36 - with 37 - | _ -> false 32 + let file_exists = Eio.Path.is_file 38 33 39 34 (** Get file size *) 40 - let file_size ~fs path = 35 + let file_size path = 41 36 try 42 - let stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in 37 + let stat = Eio.Path.stat ~follow:true path in 43 38 Optint.Int63.to_int stat.size 44 39 with 45 40 | exn -> raise (Gpx.Gpx_error (Gpx.Error.io_error (Printexc.to_string exn))) 46 41 47 42 (** Create backup of existing file *) 48 - let create_backup ~fs path = 49 - if file_exists ~fs path then 50 - let backup_path = path ^ ".backup" in 51 - let content = Eio.Path.load Eio.Path.(fs / path) in 52 - Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / backup_path) content; 53 - backup_path 43 + let create_backup ((fs, inner_path) as path) = 44 + if file_exists path then 45 + let backup_path = inner_path ^ ".backup" in 46 + let content = Eio.Path.load path in 47 + Eio.Path.save ~create:(`Or_truncate 0o644) (fs, backup_path) content; 48 + Some (fs, backup_path) 54 49 else 55 - "" 50 + None 56 51 57 52 (** Write GPX to file with automatic backup *) 58 - let write_file_with_backup ?(validate=false) ~fs path gpx = 59 - let backup_path = create_backup ~fs path in 53 + let write_file_with_backup ?(validate=false) path gpx = 54 + let backup_path = create_backup path in 60 55 try 61 - write_file ~validate ~fs path gpx; 56 + write_file ~validate path gpx; 62 57 backup_path 63 58 with 64 59 | Gpx.Gpx_error _ as err -> 65 60 (* Try to restore backup if write failed *) 66 - if backup_path <> "" && file_exists ~fs backup_path then ( 67 - try 68 - let backup_content = Eio.Path.load Eio.Path.(fs / backup_path) in 69 - Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) backup_content 70 - with _ -> () (* Ignore restore errors *) 71 - ); 72 - raise err 61 + match backup_path with 62 + | Some backup_path -> 63 + if file_exists backup_path then ( 64 + try 65 + let backup_content = Eio.Path.load backup_path in 66 + Eio.Path.save ~create:(`Or_truncate 0o644) path backup_content 67 + with _ -> () (* Ignore restore errors *) 68 + ); 69 + raise err 70 + | _ -> raise err
+7 -13
lib/gpx_eio/gpx_io.mli
··· 8 8 (** {1 File Operations} *) 9 9 10 10 (** Read GPX from file path. 11 - @param fs Filesystem capability 12 11 @param path File path to read 13 12 @param ?validate Optional validation flag (default: false) 14 13 @return GPX document or error *) 15 - val read_file : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t 14 + val read_file : ?validate:bool -> _ Eio.Path.t -> Gpx.t 16 15 17 16 (** Write GPX to file path. 18 - @param fs Filesystem capability 19 17 @param path File path to write 20 18 @param gpx GPX document to write 21 19 @param ?validate Optional validation flag (default: false) 22 20 @raises Gpx.Gpx_error on write failure *) 23 - val write_file : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> unit 21 + val write_file : ?validate:bool -> _ Eio.Path.t -> Gpx.t -> unit 24 22 25 23 (** {1 Stream Operations} 26 24 ··· 41 39 (** {1 Utility Functions} *) 42 40 43 41 (** Check if file exists. 44 - @param fs Filesystem capability 45 42 @param path File path to check 46 43 @return [true] if file exists and is readable *) 47 - val file_exists : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> bool 44 + val file_exists : _ Eio.Path.t -> bool 48 45 49 46 (** Get file size. 50 - @param fs Filesystem capability 51 47 @param path File path 52 48 @return File size in bytes *) 53 - val file_size : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> int 49 + val file_size : _ Eio.Path.t -> int 54 50 55 51 (** Create backup of existing file. 56 - @param fs Filesystem capability 57 52 @param path Original file path 58 53 @return Backup file path *) 59 - val create_backup : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> string 54 + val create_backup : 'a Eio.Path.t -> 'a Eio.Path.t option 60 55 61 56 (** Write GPX to file with automatic backup. 62 57 Creates a backup of existing file before writing new content. 63 - @param fs Filesystem capability 64 58 @param path File path to write 65 59 @param gpx GPX document to write 66 60 @param ?validate Optional validation flag (default: false) 67 - @return Backup file path (empty string if no backup needed) *) 68 - val write_file_with_backup : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> string 61 + @return Backup file path ([None] if no backup needed) *) 62 + val write_file_with_backup : ?validate:bool -> 'a Eio.Path.t -> Gpx.t -> 'a Eio.Path.t option
+7 -5
test/test_corpus_unix_eio.ml
··· 2 2 3 3 open Alcotest 4 4 5 + let ( / ) = Eio.Path. ( / ) 6 + 5 7 let test_data_dir = "test/data" 6 8 7 9 let test_files = [ ··· 44 46 let fs = Eio.Stdenv.fs env in 45 47 let path = Filename.concat test_data_dir filename in 46 48 try 47 - let gpx = Gpx_eio.read ~fs path in 49 + let gpx = Gpx_eio.read (fs / path) in 48 50 let validation = Gpx.validate_gpx gpx in 49 51 check bool "GPX is valid" true validation.is_valid; 50 52 check bool "Has some content" true ( ··· 68 70 try 69 71 Eio_main.run @@ fun env -> 70 72 let fs = Eio.Stdenv.fs env in 71 - Ok (Gpx_eio.read ~fs path) 73 + Ok (Gpx_eio.read (fs / path)) 72 74 with 73 75 | Gpx.Gpx_error err -> Error err 74 76 in ··· 120 122 let fs = Eio.Stdenv.fs env in 121 123 let path = Filename.concat test_data_dir filename in 122 124 try 123 - let gpx_original = Gpx_eio.read ~fs path in 125 + let gpx_original = Gpx_eio.read (fs / path) in 124 126 (* Write to temporary string via GPX core *) 125 127 match Gpx.write_string gpx_original with 126 128 | Ok xml_string -> ··· 171 173 (try 172 174 Eio_main.run @@ fun env -> 173 175 let fs = Eio.Stdenv.fs env in 174 - let _ = Gpx_eio.read ~fs path in 176 + let _ = Gpx_eio.read (fs / path) in 175 177 failf "Eio should have failed to parse invalid.gpx" 176 178 with 177 179 | Gpx.Gpx_error _ -> ··· 190 192 let start_eio = Sys.time () in 191 193 let _ = Eio_main.run @@ fun env -> 192 194 let fs = Eio.Stdenv.fs env in 193 - try Some (Gpx_eio.read ~fs path) 195 + try Some (Gpx_eio.read (fs / path)) 194 196 with Gpx.Gpx_error _ -> None 195 197 in 196 198 let eio_time = Sys.time () -. start_eio in