Optimisation: avoid re-checking the entire repo when recording after an unrecord

pmeunier
Dec 26, 2025, 7:39 PM
7FP2DFNXGKH2GQIH35BAIHMRORXERI6ARZGVVN7LZKMUYIADIULAC

Dependencies

  • [2] 5PZN75Y6 Unrecord the pending patch when pulling, in the special case that there is nothing to download
  • [3] Q6MRVSJX Higher resolution for status change times on Unix, and coarser test for 1-second-resolution filesystems
  • [4] TLGB23EK When unrecording, report "change not in channel" if that is the case *before* trying to load the change
  • [5] 4UY2WBBP Adding a "Sink" working copy and avoid outputting ignored files
  • [6] BSEJ3J6P Follow the keep-changes feature instead of its negation (in `pijul unrecord`)
  • [7] HP7CKJIW Fixing a bug in unrecord
  • [8] N26HD5PF Replace `chrono` with `jiff`
  • [9] N5XHCYVT Remove use of unsafe
  • [10] BXD3IQYN Fixing --features git
  • [11] MU5GSJAW Partial push and pull (WARNING: breaks the existing protocol)
  • [12] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [13] IIV3EL2X Cleanup, formatting, and fixing the Git feature
  • [14] RP7YRM5Q Import Git repos without writing anything to disk
  • [15] GHO6DWPI Refactoring iterators
  • [16] P6WE7YKL Unrecord did not check whether a file already existed before adding it back
  • [17] LODKR74E Changing touched_channel resolution to milliseconds instead of seconds
  • [18] V4T4SC7O Testing binary diff
  • [19] BOJEBIOI Fixing "block error" in unrecord
  • [20] LCERQSWM Cleanup
  • [21] RRCSHAYZ Formatting
  • [22] RMDMAYRX Adding a root inode (aka supporting submodules)
  • [23] EUZFFJSO Updating Pijul with the latest changes in Libpijul
  • [24] BD5PC25A Deleting conflict resolution vertices when the sides are deleted
  • [25] 2RXOCWUW Making libpijul deterministic (and getting rid of `rand`)
  • [26] 7UPL3Y2A Unrecord: don't restore the same unrecorded file deletion twice in the inodes and tree tables
  • [27] ZXTHL45O address clippy lints
  • [28] FXEDPLRI Resurrecting tests, and type cleanup (no need for Arc<RwLock<…>> anymore)
  • [29] 2UMXNSD5 Record: simpler detection of moves vs conflicts
  • [30] HMMMKONL Fixing alive vertices
  • [31] 7ZFRYVVQ Cargo.nix and formatting
  • [32] TVHECUPY Fixing an unwrap on bad patches in unrecord (these patches cannot even be produced outside of bugs)
  • [33] K7JPP64S Faster error in unrecord when the change is not on the channel
  • [34] 6YMDOZIB Refactoring apply
  • [35] KQTD46KV Unrecord: restore files *after* having unapplied the *entire* change
  • [36] K34KD3FT Refactor fork command's handling of repo and channel
  • [37] I24UEJQL Various post-fire fixes
  • [38] WUBONLD6 Fixing libpijul::fs::find_path for metadata/encodings
  • [39] YXAVFTPP Allowing vertex buffer to use references to the transaction, by changing `output::output` to take an ArcTxn<T> instead of a simple T
  • [40] 3CFU4DQN Fixing a bug in unrecord, where a patch creating an undeletion conflict would not be properly unrecorded
  • [41] YHG37GA4 Removing one buffer copy in VertexBuffer
  • [42] MQ6ERQ43 Bug fixes when unrecording a patch that introduced zombie files
  • [43] MDADYULS Fix a panic when switching between channels that have different files
  • [44] IXC43DSH Fixing a bug in unrecord
  • [45] TIPZ7UXN Started fixing the tests for parallel record/output
  • [46] WZVCLZKY address clippy lints
  • [47] VO5OQW4W Removing anyhow in libpijul
  • [48] 3AMEP2Y5 More convenient interface for channels
  • [49] OXZVZDQZ Simplification of missing context repairs
  • [50] GUL4M5FI Cleanup and formatting
  • [51] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [52] E3DD265T Fork to a *state*
  • [53] 27PYHR6L Making the get_latest_touch function (useful to make archives) public in libpijul
  • [54] DJYHARZ7 Skipping old files when recording
  • [55] 3M7WBE24 Re-adding anyhow in the tests of libpijul
  • [56] ZDK3GNDB Tag transactions (including a massive refactoring of errors)
  • [57] YN63NUZO Sanakirja 1.0
  • [58] Q45QHPO4 Feedback on network stuff
  • [59] I52XSRUH Massive cleanup, and simplification
  • [60] CVLQ7DBF Committing the remotes even if we do not push anything
  • [*] TYAKEAJL A better estimate of the maximum number of open patches we can keep (Unix-only at the moment)
  • [*] WW2EOFBB Umask in archives
  • [*] LPM4PBYJ More precise API for working copy in record and output
  • [*] MOPABMFW Fixing a deadlock in working_copy::memory (used only in tests for now)

Change contents

  • edit in pijul-remote/src/lib.rs at line 1048
    [62.835]
    [63.21]
    let mut working_copy =
    libpijul::working_copy::filesystem::FileSystem::from_root(&l.root);
  • replacement in pijul-remote/src/lib.rs at line 1057
    [10.227][10.227:323]()
    txn.archive_with_state(&changes, &channel, &state, extra, &mut tarball, 0)?
    [10.227]
    [10.61504]
    txn.archive_with_state(
    &changes,
    &channel,
    &state,
    extra,
    &mut tarball,
    0,
    &mut working_copy,
    )?
  • replacement in pijul/src/commands/unrecord.rs at line 128
    [10.998][10.2116:2186]()
    txn.write().unrecord(&repo.changes, &channel, &hash, 0)?;
    [10.998]
    [10.5477]
    txn.write()
    .unrecord(&repo.changes, &channel, &hash, 0, &repo.working_copy)?;
  • replacement in pijul/src/commands/unrecord.rs at line 146
    [10.5939][10.2273:2340]()
    txn.write().unrecord(&repo.changes, &channel, &h, 0)?;
    [10.5939]
    [6.0]
    txn.write()
    .unrecord(&repo.changes, &channel, &h, 0, &repo.working_copy)?;
  • edit in pijul/src/commands/record.rs at line 123
    [8.1524]
    [10.501]
    &repo.working_copy,
  • replacement in pijul/src/commands/pushpull.rs at line 745
    [2.40][2.40:114]()
    txn.write().unrecord(&repo.changes, &mut channel, h, 0)?;
    [2.40]
    [2.114]
    txn.write()
    .unrecord(&repo.changes, &mut channel, h, 0, &repo.working_copy)?;
  • replacement in pijul/src/commands/pushpull.rs at line 892
    [10.120988][10.11296:11367]()
    txn.write().unrecord(&repo.changes, &mut channel, &h, 0)?;
    [10.120988]
    [10.121048]
    txn.write()
    .unrecord(&repo.changes, &mut channel, &h, 0, &repo.working_copy)?;
  • edit in pijul/src/commands/protocol.rs at line 312
    [10.826]
    [10.132573]
    &repo.working_copy,
  • replacement in pijul/src/commands/fork.rs at line 57
    [10.1912][10.1912:1988]()
    txn.unrecord(&repo.changes, &mut fork, &h, 0)?;
    [10.1912]
    [10.1988]
    txn.unrecord(&repo.changes, &mut fork, &h, 0, &repo.working_copy)?;
  • edit in pijul/src/commands/archive.rs at line 120
    [10.1652]
    [10.193775]
    &repo.working_copy,
  • edit in libpijul/src/working_copy/mod.rs at line 50
    [64.135]
    [5.94]
    fn touch(&self, _name: &str, time: std::time::SystemTime) -> Result<(), Self::Error> {
    Ok(())
    }
  • edit in libpijul/src/working_copy/memory.rs at line 332
    [65.1007]
    [10.208875]
    }
    fn touch(&self, file: &str, time: std::time::SystemTime) -> Result<(), Self::Error> {
    let mut m = self.0.lock();
    if let Some(f) = m.get_file_mut(file) {
    if let Inode::File {
    ref mut last_modified,
    ..
    } = f
    {
    *last_modified = time
    } else {
    unreachable!()
    }
    }
    Ok(())
  • edit in libpijul/src/working_copy/filesystem.rs at line 487
    [10.216924]
    [10.216924]
    fn touch(&self, file: &str, time: std::time::SystemTime) -> Result<(), Self::Error> {
    let p = self.path(file);
    let src = std::fs::metadata(&p)?;
    let dest = std::fs::File::open(&p)?;
    let times = std::fs::FileTimes::new().set_modified(time);
    dest.set_times(times)?;
    Ok(())
    }
  • edit in libpijul/src/unrecord/working_copy.rs at line 5
    [10.226097]
    [10.0]
    use crate::working_copy::WorkingCopy;
  • replacement in libpijul/src/unrecord/working_copy.rs at line 24
    [10.3][10.8900:8984]()
    pub fn undo_file_deletion<T: ChannelTxnT + TreeMutTxnT + TreeTxnT, P: ChangeStore>(
    [10.3]
    [10.226784]
    pub fn undo_file_deletion<
    T: ChannelTxnT + TreeMutTxnT + TreeTxnT,
    P: ChangeStore,
    W: crate::working_copy::WorkingCopy,
    >(
  • replacement in libpijul/src/unrecord/working_copy.rs at line 35
    [10.2060][10.8985:9038]()
    ) -> Result<(), super::UnrecordError<P::Error, T>> {
    [10.2060]
    [10.226940]
    ) -> Result<(), super::UnrecordError<P::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/working_copy.rs at line 42
    [10.6696][10.2061:2125]()
    restore(txn, changes, channel, source, dest, salt)?
    [10.6696]
    [10.227344]
    restore::<_, _, W>(txn, changes, channel, source, dest, salt)?
  • replacement in libpijul/src/unrecord/working_copy.rs at line 48
    [10.5][10.9039:9108]()
    fn restore<T: ChannelTxnT + TreeMutTxnT + TreeTxnT, P: ChangeStore>(
    [10.5]
    [10.227468]
    fn restore<T: ChannelTxnT + TreeMutTxnT + TreeTxnT, P: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/working_copy.rs at line 55
    [10.2141][10.9109:9162]()
    ) -> Result<(), super::UnrecordError<P::Error, T>> {
    [10.2141]
    [10.227621]
    ) -> Result<(), super::UnrecordError<P::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/working_copy.rs at line 62
    [10.92][10.2142:2237]()
    return_value = restore_inode(txn, changes, source, dest, parent_inode, salt)?;
    [10.92]
    [10.181]
    return_value =
    restore_inode::<_, _, W>(txn, changes, source, dest, parent_inode, salt)?;
  • replacement in libpijul/src/unrecord/working_copy.rs at line 86
    [10.228382][10.2238:2328]()
    return_value = restore_inode(txn, changes, source, dest, Inode::ROOT, salt)?;
    [10.228382]
    [10.14972]
    return_value = restore_inode::<_, _, W>(txn, changes, source, dest, Inode::ROOT, salt)?;
  • replacement in libpijul/src/unrecord/working_copy.rs at line 88
    [10.15052][10.2329:2413]()
    return_value = restore_inode(txn, changes, source, dest, inode, salt)?;
    [10.15052]
    [10.228631]
    return_value = restore_inode::<_, _, W>(txn, changes, source, dest, inode, salt)?;
  • replacement in libpijul/src/unrecord/working_copy.rs at line 92
    [10.336][10.336:430]()
    return_value = restore_inode(txn, changes, source, dest, Inode::ROOT, salt)?;
    [10.336]
    [10.430]
    return_value =
    restore_inode::<_, _, W>(txn, changes, source, dest, Inode::ROOT, salt)?;
  • replacement in libpijul/src/unrecord/working_copy.rs at line 103
    [10.9][10.9163:9236]()
    fn restore_inode<T: TreeMutTxnT + GraphTxnT + TreeTxnT, P: ChangeStore>(
    [10.9]
    [10.228969]
    fn restore_inode<T: TreeMutTxnT + GraphTxnT + TreeTxnT, P: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/working_copy.rs at line 110
    [10.2429][10.9237:9301]()
    ) -> Result<Option<Inode>, super::UnrecordError<P::Error, T>> {
    [10.2429]
    [10.353]
    ) -> Result<Option<Inode>, super::UnrecordError<P::Error, W::Error, T>> {
  • edit in libpijul/src/unrecord/working_copy.rs at line 188
    [10.21979]
    [10.21979]
    W: WorkingCopy,
  • replacement in libpijul/src/unrecord/working_copy.rs at line 193
    [10.230916][10.9302:9355]()
    ) -> Result<(), super::UnrecordError<P::Error, T>> {
    [10.230916]
    [10.230949]
    ) -> Result<(), super::UnrecordError<P::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 5
    [10.231689][10.231689:231690]()
    [10.231671]
    [10.231690]
    use crate::working_copy::WorkingCopy;
  • replacement in libpijul/src/unrecord/mod.rs at line 11
    [10.9373][10.9373:9470]()
    pub enum UnrecordError<ChangestoreError: std::error::Error + 'static, T: GraphTxnT + TreeTxnT> {
    [10.9373]
    [10.7820]
    pub enum UnrecordError<
    ChangestoreError: std::error::Error + 'static,
    WorkingCopyError: std::error::Error + 'static,
    T: GraphTxnT + TreeTxnT,
    > {
  • edit in libpijul/src/unrecord/mod.rs at line 39
    [10.9928]
    [10.22318]
    #[error(transparent)]
    WorkingCopy(WorkingCopyError),
  • replacement in libpijul/src/unrecord/mod.rs at line 43
    [10.22321][10.9929:10023]()
    impl<C: std::error::Error, T: GraphTxnT + TreeTxnT> std::fmt::Debug for UnrecordError<C, T> {
    [10.22321]
    [10.10023]
    impl<C: std::error::Error, W: std::error::Error, T: GraphTxnT + TreeTxnT> std::fmt::Debug
    for UnrecordError<C, W, T>
    {
  • edit in libpijul/src/unrecord/mod.rs at line 68
    [10.11131]
    [10.11131]
    UnrecordError::WorkingCopy(e) => std::fmt::Debug::fmt(e, fmt),
  • replacement in libpijul/src/unrecord/mod.rs at line 73
    [10.8614][10.231752:231797](),[10.231752][10.231752:231797]()
    pub fn unrecord<T: MutTxnT, P: ChangeStore>(
    [10.8614]
    [10.231797]
    pub fn unrecord<T: MutTxnT, P: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 79
    [10.2521][10.11142:11190]()
    ) -> Result<bool, UnrecordError<P::Error, T>> {
    [10.2521]
    [10.15913]
    working_copy: &W,
    ) -> Result<bool, UnrecordError<P::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 89
    [10.232195][10.8769:8833]()
    del_channel_changes::<T, P>(txn, &mut channel, change_id)?;
    [10.232195]
    [10.232251]
    del_channel_changes::<T, P, W>(txn, &mut channel, change_id)?;
  • replacement in libpijul/src/unrecord/mod.rs at line 95
    [4.99][10.2522:2590](),[10.232252][10.2522:2590]()
    unapply(txn, &mut channel, changes, change_id, &change, salt)?;
    [4.99]
    [10.232314]
    unapply(
    txn,
    &mut channel,
    changes,
    change_id,
    &change,
    salt,
    working_copy,
    )?;
  • edit in libpijul/src/unrecord/mod.rs at line 123
    [10.23143]
    [10.23143]
    W: WorkingCopy,
  • replacement in libpijul/src/unrecord/mod.rs at line 128
    [10.232905][10.11279:11325]()
    ) -> Result<(), UnrecordError<P::Error, T>> {
    [10.232905]
    [10.16307]
    ) -> Result<(), UnrecordError<P::Error, W::Error, T>> {
  • edit in libpijul/src/unrecord/mod.rs at line 179
    [10.23854]
    [10.23854]
    W: WorkingCopy,
  • replacement in libpijul/src/unrecord/mod.rs at line 187
    [10.2606][10.11326:11372]()
    ) -> Result<(), UnrecordError<C::Error, T>> {
    [10.2606]
    [10.0]
    working_copy: &W,
    ) -> Result<(), UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 199
    [10.244][10.244:275]()
    unapply_edges(
    [10.244]
    [10.275]
    unapply_edges::<_, _, W>(
  • replacement in libpijul/src/unrecord/mod.rs at line 217
    [10.234880][10.1909:1952]()
    unapply_newvertex::<T, C>(
    [10.234880]
    [10.1952]
    unapply_newvertex::<T, C, W>(
  • replacement in libpijul/src/unrecord/mod.rs at line 233
    [10.737][10.2220:2308](),[10.2017][10.2220:2308]()
    remove_zombies::<_, C>(txn, T::graph_mut(channel), &mut ws, change_id, n)?;
    [10.737]
    [10.235581]
    remove_zombies::<_, C, W>(txn, T::graph_mut(channel), &mut ws, change_id, n)?;
  • replacement in libpijul/src/unrecord/mod.rs at line 242
    [10.372][10.723:777]()
    working_copy::undo_file_deletion(
    [10.372]
    [10.777]
    working_copy::undo_file_deletion::<_, _, W>(
  • replacement in libpijul/src/unrecord/mod.rs at line 246
    [10.653][10.653:744]()
    working_copy::undo_file_reinsertion::<C, _>(txn, change_id, newedges)?
    [10.653]
    [10.744]
    working_copy::undo_file_reinsertion::<C, _, W>(txn, change_id, newedges)?
  • replacement in libpijul/src/unrecord/mod.rs at line 261
    [10.839][10.839:873]()
    for inode in touched_inodes {
    [10.839]
    [10.873]
    for inode in touched_inodes.iter() {
  • replacement in libpijul/src/unrecord/mod.rs at line 264
    [10.1201][10.968:1034](),[10.968][10.968:1034]()
    if let Ok(inode) = internal_pos(txn, &inode, change_id) {
    [10.1201]
    [10.1034]
    if let Ok(inode) = internal_pos(txn, inode, change_id) {
  • replacement in libpijul/src/unrecord/mod.rs at line 305
    [10.2573][10.884:925]()
    txn.touch_channel(channel, Some(0));
    [10.2573]
    [7.409]
    let now = std::time::SystemTime::now();
    for inode in touched_inodes.iter() {
    if let Ok(inode) = internal_pos(txn, inode, change_id) {
    if let Some(inode) = txn.get_revinodes(&inode, None)? {
    if let Some(name) = crate::fs::inode_filename(txn, *inode)? {
    debug!(
    "touching file {:?} {:?}",
    name,
    now.duration_since(std::time::SystemTime::UNIX_EPOCH)
    .unwrap()
    .as_millis()
    );
    working_copy
    .touch(&name, now)
    .map_err(UnrecordError::WorkingCopy)?
    }
    }
    }
    }
  • replacement in libpijul/src/unrecord/mod.rs at line 342
    [10.235980][10.11373:11439]()
    fn unapply_newvertex<T: GraphMutTxnT + TreeTxnT, C: ChangeStore>(
    [10.235980]
    [10.236239]
    fn unapply_newvertex<T: GraphMutTxnT + TreeTxnT, C: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 348
    [10.236377][10.11440:11486]()
    ) -> Result<(), UnrecordError<C::Error, T>> {
    [10.236377]
    [10.236410]
    ) -> Result<(), UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 378
    [10.238115][10.990:1045]()
    ws.perform_del::<C, T>(txn, channel, vertex)?;
    [10.238115]
    [10.1045]
    ws.perform_del::<C, T, W>(txn, channel, vertex)?;
  • replacement in libpijul/src/unrecord/mod.rs at line 387
    [10.1166][10.11487:11551]()
    fn perform_del<C: ChangeStore, T: GraphMutTxnT + TreeTxnT>(
    [10.1166]
    [10.1214]
    fn perform_del<C: ChangeStore, T: GraphMutTxnT + TreeTxnT, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 392
    [10.1322][10.11552:11602]()
    ) -> Result<(), UnrecordError<C::Error, T>> {
    [10.1322]
    [10.1379]
    ) -> Result<(), UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 413
    [10.10239][10.11725:11787]()
    fn unapply_edges<T: GraphMutTxnT + TreeTxnT, P: ChangeStore>(
    [10.239447]
    [10.240406]
    fn unapply_edges<T: GraphMutTxnT + TreeTxnT, P: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 420
    [10.240557][10.11788:11834]()
    ) -> Result<(), UnrecordError<P::Error, T>> {
    [10.240557]
    [10.240590]
    ) -> Result<(), UnrecordError<P::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 446
    [10.569][10.1342:1375]()
    if must_reintroduce(
    [10.569]
    [10.1375]
    if must_reintroduce::<_, _, W>(
  • replacement in libpijul/src/unrecord/mod.rs at line 499
    [10.241975][10.11835:11897]()
    fn must_reintroduce<T: GraphTxnT + TreeTxnT, C: ChangeStore>(
    [10.241975]
    [10.242021]
    fn must_reintroduce<T: GraphTxnT + TreeTxnT, C: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 508
    [10.1958][10.11898:11946]()
    ) -> Result<bool, UnrecordError<C::Error, T>> {
    [10.1958]
    [10.242203]
    ) -> Result<bool, UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 539
    [10.243198][10.243198:243261]()
    edge_is_in_channel(txn, changes, b_ext, intro, &mut stack)
    [10.243198]
    [10.243261]
    edge_is_in_channel::<_, _, W>(txn, changes, b_ext, intro, &mut stack)
  • replacement in libpijul/src/unrecord/mod.rs at line 542
    [10.243264][10.11947:12011]()
    fn edge_is_in_channel<T: GraphTxnT + TreeTxnT, C: ChangeStore>(
    [10.243264]
    [10.243312]
    fn edge_is_in_channel<T: GraphTxnT + TreeTxnT, C: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 548
    [10.243431][10.12012:12060]()
    ) -> Result<bool, UnrecordError<C::Error, T>> {
    [10.243431]
    [10.243466]
    ) -> Result<bool, UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/unrecord/mod.rs at line 571
    [7.1048][10.12061:12124](),[10.243938][10.12061:12124]()
    fn remove_zombies<T: GraphMutTxnT + TreeTxnT, C: ChangeStore>(
    [7.1048]
    [10.243969]
    fn remove_zombies<T: GraphMutTxnT + TreeTxnT, C: ChangeStore, W: WorkingCopy>(
  • replacement in libpijul/src/unrecord/mod.rs at line 577
    [10.244079][10.12125:12171]()
    ) -> Result<(), UnrecordError<C::Error, T>> {
    [10.244079]
    [10.244208]
    ) -> Result<(), UnrecordError<C::Error, W::Error, T>> {
  • replacement in libpijul/src/tests/unrecord.rs at line 30
    [10.1353][10.1353:1432]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    [10.1353]
    [10.249770]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 68
    [10.1907][10.1907:1986]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    [10.1907]
    [10.251116]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 106
    [10.252428][10.2451:2530]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    [10.252428]
    [10.252499]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 203
    [10.255738][10.4125:4204]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0)?;
    [10.255738]
    [10.255856]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 259
    [10.257744][10.5018:5097]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0)?;
    [10.257744]
    [10.257815]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 294
    [10.258960][10.5328:5409]()
    crate::unrecord::unrecord(&mut *txn2.write(), &channel2, &changes, &h1, 0)?;
    [10.258960]
    [10.259082]
    crate::unrecord::unrecord(&mut *txn2.write(), &channel2, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 331
    [10.260384][10.5987:6066]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    [10.260384]
    [10.260549]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 388
    [10.262135][10.6628:6713]()
    match crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0) {
    [10.262135]
    [10.495]
    match crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0, &repo) {
  • replacement in libpijul/src/tests/unrecord.rs at line 395
    [10.6811][10.6811:6897]()
    match crate::unrecord::unrecord(&mut *txn.write(), &channel2, &changes, &h0, 0) {
    [10.6811]
    [10.575]
    match crate::unrecord::unrecord(&mut *txn.write(), &channel2, &changes, &h0, 0, &repo) {
  • replacement in libpijul/src/tests/unrecord.rs at line 405
    [10.6991][10.6991:7070]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    [10.6991]
    [10.263106]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 412
    [10.7164][10.7164:7243]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0)?;
    [10.7164]
    [10.263373]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 451
    [10.264448][10.7795:7873]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h, 0)?;
    [10.264448]
    [10.264562]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 462
    [10.264932][10.7938:8017]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0)?;
    [10.264932]
    [10.265047]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h0, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 532
    [10.267354][10.8726:8808]()
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel, &changes, &c, 0)?;
    [10.267354]
    [10.267468]
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel, &changes, &c, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 622
    [10.270241][10.9344:9426]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h_inv, 0)?;
    [10.270241]
    [10.270315]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h_inv, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 680
    [10.272403][10.10093:10172]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0)?;
    [10.272403]
    [10.272518]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 736
    [10.274399][10.10847:10930]()
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel, &changes, &h2, 0)?;
    [10.274399]
    [10.274514]
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel, &changes, &h2, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 771
    [10.275627][10.11154:11238]()
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel2, &changes, &h1, 0)?;
    [10.275627]
    [10.275749]
    crate::unrecord::unrecord(&mut *txn.write(), &mut channel2, &changes, &h1, 0, &repo)?;
  • replacement in libpijul/src/tests/unrecord.rs at line 817
    [10.1611][10.11905:12063]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0)?;
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0)?;
    [10.1611]
    [10.1753]
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h2, 0, &repo)?;
  • edit in libpijul/src/tests/unrecord.rs at line 826
    [10.1870]
    [10.276024]
    Ok(())
    }
    /// Delete the same file on two different channels, merge, unrecord each patch on the same channel. What happens to tree/revtree?
    #[test]
    fn fs_times() -> Result<(), anyhow::Error> {
    env_logger::try_init().unwrap_or(());
    let repo = working_copy::memory::Memory::new();
    let changes = changestore::memory::Memory::new();
    let env = pristine::sanakirja::Pristine::new_anon()?;
    let txn = env.arc_txn_begin().unwrap();
    let channel = txn.write().open_or_create_channel("main")?;
    repo.add_file("file", b"blabla\nblibli\nblublu\n".to_vec());
    repo.add_file("file2", b"blabla\nblibli\nblublu\n".to_vec());
    txn.write().add_file("file", 0)?;
    txn.write().add_file("file2", 0)?;
    let h0 = record_all(&repo, &changes, &txn, &channel, "")?;
    debug!("h0 = {:?}", h0);
    repo.write_file("file", Inode::ROOT)?
    .write_all(b"blabla\nblublu\n")?;
    let h1 = record_all(&repo, &changes, &txn, &channel, "")?;
    debug!("last {:?}", txn.read().last_modified(&channel.r.read()));
    // Modify file2, but set its modification time one hour ago, so we
    // can check that `unrecord` doesn't read the entire repo.
    repo.write_file("file2", Inode::ROOT)?
    .write_all(b"blabla\nblublu\n")?;
    repo.touch(
    "file2",
    std::time::SystemTime::now() - std::time::Duration::from_hours(1),
    )?;
    crate::unrecord::unrecord(&mut *txn.write(), &channel, &changes, &h1, 0, &repo)?;
    debug!("last {:?}", txn.read().last_modified(&channel.r.read()));
    info!("Final record");
    let h1 = record_all(&repo, &changes, &txn, &channel, "")?;
    let change1 = changes.get_change(&h1).unwrap();
    assert_eq!(change1.changes.len(), 1);
  • edit in libpijul/src/tests/missing_context.rs at line 101
    [10.22500]
    [10.22500]
    &repo_alice,
  • replacement in libpijul/src/tests/missing_context.rs at line 103
    [10.22508][10.22508:22602]()
    crate::unrecord::unrecord(&mut *txn_alice.write(), &channel_alice, &changes, &bob_h, 0)?;
    [10.22508]
    [10.14172]
    crate::unrecord::unrecord(
    &mut *txn_alice.write(),
    &channel_alice,
    &changes,
    &bob_h,
    0,
    &repo_alice,
    )?;
  • edit in libpijul/src/tests/missing_context.rs at line 155
    [10.23378]
    [10.23378]
    &repo_bob,
  • edit in libpijul/src/tests/file_conflicts.rs at line 1460
    [10.48051]
    [10.48051]
    &repo_alice,
  • replacement in libpijul/src/tests/diff.rs at line 28
    [10.1138][10.1138:1230](),[10.1230][9.81:108](),[9.108][10.1290:1301](),[10.1290][10.1290:1301]()
    contents.extend(
    (&mut rng)
    .sample_iter(&Alphanumeric)
    .take(80),
    );
    [10.1138]
    [9.109]
    contents.extend((&mut rng).sample_iter(&Alphanumeric).take(80));
  • replacement in libpijul/src/tests/conflict.rs at line 179
    [10.362243][10.51524:51623]()
    crate::unrecord::unrecord(&mut *txn.write(), &channel_bob, &changes, &resolution, 0).unwrap();
    [10.362243]
    [10.362394]
    crate::unrecord::unrecord(
    &mut *txn.write(),
    &channel_bob,
    &changes,
    &resolution,
    0,
    &repo_bob,
    )
    .unwrap();
  • edit in libpijul/src/tests/conflict.rs at line 2279
    [10.74463]
    [10.74463]
    &repo_bob,
  • edit in libpijul/src/record.rs at line 550
    [10.495538]
    [10.50469]
    txn.write().touch_channel(&mut channel.write(), None);
  • replacement in libpijul/src/record.rs at line 909
    [10.160][10.56558:56597](),[10.56558][10.56558:56597]()
    txn.last_modified(channel)
    [10.160]
    [10.56597]
    txn.last_modified(channel),
  • edit in libpijul/src/record.rs at line 922
    [3.817]
    [3.817]
    debug!("recording = {:?}", last_mod >= channel_mod);
  • replacement in libpijul/src/record.rs at line 1357
    [10.2023][10.2023:2051]()
    .0,
    [10.2023]
    [10.509979]
    .0
    .join("/"),
  • replacement in libpijul/src/pristine/mod.rs at line 2156
    [10.750][10.590:633](),[10.2073][10.590:633](),[10.77352][10.590:633](),[10.590][10.590:633]()
    let path = path.replace("/", "_");
    [10.750]
    [10.633]
    let path = path.join("_");
  • edit in libpijul/src/output/archive.rs at line 3
    [10.690096]
    [10.690096]
    use crate::working_copy::WorkingCopy;
  • edit in libpijul/src/output/archive.rs at line 104
    [10.25378]
    [10.25378]
    W: std::error::Error + 'static,
  • replacement in libpijul/src/output/archive.rs at line 115
    [10.25482][10.25482:25542]()
    Unrecord(#[from] crate::unrecord::UnrecordError<P, T>),
    [10.25482]
    [10.25542]
    Unrecord(#[from] crate::unrecord::UnrecordError<P, W, T>),
  • replacement in libpijul/src/output/archive.rs at line 126
    [10.692169][10.31345:31485]()
    impl<P: std::error::Error + 'static, T: GraphTxnT + TreeTxnT, A: std::error::Error + 'static>
    std::fmt::Debug for ArchiveError<P, T, A>
    [10.692169]
    [10.87733]
    impl<
    P: std::error::Error + 'static,
    T: GraphTxnT + TreeTxnT,
    A: std::error::Error + 'static,
    W: std::error::Error + 'static,
    > std::fmt::Debug for ArchiveError<P, T, A, W>
  • edit in libpijul/src/output/archive.rs at line 154
    [10.87931]
    [10.87931]
    W: WorkingCopy,
  • replacement in libpijul/src/output/archive.rs at line 161
    [10.692359][10.32308:32374]()
    ) -> Result<Vec<Conflict>, ArchiveError<P::Error, T, A::Error>> {
    [10.692359]
    [10.692439]
    ) -> Result<Vec<Conflict>, ArchiveError<P::Error, T, A::Error, W::Error>> {
  • replacement in libpijul/src/lib.rs at line 219
    [10.725196][10.725196:725242]()
    fn unrecord<C: changestore::ChangeStore>(
    [10.725196]
    [10.725242]
    fn unrecord<C: changestore::ChangeStore, W: working_copy::WorkingCopy>(
  • replacement in libpijul/src/lib.rs at line 225
    [10.4209][10.33168:33233](),[10.33233][10.4210:4273](),[10.94683][10.4210:4273]()
    ) -> Result<bool, unrecord::UnrecordError<C::Error, Self>> {
    unrecord::unrecord(self, channel, changes, hash, salt)
    [10.4209]
    [10.725459]
    working_copy: &W,
    ) -> Result<bool, unrecord::UnrecordError<C::Error, W::Error, Self>> {
    unrecord::unrecord(self, channel, changes, hash, salt, working_copy)
  • replacement in libpijul/src/lib.rs at line 431
    [10.732181][10.104220:104291]()
    fs::find_path(changes, self, &channel.read(), false, position)
    [10.732181]
    [10.732254]
    if let Some((a, b)) = fs::find_path(changes, self, &channel.read(), false, position)? {
    Ok(Some((a.join("/"), b)))
    } else {
    Ok(None)
    }
  • replacement in libpijul/src/lib.rs at line 448
    [10.732653][10.104292:104362]()
    fs::find_path(changes, self, &channel.read(), true, position)
    [10.732653]
    [10.732725]
    if let Some((a, b)) = fs::find_path(changes, self, &channel.read(), true, position)? {
    Ok(Some((a.join("/"), b)))
    } else {
    Ok(None)
    }
  • replacement in libpijul/src/lib.rs at line 476
    [10.6399][10.6399:6460]()
    pub fn archive<C: changestore::ChangeStore, A: Archive>(
    [10.6399]
    [10.733620]
    pub fn archive<C: changestore::ChangeStore, A: Archive, W: working_copy::WorkingCopy>(
  • replacement in libpijul/src/lib.rs at line 481
    [10.733724][10.6505:6591](),[10.6591][10.733780:733859](),[10.30328][10.733780:733859](),[10.34199][10.733780:733859](),[10.99249][10.733780:733859](),[10.733780][10.733780:733859]()
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, T, A::Error>> {
    output::archive(changes, self, channel, &mut std::iter::empty(), arch)
    [10.733724]
    [10.733859]
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, T, A::Error, W::Error>> {
    output::archive::<_, _, _, _, W>(changes, self, channel, &mut std::iter::empty(), arch)
  • edit in libpijul/src/lib.rs at line 490
    [10.6725]
    [10.6725]
    W: working_copy::WorkingCopy,
  • replacement in libpijul/src/lib.rs at line 497
    [10.734091][10.6777:6863](),[10.6863][10.734147:734209](),[10.30425][10.734147:734209](),[10.34289][10.734147:734209](),[10.99355][10.734147:734209](),[10.734147][10.734147:734209]()
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, T, A::Error>> {
    output::archive(changes, self, channel, prefix, arch)
    [10.734091]
    [10.6864]
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, T, A::Error, W::Error>> {
    output::archive::<_, _, _, _, W>(changes, self, channel, prefix, arch)
  • replacement in libpijul/src/lib.rs at line 503
    [10.6902][10.6902:6974]()
    pub fn archive_with_state<P: changestore::ChangeStore, A: Archive>(
    [10.6902]
    [10.6974]
    pub fn archive_with_state<
    P: changestore::ChangeStore,
    A: Archive,
    W: working_copy::WorkingCopy,
    >(
  • replacement in libpijul/src/lib.rs at line 515
    [10.7162][10.7162:7248]()
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, T, A::Error>> {
    [10.7162]
    [10.7248]
    working_copy: &W,
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, T, A::Error, W::Error>> {
  • edit in libpijul/src/lib.rs at line 525
    [10.7441]
    [10.7441]
    working_copy,
  • edit in libpijul/src/lib.rs at line 536
    [10.7710]
    [10.7710]
    W: working_copy::WorkingCopy,
  • replacement in libpijul/src/lib.rs at line 547
    [10.7966][10.7966:8052]()
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, T, A::Error>> {
    [10.7966]
    [10.8052]
    working_copy: &W,
    ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, T, A::Error, W::Error>> {
  • replacement in libpijul/src/lib.rs at line 566
    [10.8641][10.8641:8717]()
    unrecord::unrecord(&mut *txn, channel, changes, &h, salt)?;
    [10.8641]
    [10.8717]
    unrecord::unrecord(&mut *txn, channel, changes, &h, salt, working_copy)?;
  • replacement in libpijul/src/lib.rs at line 575
    [10.9003][10.9003:9069]()
    output::archive(changes, self, channel, prefix, arch)
    [10.9003]
    [10.9069]
    output::archive::<_, _, _, _, W>(changes, self, channel, prefix, arch)
  • replacement in libpijul/src/fs.rs at line 181
    [10.9][10.741561:741617](),[10.4882][10.741561:741617](),[10.741561][10.741561:741617]()
    /// Find the filename leading from the root to ~inode~.
    [10.4882]
    [10.103454]
    /// Find the filename leading from the root to `inode`.
  • edit in libpijul/src/fs.rs at line 952
    [10.760897]
    [10.113826]
    /// Compute either the oldest or the youngest filesystem path to a
    /// graph vertex.
  • replacement in libpijul/src/fs.rs at line 960
    [10.761102][10.36150:36227]()
    ) -> Result<Option<(String, bool)>, crate::output::FileError<C::Error, T>> {
    [10.761102]
    [10.761147]
    ) -> Result<Option<(Vec<String>, bool)>, crate::output::FileError<C::Error, T>> {
  • replacement in libpijul/src/fs.rs at line 1062
    [10.763251][10.2748:2790]()
    Ok(Some((path.join("/"), all_alive)))
    [10.763251]
    [10.628]
    Ok(Some((path, all_alive)))