package b0
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Software construction and deployment kit
Install
dune-project
Dependency
Authors
Maintainers
Sources
b0-0.0.5.tbz
sha512=00a6868b4dfa34565d0141b335622a81a0e8d5b9e3c6dfad025dabfa3df2db2a1302b492953bbbce30c3a4406c324fcec25250a00b38f6d18a69e15605e3b07e
doc/src/b0.kit/b0_expect.ml.html
Source file b0_expect.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200(*--------------------------------------------------------------------------- Copyright (c) 2022 The b0 programmers. All rights reserved. Distributed under the ISC license, see terms at the end of the file. ---------------------------------------------------------------------------*) open B0_std open Result.Syntax (* FIXME potentially add these things to Fmt/fpath *) let pp_cli_arg fmt = Fmt.tty [`Underline] fmt let fpath_pp_high_suffix pre ppf p = match Fpath.strip_prefix pre p with | None -> (Fmt.code Fpath.pp) ppf p | Some p -> Fpath.pp ppf pre; (if not (Fpath.is_dir_path pre) then Fmt.char ppf Fpath.dir_sep_char); (Fmt.code Fpath.pp) ppf p type t = { base : Fpath.t; prefix : Fpath.t; time : Os.Mtime.counter; vcs : B00_vcs.t } let make ?vcs ?prefix env ~base = let scope_dir = B0_cmdlet.Env.scope_dir env in let prefix = Option.value ~default:scope_dir prefix in let* vcs = match vcs with | None -> B00_vcs.get ~dir:scope_dir () | Some vcs -> Ok vcs in let time = Os.Mtime.counter () in let base = Fpath.(prefix // base) in Ok { base; prefix; time; vcs } let prefix exp = exp.prefix let base exp = exp.base let base_files exp ~recurse = Os.Dir.fold_files ~recurse Os.Dir.path_list exp.base [] let dur exp = Os.Mtime.count exp.time (* Outcomes *) module Outcome = struct type status = [ `Corrected | `Expected | `New | `Unexpected | `Unknown ] let merge_statuses sts = let merge acc st = match acc, st with | `Unknown, _ | _, `Unknown -> `Unknown | `Unexpected, _ | _, `Unexpected -> `Unexpected | `New, _ | _, `New -> `New | `Corrected, _ | _, `Corrected -> `Corrected | `Expected, `Expected -> `Expected in List.fold_left merge `Expected sts type t = status (* In the future hold here all the observations. *) let status = Fun.id let merge = merge_statuses end let file_outcome r file = match B00_vcs.kind r.vcs with | B00_vcs.Git -> let git = B00_vcs.repo_cmd r.vcs in let cmd = Cmd.(git % "status" % "--porcelain" %% path file) in let* st = Os.Cmd.run_out ~trim:false cmd in begin match String.take_left 2 st with | "" -> Ok `Expected | "M " | "A " -> Ok `Corrected | "??" -> Ok `New | s when s.[1] = 'M' -> Ok `Unexpected | _ -> Ok `Unknown end | B00_vcs.Hg -> failwith "TODO" (* Logging stuff *) let pp_label ppf o = let label ppf st l = Fmt.tty_string st ppf (String.concat " " [""; l; ""]) in match o with | `Unexpected -> label ppf [`Bg `Red; `Fg `White] "M" | `New -> label ppf [`Bg `Yellow; `Fg `Black] "?" let log_outcome r file = function | `Unexpected | `New as o -> Log.app (fun m -> m "%a %a" pp_label o (fpath_pp_high_suffix r.prefix) file) | _ -> () (* Results log *) let pp_vcs_cmd vcs ?(file = false) ppf cmd = let pp_file_arg ppf () = Fmt.(pp_cli_arg string) ppf "file" in let file = if file then pp_file_arg else Fmt.nop in Fmt.pf ppf "%a %a" Fmt.(code string) (String.concat " " [vcs; cmd]) file () let pp_git = pp_vcs_cmd "git" let pp_hg = pp_vcs_cmd "hg" let pp_new_cmd ppf vcs = match B00_vcs.kind vcs with | B00_vcs.Git -> pp_git ~file:true ppf "add" | B00_vcs.Hg -> pp_hg ppf ~file:true "TODO" let pp_correct_cmd ppf vcs = match B00_vcs.kind vcs with | B00_vcs.Git -> pp_git ~file:true ppf "add -p" | B00_vcs.Hg -> pp_hg ~file:true ppf "TODO" let pp_unexpected_cmd ppf vcs = match B00_vcs.kind vcs with | B00_vcs.Git -> pp_git ~file:true ppf "diff" | B00_vcs.Hg -> pp_hg ppf ~file:true "TODO" let pp_status_cmd ppf (vcs, dir) = match B00_vcs.kind vcs with | B00_vcs.Git -> pp_git ppf ("status -s " ^ Fpath.to_string dir) | B00_vcs.Hg -> pp_hg ppf "TODO" let pp_diff_cmd ppf (vcs, dir) = match B00_vcs.kind vcs with | B00_vcs.Git -> pp_git ppf ("diff " ^ Fpath.to_string dir) | B00_vcs.Hg -> pp_hg ppf "TODO" let pp_status st status = Fmt.tty st (fun ppf c -> Fmt.pf ppf "%d %s" c status) let pp_corrected ppf n = if n = 0 then () else Fmt.pf ppf " (%d corrected)" n let pp_expected = pp_status [`Fg `Green] "expected" let pp_unexpected = pp_status [`Fg `Red] "unexpected" let pp_new = pp_status [`Fg `Yellow] "new" let pp_unknown = pp_status [`Fg `Red] "unknown" let pp_expected ppf = function | (0, _) -> () | (n, c) -> Fmt.pf ppf "@,%a%a" pp_expected n pp_corrected c let pp_unexpected ppf = function | (0, _) -> () | (n, vcs) -> Fmt.pf ppf "@,%a (check with %a, correct with %a)" pp_unexpected n pp_unexpected_cmd vcs pp_correct_cmd vcs let pp_new ppf = function | (0, _) -> () | (n, vcs) -> Fmt.pf ppf "@,%a (integrate with %a)" pp_new n pp_new_cmd vcs let pp_unknown ppf = function 0 -> () | n -> Fmt.pf ppf "@,%a" pp_unknown n let pp_all_pass ppf (count, corr, dur) = let test = if count > 1 then "tests expected" else "test expected" in let green = [`Fg `Green] in Fmt.pf ppf "%a %a%a in %a" (Fmt.tty_string green) "All" (pp_status green test) count pp_corrected corr Mtime.Span.pp dur let pp_total ppf (count, dur) = let test = if count > 1 then "tests" else "test" in Fmt.pf ppf "@,%a in %a" (pp_status [`Bold] test) count Mtime.Span.pp dur let log_results exp os = let expected = ref 0 and unexpected = ref 0 and new' = ref 0 and corrected = ref 0 and unknown = ref 0 in let incr o = match Outcome.status o with | `Expected -> incr expected | `Unexpected -> incr unexpected | `New -> incr new' | `Corrected -> incr expected; incr corrected | `Unknown -> incr unknown in let count = List.length os in let () = List.iter incr os in match !expected = count with | true -> Log.app (fun m -> m "%a" pp_all_pass (count, !corrected, dur exp)); B00_cli.Exit.ok | false -> Log.app (fun m -> m "@[<v> @[<v>%a%a%a%a%a@]@,@,\ Summary with %a@,Details with %a@]" pp_expected (!expected, !corrected) pp_new (!new', exp.vcs) pp_unknown !unknown pp_unexpected (!unexpected, exp.vcs) pp_total (count, dur exp) pp_status_cmd (exp.vcs, exp.base) pp_diff_cmd (exp.vcs, exp.base)); Os.Exit.code 1 let stdout exp ?env ?cwd ~stdout:out cmd = let stdout = Os.Cmd.out_file ~force:true ~make_path:true out in let* () = Os.Cmd.run ?env ?cwd ~stdout cmd in let* o = file_outcome exp out in log_outcome exp out o; Ok o (*--------------------------------------------------------------------------- Copyright (c) 2022 The b0 programmers Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---------------------------------------------------------------------------*)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>