use anyhow::{Context, Result};
use pushkin_core::events::{EventLog, Telemetry};
use pushkin_core::waivers::{parse_ttl, GrantRequest, Waiver, WaiverSet};
use std::path::Path;
use super::events_db_path;
pub const WAIVERS_FILE: &str = "pushkin/waivers.toml";
pub const WAIVER_GRANTED_RULE: &str = "pushkin.waiver.granted";
pub struct WaiveArgs {
pub rule: String,
pub path: String,
pub ttl: String,
pub reason: String,
pub supersedes: Option<String>,
pub contradicts: Option<String>,
}
pub fn run(args: WaiveArgs) -> Result<i32> {
let ttl = parse_ttl(&args.ttl)?;
let waiver = Waiver::grant(GrantRequest {
rule: args.rule,
path: args.path,
reason: args.reason,
author: git_identity(),
ttl,
supersedes: args.supersedes,
contradicts: args.contradicts,
})?;
let stored = WaiverSet::append(Path::new(WAIVERS_FILE), waiver)
.context("cannot append to pushkin/waivers.toml")?;
let log = EventLog::open(events_db_path()?)?;
let session = log.begin_session()?;
log.append_telemetry(
&session,
Telemetry {
rule: WAIVER_GRANTED_RULE,
payload: serde_json::to_string(&stored)?,
},
)?;
println!(
"pushkin: waiver {} granted — {} on {} until {} (by {}). \
Recorded in {WAIVERS_FILE} and the event log.",
stored.id, stored.rule, stored.path, stored.expires_at, stored.author
);
Ok(0)
}
fn git_identity() -> String {
if let Ok(name) = std::env::var("GIT_AUTHOR_NAME") {
if !name.trim().is_empty() {
return name;
}
}
std::process::Command::new("git")
.args(["config", "user.name"])
.output()
.ok()
.filter(|output| output.status.success())
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_owned())
.filter(|name| !name.is_empty())
.unwrap_or_else(|| "unknown".to_owned())
}