Skip to content

Commit 9749fb4

Browse files
committed
add lock info to repofiles
1 parent 5ccf12c commit 9749fb4

File tree

3 files changed

+84
-5
lines changed

3 files changed

+84
-5
lines changed

crates/core/src/commands/prune.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::{
3838
GlobalIndex, ReadGlobalIndex, ReadIndex,
3939
},
4040
progress::{Progress, ProgressBars},
41-
repofile::{HeaderEntry, IndexBlob, IndexFile, IndexPack, SnapshotFile},
41+
repofile::{indexfile::LockOption, HeaderEntry, IndexBlob, IndexFile, IndexPack, SnapshotFile},
4242
repository::{Open, Repository},
4343
};
4444

@@ -434,6 +434,8 @@ struct PrunePack {
434434
to_do: PackToDo,
435435
/// The time the pack was created
436436
time: Option<DateTime<Local>>,
437+
/// Locking information
438+
lock: LockOption,
437439
/// The blobs in the pack
438440
blobs: Vec<IndexBlob>,
439441
}
@@ -453,6 +455,7 @@ impl PrunePack {
453455
delete_mark,
454456
to_do: PackToDo::Undecided,
455457
time: p.time,
458+
lock: p.lock,
456459
blobs: p.blobs,
457460
}
458461
}
@@ -481,6 +484,7 @@ impl PrunePack {
481484
id: self.id,
482485
time: self.time,
483486
size: None,
487+
lock: self.lock,
484488
blobs: self.blobs,
485489
}
486490
}
@@ -495,6 +499,7 @@ impl PrunePack {
495499
id: self.id,
496500
time: Some(time),
497501
size: None,
502+
lock: self.lock,
498503
blobs: self.blobs,
499504
}
500505
}
@@ -739,6 +744,12 @@ impl PrunePlan {
739744
let to_compress = repack_uncompressed && !pack.is_compressed();
740745
let size_mismatch = !pack_sizer[pack.blob_type].size_ok(pack.size);
741746

747+
if pack.lock.is_locked(Some(self.time)) {
748+
// keep packs which are locked
749+
pack.set_todo(PackToDo::Keep, &pi, &mut self.stats);
750+
continue;
751+
}
752+
742753
match (pack.delete_mark, pi.used_blobs, pi.unused_blobs) {
743754
(false, 0, _) => {
744755
// unused pack
@@ -1056,6 +1067,7 @@ impl PrunePlan {
10561067
id,
10571068
size: Some(size),
10581069
time: Some(Local::now()),
1070+
lock: LockOption::NotSet,
10591071
blobs: Vec::new(),
10601072
};
10611073
indexer.write().unwrap().add_remove(pack)?;

crates/core/src/repofile/indexfile.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{cmp::Ordering, num::NonZeroU32};
22

33
use chrono::{DateTime, Local};
4-
4+
use derivative::Derivative;
55
use serde_derive::{Deserialize, Serialize};
66

77
use crate::{
@@ -47,6 +47,40 @@ impl IndexFile {
4747
}
4848
}
4949

50+
/// Options for locking packfiles.
51+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Derivative, Copy)]
52+
#[derivative(Default)]
53+
pub enum LockOption {
54+
/// No lock set.
55+
#[derivative(Default)]
56+
NotSet,
57+
/// The pack is locked forever and we have a permanent lock on the backend for the packfile
58+
LockedForever,
59+
/// The pack is locked until the given timestamp and we have a temporary lock on the backend for the packfile
60+
LockedUntil(DateTime<Local>),
61+
}
62+
63+
impl From<Option<DateTime<Local>>> for LockOption {
64+
fn from(value: Option<DateTime<Local>>) -> Self {
65+
value.map_or(Self::LockedForever, Self::LockedUntil)
66+
}
67+
}
68+
69+
impl LockOption {
70+
/// Returns whether the delete option is set to `NotSet`.
71+
const fn is_not_set(&self) -> bool {
72+
matches!(self, Self::NotSet)
73+
}
74+
75+
pub fn is_locked(&self, time: Option<DateTime<Local>>) -> bool {
76+
match (self, time) {
77+
(Self::LockedForever, _) => true,
78+
(Self::LockedUntil(locktime), Some(time)) => locktime >= &time,
79+
_ => false,
80+
}
81+
}
82+
}
83+
5084
#[derive(Serialize, Deserialize, Default, Debug, Clone)]
5185
/// Index information about a `pack`
5286
pub struct IndexPack {
@@ -57,6 +91,9 @@ pub struct IndexPack {
5791
#[serde(skip_serializing_if = "Option::is_none")]
5892
/// The pack creation time or time when the pack was marked for deletion
5993
pub time: Option<DateTime<Local>>,
94+
/// Indication if the pack file is locked in the backend
95+
#[serde(default, skip_serializing_if = "LockOption::is_not_set")]
96+
pub lock: LockOption,
6097
#[serde(skip_serializing_if = "Option::is_none")]
6198
/// The pack size
6299
pub size: Option<u32>,

crates/core/src/repofile/snapshotfile.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,33 @@ pub enum DeleteOption {
228228
Never,
229229
/// Remove this snapshot after the given timestamp, but prevent removing it before.
230230
After(DateTime<Local>),
231+
/// This snapshot is locked forever. This is similar to Never, but additionally indicates that we have a permanent lock on the
232+
/// backend for the snapshot file
233+
LockedForever,
234+
/// This snapshot pack is locked until the given timestamp and we have a temporary lock on the backend for the snapshot file
235+
LockedUntil(DateTime<Local>),
236+
}
237+
238+
impl From<Option<DateTime<Local>>> for DeleteOption {
239+
fn from(value: Option<DateTime<Local>>) -> Self {
240+
value.map_or(Self::LockedForever, Self::LockedUntil)
241+
}
231242
}
232243

233244
impl DeleteOption {
234245
/// Returns whether the delete option is set to `NotSet`.
235246
const fn is_not_set(&self) -> bool {
236247
matches!(self, Self::NotSet)
237248
}
249+
250+
/// Returns whether a lock exists which extends the given time, where `None` means "forever"
251+
pub fn is_locked(&self, time: Option<DateTime<Local>>) -> bool {
252+
match (self, time) {
253+
(Self::LockedForever, _) => true,
254+
(Self::LockedUntil(locktime), Some(time)) => locktime >= &time,
255+
_ => false,
256+
}
257+
}
238258
}
239259

240260
#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
@@ -700,20 +720,30 @@ impl SnapshotFile {
700720
matches!(self.delete,DeleteOption::After(time) if time < now)
701721
}
702722

703-
/// Returns whether a snapshot must be kept now
723+
/// Returns whether a snapshot must be kept at the given time
704724
///
705725
/// # Arguments
706726
///
707727
/// * `now` - The current time
708728
#[must_use]
709729
pub fn must_keep(&self, now: DateTime<Local>) -> bool {
710730
match self.delete {
711-
DeleteOption::Never => true,
712-
DeleteOption::After(time) if time >= now => true,
731+
DeleteOption::Never | DeleteOption::LockedForever => true,
732+
DeleteOption::After(time) | DeleteOption::LockedUntil(time) => time >= now,
713733
_ => false,
714734
}
715735
}
716736

737+
/// Returns whether a snapshot is locked at the given time
738+
///
739+
/// # Arguments
740+
///
741+
/// * `now` - The current time
742+
#[must_use]
743+
pub fn is_locked(&self, now: DateTime<Local>) -> bool {
744+
self.delete.is_locked(Some(now))
745+
}
746+
717747
/// Modifies the snapshot setting/adding/removing tag(s) and modifying [`DeleteOption`]s.
718748
///
719749
/// # Arguments

0 commit comments

Comments
 (0)