Repositories / agent-snapshot.git

agent-snapshot.git

Clone (read-only): git clone http://git.guha-anderson.com/git/agent-snapshot.git

Branch

Print plain no-args usage error

Author
Arjun Guha <a.guha@northeastern.edu>
Date
2026-05-03 17:50:42 -0400
Commit
93475ff4aa7292e55b5d2f19275102633c91bc0f
src/ocaml/agent_snapshot.ml
index 88a8507..fd7ffe8 100644
--- a/src/ocaml/agent_snapshot.ml
+++ b/src/ocaml/agent_snapshot.ml
@@ -126,6 +126,8 @@ let snapshot_dir : string ref = ref ""
 let tracer_uid : int = Unix.getuid ()
 let tracer_gid : int = Unix.getgid ()
 
+exception Usage_error of string
+
 let split_path (path : string) : string list =
   if path = "" then []
   else Fpath.segs (Fpath.normalize (Fpath.v path)) |> List.filter (fun seg -> seg <> "")
@@ -818,7 +820,7 @@ let snapshot_term : unit Term.t =
   Term.(
     const (fun output cmd ->
       if cmd = [] then
-        failwith "usage: agent-snapshot [--snapshot-dir SNAPDIR] command args...";
+        raise (Usage_error "usage: agent-snapshot [--snapshot-dir SNAPDIR] command args...");
       ignore (run_snapshot output cmd : int))
     $ output_arg
     $ command_arg)
@@ -889,9 +891,14 @@ let main () : unit =
     let rc = Cmd.eval ~catch:false ~argv:(normalize_snapshot_argv Sys.argv) cmd_main in
     Ocaml_git.shutdown ();
     exit rc
-  with exn ->
-    Ocaml_git.shutdown ();
-    Printf.eprintf "agent-snapshot: %s\n%!" (Printexc.to_string exn);
-    exit 1
+  with
+  | Usage_error msg ->
+      Ocaml_git.shutdown ();
+      Printf.eprintf "agent-snapshot: %s\n%!" msg;
+      exit 1
+  | exn ->
+      Ocaml_git.shutdown ();
+      Printf.eprintf "agent-snapshot: %s\n%!" (Printexc.to_string exn);
+      exit 1
 
 let () = main ()
tests/test_agent_snapshot.py
index b8c13ff..9e599c0 100644
--- a/tests/test_agent_snapshot.py
+++ b/tests/test_agent_snapshot.py
@@ -374,6 +374,18 @@ def test_help_includes_copyright_and_license():
     assert "BSD-3 licensed." in completed.stdout
 
 
+def test_no_args_prints_plain_usage_error():
+    completed = subprocess.run(
+        [str(BIN)],
+        cwd=ROOT,
+        text=True,
+        capture_output=True,
+    )
+
+    assert completed.returncode == 1
+    assert completed.stderr == "agent-snapshot: usage: agent-snapshot [--snapshot-dir SNAPDIR] command args...\n"
+
+
 def test_rename_records_source_tombstone_and_destination_content(tmp_path):
     # Rename is not just a write: a replay-equivalent snapshot needs to know that
     # the source path stopped existing and that the destination path acquired the