Skip to content

Commit

Permalink
Errors for bad startup states
Browse files Browse the repository at this point in the history
  • Loading branch information
faldor20 committed Jun 21, 2024
1 parent 3f861a3 commit a5a1de3
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 36 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
[![nix](https://github.com/faldor20/jj_tui/actions/workflows/build-nix.yml/badge.svg)](https://github.com/faldor20/jj_tui/actions/workflows/build-nix.yml)
A TUI for the new version control system Jujutsu

![screenshot](./screenshot.jpg)

![jj_tui-ezgif com-optimize](https://github.com/faldor20/jj_tui/assets/26968035/fb053320-484a-4d6f-9b66-e5b9d0d49e5d)


Press `h` to show the help.
Press `Alt+Up`and`Alt+Down` to navigate windows
Expand Down
15 changes: 13 additions & 2 deletions jj_tui/bin/global_funcs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,19 @@ let list_files ?(rev = "@") () =
the start ")
else None)
;;
let is_jj_repo() =
jj_no_log ~color:false [ "log";"''" ] |> Base.String.is_substring ~substring:"There is no jj repo"|>not

let check_startup () =
match jj_no_log_errorable ~color:false [ "log"; "''" ] with
| Ok _ ->
`Good
| Error (`BadExit (i, str)) ->
if str |> Base.String.is_substring ~substring:"There is no jj repo"
then `NotInRepo
else `OtherError str
| Error (`EioErr a) ->
`CantStartProcess
;;

(**Updates the status windows; Without snapshotting the working copy by default
This should be called after any command that performs a change *)
let update_status ?(cause_snapshot = false) () =
Expand Down
41 changes: 32 additions & 9 deletions jj_tui/bin/jj_process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,19 @@ module Make (Vars : Global_vars.Vars) = struct
~f:(fun x ->
(match x.exit_status with
| `Exited i ->
if i == 0 then x.stdout else x.stdout ^ x.stderr
| `Signaled _ ->
x.stderr)
if i == 0 then `Ok x.stdout else `BadExit (i, x.stderr)
| `Signaled i ->
`BadExit (i, x.stderr))
|> Base.Or_error.return)
()
in
out |> Result.to_option |> Option.value ~default:"there was an error"
match out with
| Error a ->
Error (`EioErr a)
| Ok (`Ok a) ->
Ok a
| Ok (`BadExit _ as a) ->
Error a
;;

(** Prevents concurrent acess to jj when running commands that cause snapshotting.
Expand All @@ -47,7 +53,7 @@ module Make (Vars : Global_vars.Vars) = struct
@param ?snapshot=true
When true snapshots the state when running the command and also aquires a lock before running it. Set to false for commands you wish to run concurrently. like those for generating content in the UI
@param ?color=true When true output will have terminal escape codes for color *)
let jj_no_log ?(snapshot = true) ?(color = true) args =
let jj_no_log_errorable ?(snapshot = true) ?(color = true) args =
let locked =
if snapshot
then (
Expand All @@ -69,6 +75,24 @@ module Make (Vars : Global_vars.Vars) = struct
res
;;

(** Run a jj command without outputting to the command_log.
@param ?snapshot=true
When true snapshots the state when running the command and also aquires a lock before running it. Set to false for commands you wish to run concurrently. like those for generating content in the UI
@param ?color=true When true output will have terminal escape codes for color *)
let jj_no_log ?(snapshot = true) ?(color = true) args =
match jj_no_log_errorable ~snapshot ~color args with
| Ok a ->
a
| Error (`BadExit (code, str)) ->
failwith (Printf.sprintf "Exited with code %i; Message:\n%s" code str)
| Error (`EioErr a) ->
failwith
(Printf.sprintf
"Error running jj process:\n%a"
(fun _ -> Base.Error.to_string_hum)
a)
;;

let jj args =
(*update the command log*)
let current_log = Lwd.peek Vars.ui_state.command_log in
Expand All @@ -80,6 +104,7 @@ module Make (Vars : Global_vars.Vars) = struct

(**gets the description of the current and previous change. Useful when squashing*)
let get_messages () =
let open Base.Result in
let output =
jj
[
Expand All @@ -88,11 +113,9 @@ module Make (Vars : Global_vars.Vars) = struct
; "-T"
; {|"::"++current_working_copy++"::\n"++description++"\n::end::\n"|}
]
|> String.trim
in
let current, prev =
output |> Jj_tui.OutputParsing.parse_descriptions |> Result.get_ok
|>String.trim
in
let current, prev = output |>Jj_tui.OutputParsing.parse_descriptions|>Result.get_ok in
current |> String.concat "", prev |> String.concat ""
;;
end
61 changes: 37 additions & 24 deletions jj_tui/bin/jj_ui.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ module Make (Vars : Global_vars.Vars) = struct
`Unhandled
;;

(* shows a pretty box in the middle of the screen with our error in it*)
let render_startup_error error =
let message =
match error with
| `NotInRepo ->
"Not in a jj repo."
| `OtherError str ->
str
| `CantStartProcess ->
"Can't start jj process, maybe it's not installed?"
in
W.string message
|> Lwd.pure
|> Wd.border_box
|>$ Ui.resize
~sw:1
~sh:1
~mw:10000
~mh:10000
~crop:Wd.neutral_grav
~pad:Wd.neutral_grav
|> inputs
;;

(** The primary view for the UI with the file_view graph_view and summary*)
let main_view ~sw =
let file_focus = Focus.make () in
Expand Down Expand Up @@ -107,21 +131,8 @@ module Make (Vars : Global_vars.Vars) = struct

let mainUi ~sw env =
(*we want to initialize our states and keep them up to date*)
let is_jj_repo = is_jj_repo () in
if not is_jj_repo
then
W.string "Not in a jj repo."
|> Lwd.pure
|> Wd.border_box
|>$ Ui.resize
~sw:1
~sh:1
~mw:10000
~mh:10000
~crop:Wd.neutral_grav
~pad:Wd.neutral_grav
|> inputs
else (
match check_startup () with
| `Good ->
update_status ~cause_snapshot:true ();
Eio.Fiber.fork_daemon ~sw (fun _ ->
let clock = Eio.Stdenv.clock env in
Expand All @@ -134,14 +145,16 @@ module Make (Vars : Global_vars.Vars) = struct
done;
`Stop_daemon);
let$* running = Lwd.get ui_state.view in
match running with
| `Cmd_I cmd ->
(*We have this extra step to paint the terminal empty for one step*)
Lwd.set ui_state.view @@ `RunCmd cmd;
full_term_sized_background
| `RunCmd cmd ->
Jj_widgets.interactive_process env ("jj" :: cmd)
| `Main ->
main_view ~sw)
(match running with
| `Cmd_I cmd ->
(*We have this extra step to paint the terminal empty for one step*)
Lwd.set ui_state.view @@ `RunCmd cmd;
full_term_sized_background
| `RunCmd cmd ->
Jj_widgets.interactive_process env ("jj" :: cmd)
| `Main ->
main_view ~sw)
| (`CantStartProcess | `NotInRepo | `OtherError _) as other ->
render_startup_error other
;;
end

0 comments on commit a5a1de3

Please sign in to comment.