From c32d8b7a599c0ee0d8936a0c5aee658b5d986453 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Jul 2021 20:00:28 +0800 Subject: [PATCH] [ref #139] Allow 'git pack-ref --no-purge' essentially It's surprisingly easy to implement as well, neat. --- git-ref/src/store/file/mod.rs | 1 + git-ref/src/store/file/transaction/mod.rs | 27 +++++++++++++++++++ git-ref/src/store/file/transaction/prepare.rs | 18 ++++++++++++- .../prepare_and_commit/create_or_update.rs | 13 +++++---- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/git-ref/src/store/file/mod.rs b/git-ref/src/store/file/mod.rs index e1ee02e377..f126b82afb 100644 --- a/git-ref/src/store/file/mod.rs +++ b/git-ref/src/store/file/mod.rs @@ -34,6 +34,7 @@ pub struct Transaction<'s> { store: &'s Store, packed_transaction: Option, updates: Option>, + packed_refs: transaction::PackedRefs, } pub(in crate::store::file) fn path_to_name(path: impl Into) -> bstr::BString { diff --git a/git-ref/src/store/file/transaction/mod.rs b/git-ref/src/store/file/transaction/mod.rs index fca992497f..9a345ef4b3 100644 --- a/git-ref/src/store/file/transaction/mod.rs +++ b/git-ref/src/store/file/transaction/mod.rs @@ -5,6 +5,24 @@ use crate::{ use bstr::BString; use git_hash::ObjectId; +/// How to handle packed refs during a transaction +#[derive(Debug, Clone, Copy)] +pub enum PackedRefs { + /// Only propagate deletions of references. This is the default + DeletionsOnly, + /// Propagate deletions as well as updates to references which are peeled, that is contain an object id + DeletionsAndNonSymbolicUpdates, + /// Propagate deletions as well as updates to references which are peeled, that is contain an object id. Furthermore delete the + /// reference which is originally updated if it exists. If it doesn't, the new value will be written into the packed ref right away. + DeletionsAndNonSymbolicUpdatesRemoveLooseSourceReference, +} + +impl Default for PackedRefs { + fn default() -> Self { + PackedRefs::DeletionsOnly + } +} + #[derive(Debug)] pub(in crate::store::file) struct Edit { update: RefEdit, @@ -46,10 +64,19 @@ impl file::Store { store: self, packed_transaction: None, updates: None, + packed_refs: PackedRefs::default(), } } } +impl<'s> Transaction<'s> { + /// Configure the way packed refs are handled during the transaction + pub fn packed_refs(mut self, packed_refs: PackedRefs) -> Self { + self.packed_refs = packed_refs; + self + } +} + /// pub mod prepare; diff --git a/git-ref/src/store/file/transaction/prepare.rs b/git-ref/src/store/file/transaction/prepare.rs index 04c04c3dea..4fa8634b02 100644 --- a/git-ref/src/store/file/transaction/prepare.rs +++ b/git-ref/src/store/file/transaction/prepare.rs @@ -4,7 +4,10 @@ use crate::{ store::{ file, file::loose, - file::{transaction::Edit, Transaction}, + file::{ + transaction::{Edit, PackedRefs}, + Transaction, + }, }, transaction::{Change, Create, LogChange, RefEdit, RefEditsExt, RefLog}, }; @@ -215,6 +218,19 @@ impl<'s> Transaction<'s> { if log_mode == RefLog::Only { continue; } + if matches!( + self.packed_refs, + PackedRefs::DeletionsAndNonSymbolicUpdates + | PackedRefs::DeletionsAndNonSymbolicUpdatesRemoveLooseSourceReference + ) { + if let Change::Update { + new: Target::Peeled(_), .. + } = edit.update.change + { + edits_for_packed_transaction.push(edit.update.clone()); + } + continue; + } match edit.update.change { Change::Update { mode: Create::OrUpdate { previous: None }, diff --git a/git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs b/git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs index 958d1287d5..f797751704 100644 --- a/git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs +++ b/git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs @@ -6,7 +6,10 @@ use bstr::ByteSlice; use git_hash::ObjectId; use git_lock::acquire::Fail; use git_ref::{ - file::{transaction, WriteReflog}, + file::{ + transaction::{self, PackedRefs}, + WriteReflog, + }, mutable::Target, transaction::{Change, Create, LogChange, RefEdit, RefLog}, }; @@ -504,7 +507,7 @@ fn packed_refs_are_looked_up_when_checking_existing_values() -> crate::Result { #[test] #[ignore] fn packed_refs_creation_with_packed_refs_mode_prune_removes_original_loose_refs() { - // Also: make sure tags are going to be peeled + // TODO: Also: make sure tags are going to be peeled todo!("use file::Store::packed_transaction(), figure out how to incorporate this into loose transactions to support purge/purge-delete-original") } @@ -540,15 +543,15 @@ fn packed_refs_creation_with_packed_refs_mode_leave_keeps_original_loose_refs() let edits = store .transaction() - // .packed_refs(PackedRefs::Update) + .packed_refs(PackedRefs::DeletionsAndNonSymbolicUpdates) .prepare(edits, git_lock::acquire::Fail::Immediately) .unwrap() .commit(&committer()) .unwrap(); assert_eq!( edits.len(), - 1, - "there really is just one ref that needs updating, symbolic refs are ignored if they don't change the value" + 2, + "it claims to have performed all desired operations, even though some don't make it into the pack as 'side-car'" ); assert_eq!(