diff --git a/.gitignore b/.gitignore index 38a50df..587912a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ _build _coverage +_orel_view diff --git a/src/check.ml b/src/check.ml index 1a7f866..732a411 100644 --- a/src/check.ml +++ b/src/check.ml @@ -1,55 +1,46 @@ -let check_local path = - let fpath = Fpath.v path in - (* Format.printf "checking your repository content:@."; *) - match Bos.OS.Dir.set_current fpath with - | Error e -> - (match e with - | `Msg e ->Format.eprintf "%s@." e); - Utils.error "can't set current working directory." - | Ok _res -> - let contents = Bos.OS.Dir.contents ~dotfiles:true ~rel:true fpath in +let check_with arg func = func arg + +let existence_checks = + let open Check_existence in + [ license + ; readme + ; changelog + ; makefile + ; dune + ; ml_file + ; src_dir + ; test_dir + ; example_dir + ; doc_dir + ; ocamlformat + ; opam_file + ; gitignore + ] + +let content_checks = + let open Check_content in + [ dune_project; readme_size; opam_description; opam_license; opam_dev_repo; opam_tags] - let contents = - match contents with - | Ok contents -> contents - | Error _e -> Utils.error "can't get your repository content@." - in - let check_with arg func = func arg in - let existence_checks = - let open Check_existence in - [ license - ; readme - ; changelog - ; makefile - ; dune - ; ml_file - ; src_dir - ; test_dir - ; example_dir - ; doc_dir - ; ocamlformat - ; opam_file - ; gitignore - ] - in - let existence_results = List.map (check_with contents) existence_checks in - let content_checks = - let open Check_content in - [ dune_project; readme_size; opam_description; opam_license; opam_dev_repo; opam_tags] - in - let content_results = List.map (check_with contents) content_checks in - let repo_checks = - let open Check_repo in - [ platform; url_package_name; package_name ] - in - let repo_results = List.map (check_with contents) repo_checks in - let directory_checks = - let open Check_directory in - [ opamlint; formatted; check_src; check_examples; check_test; check_doc ] - in - let directory_results = List.map (check_with ()) directory_checks in +let repo_checks = + let open Check_repo in + [ platform; url_package_name; package_name ] - existence_results @ content_results @ repo_results @ directory_results +let directory_checks = + let open Check_directory in + [ opamlint; formatted; check_src; check_examples; check_test; check_doc ] + +let check_local path = + let contents = Bos.OS.Dir.contents ~dotfiles:true ~rel:true path in + let contents = + match contents with + | Ok contents -> List.map (Fpath.append path) contents + | Error _e -> Utils.error "can't get your repository content" + in + let existence_results = List.map (check_with contents) existence_checks in + let content_results = List.map (fun func -> check_with contents func) content_checks in + let repo_results = List.map (check_with contents) repo_checks in + let directory_results = List.map (check_with ()) directory_checks in + existence_results @ content_results @ repo_results @ directory_results let check repo = let tmp_dir = @@ -67,4 +58,4 @@ let check repo = | Ok _res -> () | Error _e -> Utils.error "can't clone repository" ); - check_local tmp_dir_s + check_local tmp_dir diff --git a/src/check_content.ml b/src/check_content.ml index ca15e5e..8daec0a 100644 --- a/src/check_content.ml +++ b/src/check_content.ml @@ -52,8 +52,7 @@ let opam_description repo_contents = let results = List.map (fun opam_file_name -> - let opam_file = "./" ^ opam_file_name in - let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "description:" % opam_file) in + let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "description:" % opam_file_name) in match Bos.OS.Cmd.run_out opam_show |> Bos.OS.Cmd.to_lines with | Error _e -> Error opam_file_name @@ -90,8 +89,7 @@ let opam_license repo_contents = let results = List.map (fun opam_file_name -> - let opam_file = "./" ^ opam_file_name in - let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--empty-fields" % "--no-lint" % "--normalise" % "-f" % "license:" % opam_file) in + let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--empty-fields" % "--no-lint" % "--normalise" % "-f" % "license:" % opam_file_name) in match Bos.OS.Cmd.run_out opam_show |> Bos.OS.Cmd.to_lines with | Error _e -> Error opam_file_name @@ -128,8 +126,7 @@ let opam_dev_repo repo_contents = let results = List.map (fun opam_file_name -> - let opam_file = "./" ^ opam_file_name in - let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "dev-repo:" % opam_file) in + let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "dev-repo:" % opam_file_name) in match Bos.OS.Cmd.run_out opam_show |> Bos.OS.Cmd.to_lines with | Error _e -> Error opam_file_name @@ -165,8 +162,7 @@ let opam_tags repo_contents = let results = List.map (fun opam_file_name -> - let opam_file = "./" ^ opam_file_name in - let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "tags:" % opam_file) in + let opam_show = Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "tags:" % opam_file_name) in match Bos.OS.Cmd.run_out opam_show |> Bos.OS.Cmd.to_lines with | Error _e -> Error opam_file_name diff --git a/src/check_existence.ml b/src/check_existence.ml index e7af488..b31ba4d 100644 --- a/src/check_existence.ml +++ b/src/check_existence.ml @@ -1,6 +1,6 @@ (** [has_name name path] compares a [name] of type string with a [path] of type Fpath. *) -let has_name name path = String.equal name (Fpath.to_string path) +let has_name name path = String.equal name (Filename.basename (Fpath.to_string path)) (** [has_filename filename path] checks if given [filename] fits with given [path] Fpath. *) diff --git a/src/check_repo.ml b/src/check_repo.ml index 12207a3..f144ac3 100644 --- a/src/check_repo.ml +++ b/src/check_repo.ml @@ -26,7 +26,7 @@ let get_repo_url contents = match List.find_opt (Fpath.has_ext ".opam") contents with | None -> None | Some file -> - match Bos.OS.Cmd.run_out Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % ":dev-repo" % (Fpath.to_string file)) |> Bos.OS.Cmd.to_lines with + match Bos.OS.Cmd.run_out Bos.Cmd.(v "opam" % "show" % "--color" % "never" % "--no-lint" % "--normalise" % "-f" % "dev-repo:" % (Fpath.to_string file)) |> Bos.OS.Cmd.to_lines with | Error _e -> None | Ok (url::_urls) -> if String.length url > 2 then Some (String.sub url 1 (String.length url - 2)) else None diff --git a/src/html.ml b/src/html.ml index 6317dae..552b1f1 100644 --- a/src/html.ml +++ b/src/html.ml @@ -2,13 +2,13 @@ let result_to_html fmt results = let score, max_score = List.fold_left (fun (acc_score, acc_max_score) r -> - match r with - | Ok (msg, max_score) -> - Utils.log fmt "-- %s (%d/%d)
" msg max_score max_score; - (acc_score + max_score, acc_max_score + max_score) - | Error (msg, score, max_score) -> - Format.fprintf fmt "-- %s (%d/%d)
" msg score max_score; - (acc_score + score, acc_max_score + max_score) ) + match r with + | Ok (msg, max_score) -> + Utils.log fmt "-- %s (%d/%d)
" msg max_score max_score; + (acc_score + max_score, acc_max_score + max_score) + | Error (msg, score, max_score) -> + Format.fprintf fmt "-- %s (%d/%d)
" msg score max_score; + (acc_score + score, acc_max_score + max_score) ) (0, 0) results in Format.fprintf fmt "Final score: %d / %d
" score max_score @@ -30,8 +30,128 @@ let output fmt result =

Orel results

+

verbose is %s

%a
+
+ Go back to view home |} - result_to_html result + (if !Utils.verbose then "on" else "off") result_to_html result + +(** [view_summary fmt view_files] prints HTML into formatter [fmt]. [view_files] is a list of type [(file:string * score:string)] where file is a [.html] file found in directory _orel_view and [score] the final score given by orel. *) +let view_summary fmt view_files = + Format.fprintf fmt + {| + + + + + + + + Orel results summary + + + +

Orel_view Summary

+

verbose is %s

+
+
    + %a +
+
+
+ + + |} (if !Utils.verbose then "on" else "off") + (Format.pp_print_list ~pp_sep:(fun fmt () -> + Format.fprintf fmt "") + (fun fmt (target_file, final_score) -> + Format.fprintf fmt {|
  • Package: %s has score %s... (View detail)
  • |} + (Filename.chop_extension target_file) final_score target_file )) + view_files + +(** [view source_dirs] takes a list of source directories and creates a directory name [_orel_view] in which *) +let view source_dirs = + let orel_view_dir = "_orel_view" in + + (* check existence of [_orel_view] directory *) + match Bos.OS.Dir.exists (Fpath.v orel_view_dir) with + | Error e -> (match e with + | `Msg m -> Format.eprintf "%s@." m); + Utils.error "`Bos.OS.Dir.exists _orel_view` returned Error. (orel_opam_repo.ml)." + | Ok b -> + + (* stop view construction if [_orel_view] directory already exists *) + if b then + begin + Format.eprintf "Directory _orel_view already exists...@."; + Utils.error "can't delete _orel_view dir." + end + else + (* else create [_orel_view] directory and proceed *) + match Bos.OS.Dir.create (Fpath.v orel_view_dir) with + | Error e -> (match e with + | `Msg m -> Format.eprintf "%s@." m); + Utils.error "can't create _orel_view dir." + | Ok _b -> + + (* + * view_files is a list of type (file:string * score:string) where: + * [file] is the name of a given HTML file for a given package + * [score] its score based on orel's checks + * *) + let view_files = + List.map + (fun path -> + (* name the file *) + let file = Filename.basename path ^ ".html" in + (* prepend the path to it *) + let target_file = orel_view_dir ^ "/" ^ file in + + (* create file *) + ( match Bos.OS.Cmd.run_status ~quiet:true Bos.Cmd.(v "touch" % target_file) with + | Ok (`Exited 0) -> () + | Error _ | Ok _ -> + Utils.error ("can't create " ^ path) ); + + (* collect orel's results *) + let results = Check.check_local (Fpath.v path) in + + (* open file, write to corresponding formatter and close *) + let out = open_out target_file in + let fmt = Format.formatter_of_out_channel out in + output fmt results; + close_out out; + + (* collect score *) + let score, max_score = + List.fold_left + (fun (acc_score, acc_max_score) r -> + match r with + | Ok (_msg, max_score) -> (acc_score + max_score, acc_max_score + max_score) + | Error (_msg, score, max_score) -> (acc_score + score, acc_max_score + max_score) + ) (0, 0) results + in + + file, Format.sprintf "%d / %d" score max_score) + source_dirs + in + + (* writes summary of all view files in a index.html file under [_orel_view/]*) + let index_file = orel_view_dir ^ "/" ^ "index.html" in + + (* create file *) + ( match Bos.OS.Cmd.run_status ~quiet:true Bos.Cmd.(v "touch" % index_file) with + | Ok (`Exited 0) -> () + | Error _ | Ok _ -> + Utils.error ("can't create " ^ index_file) ); + + (* open index.html, write to corresponding formatter and close *) + let out = open_out index_file in + let fmt = Format.formatter_of_out_channel out in + view_summary fmt view_files; + close_out out; diff --git a/src/orel_opam_repo.ml b/src/orel_opam_repo.ml index a2d31e2..88707fe 100644 --- a/src/orel_opam_repo.ml +++ b/src/orel_opam_repo.ml @@ -137,7 +137,7 @@ let () = match get_source p with | None | Some "" -> (p :: not_found, packages) | Some source_dir -> - (not_found, (p, source_dir) :: packages) ) + (not_found, source_dir :: packages) ) ([], []) packages in (List.rev not_found, List.rev packages) @@ -150,10 +150,4 @@ let () = Format.printf "can't find package or it doesn't have a dev-repo field %s@." p ) not_found; - - List.iter - (fun (p, path) -> - Format.printf "======== CHECKING PACKAGE %s ========@." p; - let results = Orel.Check.check_local path in - Orel.Raw.output Format.std_formatter results ) - packages + Orel.Html.view packages