+ 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(())
+ }
+ }