first pass at prefix rules

This commit is contained in:
kevin zhao
2025-11-10 10:38:08 -08:00
parent 6c384eb9c6
commit 773177ec8b
13 changed files with 664 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
use std::fs;
use std::path::Path;
use anyhow::Context;
use anyhow::Result;
use anyhow::bail;
use codex_execpolicy2::PolicyParser;
use codex_execpolicy2::load_default_policy;
use codex_execpolicy2::tokenize_command;
fn main() -> Result<()> {
let mut args = std::env::args().skip(1);
let mut policy_path: Option<String> = None;
while let Some(arg) = args.next() {
if arg == "--policy" || arg == "-p" {
let path = args
.next()
.context("expected a policy path after --policy/-p")?;
policy_path = Some(path);
continue;
}
// First non-flag argument is the subcommand.
let subcommand = arg;
return run_subcommand(subcommand, policy_path, args.collect());
}
print_usage();
bail!("missing subcommand")
}
fn run_subcommand(
subcommand: String,
policy_path: Option<String>,
args: Vec<String>,
) -> Result<()> {
match subcommand.as_str() {
"check" => cmd_check(policy_path, args),
_ => {
print_usage();
bail!("unknown subcommand: {subcommand}")
}
}
}
fn cmd_check(policy_path: Option<String>, args: Vec<String>) -> Result<()> {
if args.is_empty() {
bail!("usage: codex-execpolicy2 check <command tokens...|\"command string\">");
}
let policy = load_policy(policy_path)?;
let tokens = if args.len() == 1 {
tokenize_command(&args[0])?
} else {
args
};
match policy.evaluate(&tokens) {
Some(eval) => {
let json = serde_json::to_string_pretty(&eval)?;
println!("{json}");
}
None => {
println!("no match");
}
}
Ok(())
}
fn load_policy(policy_path: Option<String>) -> Result<codex_execpolicy2::Policy> {
if let Some(path) = policy_path {
let content = fs::read_to_string(&path)
.with_context(|| format!("failed to read policy at {}", Path::new(&path).display()))?;
let parser = PolicyParser::new(&path, &content);
return Ok(parser.parse()?);
}
Ok(load_default_policy()?)
}
fn print_usage() {
eprintln!(
"usage:
codex-execpolicy2 [--policy path] check <command tokens...|\"command string\">"
);
}