Simplifying pijul::commands::log, and fixing Broken Pipe errors

pmeunier
Sep 15, 2021, 8:29 AM
6F6AAHK4M2IVS23TVISR5OJSTZXUSEKLOP5BMM7SUHYG2FQNTSGQC

Dependencies

  • [2] 6O43WXDA Version bump
  • [3] TYAKEAJL A better estimate of the maximum number of open patches we can keep (Unix-only at the moment)
  • [4] F2S6XETO Fixing log --hash-only
  • [5] BECIRKR2 Avoid a double formatting
  • [6] YN63NUZO Sanakirja 1.0
  • [7] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [8] Y6EVFMTA Don't output files if they aren't in the current channel
  • [9] SMMBFECL Converting to the new patch format "online"
  • [10] I52XSRUH Massive cleanup, and simplification
  • [11] FYUDBQ3C Formatting changes + version bump
  • [12] XF3FRWJ6 Version bump (including clap 3.0.0-beta.4)
  • [13] I7VL7VPZ Minor cleanup
  • [14] YMWMWFA5 Version bumps
  • [15] L4JXJHWX pijul/*: reorganize imports and remove extern crate
  • [16] 6XDVUSBM Version bump
  • [17] 23LVKATN Use pager crate for log output
  • [18] JL4WKA5P Implement the Sanakirja concurrency model in a cross-process way
  • [19] A3RM526Y Integrating identity malleability
  • [20] OU6JOR3C Add path filtering for log, add json output for log
  • [21] 2K7JLB4Z No pager on Windows
  • [22] RUBBHYZ7 Removing unnecessary async/await
  • [23] TNN56XYK libpijul alpha.43
  • [24] 5OGOE4VW Store the current channel in the pristine
  • [25] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [26] V4T4SC7O Testing binary diff
  • [27] NWYJJHDF Version bump
  • [28] VIHXB7SG commands: set up pager for diff, change, and credit
  • [29] QJXNUQFJ Solving conflicts

Change contents

  • replacement in "pijul/src/commands/log.rs" at line 11
    [5.134460][5.139:224]()
    use libpijul::pristine::{sanakirja::Txn, ChannelRef, DepsTxnT, GraphTxnT, TreeTxnT};
    [5.134460]
    [5.3357]
    use libpijul::pristine::{sanakirja::Txn, ChannelRef, DepsTxnT, GraphTxnT, TreeTxnT, TxnErr};
  • edit in "pijul/src/commands/log.rs" at line 15
    [5.291]
    [5.134559]
    use thiserror::*;
  • edit in "pijul/src/commands/log.rs" at line 51
    [5.134884]
    [5.723]
    impl TryFrom<Log> for LogIterator {
    type Error = anyhow::Error;
    fn try_from(cmd: Log) -> Result<LogIterator, Self::Error> {
    let repo = Repository::find_root(cmd.repo_path.clone())?;
    let repo_path = repo.path.clone();
    let txn = repo.pristine.txn_begin()?;
    let channel_name = if let Some(ref c) = cmd.channel {
    c
    } else {
    txn.current_channel().unwrap_or(crate::DEFAULT_CHANNEL)
    };
    // The only situation that's disallowed is if the user's trying to apply
    // path filters AND get the logs for a channel other than the one they're
    // currently using (where using means the one that comprises the working copy)
    if !cmd.filters.is_empty()
    && !(channel_name == txn.current_channel().unwrap_or(crate::DEFAULT_CHANNEL))
    {
    bail!("Currently, log filters can only be applied to the channel currently in use.")
    }
    let channel_ref = if let Some(channel) = txn.load_channel(channel_name)? {
    channel
    } else {
    bail!("No such channel: {:?}", channel_name)
    };
    let changes = repo.changes;
    let limit = cmd.limit.unwrap_or(std::usize::MAX);
    let offset = cmd.offset.unwrap_or(0);
    let mut id_path = repo.path.join(libpijul::DOT_DIR);
    id_path.push("identities");
    Ok(Self {
    txn,
    cmd,
    changes,
    repo_path,
    id_path,
    channel_ref,
    limit,
    offset,
    })
    }
    }
    #[derive(Debug, Error)]
    pub enum Error<E: std::error::Error> {
    #[error("pijul log couldn't find a file or directory corresponding to `{}`", 0)]
    NotFound(String),
    #[error(transparent)]
    Txn(#[from] libpijul::pristine::sanakirja::SanakirjaError),
    #[error(transparent)]
    TxnErr(#[from] TxnErr<libpijul::pristine::sanakirja::SanakirjaError>),
    #[error(transparent)]
    Fs(#[from] libpijul::FsError<libpijul::pristine::sanakirja::SanakirjaError>),
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error("pijul log couldn't assemble file prefix for pattern `{}`: {} was not a file in the repository at {}", pat, canon_path.display(), repo_path.display())]
    FilterPath {
    pat: String,
    canon_path: PathBuf,
    repo_path: PathBuf,
    },
    #[error("pijul log couldn't assemble file prefix for pattern `{}`: the path contained invalid UTF-8", 0)]
    InvalidUtf8(String),
    #[error(transparent)]
    E(E),
    #[error(transparent)]
    Filesystem(#[from] libpijul::changestore::filesystem::Error),
    }
  • replacement in "pijul/src/commands/log.rs" at line 124
    [5.906][5.906:966]()
    fn get_inodes(
    txn: &impl libpijul::pristine::TreeTxnT,
    [5.906]
    [5.966]
    fn get_inodes<E: std::error::Error>(
    txn: &Txn,
  • replacement in "pijul/src/commands/log.rs" at line 128
    [5.1009][5.1009:1060]()
    ) -> Result<Vec<libpijul::Inode>, anyhow::Error> {
    [5.1009]
    [5.1060]
    ) -> Result<Vec<libpijul::Inode>, Error<E>> {
  • replacement in "pijul/src/commands/log.rs" at line 133
    [5.1254][5.1254:1408]()
    bail!(
    "pijul log couldn't find a file or directory corresponding to `{}`",
    pat
    )
    [5.1254]
    [5.1408]
    return Err(Error::NotFound(pat.to_string()))
  • replacement in "pijul/src/commands/log.rs" at line 143
    [5.1769][5.1769:2045]()
    Err(_) => bail!(
    "pijul log couldn't assemble file prefix for pattern `{}`; \
    {} was not a file in the repository at {}",
    pat,
    canon_path.display(),
    repo_path.display()
    ),
    [5.1769]
    [5.2045]
    Err(_) => {
    return Err(Error::FilterPath {
    pat: pat.to_string(),
    canon_path,
    repo_path: repo_path.to_path_buf(),
    })
    }
  • replacement in "pijul/src/commands/log.rs" at line 151
    [5.2127][5.2127:2759]()
    Ok(None) => bail!(
    "pijul log couldn't assemble file prefix for pattern `{}`; \
    the path contained invalid UTF-8",
    pat
    ),
    Ok(Some(s)) => match libpijul::fs::find_inode(txn, s) {
    Err(e) => bail!(
    "pijul log couldn't assemble file prefix for pattern `{}`; \
    no Inode found for the corresponding path. Internal error: {:?}",
    pat,
    e
    ),
    Ok(inode) => {
    inodes.push(inode);
    }
    },
    [5.2127]
    [5.2759]
    Ok(None) => return Err(Error::InvalidUtf8(pat.to_string())),
    Ok(Some(s)) => inodes.push(libpijul::fs::find_inode(txn, s)?),
  • replacement in "pijul/src/commands/log.rs" at line 161
    [5.3001][5.3001:3070]()
    fn filtered_hashes<T: TreeTxnT + GraphTxnT + DepsTxnT>(
    txn: &T,
    [5.3001]
    [5.3070]
    fn filtered_hashes<E: std::error::Error>(
    txn: &Txn,
  • replacement in "pijul/src/commands/log.rs" at line 165
    [5.3111][5.3111:3165]()
    ) -> Result<HashSet<libpijul::Hash>, anyhow::Error> {
    [5.3111]
    [5.3165]
    ) -> Result<HashSet<libpijul::Hash>, Error<E>> {
  • replacement in "pijul/src/commands/log.rs" at line 171
    [5.3417][5.3417:3489]()
    None => bail!("Failed to get matching inode: {:?}", inode),
    [5.3417]
    [5.3489]
    None => continue,
  • replacement in "pijul/src/commands/log.rs" at line 178
    [5.3787][5.3787:4336]()
    match txn.get_external(touched_change_id)? {
    Some(ser_h) => {
    hashes.insert(libpijul::Hash::from(*ser_h));
    }
    _ => {
    log::error!(
    "`get_external` failed to retrieve full hash for ChangeId {:?}",
    touched_change_id
    );
    bail!("Failed to retrieve full hash for {:?}", touched_change_id)
    }
    }
    [5.3787]
    [5.4336]
    let ser_h = txn.get_external(touched_change_id)?.unwrap();
    hashes.insert(libpijul::Hash::from(*ser_h));
  • edit in "pijul/src/commands/log.rs" at line 317
    [5.8452][5.8452:8694](),[5.7169][5.135006:135052](),[5.8694][5.135006:135052](),[5.12911][5.135006:135052](),[5.21108][5.135006:135052](),[5.135006][5.135006:135052](),[5.135052][5.8695:8757](),[5.8757][5.2523:2633](),[5.2523][5.2523:2633](),[5.2633][5.8758:9250]()
    impl TryFrom<Log> for LogIterator {
    type Error = anyhow::Error;
    fn try_from(cmd: Log) -> Result<LogIterator, Self::Error> {
    let repo = Repository::find_root(cmd.repo_path.clone())?;
    let repo_path = repo.path.clone();
    let txn = repo.pristine.txn_begin()?;
    let channel_name = if let Some(ref c) = cmd.channel {
    c
    } else {
    txn.current_channel().unwrap_or(crate::DEFAULT_CHANNEL)
    };
    // The only situation that's disallowed is if the user's trying to apply
    // path filters AND get the logs for a channel other than the one they're
    // currently using (where using means the one that comprises the working copy)
    if !cmd.filters.is_empty()
    && !(channel_name == txn.current_channel().unwrap_or(crate::DEFAULT_CHANNEL))
    {
    bail!("Currently, log filters can only be applied to the channel currently in use.")
    }
  • edit in "pijul/src/commands/log.rs" at line 318
    [5.9251][5.9251:9334](),[5.9334][5.135251:135288](),[5.17023][5.135251:135288](),[5.135251][5.135251:135288](),[5.135288][5.17024:17081](),[5.17081][5.135423:135434](),[5.135423][5.135423:135434](),[5.46][5.135434:135470](),[5.66][5.135434:135470](),[5.187][5.135434:135470](),[5.135434][5.135434:135470](),[5.135470][5.9335:9737]()
    let channel_ref = if let Some(channel) = txn.load_channel(channel_name)? {
    channel
    } else {
    bail!("No such channel: {:?}", channel_name)
    };
    let changes = repo.changes;
    let limit = cmd.limit.unwrap_or(std::usize::MAX);
    let offset = cmd.offset.unwrap_or(0);
    let mut id_path = repo.path.join(libpijul::DOT_DIR);
    id_path.push("identities");
    Ok(Self {
    txn,
    cmd,
    changes,
    repo_path,
    id_path,
    channel_ref,
    limit,
    offset,
    })
    }
    }
  • replacement in "pijul/src/commands/log.rs" at line 324
    [5.10027][5.10027:10050]()
    fn for_each<A, E>(
    [5.10027]
    [5.10050]
    fn for_each<A, E: std::error::Error>(
  • replacement in "pijul/src/commands/log.rs" at line 327
    [5.10118][5.10118:10199]()
    ) -> Result<(), anyhow::Error>
    where
    E: std::fmt::Display,
    {
    [5.10118]
    [5.10199]
    ) -> Result<(), Error<E>> {
  • replacement in "pijul/src/commands/log.rs" at line 359
    [5.11547][5.11547:11678]()
    if let Err(e) = f(entry) {
    return Err(anyhow::Error::msg(format!("{}", e)));
    }
    [5.11547]
    [5.11678]
    f(entry).map_err(Error::E)?;
  • replacement in "pijul/src/commands/log.rs" at line 378
    [5.12281][5.12281:12306]()
    fn mk_log_entry<'x>(
    [5.12281]
    [5.12306]
    fn mk_log_entry<'x, E: std::error::Error>(
  • replacement in "pijul/src/commands/log.rs" at line 384
    [5.12469][5.12469:12512]()
    ) -> Result<LogEntry, anyhow::Error> {
    [5.12469]
    [4.2180]
    ) -> Result<LogEntry, Error<E>> {
  • replacement in "pijul/src/commands/log.rs" at line 431
    [5.14053][5.14053:14212]()
    // In order to accommodate both pretty-printing and efficient serialization to a serde
    // target format, this now delegates mostly to [`LogIterator`].
    [5.14053]
    [5.14212]
    // In order to accommodate both pretty-printing and efficient
    // serialization to a serde target format, this now delegates
    // mostly to [`LogIterator`].
  • replacement in "pijul/src/commands/log.rs" at line 442
    [5.14586][5.14586:14683]()
    LogIterator::try_from(self)?.for_each(|entry| write!(&mut stdout, "{}", entry))?
    [5.14586]
    [5.136485]
    LogIterator::try_from(self)?.for_each(|entry| {
    match write!(&mut stdout, "{}", entry) {
    Ok(_) => Ok(()),
    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => Ok(()),
    Err(e) => Err(e),
    }
    })?
  • edit in "pijul/Cargo.toml" at line 93
    [3.1355]
    [5.309]
    thiserror = "1.0"
  • replacement in "Cargo.lock" at line 1063
    [5.22930][2.28:55]()
    version = "1.0.0-alpha.47"
    [5.22930]
    [5.22957]
    version = "1.0.0-alpha.48"
  • edit in "Cargo.lock" at line 1520
    [5.33986]
    [5.33986]
    "thiserror",
  • edit in "Cargo.lock" at line 2109
    [5.49058][5.49058:49284]()
    name = "threadpool"
    version = "1.8.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
    dependencies = [
    "num_cpus",
    ]
    [[package]]
  • edit in "Cargo.lock" at line 2599
    [5.61252]
    [5.61252]
    name = "xxhash-rust"
    version = "0.8.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "e575e15bedf6e57b5c2d763ffc6c3c760143466cbd09d762d539680ab5992ded"
    [[package]]
  • replacement in "Cargo.lock" at line 2637
    [5.62007][5.62007:62025]()
    version = "0.1.7"
    [5.62007]
    [5.62025]
    version = "0.2.0"
  • replacement in "Cargo.lock" at line 2639
    [5.62090][5.62090:62168]()
    checksum = "3e3b99cee88f0309ca765c6aa8c284a00394c35ef8ca012e2409485fc369bf2f"
    [5.62090]
    [5.62168]
    checksum = "62d9eace42d7bf64591d547cb727d89277e3de1c1b934e3d9d0af8c6687587ef"
  • edit in "Cargo.lock" at line 2641
    [5.62185][5.62185:62192]()
    "cc",
  • replacement in "Cargo.lock" at line 2644
    [5.62230][5.62230:62245]()
    "threadpool",
    [5.62230]
    [5.62245]
    "xxhash-rust",