use std::path::PathBuf;
use std::io::Write;
use clap::Parser;
use libpijul::*;
use crate::repository::*;
#[derive(Parser, Debug)]
pub struct Dependents {
/// Use the repository at PATH instead of the current directory
#[clap(long = "repository", value_name = "PATH")]
repo_path: Option<PathBuf>,
/// The hash of the change to show, or an unambiguous prefix thereof
#[clap(value_name = "HASH")]
hash: Option<String>,
}
impl Dependents {
pub fn run(self) -> Result<(), anyhow::Error> {
let repo = Repository::find_root(self.repo_path.clone())?;
let txn = repo.pristine.txn_begin()?;
let hash = if let Some(hash) = self.hash {
if let Some(h) = Hash::from_base32(hash.as_bytes()) {
h
} else {
txn.hash_from_prefix(&hash)?.0
}
} else {
let channel_name = txn.current_channel().unwrap_or(crate::DEFAULT_CHANNEL);
let channel = if let Some(channel) = txn.load_channel(&channel_name)? {
channel
} else {
return Ok(());
};
let channel = channel.read();
if let Some(h) = txn.reverse_log(&*channel, None)?.next() {
(h?.1).0.into()
} else {
return Ok(());
}
};
let mut ids = vec![(txn.get_internal(&hash.into())?.unwrap(), false)];
let mut seen = HashSet::new();
let mut stdout = std::io::stdout();
while let Some((id, v)) = ids.pop() {
if v {
let h: Hash = txn.get_external(&id)?.unwrap().into();
writeln!(stdout, "{}", h.to_base32())?;
} else if seen.insert(id) {
ids.push((id, true));
for t in txn.iter_revdep(&id).unwrap() {
let (_, t) = t?;
ids.push((t, false));
}
}
}
Ok(())
}
}