Support for sub-transactions

pmeunier
Jan 13, 2026, 11:13 AM
AZM7VL5ZYNM2T2QOF2W24SALXGNYOVKNJJ4IQIFCMAWKG4V52IHAC

Dependencies

  • [2] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [3] VO5OQW4W Removing anyhow in libpijul
  • [4] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [5] GHO6DWPI Refactoring iterators
  • [6] YN63NUZO Sanakirja 1.0
  • [7] QL6K2ZM3 Tags
  • [8] FXEDPLRI Resurrecting tests, and type cleanup (no need for Arc<RwLock<…>> anymore)
  • [9] IVLLXQ5Z Improved push/pull reporting
  • [10] 7HOBLRD4 Fixing remote push/pull
  • [11] U2CGP7OP Record a separate change for Hunk::AddRoot, to avoid #571
  • [12] ZDK3GNDB Tag transactions (including a massive refactoring of errors)
  • [13] 5MRZLKBH Changing the type of the tags db, to make it identical to remote tags
  • [14] DO2Y5TY5 Tag synchronisation
  • [15] TCFJMFFE Using state_from_prefix and hash_from_prefix on remotes to complete (or find) hashes and states
  • [16] GDAKVAFR Fixing apply (ghost channels could happen in case of error)
  • [17] QWIYNMI5 Formatting + big-endian Sanakirja
  • [18] OYN2YVPA Create `pijul_remote` crate
  • [19] IP4CUEBE reset: Require --force to reset unspecified unrecorded changes
  • [20] 44SHUW5W Fixing conflicts
  • [21] 2MKP7CB7 Move dependencies into workspace `Cargo.toml`
  • [22] QAS4VLXU Use `serde_derive` instead of `serde`'s `derive` feature'
  • [23] LTI3LT2G Bump all dependencies to latest compatible minor versions
  • [24] NMXHEBFI Upgrade workspace dependencies
  • [25] SCUBUHIA Remove `lazy_static` dependency
  • [26] OWJL5HO7 Allow deleting remote by URL and remove default remote if set to deleted remote
  • [27] 67GIAQEU Handle named remotes in pijul remote and remote delete
  • [28] Q5PNWJ5W Refactor reset command's handling of repo and channel
  • [29] MKDWLE4V 🩹 Reorder imports, solve merge conflicts, post merge cleanup
  • [30] 7FP2DFNX Optimisation: avoid re-checking the entire repo when recording after an unrecord
  • [31] XYTAZR36 Solving conflicts
  • [32] YD7QFAD7 Simplifying pijul::remote::PushDelta
  • [33] I52XSRUH Massive cleanup, and simplification
  • [34] CXSCA5HN Fixing a counter-intuitive error when a local repo does not exist
  • [35] HP7CKJIW Fixing a bug in unrecord
  • [36] IIV3EL2X Cleanup, formatting, and fixing the Git feature
  • [37] L4JXJHWX pijul/*: reorganize imports and remove extern crate
  • [38] R3H7D42U Debugging `pijul git`: proper error reporting
  • [39] EUZFFJSO Updating Pijul with the latest changes in Libpijul
  • [40] S2B5MEWP Minor change in the type of sanakirja::GraphTxnT::Graph (prepare for more general backends)
  • [41] EEBKW7VT Keys and identities
  • [42] YXAVFTPP Allowing vertex buffer to use references to the transaction, by changing `output::output` to take an ArcTxn<T> instead of a simple T
  • [43] 26VQKD25 A more accurate safeguard for apply, to check if the output is nondestructive
  • [44] G7HJHNFD Migrate from `pijul_interaction::progress` to `pijul_interaction`
  • [45] M2HRKB7F Remove warning that `serde` and `serde_derive` must be exactly equal
  • [46] SYZ44SKF Remove `async_trait` crate
  • [47] VQQ23NP7 Fix conflicts
  • [48] CRLBACYQ Fixing conflicts
  • [49] TCXM4WIJ Remove unused dependencies
  • [50] MU5GSJAW Partial push and pull (WARNING: breaks the existing protocol)
  • [51] ABQDWHNG Migrate from `pijul::repository` to `pijul-repository`
  • [52] ZBNKSYA6 Fixing a bus error when starting a transaction on a full disk
  • [53] FKUPWOP7 Removing the `--tag` option to push and pull

Change contents

  • replacement in pijul-remote/src/lib.rs at line 10
    [25.582][25.582:622]()
    RemoteRef, TxnT, sanakirja::MutTxn,
    [25.582]
    [9.134]
    RemoteRef, TxnT, sanakirja::MutTxn, sanakirja::RawMutTxnT,
  • replacement in pijul-remote/src/lib.rs at line 246
    [9.273][18.172:197](),[18.197][9.294:358](),[9.294][9.294:358]()
    pub fn get_local_inodes(
    txn: &mut MutTxn<()>,
    channel: &ChannelRef<MutTxn<()>>,
    [9.273]
    [9.358]
    pub fn get_local_inodes<T: RawMutTxnT + 'static>(
    txn: &mut MutTxn<T>,
    channel: &ChannelRef<MutTxn<T>>,
  • replacement in pijul-remote/src/lib.rs at line 310
    [9.3294][9.3294:3325]()
    impl RemoteDelta<MutTxn<()>> {
    [9.3294]
    [9.3325]
    impl<T: RawMutTxnT + 'static> RemoteDelta<MutTxn<T>> {
  • replacement in pijul-remote/src/lib.rs at line 316
    [9.3521][9.3521:3551]()
    txn: &mut MutTxn<()>,
    [9.3521]
    [9.3551]
    txn: &mut MutTxn<T>,
  • replacement in pijul-remote/src/lib.rs at line 318
    [9.3576][9.3576:3618]()
    channel: &ChannelRef<MutTxn<()>>,
    [9.3576]
    [9.3618]
    channel: &ChannelRef<MutTxn<T>>,
  • replacement in pijul-remote/src/lib.rs at line 358
    [9.5192][9.5192:5222]()
    txn: &mut MutTxn<()>,
    [9.5192]
    [9.5222]
    txn: &mut MutTxn<T>,
  • replacement in pijul-remote/src/lib.rs at line 360
    [9.5247][9.5247:5289]()
    channel: &ChannelRef<MutTxn<()>>,
    [9.5247]
    [9.5289]
    channel: &ChannelRef<MutTxn<T>>,
  • replacement in pijul-remote/src/lib.rs at line 471
    [9.7643][18.336:376]()
    pub fn update_changelist_local_channel(
    [9.7643]
    [9.7690]
    pub fn update_changelist_local_channel<T: RawMutTxnT + 'static>(
  • replacement in pijul-remote/src/lib.rs at line 473
    [9.7716][9.7716:7742]()
    txn: &mut MutTxn<()>,
    [9.7716]
    [9.7742]
    txn: &mut MutTxn<T>,
  • replacement in pijul-remote/src/lib.rs at line 475
    [9.7763][9.7763:7809]()
    current_channel: &ChannelRef<MutTxn<()>>,
    [9.7763]
    [9.7809]
    current_channel: &ChannelRef<MutTxn<T>>,
  • replacement in pijul-remote/src/lib.rs at line 478
    [9.7865][9.7865:7919]()
    ) -> Result<RemoteDelta<MutTxn<()>>, anyhow::Error> {
    [9.7865]
    [9.7919]
    ) -> Result<RemoteDelta<MutTxn<T>>, anyhow::Error> {
  • replacement in pijul-remote/src/lib.rs at line 642
    [14.8976][14.8976:9030]()
    async fn update_changelist_pushpull_from_scratch(
    [14.8976]
    [14.9030]
    async fn update_changelist_pushpull_from_scratch<T: RawMutTxnT>(
  • replacement in pijul-remote/src/lib.rs at line 644
    [14.9049][14.9049:9079]()
    txn: &mut MutTxn<()>,
    [14.9049]
    [14.9079]
    txn: &mut MutTxn<T>,
  • replacement in pijul-remote/src/lib.rs at line 646
    [14.9104][14.9104:9212]()
    current_channel: &ChannelRef<MutTxn<()>>,
    ) -> Result<RemoteDelta<MutTxn<()>>, anyhow::Error> {
    [14.9104]
    [14.9212]
    current_channel: &ChannelRef<MutTxn<T>>,
    ) -> Result<RemoteDelta<MutTxn<T>>, anyhow::Error> {
  • replacement in pijul-remote/src/lib.rs at line 691
    [9.10802][18.377:422]()
    pub async fn update_changelist_pushpull(
    [9.10802]
    [9.10854]
    pub async fn update_changelist_pushpull<T: RawMutTxnT + 'static>(
  • replacement in pijul-remote/src/lib.rs at line 693
    [9.10873][9.10873:10903]()
    txn: &mut MutTxn<()>,
    [9.10873]
    [9.10903]
    txn: &mut MutTxn<T>,
  • replacement in pijul-remote/src/lib.rs at line 695
    [9.10928][9.10928:10978]()
    current_channel: &ChannelRef<MutTxn<()>>,
    [9.10928]
    [9.10978]
    current_channel: &ChannelRef<MutTxn<T>>,
  • replacement in pijul-remote/src/lib.rs at line 700
    [14.10428][9.11077:11135](),[9.11077][9.11077:11135]()
    ) -> Result<RemoteDelta<MutTxn<()>>, anyhow::Error> {
    [15.23]
    [10.403]
    ) -> Result<RemoteDelta<MutTxn<T>>, anyhow::Error> {
  • replacement in pijul-remote/Cargo.toml at line 15
    [18.889][21.149:175]()
    libpijul.workspace = true
    [18.889]
    [21.175]
    libpijul = { workspace = true, features = [ "tarball" ] }
  • replacement in pijul/src/commands/reset.rs at line 11
    [28.79][29.114:195]()
    use libpijul::pristine::{ChangeId, ChannelMutTxnT, Position, sanakirja::MutTxn};
    [28.79]
    [29.195]
    use libpijul::pristine::{
    ChangeId, ChannelMutTxnT, Position,
    sanakirja::{MutTxn, RawMutTxnT},
    };
  • replacement in pijul/src/commands/reset.rs at line 290
    [19.474][20.142:235]()
    fn has_unrecorded_changes(
    txn: ArcTxn<MutTxn<()>>,
    channel: ChannelRef<MutTxn<()>>,
    [19.474]
    [20.235]
    fn has_unrecorded_changes<T: RawMutTxnT + Sync + 'static>(
    txn: ArcTxn<MutTxn<T>>,
    channel: ChannelRef<MutTxn<T>>,
  • replacement in pijul/src/commands/record.rs at line 146
    [11.20][11.20:108]()
    .apply_root_change_if_needed(&repo.changes, &channel, rand::thread_rng())?;
    [11.20]
    [11.108]
    .apply_root_change_if_needed(&repo.changes, &channel, rand::rng())?;
  • replacement in pijul/src/commands/pushpull.rs at line 15
    [26.34][29.570:613]()
    use libpijul::pristine::sanakirja::MutTxn;
    [26.34]
    [4.12857]
    use libpijul::pristine::sanakirja::{MutTxn, RawMutTxnT};
  • replacement in pijul/src/commands/pushpull.rs at line 301
    [26.1485][27.8134:8167]()
    fn flood_delete(
    [26.1485]
    [27.8167]
    fn flood_delete<T: RawMutTxnT>(
  • replacement in pijul/src/commands/pushpull.rs at line 306
    [27.8312][27.8312:8354]()
    txn: &mut MutTxn<()>,
    [27.8312]
    [27.8354]
    txn: &mut MutTxn<T>,
  • replacement in pijul/src/commands/pushpull.rs at line 471
    [9.19162][9.19162:19186]()
    async fn to_upload(
    [9.19162]
    [9.19186]
    async fn to_upload<T: RawMutTxnT + 'static>(
  • replacement in pijul/src/commands/pushpull.rs at line 473
    [9.19201][9.19201:19277]()
    txn: &mut MutTxn<()>,
    channel: &mut ChannelRef<MutTxn<()>>,
    [9.19201]
    [9.19277]
    txn: &mut MutTxn<T>,
    channel: &mut ChannelRef<MutTxn<T>>,
  • replacement in pijul/src/commands/pushpull.rs at line 648
    [9.20806][9.20806:20832]()
    async fn to_download(
    [9.20806]
    [9.20832]
    async fn to_download<T: RawMutTxnT + 'static>(
  • replacement in pijul/src/commands/pushpull.rs at line 650
    [9.20847][9.20847:20923]()
    txn: &mut MutTxn<()>,
    channel: &mut ChannelRef<MutTxn<()>>,
    [9.20847]
    [9.20923]
    txn: &mut MutTxn<T>,
    channel: &mut ChannelRef<MutTxn<T>>,
  • replacement in pijul/src/commands/pushpull.rs at line 654
    [14.28443][9.20987:21045](),[9.20987][9.20987:21045]()
    ) -> Result<RemoteDelta<MutTxn<()>>, anyhow::Error> {
    [9.20987]
    [9.21045]
    ) -> Result<RemoteDelta<MutTxn<T>>, anyhow::Error> {
  • replacement in pijul/src/commands/protocol.rs at line 298
    [2.132020][2.132020:132164]()
    let fork_name: String = rand::thread_rng()
    .sample_iter(&rand::distributions::Alphanumeric)
    [2.132020]
    [2.132164]
    let fork_name: String = rand::rng()
    .sample_iter(&rand::distr::Alphanumeric)
  • replacement in pijul/src/commands/apply.rs at line 49
    [16.153][16.153:272]()
    let forked_s: String = rand::thread_rng()
    .sample_iter(&rand::distributions::Alphanumeric)
    [16.153]
    [16.272]
    let forked_s: String = rand::rng()
    .sample_iter(&rand::distr::Alphanumeric)
  • replacement in libpijul/src/unrecord/mod.rs at line 318
    [30.5175][30.5175:5313]()
    working_copy
    .touch(&name, now)
    .map_err(UnrecordError::WorkingCopy)?
    [30.5175]
    [30.5313]
    working_copy.touch(&name, now).unwrap_or(())
  • edit in libpijul/src/tests/conflict.rs at line 1282
    [2.394418]
    [2.394418]
    crate::pristine::debug(
    &*txn.read(),
    &*channel_alice.read(),
    std::fs::File::create("alice.dot").unwrap(),
    )?;
  • edit in libpijul/src/tests/conflict.rs at line 1306
    [8.63059]
    [2.394986]
    crate::pristine::debug(
    &*txn.read(),
    &*channel_bob.read(),
    std::fs::File::create("bob.dot").unwrap(),
    )?;
  • replacement in libpijul/src/pristine/sanakirja.rs at line 174
    [2.534125][8.98445:98525]()
    pub fn arc_txn_begin(&self) -> Result<ArcTxn<MutTxn<()>>, SanakirjaError> {
    [2.534125]
    [8.98525]
    pub fn arc_txn_begin(
    &self,
    ) -> Result<ArcTxn<MutTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>>, SanakirjaError> {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 180
    [8.98597][7.22355:22427](),[2.534125][7.22355:22427]()
    pub fn mut_txn_begin(&self) -> Result<MutTxn<()>, SanakirjaError> {
    [8.98597]
    [17.12499]
    pub fn mut_txn_begin(
    &self,
    ) -> Result<MutTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>, SanakirjaError> {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 269
    [6.59992][6.59992:60072]()
    pub type MutTxn<T> = GenericTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>, T>>;
    [6.59992]
    [2.536591]
    pub type MutTxn<T> = GenericTxn<T>;
    pub type MutTxn0 = GenericTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>;
    pub trait RawMutTxnT:
    ::sanakirja::AllocPage<Error = ::sanakirja::Error>
    + ::sanakirja::RootPageMut
    + ::sanakirja::Commit
    + ::sanakirja::LoadPage<Error = ::sanakirja::Error>
    {
    }
    impl<
    T: ::sanakirja::AllocPage<Error = ::sanakirja::Error>
    + ::sanakirja::RootPageMut
    + ::sanakirja::Commit
    + ::sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > RawMutTxnT for T
    {
    }
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1650
    [2.558873][4.49977:50012]()
    impl GraphMutTxnT for MutTxn<()> {
    [2.558873]
    [2.558892]
    impl<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPage
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > GraphMutTxnT for MutTxn<T>
    {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1760
    [2.559395][4.50242:50279]()
    impl ChannelMutTxnT for MutTxn<()> {
    [2.559395]
    [5.47629]
    impl<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPage
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > ChannelMutTxnT for MutTxn<T>
    {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1906
    [4.50939][13.2610:2652]()
    fn replay_tags(
    txn: &mut MutTxn<()>,
    [4.50939]
    [13.2652]
    fn replay_tags<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPage
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    >(
    txn: &mut MutTxn<T>,
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1942
    [13.3541][4.50939:50973](),[4.50939][4.50939:50973]()
    impl DepsMutTxnT for MutTxn<()> {
    [13.3541]
    [4.50973]
    impl<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPage
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > DepsMutTxnT for MutTxn<T>
    {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1954
    [4.51263][4.51263:51297]()
    impl TreeMutTxnT for MutTxn<()> {
    [4.51263]
    [12.20216]
    impl<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPageMut
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > TreeMutTxnT for MutTxn<T>
    {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 1985
    [4.52453][4.52453:52483]()
    impl MutTxnT for MutTxn<()> {
    [4.52453]
    [2.562200]
    impl<T: RawMutTxnT> MutTxnT for MutTxn<T> {
  • replacement in libpijul/src/pristine/sanakirja.rs at line 2432
    [2.572764][2.572764:572784]()
    impl<T> MutTxn<T> {
    [2.572764]
    [3.16532]
    impl<
    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
    + sanakirja::RootPage
    + sanakirja::LoadPage<Error = ::sanakirja::Error>,
    > MutTxn<T>
    {
  • replacement in Cargo.toml at line 92
    [24.183][23.453:533](),[21.7405][23.453:533]()
    sanakirja = { version = "1.4", default-features = false, features = ["crc32"] }
    [24.183]
    [22.275]
    sanakirja = { version = "2.0.0-beta", default-features = false, features = ["crc32"] }
  • replacement in Cargo.lock at line 2764
    [31.68481][31.68481:68499]()
    version = "1.4.3"
    [31.68481]
    [31.68499]
    version = "2.0.0-beta"
  • replacement in Cargo.lock at line 2766
    [31.68564][31.68564:68642]()
    checksum = "81aaf70d064e2122209f04d01fd91e8908e7a327b516236e1cbc0c3f34ac6d11"
    [31.68564]
    [31.68642]
    checksum = "4fc53a1e7a19d27c070749c0d2717427d1612c9b100274b205dbb438e605e34a"