diff --git a/src/commands.rs b/src/commands.rs index 8e27d53ac..6f1345ec6 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -812,6 +812,12 @@ fn resolve_single_op_from_store( op_heads_store: &Arc, op_str: &str, ) -> Result { + if op_str.is_empty() || !op_str.as_bytes().iter().all(|b| b.is_ascii_hexdigit()) { + return Err(CommandError::UserError(format!( + "Operation ID \"{}\" is not a valid hexadecimal prefix", + op_str + ))); + } if let Ok(binary_op_id) = hex::decode(op_str) { let op_id = OperationId::new(binary_op_id); match op_store.read_operation(&op_id) { diff --git a/tests/test_operations.rs b/tests/test_operations.rs index 08e4dbb75..c5195a792 100644 --- a/tests/test_operations.rs +++ b/tests/test_operations.rs @@ -48,7 +48,7 @@ fn test_op_log() { "###); // We get a reasonable message if an invalid operation ID is specified - insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", "foo"]), @r###"Error: No operation ID matching "foo" + insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", "foo"]), @r###"Error: Operation ID "foo" is not a valid hexadecimal prefix "###); // Odd length insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", "123456789"]), @r###"Error: No operation ID matching "123456789" @@ -57,8 +57,7 @@ fn test_op_log() { insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", "0123456789"]), @r###"Error: No operation ID matching "0123456789" "###); // Empty ID - // TODO: This is not a reasonable message - insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", ""]), @r###"Internal error: Failed to read operation: Other("IO error: Is a directory (os error 21)") + insta::assert_snapshot!(test_env.jj_cmd_failure(&repo_path, &["log", "--at-op", ""]), @r###"Error: Operation ID "" is not a valid hexadecimal prefix "###); }