src/backup/prune.rs: implement --keep-hourly
This commit is contained in:
parent
1af6637004
commit
102d8d4136
@ -425,12 +425,16 @@ following retention options:
|
|||||||
``--keep-last <N>``
|
``--keep-last <N>``
|
||||||
Keep the last ``<N>`` backup snapshots.
|
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-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.
|
backup for a single day, only the latest one is kept.
|
||||||
|
|
||||||
``--keep-weekly <N>``
|
``--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.
|
backup for a single week, only the latest one is kept.
|
||||||
|
|
||||||
.. note:: The weeks start on Monday and end on Sunday. The software
|
.. note:: The weeks start on Monday and end on Sunday. The software
|
||||||
@ -438,11 +442,11 @@ following retention options:
|
|||||||
the end of the year.
|
the end of the year.
|
||||||
|
|
||||||
``--keep-monthly <N>``
|
``--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.
|
backup for a single month, only the latest one is kept.
|
||||||
|
|
||||||
``--keep-yearly <N>``
|
``--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.
|
backup for a single year, only the latest one is kept.
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,6 +247,13 @@ macro_rules! add_common_prune_prameters {
|
|||||||
.minimum(1)
|
.minimum(1)
|
||||||
.schema()
|
.schema()
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"keep-hourly",
|
||||||
|
true,
|
||||||
|
&IntegerSchema::new("Number of hourly backups to keep.")
|
||||||
|
.minimum(1)
|
||||||
|
.schema()
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"keep-last",
|
"keep-last",
|
||||||
true,
|
true,
|
||||||
@ -310,6 +317,7 @@ fn test_prune(
|
|||||||
|
|
||||||
let prune_options = PruneOptions {
|
let prune_options = PruneOptions {
|
||||||
keep_last: param["keep-last"].as_u64(),
|
keep_last: param["keep-last"].as_u64(),
|
||||||
|
keep_hourly: param["keep-hourly"].as_u64(),
|
||||||
keep_daily: param["keep-daily"].as_u64(),
|
keep_daily: param["keep-daily"].as_u64(),
|
||||||
keep_weekly: param["keep-weekly"].as_u64(),
|
keep_weekly: param["keep-weekly"].as_u64(),
|
||||||
keep_monthly: param["keep-monthly"].as_u64(),
|
keep_monthly: param["keep-monthly"].as_u64(),
|
||||||
@ -368,6 +376,7 @@ fn prune(
|
|||||||
|
|
||||||
let prune_options = PruneOptions {
|
let prune_options = PruneOptions {
|
||||||
keep_last: param["keep-last"].as_u64(),
|
keep_last: param["keep-last"].as_u64(),
|
||||||
|
keep_hourly: param["keep-hourly"].as_u64(),
|
||||||
keep_daily: param["keep-daily"].as_u64(),
|
keep_daily: param["keep-daily"].as_u64(),
|
||||||
keep_weekly: param["keep-weekly"].as_u64(),
|
keep_weekly: param["keep-weekly"].as_u64(),
|
||||||
keep_monthly: param["keep-monthly"].as_u64(),
|
keep_monthly: param["keep-monthly"].as_u64(),
|
||||||
|
@ -2,7 +2,7 @@ use failure::*;
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Local};
|
use chrono::{DateTime, Timelike, Datelike, Local};
|
||||||
|
|
||||||
use super::{BackupDir, BackupInfo};
|
use super::{BackupDir, BackupInfo};
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ fn remove_incomplete_snapshots(
|
|||||||
|
|
||||||
pub struct PruneOptions {
|
pub struct PruneOptions {
|
||||||
pub keep_last: Option<u64>,
|
pub keep_last: Option<u64>,
|
||||||
|
pub keep_hourly: Option<u64>,
|
||||||
pub keep_daily: Option<u64>,
|
pub keep_daily: Option<u64>,
|
||||||
pub keep_weekly: Option<u64>,
|
pub keep_weekly: Option<u64>,
|
||||||
pub keep_monthly: Option<u64>,
|
pub keep_monthly: Option<u64>,
|
||||||
@ -82,6 +83,7 @@ impl PruneOptions {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
keep_last: None,
|
keep_last: None,
|
||||||
|
keep_hourly: None,
|
||||||
keep_daily: None,
|
keep_daily: None,
|
||||||
keep_weekly: None,
|
keep_weekly: None,
|
||||||
keep_monthly: None,
|
keep_monthly: None,
|
||||||
@ -89,6 +91,11 @@ impl PruneOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
pub fn keep_last(mut self, value: Option<u64>) -> Self {
|
||||||
self.keep_last = value;
|
self.keep_last = value;
|
||||||
self
|
self
|
||||||
@ -117,6 +124,7 @@ impl PruneOptions {
|
|||||||
pub fn keeps_something(&self) -> bool {
|
pub fn keeps_something(&self) -> bool {
|
||||||
let mut keep_something = false;
|
let mut keep_something = false;
|
||||||
if let Some(count) = self.keep_last { if count > 0 { keep_something = true; } }
|
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_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_weekly { if count > 0 { keep_something = true; } }
|
||||||
if let Some(count) = self.keep_monthly { if count > 0 { keep_something = true; } }
|
if let Some(count) = self.keep_monthly { if count > 0 { keep_something = true; } }
|
||||||
@ -142,6 +150,13 @@ pub fn compute_prune_info(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
if let Some(keep_daily) = options.keep_daily {
|
||||||
mark_selections(&mut mark, &list, keep_daily as usize, |local_time, _info| {
|
mark_selections(&mut mark, &list, keep_daily as usize, |local_time, _info| {
|
||||||
format!("{}/{}/{}", local_time.year(), local_time.month(), local_time.day())
|
format!("{}/{}/{}", local_time.year(), local_time.month(), local_time.day())
|
||||||
@ -154,7 +169,7 @@ pub fn compute_prune_info(
|
|||||||
let week = iso_week.week();
|
let week = iso_week.week();
|
||||||
// Note: This year number might not match the calendar year number.
|
// Note: This year number might not match the calendar year number.
|
||||||
let iso_week_year = iso_week.year();
|
let iso_week_year = iso_week.year();
|
||||||
format!("{}/{}", iso_week_year, week);
|
format!("{}/{}", iso_week_year, week)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,40 @@ fn create_info(
|
|||||||
BackupInfo { backup_dir, files }
|
BackupInfo { backup_dir, files }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn test_prune_simple2() -> Result<(), Error> {
|
fn test_prune_simple2() -> Result<(), Error> {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user