Partial push and pull (WARNING: breaks the existing protocol)

[?]
Dec 19, 2020, 5:01 PM
MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC

Dependencies

  • [2] VO5OQW4W Removing anyhow in libpijul
  • [3] X6YFD4WV Do not download changes if we already have them
  • [4] FE5ES6Q4 Stop pushing/pulling if the remote returns an error
  • [5] SLJ3OHD4 unrecord: show list of changes if none were given as arguments
  • [6] 76PCXGML Pushing to, and pulling from the local repository
  • [7] VQPAUKBQ channel switch as an alias to reset
  • [8] BAUL3WR2 Format, versions, README
  • [9] KDF6FJRV bigger clippy refactors
  • [10] 5QTMRUXN Fixing a race condition between progress bars
  • [11] PCEJFKFX Progress bar for upload and apply
  • [12] HXEIH4UQ Pulling more than 100 changes at once
  • [13] YAJAXIV5 Unrecording changes atomically
  • [14] WLUID7NA Do not block when downloading more than 100 changes over SSH
  • [15] 7L32EXDW When pulling, treating the pending change as a local change
  • [16] I52XSRUH Massive cleanup, and simplification
  • [17] L4JXJHWX pijul/*: reorganize imports and remove extern crate
  • [18] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [19] 367UBQ6K Forwarding SSH stderr, and progress bar for push
  • [20] QWD7UE76 push/pull: rename `channel` option
  • [21] 5DVRL6MF Hard-unrecord
  • [22] Q45QHPO4 Feedback on network stuff
  • [23] FBXYP7QM Forgot to add remote::http
  • [24] K6GWUOD5 Styling progress bars
  • [25] AN7IDX26 pijul: added ChangesNotFound error variant
  • [26] 5HF7C67M push/pull: fixed "changes" arguments
  • [27] 4H2XTVJ2 Fix some mistakes in the docs
  • [28] WZVCLZKY address clippy lints
  • [29] AEPEFS7O Write help for each argument
  • [30] UDHP4ZVB Fixing SSH asynchronicity issues
  • [*] BBKV6VMN Fixing push/pull messages, and do not reverse the changes to download/upload
  • [*] M5FK3ABT Complete dependencies when pushing and pulling

Change contents

  • edit in pijul/src/remote/ssh.rs at line 1
    [6.25380]
    [6.25647]
    use std::collections::HashSet;
  • edit in pijul/src/remote/ssh.rs at line 12
    [6.156]
    [6.0]
    use libpijul::pristine::Position;
  • replacement in pijul/src/remote/ssh.rs at line 260
    [6.587][6.587:659]()
    sender: tokio::sync::mpsc::Sender<Option<(u64, Hash, Merkle)>>,
    [6.587]
    [6.659]
    sender: tokio::sync::mpsc::Sender<Option<super::ListLine>>,
  • replacement in pijul/src/remote/ssh.rs at line 477
    [6.6208][6.6208:6354]()
    let (n, h, m) = parse_line(l)?;
    sender.send(Some((n, h, m))).await.unwrap_or(());
    [6.6208]
    [6.6354]
    sender.send(parse_line(l).ok()).await.unwrap_or(())
  • replacement in pijul/src/remote/ssh.rs at line 683
    [6.42185][6.42185:42222]()
    ) -> Result<(), anyhow::Error> {
    [6.42185]
    [6.8399]
    ) -> Result<HashSet<Position<Hash>>, anyhow::Error> {
  • replacement in pijul/src/remote/ssh.rs at line 691
    [6.42434][6.42434:42481]()
    write!(command, " {}", p).unwrap()
    [6.42434]
    [6.42481]
    write!(command, " {:?}", p).unwrap()
  • replacement in pijul/src/remote/ssh.rs at line 695
    [6.42562][6.42562:42593](),[6.42593][6.8555:8669]()
    debug!("waiting ssh");
    while let Some(Some((n, h, m))) = receiver.recv().await {
    txn.put_remote(remote, n, (h, m))?;
    [6.42562]
    [6.44262]
    debug!("waiting ssh, command: {:?}", std::str::from_utf8(&command));
    let mut result = HashSet::new();
    while let Some(Some(m)) = receiver.recv().await {
    match m {
    super::ListLine::Change { n, h, m } => {
    txn.put_remote(remote, n, (h, m))?;
    }
    super::ListLine::Position(pos) => {
    result.insert(pos);
    }
    }
  • replacement in pijul/src/remote/ssh.rs at line 710
    [4.767][6.44272:44313](),[6.44272][6.44272:44313]()
    debug!("no msg");
    Ok(())
    [4.767]
    [6.44313]
    debug!("no msg, result = {:?}", result);
    Ok(result)
  • edit in pijul/src/remote/mod.rs at line 1
    [6.52474]
    [6.406]
    use std::collections::HashSet;
  • edit in pijul/src/remote/mod.rs at line 5
    [6.439]
    [6.363]
    use anyhow::bail;
  • replacement in pijul/src/remote/mod.rs at line 168
    [6.56804][6.1453:1508]()
    ) -> Result<Option<RemoteRef<T>>, anyhow::Error> {
    [6.56804]
    [6.471]
    ) -> Result<Option<(HashSet<Position<Hash>>, RemoteRef<T>)>, anyhow::Error> {
  • replacement in pijul/src/remote/mod.rs at line 195
    [6.57429][6.57429:57497]()
    self.download_changelist(txn, &mut remote, n, path).await?;
    [6.57429]
    [4.940]
    let paths = self.download_changelist(txn, &mut remote, n, path).await?;
  • replacement in pijul/src/remote/mod.rs at line 203
    [4.1215][6.1637:1662](),[6.904][6.1637:1662](),[6.57497][6.1637:1662]()
    Ok(Some(remote))
    [4.1215]
    [6.57516]
    Ok(Some((paths, remote)))
  • replacement in pijul/src/remote/mod.rs at line 373
    [6.63715][6.63715:63752]()
    ) -> Result<(), anyhow::Error> {
    [6.63715]
    [6.63752]
    ) -> Result<HashSet<Position<Hash>>, anyhow::Error> {
  • replacement in pijul/src/remote/mod.rs at line 377
    [6.63964][6.63964:64637](),[6.64637][6.64637:64787](),[6.64787][6.64787:64911](),[6.64911][6.64911:65045](),[6.65045][6.65045:65068](),[6.65068][6.65068:65082](),[6.65082][6.2257:2308]()
    RemoteRepo::Http(ref h) => {
    let url = h.url.clone() + "/" + DOT_DIR;
    let from_ = from.to_string();
    let mut query = vec![("changelist", &from_), ("channel", &h.channel)];
    for p in paths.iter() {
    query.push(("path", p));
    }
    let res = h.client.get(&url).query(&query).send().await?;
    if !res.status().is_success() {
    return Err((crate::Error::Http {
    status: res.status(),
    })
    .into());
    }
    let resp = res.bytes().await?;
    if let Ok(data) = std::str::from_utf8(&resp) {
    for l in data.lines() {
    if !l.is_empty() {
    let (n, h, m) = parse_line(l)?;
    txn.put_remote(remote, n, (h, m))?;
    } else {
    break;
    }
    }
    }
    Ok(())
    }
    RemoteRepo::LocalChannel(_) => Ok(()),
    [6.63964]
    [6.65082]
    RemoteRepo::Http(ref h) => h.download_changelist(txn, remote, from, paths).await,
    RemoteRepo::LocalChannel(_) => Ok(HashSet::new()),
  • edit in pijul/src/remote/mod.rs at line 429
    [3.187]
    [6.68924]
    inodes: &HashSet<Position<Hash>>,
  • replacement in pijul/src/remote/mod.rs at line 431
    [6.68948][6.68948:68985]()
    ) -> Result<(), anyhow::Error> {
    [6.68948]
    [6.68985]
    ) -> Result<Vec<Hash>, anyhow::Error> {
  • edit in pijul/src/remote/mod.rs at line 468
    [6.735]
    [3.593]
    let mut to_apply_inodes = Vec::new();
  • edit in pijul/src/remote/mod.rs at line 484
    [6.70391]
    [6.921]
    let touches_inodes = inodes.is_empty()
    || {
    debug!("inodes = {:?}", inodes);
    use libpijul::changestore::ChangeStore;
    let changes = repo.changes.get_changes(h)?;
    changes.iter().any(|c| {
    c.iter().any(|c| {
    let inode = c.inode();
    debug!("inode = {:?}", inode);
    if let Some(h) = inode.change {
    inodes.contains(&Position {
    change: h,
    pos: inode.pos,
    })
    } else {
    false
    }
    })
    })
    }
    || { inodes.iter().any(|i| i.change == *h) };
    if touches_inodes {
    to_apply_inodes.push(*h);
    } else {
    continue;
    }
  • replacement in pijul/src/remote/mod.rs at line 534
    [6.70859][6.70859:70874]()
    Ok(())
    [6.847]
    [6.70874]
    Ok(to_apply_inodes)
  • replacement in pijul/src/remote/mod.rs at line 612
    [6.74014][3.748:819]()
    self.pull(repo, txn, channel, &to_unrecord, false).await?;
    [6.74014]
    [6.74109]
    self.pull(repo, txn, channel, &to_unrecord, &HashSet::new(), false)
    .await?;
  • replacement in pijul/src/remote/mod.rs at line 633
    [6.74687][3.820:882]()
    self.pull(repo, txn, channel, &to_pull, true).await?;
    [6.74687]
    [6.74748]
    self.pull(repo, txn, channel, &to_pull, &HashSet::new(), true)
    .await?;
  • replacement in pijul/src/remote/mod.rs at line 709
    [6.78229][6.2849:2883]()
    let remote_changes = self
    [6.78229]
    [6.2883]
    let (inodes, remote_changes) = self
  • replacement in pijul/src/remote/mod.rs at line 717
    [6.78459][3.883:950]()
    self.pull(repo, txn, local_channel, &pullable, true).await
    [6.78459]
    [6.78599]
    self.pull(repo, txn, local_channel, &pullable, &inodes, true)
    .await?;
    Ok(())
  • replacement in pijul/src/remote/mod.rs at line 723
    [6.78608][6.78608:78682]()
    fn parse_line(data: &str) -> Result<(u64, Hash, Merkle), anyhow::Error> {
    [6.78608]
    [6.78682]
    use libpijul::pristine::{ChangePosition, Position};
    use regex::Regex;
    lazy_static! {
    static ref CHANGELIST_LINE: Regex =
    Regex::new(r#"(?P<num>[0-9]+)\.(?P<hash>[A-Za-z0-9]+)\.(?P<merkle>[A-Za-z0-9]+)"#).unwrap();
    static ref PATHS_LINE: Regex =
    Regex::new(r#"(?P<hash>[A-Za-z0-9]+)\.(?P<num>[0-9]+)"#).unwrap();
    }
    enum ListLine {
    Change { n: u64, h: Hash, m: Merkle },
    Position(Position<Hash>),
    }
    fn parse_line(data: &str) -> Result<ListLine, anyhow::Error> {
  • replacement in pijul/src/remote/mod.rs at line 740
    [6.78715][6.78715:79707]()
    let mut it = data.split('.');
    let n = if let Some(n) = it.next().and_then(|n| n.parse().ok()) {
    n
    } else {
    return Err((Error::ProtocolError {
    line: data.as_bytes().to_vec(),
    })
    .into());
    };
    debug!("n = {:?}", n);
    let h = if let Some(h) = it.next().and_then(|h| Hash::from_base32(h.as_bytes())) {
    h
    } else {
    return Err((Error::ProtocolError {
    line: data.as_bytes().to_vec(),
    })
    .into());
    };
    debug!("h = {:?}", h);
    let m = if let Some(m) = it.next().and_then(|m| {
    debug!("m = {:?}", m);
    Merkle::from_base32(m.as_bytes())
    }) {
    m
    } else {
    return Err((Error::ProtocolError {
    line: data.as_bytes().to_vec(),
    })
    .into());
    };
    debug!("m = {:?}", m);
    if it.next().is_some() {
    return Err((Error::ProtocolError {
    line: data.as_bytes().to_vec(),
    })
    .into());
    [6.78715]
    [6.79707]
    if let Some(caps) = CHANGELIST_LINE.captures(data) {
    if let (Some(h), Some(m)) = (
    Hash::from_base32(caps.name("hash").unwrap().as_str().as_bytes()),
    Merkle::from_base32(caps.name("merkle").unwrap().as_str().as_bytes()),
    ) {
    return Ok(ListLine::Change {
    n: caps.name("num").unwrap().as_str().parse()?,
    h,
    m,
    });
    }
    }
    if let Some(caps) = PATHS_LINE.captures(data) {
    return Ok(ListLine::Position(Position {
    change: Hash::from_base32(caps.name("hash").unwrap().as_str().as_bytes()).unwrap(),
    pos: ChangePosition(caps.name("num").unwrap().as_str().parse().unwrap()),
    }));
  • replacement in pijul/src/remote/mod.rs at line 758
    [6.79713][6.79713:79731]()
    Ok((n, h, m))
    [6.79713]
    [6.79731]
    bail!("Protocol error, offending line: {:?}", data)
  • edit in pijul/src/remote/local.rs at line 1
    [6.79745]
    [6.11563]
    use std::collections::HashSet;
  • replacement in pijul/src/remote/local.rs at line 5
    [6.535][6.79768:79831](),[6.79768][6.79768:79831]()
    use libpijul::pristine::{Base32, Hash, Merkle, MutTxnT, TxnT};
    [6.535]
    [6.79831]
    use libpijul::pristine::{Base32, Hash, Merkle, MutTxnT, Position, TxnT};
  • replacement in pijul/src/remote/local.rs at line 47
    [6.80769][6.80769:80806]()
    ) -> Result<(), anyhow::Error> {
    [6.80769]
    [6.80806]
    ) -> Result<HashSet<Position<Hash>>, anyhow::Error> {
  • replacement in pijul/src/remote/local.rs at line 54
    [6.81145][6.81145:81172]()
    return Ok(());
    [6.81145]
    [6.81172]
    return Ok(HashSet::new());
  • replacement in pijul/src/remote/local.rs at line 56
    [6.81183][6.81183:81220]()
    let mut paths_ = Vec::new();
    [6.81183]
    [6.81220]
    let mut paths_ = HashSet::new();
    let mut result = HashSet::new();
  • replacement in pijul/src/remote/local.rs at line 60
    [6.81346][6.81346:81377]()
    paths_.push(p)
    [6.81346]
    [6.81377]
    debug!("p = {:?}", p);
    result.insert(Position {
    change: remote_txn.get_external(p.change).unwrap(),
    pos: p.pos,
    });
    paths_.insert(p);
    paths_.extend(libpijul::fs::iter_graph_descendants(
    &remote_txn,
    &remote_channel.borrow(),
    p,
    ));
  • edit in pijul/src/remote/local.rs at line 73
    [6.81401]
    [6.81401]
    debug!("paths_ = {:?}", paths_);
  • replacement in pijul/src/remote/local.rs at line 92
    [6.82075][6.82075:82090]()
    Ok(())
    [6.82075]
    [6.82090]
    Ok(result)
  • edit in pijul/src/remote/http.rs at line 1
    [6.10]
    [6.11]
    use std::collections::HashSet;
  • replacement in pijul/src/remote/http.rs at line 6
    [6.1221][6.1221:1253]()
    use libpijul::pristine::Base32;
    [6.1221]
    [6.779]
    use libpijul::pristine::{Base32, MutTxnT, Position};
    use libpijul::{Hash, RemoteRef};
  • edit in pijul/src/remote/http.rs at line 113
    [6.1380]
    [6.1380]
    pub async fn download_changelist<T: MutTxnT>(
    &self,
    txn: &mut T,
    remote: &mut RemoteRef<T>,
    from: u64,
    paths: &[String],
    ) -> Result<HashSet<Position<Hash>>, anyhow::Error> {
    let url = self.url.clone() + "/" + super::DOT_DIR;
    let from_ = from.to_string();
    let mut query = vec![("changelist", &from_), ("channel", &self.channel)];
    for p in paths.iter() {
    query.push(("path", p));
    }
    let res = self.client.get(&url).query(&query).send().await?;
    if !res.status().is_success() {
    return Err((crate::Error::Http {
    status: res.status(),
    })
    .into());
    }
    let resp = res.bytes().await?;
    let mut result = HashSet::new();
    if let Ok(data) = std::str::from_utf8(&resp) {
    for l in data.lines() {
    if !l.is_empty() {
    match super::parse_line(l)? {
    super::ListLine::Change { n, m, h } => {
    txn.put_remote(remote, n, (h, m))?;
    }
    super::ListLine::Position(pos) => {
    result.insert(pos);
    }
    }
    } else {
    break;
    }
    }
    }
    Ok(result)
    }
  • edit in pijul/src/main.rs at line 166
    [6.87334][6.87334:87413]()
    #[error("Ambiguous path: {:?}", path)]
    AmbiguousPath { path: String },
  • edit in pijul/src/main.rs at line 182
    [6.88054][6.0:93]()
    #[error("Changes not found: {:?}", hashes)]
    ChangesNotFound { hashes: Vec<String> },
  • edit in pijul/src/commands/reset.rs at line 100
    [6.100716]
    [6.100907]
    let now = std::time::Instant::now();
  • replacement in pijul/src/commands/reset.rs at line 122
    [6.101687][6.101687:101713]()
    txn.commit()?
    [6.101687]
    [6.101713]
    txn.commit()?;
    debug!("now = {:?}", now.elapsed());
  • edit in pijul/src/commands/reset.rs at line 125
    [6.101723]
    [6.101723]
    let locks = libpijul::TIMERS.lock().unwrap();
    debug!(
    "retrieve: {:?}, graph: {:?}, output: {:?}",
    locks.alive_retrieve, locks.alive_graph, locks.alive_output,
    );
  • edit in pijul/src/commands/pushpull.rs at line 6
    [5.2969]
    [6.1696]
    use anyhow::bail;
  • replacement in pijul/src/commands/pushpull.rs at line 73
    [6.113407][6.113407:113433]()
    path: Option<String>,
    [6.113407]
    [6.1799]
    path: Vec<String>,
  • replacement in pijul/src/commands/pushpull.rs at line 103
    [6.250][6.250:276]()
    path: Option<String>,
    [6.250]
    [6.2374]
    path: Vec<String>,
  • replacement in pijul/src/commands/pushpull.rs at line 129
    [6.114865][6.114865:114925]()
    return Err(crate::Error::MissingRemote.into());
    [6.114865]
    [6.114925]
    bail!("Missing remote");
  • replacement in pijul/src/commands/pushpull.rs at line 154
    [6.115611][6.115611:115664](),[6.115664][6.0:20](),[6.20][6.115696:115743](),[6.115696][6.115696:115743](),[6.1778][6.115743:115823](),[6.115743][6.115743:115823]()
    let mut paths = if let Some(p) = self.path {
    vec![p]
    } else {
    vec![]
    };
    let remote_changes = remote.update_changelist(&mut txn, &paths).await?;
    [6.115611]
    [6.115823]
    let remote_changes = remote.update_changelist(&mut txn, &self.path).await?;
  • replacement in pijul/src/commands/pushpull.rs at line 157
    [6.115889][6.115889:116032]()
    let path = if let Some(path) = paths.pop() {
    let (p, ambiguous) = txn.follow_oldest_path(&repo.changes, &channel, &path)?;
    [6.115889]
    [6.116032]
    let mut paths = HashSet::new();
    for path in self.path.iter() {
    let (p, ambiguous) = txn.follow_oldest_path(&repo.changes, &channel, path)?;
  • replacement in pijul/src/commands/pushpull.rs at line 161
    [6.116059][6.677:752]()
    return Err((crate::Error::AmbiguousPath { path }).into());
    [6.116059]
    [6.116148]
    bail!("Ambiguous path: {:?}", path)
  • replacement in pijul/src/commands/pushpull.rs at line 163
    [6.116162][6.116162:116227]()
    Some(p)
    } else {
    None
    };
    [6.116162]
    [6.116227]
    paths.insert(p);
    paths.extend(libpijul::fs::iter_graph_descendants(
    &txn,
    &channel.borrow(),
    p,
    ));
    }
  • replacement in pijul/src/commands/pushpull.rs at line 173
    [6.116338][6.4498:4561]()
    if let Some(ref remote_changes) = remote_changes {
    [6.116338]
    [6.4561]
    if let Some((_, ref remote_changes)) = remote_changes {
  • replacement in pijul/src/commands/pushpull.rs at line 179
    [6.4789][6.4789:4961]()
    if let Some(ref p) = path {
    if txn.get_touched_files(*p, Some(h_int)).is_some() {
    to_upload.push(h)
    [6.4789]
    [6.4961]
    if paths.is_empty() {
    to_upload.push(h)
    } else {
    for p in paths.iter() {
    if txn.get_touched_files(*p, Some(h_int)).is_some() {
    to_upload.push(h);
    break;
    }
  • edit in pijul/src/commands/pushpull.rs at line 188
    [6.4987][6.4987:5016](),[6.5016][6.116665:116707](),[6.116665][6.116665:116707]()
    } else {
    to_upload.push(h)
  • replacement in pijul/src/commands/pushpull.rs at line 195
    [6.5404][6.5404:5588]()
    if let Some(ref p) = path {
    if txn.get_touched_files(*p, Some(h_int)).is_some() {
    to_upload.push(h)
    [6.5404]
    [6.5588]
    if paths.is_empty() {
    to_upload.push(h)
    } else {
    for p in paths.iter() {
    if txn.get_touched_files(*p, Some(h_int)).is_some() {
    to_upload.push(h);
    break;
    }
  • edit in pijul/src/commands/pushpull.rs at line 204
    [6.5618][6.5618:5651](),[6.5651][6.5651:5697]()
    } else {
    to_upload.push(h)
  • replacement in pijul/src/commands/pushpull.rs at line 236
    [6.952][6.362:452]()
    return Err((crate::Error::ChangesNotFound { hashes: not_found }).into());
    [6.952]
    [6.1041]
    bail!("Changes not found: {:?}", not_found)
  • edit in pijul/src/commands/pushpull.rs at line 245
    [32.77]
    [33.69]
    let remote_changes = remote_changes.map(|x| x.1);
  • replacement in pijul/src/commands/pushpull.rs at line 284
    [6.118067][6.118067:118127]()
    return Err(crate::Error::MissingRemote.into());
    [6.118067]
    [6.118127]
    bail!("Missing remote")
  • replacement in pijul/src/commands/pushpull.rs at line 301
    [6.118434][6.118434:118489](),[6.118489][6.6122:6203](),[6.6203][6.118578:118637](),[6.118578][6.118578:118637](),[6.2097][6.118637:118721](),[6.118637][6.118637:118721]()
    let to_download = if self.changes.is_empty() {
    let mut paths = if let Some(p) = self.path {
    vec![p]
    } else {
    vec![]
    };
    let remote_changes = remote.update_changelist(&mut txn, &paths).await?;
    [6.118434]
    [6.118721]
    let mut inodes: HashSet<libpijul::pristine::Position<libpijul::Hash>> = HashSet::new();
    let mut to_download = if self.changes.is_empty() {
    let remote_changes = remote.update_changelist(&mut txn, &self.path).await?;
  • replacement in pijul/src/commands/pushpull.rs at line 306
    [6.118806][6.6204:6267]()
    if let Some(ref remote_changes) = remote_changes {
    [6.118806]
    [6.6267]
    if let Some((inodes_, remote_changes)) = remote_changes {
    inodes.extend(inodes_.into_iter());
  • replacement in pijul/src/commands/pushpull.rs at line 316
    [6.6702][6.6702:6861]()
    let path = if let Some(path) = paths.pop() {
    let (p, ambiguous) = txn.follow_oldest_path(&repo.changes, &channel, &path)?;
    [6.6702]
    [6.6861]
    let mut inodes_ = HashSet::new();
    for path in self.path.iter() {
    let (p, ambiguous) = txn.follow_oldest_path(&repo.changes, &channel, path)?;
  • replacement in pijul/src/commands/pushpull.rs at line 320
    [6.6896][6.753:836]()
    return Err((crate::Error::AmbiguousPath { path }).into());
    [6.6896]
    [6.6993]
    bail!("Ambiguous path: {:?}", path)
  • replacement in pijul/src/commands/pushpull.rs at line 322
    [6.7015][6.7015:7112]()
    Some(p)
    } else {
    None
    };
    [6.7015]
    [6.7112]
    inodes_.insert(p);
    inodes_.extend(libpijul::fs::iter_graph_descendants(
    &txn,
    &channel.borrow(),
    p,
    ));
    }
    inodes.extend(inodes_.iter().map(|x| libpijul::pristine::Position {
    change: txn.get_external(x.change).unwrap(),
    pos: x.pos,
    }));
  • replacement in pijul/src/commands/pushpull.rs at line 344
    [6.7709][6.7709:7978]()
    if let Some(ref p) = path {
    if txn.get_touched_files(*p, Some(h_int)).is_some() {
    to_download.push(h)
    }
    } else {
    [6.7709]
    [6.7978]
    if inodes_.is_empty()
    || inodes_.iter().any(|&inode| {
    txn.get_rev_touched_files(h_int, Some(inode)).is_some()
    })
    {
  • edit in pijul/src/commands/pushpull.rs at line 364
    [6.119431]
    [6.119431]
    debug!("recording");
    let hash = super::pending(&mut txn, &mut channel, &mut repo)?;
    let to_download = remote
    .pull(
    &mut repo,
    &mut txn,
    &mut channel,
    &mut to_download,
    &inodes,
    self.all,
    )
    .await?;
  • replacement in pijul/src/commands/pushpull.rs at line 382
    [6.119504][6.119504:119533](),[6.119533][6.1503:1574](),[6.1574][6.119907:119922](),[6.119907][6.119907:119922](),[6.119922][3.951:1028](),[3.1028][6.120101:120122](),[6.120101][6.120101:120122]()
    debug!("recording");
    let hash = super::pending(&mut txn, &mut channel, &mut repo)?;
    remote
    .pull(&mut repo, &mut txn, &mut channel, &to_download, self.all)
    .await?;
    [6.119504]
    [6.120122]
  • replacement in pijul/src/commands/pushpull.rs at line 421
    [6.2210][6.120778:120955](),[6.120778][6.120778:120955]()
    txn.output_repository_no_pending(
    &mut repo.working_copy,
    &repo.changes,
    &mut channel,
    "",
    true,
    )?;
    [6.2210]
    [6.2211]
    debug!("inodes = {:?}", inodes);
    if inodes.is_empty() {
    txn.output_repository_no_pending(
    &mut repo.working_copy,
    &repo.changes,
    &mut channel,
    "",
    true,
    )?;
    } else {
    for i in inodes {
    let i = if let Some(change) = txn.get_internal(i.change) {
    libpijul::pristine::Position { change, pos: i.pos }
    } else {
    continue;
    };
    let (path, _) =
    libpijul::fs::find_path(&repo.changes, &txn, &channel.borrow(), false, i)?;
    debug!("path = {:?}", path);
    txn.output_repository_no_pending(
    &mut repo.working_copy,
    &repo.changes,
    &mut channel,
    &path,
    true,
    )?;
    }
    }
  • replacement in pijul/src/commands/pushpull.rs at line 512
    [6.123150][6.123150:123223]()
    return Err((crate::Error::MissingDep { h: *n }).into());
    [6.123150]
    [6.123223]
    bail!("Missing dependency: {:?}", n)
  • replacement in pijul/src/commands/protocol.rs at line 1
    [6.123281][6.1797:1828]()
    use std::collections::HashMap;
    [6.123281]
    [6.1828]
    use std::collections::{HashMap, HashSet};
  • replacement in pijul/src/commands/protocol.rs at line 31
    [6.123976][6.123976:124060]()
    static ref CHANGELIST_PATHS: Regex = Regex::new(r#""((\\")|[^"])+""#).unwrap();
    [6.123976]
    [6.124060]
    static ref CHANGELIST_PATHS: Regex = Regex::new(r#""(((\\")|[^"])+)""#).unwrap();
  • replacement in pijul/src/commands/protocol.rs at line 97
    [6.126705][6.126705:126749]()
    let mut paths = Vec::new();
    [6.126705]
    [6.126749]
    let mut paths = HashSet::new();
    debug!("cap[3] = {:?}", &cap[3]);
  • replacement in pijul/src/commands/protocol.rs at line 100
    [6.126816][6.126816:126875]()
    let s: String = r[0].parse().unwrap();
    [6.126816]
    [6.126875]
    let s: String = r[1].replace("\\\"", "\"");
  • replacement in pijul/src/commands/protocol.rs at line 109
    [6.127257][6.127257:127295]()
    paths.push(p)
    [6.127257]
    [6.127295]
    let h = txn.get_external(p.change).unwrap();
    writeln!(o, "{}.{}", h.to_base32(), p.pos.0)?;
    paths.insert(p);
    paths.extend(libpijul::fs::iter_graph_descendants(
    &txn,
    &channel.borrow(),
    p,
    ));
  • edit in pijul/src/commands/protocol.rs at line 124
    [6.127543]
    [6.127543]
    debug!("paths = {:?}", paths);
  • replacement in pijul/src/commands/protocol.rs at line 128
    [6.127715][6.127715:127871]()
    || paths
    .iter()
    .any(|x| txn.get_touched_files(*x, Some(h_int)).is_some())
    [6.127715]
    [6.127871]
    || paths.iter().any(|x| {
    x.change == h_int || txn.get_touched_files(*x, Some(h_int)).is_some()
    })
  • edit in libpijul/src/pristine/mod.rs at line 1348
    [2.19236]
    [6.54465]
    debug!("registering change {:?}", hash);
  • replacement in libpijul/src/pristine/mod.rs at line 1352
    [6.54587][6.54587:54658]()
    debug!(target:"libpijul::register_change", "dep = {:?}", dep);
    [6.54587]
    [6.54658]
    debug!("dep = {:?}", dep);
  • replacement in libpijul/src/pristine/mod.rs at line 1354
    [6.54718][6.54718:54818]()
    debug!(target:"libpijul::register_change", "{:?} depends on {:?}", internal, dep_internal);
    [6.54718]
    [6.54818]
    debug!("{:?} depends on {:?}", internal, dep_internal);
  • replacement in libpijul/src/pristine/mod.rs at line 1359
    [6.54982][6.54982:55146]()
    let inode = match *hunk {
    Atom::NewVertex(NewVertex { ref inode, .. }) => inode,
    Atom::EdgeMap(EdgeMap { ref inode, .. }) => inode,
    [6.54982]
    [6.55146]
    let (inode, pos) = match *hunk {
    Atom::NewVertex(NewVertex {
    ref inode,
    ref flag,
    ref start,
    ref end,
    ..
    }) => {
    if flag.contains(EdgeFlags::FOLDER) && start == end {
    (inode, Some(*start))
    } else {
    (inode, None)
    }
    }
    Atom::EdgeMap(EdgeMap { ref inode, .. }) => (inode, None),
  • replacement in libpijul/src/pristine/mod.rs at line 1382
    [6.55376][6.55376:55467]()
    debug!(target:"libpijul::register_change", "touched: {:?} {:?}", inode, internal);
    [6.55376]
    [6.55467]
    debug!("touched: {:?} {:?}", inode, internal);
  • edit in libpijul/src/pristine/mod.rs at line 1385
    [6.55569]
    [6.55569]
    if let Some(pos) = pos {
    let inode = Position {
    change: internal,
    pos,
    };
    txn.put_touched_files(inode, internal)?;
    txn.put_rev_touched_files(internal, inode)?;
    }
  • edit in libpijul/src/fs.rs at line 20
    [6.738443]
    [6.738461]
    use std::collections::HashSet;
  • edit in libpijul/src/fs.rs at line 427
    [6.752107]
    [6.752107]
    }
    /// An iterator over the descendants of an
    /// inode key in the graph.
    ///
    /// Constructed using
    /// [`iter_graph_descendants`](fn.iter_graph_descendants.html).
    pub struct GraphDescendants<'txn, 'channel, T: TxnT> {
    txn: &'txn T,
    channel: &'channel Channel<T>,
    stack: Vec<AdjacentIterator<'txn, T>>,
    visited: HashSet<Position<ChangeId>>,
  • edit in libpijul/src/fs.rs at line 441
    [6.752110]
    [6.752165]
    impl<'txn, 'channel, T: TxnT> Iterator for GraphDescendants<'txn, 'channel, T> {
    type Item = Position<ChangeId>;
    fn next(&mut self) -> Option<Self::Item> {
    if let Some(mut adj) = self.stack.pop() {
    if let Some(child) = adj.next() {
    self.stack.push(adj);
    let dest = find_block(self.txn, &self.channel, child.dest).unwrap();
    let grandchild = iter_adjacent(
    self.txn,
    &self.channel,
    dest,
    EdgeFlags::FOLDER,
    EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
    )
    .next()
    .unwrap();
    if self.visited.insert(grandchild.dest) {
    self.stack.push(iter_adjacent(
    self.txn,
    &self.channel,
    grandchild.dest.inode_vertex(),
    EdgeFlags::FOLDER,
    EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
    ))
    }
    return Some(grandchild.dest);
    } else {
    // No child left, actually pop.
    }
    }
    None
    }
    }
    /// Returns a list of files under the given key. The root key is
    /// [`pristine::Vertex::ROOT`](../pristine/constant.Vertex::ROOT.html).
    pub fn iter_graph_descendants<'txn, 'channel, T: TxnT>(
    txn: &'txn T,
    channel: &'channel Channel<T>,
    key: Position<ChangeId>,
    ) -> GraphDescendants<'txn, 'channel, T> {
    GraphDescendants {
    stack: vec![iter_adjacent(
    txn,
    &channel,
    key.inode_vertex(),
    EdgeFlags::FOLDER,
    EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
    )],
    visited: HashSet::new(),
    txn,
    channel,
    }
    }
  • edit in libpijul/src/changestore/mod.rs at line 46
    [6.818827]
    [6.818827]
    }
    fn get_changes(
    &self,
    hash: &Hash,
    ) -> Result<Vec<crate::change::Record<Option<Hash>, crate::change::Local>>, Self::Error> {
    Ok(self.get_change(hash)?.hashed.changes)