mod args; use std::{thread, time}; use anyhow::anyhow; use radicle::git; use radicle::git::raw::ErrorExt as _; use radicle::prelude::NodeId; use radicle::storage::{ReadRepository, ReadStorage}; use crate::terminal as term; use crate::terminal::args::rid_or_cwd; pub use args::Args; pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { let profile = ctx.profile()?; let storage = &profile.storage; let qualified = args .refstr .qualified() .ok_or_else(|| anyhow!("reference must be fully-qualified, eg. 'refs/heads/master'"))?; let nid = args.node.unwrap_or(profile.public_key); let (_, rid) = rid_or_cwd(args.repo)?; let repo = storage.repository(rid)?; let now = time::SystemTime::now(); let timeout = args.timeout(); let interval = args.interval(); if let Some(target) = args.target { while reference(&repo, &nid, &qualified)? != Some(target) { thread::sleep(interval); if now.elapsed()? >= timeout { anyhow::bail!("timed out after {}ms", timeout.as_millis()); } } } else { let initial = reference(&repo, &nid, &qualified)?; loop { thread::sleep(interval); let oid = reference(&repo, &nid, &qualified)?; if oid != initial { term::info!("{}", oid.unwrap_or(git::Oid::ZERO_SHA1)); break; } if now.elapsed()? >= timeout { anyhow::bail!("timed out after {}ms", timeout.as_millis()); } } } Ok(()) } fn reference( repo: &R, nid: &NodeId, qual: &git::fmt::Qualified, ) -> Result, git::raw::Error> { match repo.reference_oid(nid, qual) { Ok(oid) => Ok(Some(oid)), Err(e) if e.is_not_found() => Ok(None), Err(e) => Err(e), } }