``--keep-last <N>``
Keep the last ``<N>`` backup snapshots.
+``--keep-hourly <N>``
+ Keep backups for the last ``<N>`` different hours. If there is more than one
+ backup for a single hour, only the latest one is kept.
+
``--keep-daily <N>``
- Keep backups for ``<N>`` different days. If there is more than one
+ Keep backups for the last ``<N>`` different days. If there is more than one
backup for a single day, only the latest one is kept.
``--keep-weekly <N>``
- Keep backups for ``<N>`` different weeks. If there is more than one
+ Keep backups for the last ``<N>`` different weeks. If there is more than one
backup for a single week, only the latest one is kept.
.. note:: The weeks start on Monday and end on Sunday. The software
the end of the year.
``--keep-monthly <N>``
- Keep backups for ``<N>`` different months. If there is more than one
+ Keep backups for the last ``<N>`` different months. If there is more than one
backup for a single month, only the latest one is kept.
``--keep-yearly <N>``
- Keep backups for ``<N>`` different year. If there is more than one
+ Keep backups for the last ``<N>`` different years. If there is more than one
backup for a single year, only the latest one is kept.
.minimum(1)
.schema()
),
+ (
+ "keep-hourly",
+ true,
+ &IntegerSchema::new("Number of hourly backups to keep.")
+ .minimum(1)
+ .schema()
+ ),
(
"keep-last",
true,
let prune_options = PruneOptions {
keep_last: param["keep-last"].as_u64(),
+ keep_hourly: param["keep-hourly"].as_u64(),
keep_daily: param["keep-daily"].as_u64(),
keep_weekly: param["keep-weekly"].as_u64(),
keep_monthly: param["keep-monthly"].as_u64(),
let prune_options = PruneOptions {
keep_last: param["keep-last"].as_u64(),
+ keep_hourly: param["keep-hourly"].as_u64(),
keep_daily: param["keep-daily"].as_u64(),
keep_weekly: param["keep-weekly"].as_u64(),
keep_monthly: param["keep-monthly"].as_u64(),
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
-use chrono::{DateTime, Datelike, Local};
+use chrono::{DateTime, Timelike, Datelike, Local};
use super::{BackupDir, BackupInfo};
pub struct PruneOptions {
pub keep_last: Option<u64>,
+ pub keep_hourly: Option<u64>,
pub keep_daily: Option<u64>,
pub keep_weekly: Option<u64>,
pub keep_monthly: Option<u64>,
pub fn new() -> Self {
Self {
keep_last: None,
+ keep_hourly: None,
keep_daily: None,
keep_weekly: None,
keep_monthly: None,
}
}
+ pub fn keep_hourly(mut self, value: Option<u64>) -> Self {
+ self.keep_hourly = value;
+ self
+ }
+
pub fn keep_last(mut self, value: Option<u64>) -> Self {
self.keep_last = value;
self
pub fn keeps_something(&self) -> bool {
let mut keep_something = false;
if let Some(count) = self.keep_last { if count > 0 { keep_something = true; } }
+ if let Some(count) = self.keep_hourly { if count > 0 { keep_something = true; } }
if let Some(count) = self.keep_daily { if count > 0 { keep_something = true; } }
if let Some(count) = self.keep_weekly { if count > 0 { keep_something = true; } }
if let Some(count) = self.keep_monthly { if count > 0 { keep_something = true; } }
});
}
+ if let Some(keep_hourly) = options.keep_hourly {
+ mark_selections(&mut mark, &list, keep_hourly as usize, |local_time, _info| {
+ format!("{}/{}/{}/{}", local_time.year(), local_time.month(),
+ local_time.day(), local_time.hour())
+ });
+ }
+
if let Some(keep_daily) = options.keep_daily {
mark_selections(&mut mark, &list, keep_daily as usize, |local_time, _info| {
format!("{}/{}/{}", local_time.year(), local_time.month(), local_time.day())
let week = iso_week.week();
// Note: This year number might not match the calendar year number.
let iso_week_year = iso_week.year();
- format!("{}/{}", iso_week_year, week);
+ format!("{}/{}", iso_week_year, week)
});
}
}
#[test]
+fn test_prune_hourly() -> Result<(), Error> {
+
+ let mut orig_list = Vec::new();
+
+ orig_list.push(create_info("host/elsa/2019-11-15T09:39:15Z", false));
+ orig_list.push(create_info("host/elsa/2019-11-15T10:49:15Z", false));
+ orig_list.push(create_info("host/elsa/2019-11-15T10:59:15Z", false));
+ orig_list.push(create_info("host/elsa/2019-11-15T11:39:15Z", false));
+ orig_list.push(create_info("host/elsa/2019-11-15T11:49:15Z", false));
+ orig_list.push(create_info("host/elsa/2019-11-15T11:59:15Z", false));
+
+ let list = orig_list.clone();
+ let options = PruneOptions::new().keep_hourly(Some(3));
+ let remove_list = get_prune_list(list, false, &options);
+ let expect: Vec<PathBuf> = vec![
+ PathBuf::from("host/elsa/2019-11-15T10:49:15Z"),
+ PathBuf::from("host/elsa/2019-11-15T11:39:15Z"),
+ PathBuf::from("host/elsa/2019-11-15T11:49:15Z"),
+ ];
+ assert_eq!(remove_list, expect);
+
+ let list = orig_list.clone();
+ let options = PruneOptions::new().keep_hourly(Some(2));
+ let remove_list = get_prune_list(list, true, &options);
+ let expect: Vec<PathBuf> = vec![
+ PathBuf::from("host/elsa/2019-11-15T10:59:15Z"),
+ PathBuf::from("host/elsa/2019-11-15T11:59:15Z"),
+ ];
+ assert_eq!(remove_list, expect);
+
+ Ok(())
+}
+
+ #[test]
fn test_prune_simple2() -> Result<(), Error> {
let mut orig_list = Vec::new();