terminal user interface to jujutsu. Focused on speed and clarity
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix handling of odd paths

+83 -25
+23 -23
jj_tui/bin/file_commands.ml
··· 37 37 ( "Revision to move file to" 38 38 , fun rev -> 39 39 Cmd 40 - ([ 41 - "squash" 42 - ; "-u" 43 - ; "--keep-emptied" 44 - ; "--from" 45 - ; get_hovered_rev () 46 - ; "--into" 47 - ; rev 48 - ] 49 - @ Lwd.peek active_files) )) 40 + (Jj_cli.with_files 41 + [ 42 + "squash" 43 + ; "-u" 44 + ; "--keep-emptied" 45 + ; "--from" 46 + ; get_hovered_rev () 47 + ; "--into" 48 + ; rev 49 + ] 50 + (Lwd.peek active_files)) )) 50 51 } 51 52 ; { 52 53 id = "move_to_child" ··· 57 58 Dynamic_r 58 59 (fun rev -> 59 60 Cmd 60 - ([ 61 - "squash"; "-u"; "--keep-emptied"; "--from"; rev; "--into"; rev ^ "+" 62 - ] 63 - @ Lwd.peek active_files))) 61 + (Jj_cli.with_files 62 + [ "squash"; "-u"; "--keep-emptied"; "--from"; rev; "--into"; rev ^ "+" ] 63 + (Lwd.peek active_files)))) 64 64 } 65 65 ; { 66 66 id = "move_to_parent" ··· 71 71 Dynamic_r 72 72 (fun rev -> 73 73 Cmd 74 - ([ 75 - "squash"; "-u"; "--keep-emptied"; "--from"; rev; "--into"; rev ^ "-" 76 - ] 77 - @ Lwd.peek active_files))) 74 + (Jj_cli.with_files 75 + [ "squash"; "-u"; "--keep-emptied"; "--from"; rev; "--into"; rev ^ "-" ] 76 + (Lwd.peek active_files)))) 78 77 } 79 78 ; { 80 79 id = "commit" ··· 90 89 (* I need this to work with any commit. So i should split then describe instead*) 91 90 let rev = Vars.get_hovered_rev () in 92 91 jj 93 - ([ "split"; "-r"; rev; "-m"; message; "--insert-before"; "@" ] 94 - @ Lwd.peek active_files) 92 + (Jj_cli.with_files 93 + [ "split"; "-r"; rev; "-m"; message; "--insert-before"; "@" ] 94 + (Lwd.peek active_files)) 95 95 |> ignore) )) 96 96 } 97 97 ; { ··· 108 108 ^ (selected |> String.concat "\n") 109 109 ^ "\nin rev " 110 110 ^ rev) 111 - (Cmd ([ "restore"; "--to"; rev; "--from"; rev ^ "-" ] @ selected)))) 111 + (Cmd (Jj_cli.with_files [ "restore"; "--to"; rev; "--from"; rev ^ "-" ] selected)))) 112 112 } 113 113 ; { 114 114 id = "absorb" ··· 126 126 ^ (selected |> String.concat "\n") 127 127 ^ "\nin rev " 128 128 ^ rev) 129 - (Cmd ([ "absorb"; "--from"; rev ] @ selected)))) 129 + (Cmd (Jj_cli.with_files [ "absorb"; "--from"; rev ] selected)))) 130 130 } 131 131 ; { 132 132 id = "absorb-into" ··· 145 145 ^ (selected |> String.concat "\n") 146 146 ^ "\nin rev " 147 147 ^ rev) 148 - (Cmd ([ "absorb"; "--from"; rev; "--to"; dest ] @ selected))) )) 148 + (Cmd (Jj_cli.with_files [ "absorb"; "--from"; rev; "--to"; dest ] selected))) )) 149 149 } 150 150 ; { 151 151 id = "undo"
+4 -2
jj_tui/bin/show_view.ml
··· 53 53 | File_preview (rev, file) -> 54 54 let command = 55 55 if file != "" 56 - then [ "diff"; "--summary"; "-r"; rev; file ] 56 + then Jj_cli.with_files [ "diff"; "--summary"; "-r"; rev ] [ file ] 57 57 else [ "show"; "--summary"; "-r"; rev ] 58 58 in 59 59 let log = jj_no_log command in ··· 72 72 let render_detail = function 73 73 | File_preview (rev, file) -> 74 74 let command = 75 - if file != "" then [ "diff"; "-r"; rev; file ] else [ "show"; "-r"; rev ] 75 + if file != "" 76 + then Jj_cli.with_files [ "diff"; "-r"; rev ] [ file ] 77 + else [ "show"; "-r"; rev ] 76 78 in 77 79 let log = jj_no_log command in 78 80 Control.yield ();
+16
jj_tui/lib/jj_cli.ml
··· 1 + (** Utilities for constructing jj command-line argument lists. 2 + 3 + jj is invoked via [Unix.create_process_env] (direct argv), not through a 4 + shell. That means wrapping file paths in single-quotes would pass the 5 + quote characters as literal bytes to jj — wrong. The POSIX end-of-options 6 + sentinel [--] is the correct mechanism: it tells jj that every subsequent 7 + argument is a file path, not a flag. *) 8 + 9 + (** [with_files base_args paths] appends [--] followed by every non-empty 10 + string in [paths] to [base_args]. Empty strings are silently dropped so 11 + callers need not pre-filter placeholder values. When all paths are empty 12 + the list is returned unchanged (no spurious [--] emitted). *) 13 + let with_files base_args paths = 14 + match List.filter (fun p -> p <> "") paths with 15 + | [] -> base_args 16 + | real_paths -> base_args @ [ "--" ] @ real_paths
+40
jj_tui/lib/jj_cli_tests.ml
··· 1 + open Jj_cli 2 + 3 + (* Display args separated by | so spaces inside an argument are visible and 4 + distinct from argument boundaries. *) 5 + let show args = print_string (String.concat "|" args); print_newline () 6 + 7 + let%expect_test "with_files: empty path list yields no separator" = 8 + show (with_files [ "diff"; "-r"; "abc" ] []); 9 + [%expect {| diff|-r|abc |}] 10 + ;; 11 + 12 + let%expect_test "with_files: all-empty strings yield no separator" = 13 + show (with_files [ "diff" ] [ ""; "" ]); 14 + [%expect {| diff |}] 15 + ;; 16 + 17 + let%expect_test "with_files: single path" = 18 + show (with_files [ "diff"; "-r"; "abc" ] [ "src/foo.ml" ]); 19 + [%expect {| diff|-r|abc|--|src/foo.ml |}] 20 + ;; 21 + 22 + let%expect_test "with_files: multiple paths remain separate argv entries" = 23 + show (with_files [ "restore"; "--to"; "abc" ] [ "a/b.ml"; "c/d.ml" ]); 24 + [%expect {| restore|--to|abc|--|a/b.ml|c/d.ml |}] 25 + ;; 26 + 27 + let%expect_test "with_files: path with spaces is a single argv entry" = 28 + show (with_files [ "diff" ] [ "my file.txt" ]); 29 + [%expect {| diff|--|my file.txt |}] 30 + ;; 31 + 32 + let%expect_test "with_files: path with leading dash is protected by separator" = 33 + show (with_files [ "diff" ] [ "-not-a-flag.txt" ]); 34 + [%expect {| diff|--|-not-a-flag.txt |}] 35 + ;; 36 + 37 + let%expect_test "with_files: empty strings mixed with real paths are dropped" = 38 + show (with_files [ "diff" ] [ ""; "real.ml"; "" ]); 39 + [%expect {| diff|--|real.ml |}] 40 + ;;