Adding a `pijul dependents` command to list the transitive closure of the reverse dependency relation

pmeunier
Feb 28, 2023, 12:18 PM
VWJ2JL63I5OYZ2HS3N4EKM5TW7HRAF5U3OAHDQIVZINIO73IAE7AC

Dependencies

  • [2] RUBBHYZ7 Removing unnecessary async/await
  • [3] I24UEJQL Various post-fire fixes
  • [4] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [5] JL4WKA5P Implement the Sanakirja concurrency model in a cross-process way
  • [6] LBVUI6AX Rename `ls` command to `list`
  • [*] 62XVBWPY remove redundant Clap attributes
  • [*] JWTT77WJ Add help on subcommands

Change contents

  • edit in pijul/src/main.rs at line 55
    [8.43]
    [9.361]
    /// Lists the transitive closure of the reverse dependency relation
    Dependents(Dependents),
  • edit in pijul/src/main.rs at line 250
    [2.275]
    [2.275]
    SubCommand::Dependents(deps) => deps.run(),
  • edit in pijul/src/main.rs at line 260
    [2.676][3.1628:1664](),[3.5246][3.1628:1664]()
    // #[cfg(debug_assertions)]
  • edit in pijul/src/commands/mod.rs at line 24
    [3.133860]
    [3.133860]
    mod dependents;
    pub use dependents::Dependents;
  • file addition: dependents.rs (----------)
    [3.93386]
    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(())
    }
    }