expire 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.reek.yml +23 -0
- data/.rspec +3 -0
- data/.rubocop.yml +45 -0
- data/.simplecov +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +152 -0
- data/LICENSE.txt +21 -0
- data/README.md +551 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example_rules/bad_rules.yml +2 -0
- data/example_rules/good_rules.yml +1 -0
- data/exe/expire +7 -0
- data/expire.gemspec +54 -0
- data/lib/expire.rb +51 -0
- data/lib/expire/all_backups_expired_error.rb +7 -0
- data/lib/expire/backup.rb +74 -0
- data/lib/expire/backup_from_path_service.rb +56 -0
- data/lib/expire/backup_list.rb +69 -0
- data/lib/expire/cli.rb +221 -0
- data/lib/expire/command.rb +122 -0
- data/lib/expire/commands/newest.rb +21 -0
- data/lib/expire/commands/oldest.rb +21 -0
- data/lib/expire/commands/purge.rb +23 -0
- data/lib/expire/commands/remove.rb +26 -0
- data/lib/expire/commands/rule_classes.rb +18 -0
- data/lib/expire/commands/rule_names.rb +20 -0
- data/lib/expire/commands/rule_option_names.rb +20 -0
- data/lib/expire/from_now_keep_adjective_for_rule_base.rb +38 -0
- data/lib/expire/from_now_keep_daily_for_rule.rb +7 -0
- data/lib/expire/from_now_keep_hourly_for_rule.rb +7 -0
- data/lib/expire/from_now_keep_monthly_for_rule.rb +7 -0
- data/lib/expire/from_now_keep_most_recent_for_rule.rb +41 -0
- data/lib/expire/from_now_keep_weekly_for_rule.rb +8 -0
- data/lib/expire/from_now_keep_yearly_for_rule.rb +8 -0
- data/lib/expire/from_range_value.rb +29 -0
- data/lib/expire/generate_backup_list_service.rb +45 -0
- data/lib/expire/invalid_path_error.rb +7 -0
- data/lib/expire/keep_adjective_for_rule_base.rb +34 -0
- data/lib/expire/keep_adjective_rule_base.rb +97 -0
- data/lib/expire/keep_daily_for_rule.rb +7 -0
- data/lib/expire/keep_daily_rule.rb +7 -0
- data/lib/expire/keep_hourly_for_rule.rb +7 -0
- data/lib/expire/keep_hourly_rule.rb +7 -0
- data/lib/expire/keep_monthly_for_rule.rb +7 -0
- data/lib/expire/keep_monthly_rule.rb +7 -0
- data/lib/expire/keep_most_recent_for_rule.rb +31 -0
- data/lib/expire/keep_most_recent_rule.rb +38 -0
- data/lib/expire/keep_weekly_for_rule.rb +8 -0
- data/lib/expire/keep_weekly_rule.rb +7 -0
- data/lib/expire/keep_yearly_for_rule.rb +7 -0
- data/lib/expire/keep_yearly_rule.rb +7 -0
- data/lib/expire/no_backups_error.rb +7 -0
- data/lib/expire/no_rules_error.rb +7 -0
- data/lib/expire/numerus_unit.rb +10 -0
- data/lib/expire/path_already_exists_error.rb +7 -0
- data/lib/expire/playground.rb +62 -0
- data/lib/expire/purge_service.rb +91 -0
- data/lib/expire/refine_all_and_none.rb +29 -0
- data/lib/expire/report_base.rb +23 -0
- data/lib/expire/report_enhanced.rb +14 -0
- data/lib/expire/report_expired.rb +10 -0
- data/lib/expire/report_kept.rb +10 -0
- data/lib/expire/report_null.rb +21 -0
- data/lib/expire/report_simple.rb +14 -0
- data/lib/expire/rule_base.rb +56 -0
- data/lib/expire/rule_list.rb +52 -0
- data/lib/expire/rules.rb +66 -0
- data/lib/expire/templates/newest/.gitkeep +1 -0
- data/lib/expire/templates/oldest/.gitkeep +1 -0
- data/lib/expire/templates/purge/.gitkeep +1 -0
- data/lib/expire/templates/remove/.gitkeep +1 -0
- data/lib/expire/templates/rule_classes/.gitkeep +1 -0
- data/lib/expire/templates/rule_names/.gitkeep +1 -0
- data/lib/expire/templates/rule_option_names/.gitkeep +1 -0
- data/lib/expire/unknown_rule_error.rb +10 -0
- data/lib/expire/version.rb +9 -0
- metadata +321 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e2818cf2a154487c32c4019de8278bc16866d1ca333eba0df45b5abf65859696
|
4
|
+
data.tar.gz: fc10fcc4ef4e17800fdda73b4293fd071a1725d9140604e89967299dfca122e5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0b34e9c57c67bc0ca624b8f8050af4e861b681806804f582e813c0850c153f0078cd60e9f17efafce086433ed0b78ce6f9068e152478db3a3bc926225cef24d3
|
7
|
+
data.tar.gz: f6af0819e14453eee1f54623c59d9e10fc549307e0f4b357234c9163cc827bee6a27f7888cf7a879bc60588e65fa269c4d84112fe8699c4b5c8bf6376bdeb7d7
|
data/.gitignore
ADDED
data/.reek.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
detectors:
|
3
|
+
Attribute:
|
4
|
+
exclude:
|
5
|
+
- Expire::Rules#daily_to_keep
|
6
|
+
- Expire::Rules#hourly_to_keep
|
7
|
+
- Expire::Rules#monthly_to_keep
|
8
|
+
- Expire::Rules#weekly_to_keep
|
9
|
+
- Expire::Rules#yearly_to_keep
|
10
|
+
TooManyStatements:
|
11
|
+
max_statements: 8
|
12
|
+
UtilityFunction:
|
13
|
+
public_methods_only: true
|
14
|
+
UncommunicativeVariableName:
|
15
|
+
accept:
|
16
|
+
- e
|
17
|
+
- _
|
18
|
+
directories:
|
19
|
+
"lib/expire/commands":
|
20
|
+
UnusedParameters:
|
21
|
+
enabled: false
|
22
|
+
UtilityFunction:
|
23
|
+
enabled: false
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- 'Gemfile'
|
6
|
+
- 'Rakefile'
|
7
|
+
- 'bin/console'
|
8
|
+
- 'expire.gemspec'
|
9
|
+
- 'spec/spec_helper.rb'
|
10
|
+
NewCops: enable
|
11
|
+
SuggestExtensions: false
|
12
|
+
|
13
|
+
Metrics/BlockLength:
|
14
|
+
Exclude:
|
15
|
+
- 'spec/**/*'
|
16
|
+
|
17
|
+
Layout/HashAlignment:
|
18
|
+
EnforcedColonStyle: table
|
19
|
+
|
20
|
+
Naming/VariableNumber:
|
21
|
+
EnforcedStyle: snake_case
|
22
|
+
|
23
|
+
RSpec/DescribeClass:
|
24
|
+
Enabled: true
|
25
|
+
Exclude:
|
26
|
+
- 'spec/integration/*'
|
27
|
+
|
28
|
+
RSpec/FilePath:
|
29
|
+
Enabled: true
|
30
|
+
Exclude:
|
31
|
+
- 'spec/unit/*'
|
32
|
+
|
33
|
+
RSpec/ImplicitExpect:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Lint/MissingSuper:
|
37
|
+
Enabled: true
|
38
|
+
Exclude:
|
39
|
+
- 'lib/expire/*'
|
40
|
+
- 'lib/expire/commands/*'
|
41
|
+
|
42
|
+
Lint/UnusedMethodArgument:
|
43
|
+
Enabled: true
|
44
|
+
Exclude:
|
45
|
+
- lib/expire/commands/*
|
data/.simplecov
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
expire (0.2.0)
|
5
|
+
activesupport (~> 6.1)
|
6
|
+
pastel (~> 0.8)
|
7
|
+
thor (~> 1.1)
|
8
|
+
zeitwerk (~> 2.4)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (6.1.2.1)
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
+
i18n (>= 1.6, < 2)
|
16
|
+
minitest (>= 5.1)
|
17
|
+
tzinfo (~> 2.0)
|
18
|
+
zeitwerk (~> 2.3)
|
19
|
+
aruba (1.0.4)
|
20
|
+
childprocess (>= 2.0, < 5.0)
|
21
|
+
contracts (~> 0.16.0)
|
22
|
+
cucumber (>= 2.4, < 6.0)
|
23
|
+
rspec-expectations (~> 3.4)
|
24
|
+
thor (~> 1.0)
|
25
|
+
ast (2.4.2)
|
26
|
+
builder (3.2.4)
|
27
|
+
byebug (11.1.3)
|
28
|
+
childprocess (4.0.0)
|
29
|
+
concurrent-ruby (1.1.8)
|
30
|
+
contracts (0.16.0)
|
31
|
+
cucumber (5.3.0)
|
32
|
+
builder (~> 3.2, >= 3.2.4)
|
33
|
+
cucumber-core (~> 8.0, >= 8.0.1)
|
34
|
+
cucumber-create-meta (~> 2.0, >= 2.0.2)
|
35
|
+
cucumber-cucumber-expressions (~> 10.3, >= 10.3.0)
|
36
|
+
cucumber-gherkin (~> 15.0, >= 15.0.2)
|
37
|
+
cucumber-html-formatter (~> 9.0, >= 9.0.0)
|
38
|
+
cucumber-messages (~> 13.1, >= 13.1.0)
|
39
|
+
cucumber-wire (~> 4.0, >= 4.0.1)
|
40
|
+
diff-lcs (~> 1.4, >= 1.4.4)
|
41
|
+
multi_test (~> 0.1, >= 0.1.2)
|
42
|
+
sys-uname (~> 1.2, >= 1.2.1)
|
43
|
+
cucumber-core (8.0.1)
|
44
|
+
cucumber-gherkin (~> 15.0, >= 15.0.2)
|
45
|
+
cucumber-messages (~> 13.0, >= 13.0.1)
|
46
|
+
cucumber-tag-expressions (~> 2.0, >= 2.0.4)
|
47
|
+
cucumber-create-meta (2.0.4)
|
48
|
+
cucumber-messages (~> 13.1, >= 13.1.0)
|
49
|
+
sys-uname (~> 1.2, >= 1.2.1)
|
50
|
+
cucumber-cucumber-expressions (10.3.0)
|
51
|
+
cucumber-gherkin (15.0.2)
|
52
|
+
cucumber-messages (~> 13.0, >= 13.0.1)
|
53
|
+
cucumber-html-formatter (9.0.0)
|
54
|
+
cucumber-messages (~> 13.0, >= 13.0.1)
|
55
|
+
cucumber-messages (13.2.1)
|
56
|
+
protobuf-cucumber (~> 3.10, >= 3.10.8)
|
57
|
+
cucumber-tag-expressions (2.0.4)
|
58
|
+
cucumber-wire (4.0.1)
|
59
|
+
cucumber-core (~> 8.0, >= 8.0.1)
|
60
|
+
cucumber-cucumber-expressions (~> 10.3, >= 10.3.0)
|
61
|
+
cucumber-messages (~> 13.0, >= 13.0.1)
|
62
|
+
diff-lcs (1.4.4)
|
63
|
+
docile (1.3.5)
|
64
|
+
ffi (1.14.2)
|
65
|
+
i18n (1.8.9)
|
66
|
+
concurrent-ruby (~> 1.0)
|
67
|
+
kwalify (0.7.2)
|
68
|
+
middleware (0.1.0)
|
69
|
+
minitest (5.14.3)
|
70
|
+
multi_test (0.1.2)
|
71
|
+
parallel (1.20.1)
|
72
|
+
parser (3.0.0.0)
|
73
|
+
ast (~> 2.4.1)
|
74
|
+
pastel (0.8.0)
|
75
|
+
tty-color (~> 0.5)
|
76
|
+
protobuf-cucumber (3.10.8)
|
77
|
+
activesupport (>= 3.2)
|
78
|
+
middleware
|
79
|
+
thor
|
80
|
+
thread_safe
|
81
|
+
psych (3.3.0)
|
82
|
+
rainbow (3.0.0)
|
83
|
+
rake (13.0.3)
|
84
|
+
reek (6.0.3)
|
85
|
+
kwalify (~> 0.7.0)
|
86
|
+
parser (~> 3.0.0)
|
87
|
+
psych (~> 3.1)
|
88
|
+
rainbow (>= 2.0, < 4.0)
|
89
|
+
regexp_parser (2.0.3)
|
90
|
+
rexml (3.2.4)
|
91
|
+
rspec (3.10.0)
|
92
|
+
rspec-core (~> 3.10.0)
|
93
|
+
rspec-expectations (~> 3.10.0)
|
94
|
+
rspec-mocks (~> 3.10.0)
|
95
|
+
rspec-core (3.10.1)
|
96
|
+
rspec-support (~> 3.10.0)
|
97
|
+
rspec-expectations (3.10.1)
|
98
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
99
|
+
rspec-support (~> 3.10.0)
|
100
|
+
rspec-mocks (3.10.2)
|
101
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
102
|
+
rspec-support (~> 3.10.0)
|
103
|
+
rspec-support (3.10.2)
|
104
|
+
rubocop (1.10.0)
|
105
|
+
parallel (~> 1.10)
|
106
|
+
parser (>= 3.0.0.0)
|
107
|
+
rainbow (>= 2.2.2, < 4.0)
|
108
|
+
regexp_parser (>= 1.8, < 3.0)
|
109
|
+
rexml
|
110
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
111
|
+
ruby-progressbar (~> 1.7)
|
112
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
113
|
+
rubocop-ast (1.4.1)
|
114
|
+
parser (>= 2.7.1.5)
|
115
|
+
rubocop-rspec (2.2.0)
|
116
|
+
rubocop (~> 1.0)
|
117
|
+
rubocop-ast (>= 1.1.0)
|
118
|
+
ruby-progressbar (1.11.0)
|
119
|
+
simplecov (0.21.2)
|
120
|
+
docile (~> 1.1)
|
121
|
+
simplecov-html (~> 0.11)
|
122
|
+
simplecov_json_formatter (~> 0.1)
|
123
|
+
simplecov-html (0.12.3)
|
124
|
+
simplecov_json_formatter (0.1.2)
|
125
|
+
sys-uname (1.2.2)
|
126
|
+
ffi (~> 1.1)
|
127
|
+
thor (1.1.0)
|
128
|
+
thread_safe (0.3.6)
|
129
|
+
tty-color (0.6.0)
|
130
|
+
tzinfo (2.0.4)
|
131
|
+
concurrent-ruby (~> 1.0)
|
132
|
+
unicode-display_width (2.0.0)
|
133
|
+
zeitwerk (2.4.2)
|
134
|
+
|
135
|
+
PLATFORMS
|
136
|
+
ruby
|
137
|
+
|
138
|
+
DEPENDENCIES
|
139
|
+
aruba (~> 1.0)
|
140
|
+
bundler (~> 2.1)
|
141
|
+
byebug (~> 11.1)
|
142
|
+
cucumber (~> 5.3)
|
143
|
+
expire!
|
144
|
+
rake (~> 13.0)
|
145
|
+
reek (~> 6.0)
|
146
|
+
rspec (~> 3.0)
|
147
|
+
rubocop (~> 1.9)
|
148
|
+
rubocop-rspec (~> 2.2)
|
149
|
+
simplecov (~> 0.21)
|
150
|
+
|
151
|
+
BUNDLED WITH
|
152
|
+
2.2.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,551 @@
|
|
1
|
+
<!-- omit in toc -->
|
2
|
+
# Expire
|
3
|
+
|
4
|
+
**Expire** is a tool for identifying backups that are no longer needed and to delete them.
|
5
|
+
It can be used either from the command line or as a ruby gem.
|
6
|
+
|
7
|
+
<!-- omit in toc -->
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
**The installation is currently not yet possible!**
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
``` ruby
|
15
|
+
gem 'expire'
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
``` shell
|
21
|
+
bundle
|
22
|
+
```
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
``` shell
|
27
|
+
gem install expire
|
28
|
+
```
|
29
|
+
|
30
|
+
- [Usage](#usage)
|
31
|
+
- [Purge](#purge)
|
32
|
+
- [The `--simulate`, `-s` flag](#the---simulate--s-flag)
|
33
|
+
- [The `--format`, `-f` options](#the---format--f-options)
|
34
|
+
- [`--format=expired`](#--formatexpired)
|
35
|
+
- [`--format=kept`](#--formatkept)
|
36
|
+
- [`--format=none`](#--formatnone)
|
37
|
+
- [`--format=simple`](#--formatsimple)
|
38
|
+
- [`--format=enhanced`](#--formatenhanced)
|
39
|
+
- [Rules](#rules)
|
40
|
+
- [`--keep-most-recent`](#--keep-most-recent)
|
41
|
+
- [`--keep-most-recent-for`](#--keep-most-recent-for)
|
42
|
+
- [`--from-now-keep-most-recent-for`](#--from-now-keep-most-recent-for)
|
43
|
+
- [Adjectives](#adjectives)
|
44
|
+
- [`--keep-<adjective>`](#--keep-adjective)
|
45
|
+
- [`--keep-<adjective>-for`](#--keep-adjective-for)
|
46
|
+
- [`--from-now-keep-<adjective>-for`](#--from-now-keep-adjective-for)
|
47
|
+
- [Time ranges](#time-ranges)
|
48
|
+
- [`--rules-file`](#--rules-file)
|
49
|
+
- [The `--purge-command`, `--cmd` option](#the---purge-command---cmd-option)
|
50
|
+
- [How backup timestamps are detected](#how-backup-timestamps-are-detected)
|
51
|
+
- [Newest](#newest)
|
52
|
+
- [Oldest](#oldest)
|
53
|
+
- [Remove](#remove)
|
54
|
+
- [Rule classes](#rule-classes)
|
55
|
+
- [Rule names](#rule-names)
|
56
|
+
- [Rule option names](#rule-option-names)
|
57
|
+
- [Development](#development)
|
58
|
+
- [Contributing](#contributing)
|
59
|
+
- [License](#license)
|
60
|
+
|
61
|
+
## Usage
|
62
|
+
|
63
|
+
The most important command of `expire` is `purge` which is explained first.
|
64
|
+
|
65
|
+
## Purge
|
66
|
+
|
67
|
+
The `purge` command is used to calculate and delete expired backups.
|
68
|
+
It is invoked as follows:
|
69
|
+
|
70
|
+
``` shell
|
71
|
+
expire path/to/backups <rules>
|
72
|
+
```
|
73
|
+
|
74
|
+
This would delete, according to the rules, all expired backups under `path/to/backups`.
|
75
|
+
|
76
|
+
Before deleting, you may want to know what would be removed.
|
77
|
+
The `--simulate` option is suitable for this purpose.
|
78
|
+
|
79
|
+
### The `--simulate`, `-s` flag
|
80
|
+
|
81
|
+
To check the expire-rules you can call `expire purge` with the `--simulate` option:
|
82
|
+
|
83
|
+
``` shell
|
84
|
+
expire path/to/backups <rules> --simulate
|
85
|
+
```
|
86
|
+
|
87
|
+
When `purge` is called this way it will calculate the expired backups
|
88
|
+
but will not delete anything.
|
89
|
+
|
90
|
+
To see what `purge` would delete you have to specify a format, covered in the following section.
|
91
|
+
|
92
|
+
### The `--format`, `-f` options
|
93
|
+
|
94
|
+
Formats are used to control the output of `expire`.
|
95
|
+
`expire` supports various formats.
|
96
|
+
The following examples assume a backup-directory containing some backups:
|
97
|
+
|
98
|
+
```shell
|
99
|
+
backups
|
100
|
+
├── 2016-01-27T1112
|
101
|
+
├── 2019-12-24T1200
|
102
|
+
├── 2021-01-19T1113
|
103
|
+
├── 2021-01-26T1111
|
104
|
+
├── 2021-01-27T1111
|
105
|
+
└── 2021-01-27T1112
|
106
|
+
```
|
107
|
+
|
108
|
+
All `--format`-examples use the `--keep-most-recent=3` rule.
|
109
|
+
Rules are explained later in this document.
|
110
|
+
|
111
|
+
#### `--format=expired`
|
112
|
+
|
113
|
+
The **expired** format prints the paths of the expired backups, one per line.
|
114
|
+
|
115
|
+
```bash
|
116
|
+
$ expire purge backups --format=expired --keep-most-recent=3
|
117
|
+
backups/2016-01-27T1112
|
118
|
+
backups/2019-12-24T1200
|
119
|
+
backups/2021-01-19T1113
|
120
|
+
```
|
121
|
+
|
122
|
+
#### `--format=kept`
|
123
|
+
|
124
|
+
The **kept** format prints the paths of the kept backups, one per line.
|
125
|
+
|
126
|
+
```shell
|
127
|
+
$ expire purge backups --format=kept --keep-most-recent=3
|
128
|
+
backups/2021-01-26T1111
|
129
|
+
backups/2021-01-27T1111
|
130
|
+
backups/2021-01-27T1112
|
131
|
+
```
|
132
|
+
|
133
|
+
#### `--format=none`
|
134
|
+
|
135
|
+
This is the default format, it prints nothing.
|
136
|
+
Nothing is printed here, so no example.
|
137
|
+
|
138
|
+
#### `--format=simple`
|
139
|
+
|
140
|
+
The **simple** format prints the path of the kept backups preceded by the work `keeping`
|
141
|
+
and the expired backups preceded by the word `purged`.
|
142
|
+
|
143
|
+
```bash
|
144
|
+
$ expire purge backups --format=simple --keep-most-recent=3
|
145
|
+
purged backups/2016-01-27T1112
|
146
|
+
purged backups/2019-12-24T1200
|
147
|
+
purged backups/2021-01-19T1113
|
148
|
+
keeping backups/2021-01-26T1111
|
149
|
+
keeping backups/2021-01-27T1111
|
150
|
+
keeping backups/2021-01-27T1112
|
151
|
+
```
|
152
|
+
|
153
|
+
#### `--format=enhanced`
|
154
|
+
|
155
|
+
The **enhanced** format works the same way as the simple format.
|
156
|
+
In addition, it prints the reasons why a backup is kept.
|
157
|
+
|
158
|
+
```bash
|
159
|
+
$ expire purge backups --format=enhanced --keep-most-recent=3
|
160
|
+
purged backups/2016-01-27T1112
|
161
|
+
purged backups/2019-12-24T1200
|
162
|
+
purged backups/2021-01-19T1113
|
163
|
+
keeping backups/2021-01-26T1111
|
164
|
+
reasons:
|
165
|
+
- keep the 3 most recent backups
|
166
|
+
keeping backups/2021-01-27T1111
|
167
|
+
reasons:
|
168
|
+
- keep the 3 most recent backups
|
169
|
+
keeping backups/2021-01-27T1112
|
170
|
+
reasons:
|
171
|
+
- keep the 3 most recent backups
|
172
|
+
```
|
173
|
+
|
174
|
+
### Rules
|
175
|
+
|
176
|
+
Rules control which backups to keep and which to discard.
|
177
|
+
Rules can be specified by command line parameters or in a YAML-file.
|
178
|
+
|
179
|
+
You must specify at least one rule or `expire purge` will fail.
|
180
|
+
|
181
|
+
#### `--keep-most-recent`
|
182
|
+
|
183
|
+
The `--keep-most-recent=3` option preserves the three newest backups from being purged.
|
184
|
+
|
185
|
+
```shell
|
186
|
+
$ expire purge backups --keep-most-recent 3 --format simple
|
187
|
+
purged backups/2016-01-27T1112
|
188
|
+
purged backups/2019-12-24T1200
|
189
|
+
purged backups/2021-01-19T1113
|
190
|
+
keeping backups/2021-01-26T1111
|
191
|
+
keeping backups/2021-01-27T1111
|
192
|
+
keeping backups/2021-01-27T1112
|
193
|
+
```
|
194
|
+
|
195
|
+
#### `--keep-most-recent-for`
|
196
|
+
|
197
|
+
Keeps the newest backups for a **time range** specified by *amount* and *unit*.
|
198
|
+
An *amount* is an integer and a unit is something like *days* or *years*.
|
199
|
+
Time ranges are discussed in more detail within their own section.
|
200
|
+
|
201
|
+
The `--keep-most-recent-for "3 years"` option keeps all backups that are not older than three years.
|
202
|
+
The **calculation takes the timestamp of the newest backup as reference**.
|
203
|
+
|
204
|
+
```shell
|
205
|
+
$ expire purge backups --keep-most-recent-for "3 years" --format simple
|
206
|
+
purged backups/2016-01-27T1112
|
207
|
+
keeping backups/2019-12-24T1200
|
208
|
+
keeping backups/2021-01-19T1113
|
209
|
+
keeping backups/2021-01-26T1111
|
210
|
+
keeping backups/2021-01-27T1111
|
211
|
+
keeping backups/2021-01-27T1112
|
212
|
+
```
|
213
|
+
|
214
|
+
#### `--from-now-keep-most-recent-for`
|
215
|
+
|
216
|
+
The `--from-now-keep-most-recent-for` option works almost the same way as
|
217
|
+
the `--keep-most-recent-for` option does.
|
218
|
+
But it **bases its calculation on the current time**, not the timestamp of the newest backup.
|
219
|
+
|
220
|
+
Assuming today is the 28th January 2021 the option `--from-now-most-recent-for=5.days`
|
221
|
+
would act like this:
|
222
|
+
|
223
|
+
```shell
|
224
|
+
$ expire purge backups --from-now-keep-most-recent-for 5.days --format simple
|
225
|
+
purged backups/2016-01-27T1112
|
226
|
+
purged backups/2019-12-24T1200
|
227
|
+
purged backups/2021-01-19T1113
|
228
|
+
keeping backups/2021-01-26T1111
|
229
|
+
keeping backups/2021-01-27T1111
|
230
|
+
keeping backups/2021-01-27T1112
|
231
|
+
```
|
232
|
+
|
233
|
+
#### Adjectives
|
234
|
+
|
235
|
+
The following rules contain an adjective in their name.
|
236
|
+
These adjectives are *hourly*, *daily*, *weekly*, *monthly* and *yearly*.
|
237
|
+
|
238
|
+
#### `--keep-<adjective>`
|
239
|
+
|
240
|
+
To keep **one backup per time unit** the *adjective rules* are handy.
|
241
|
+
There are five adjective rules:
|
242
|
+
|
243
|
+
- `--keep-hourly`
|
244
|
+
- `--keep-daily`
|
245
|
+
- `--keep-weekly`
|
246
|
+
- `--keep-monthly`
|
247
|
+
- `--keep-yearly`
|
248
|
+
|
249
|
+
All of these expect an integer that specifies the maximum of backups they should preserve.
|
250
|
+
|
251
|
+
```shell
|
252
|
+
$ expire purge backups --keep-weekly 3 --format=simple
|
253
|
+
purged backups/2016-01-27T1112
|
254
|
+
keeping backups/2019-12-24T1200
|
255
|
+
keeping backups/2021-01-19T1113
|
256
|
+
purged backups/2021-01-26T1111
|
257
|
+
purged backups/2021-01-27T1111
|
258
|
+
keeping backups/2021-01-27T1112
|
259
|
+
```
|
260
|
+
|
261
|
+
You can also use `all` or `-1` to preserve all backups per time unit.
|
262
|
+
|
263
|
+
```shell
|
264
|
+
expire purge backups --keep-yearly all --format=simple
|
265
|
+
keeping backups/2016-01-27T1112
|
266
|
+
keeping backups/2019-12-24T1200
|
267
|
+
purged backups/2021-01-19T1113
|
268
|
+
purged backups/2021-01-26T1111
|
269
|
+
purged backups/2021-01-27T1111
|
270
|
+
keeping backups/2021-01-27T1112
|
271
|
+
```
|
272
|
+
|
273
|
+
#### `--keep-<adjective>-for`
|
274
|
+
|
275
|
+
To preserve **one backup per unit for a certain time range** you can use *adjective for rules*.
|
276
|
+
Time ranges are discussed in more detail within their own section
|
277
|
+
There are five *adjective-for* rules:
|
278
|
+
|
279
|
+
- `--keep-hourly-for`
|
280
|
+
- `--keep-daily-for`
|
281
|
+
- `--keep-weekly-for`
|
282
|
+
- `--keep-monthly-for`
|
283
|
+
- `--keep-yearly-for`
|
284
|
+
|
285
|
+
The **calculation takes the timestamp of the newest backup as reference**.
|
286
|
+
|
287
|
+
```shell
|
288
|
+
$ expire purge backups --keep-daily-for='3 months' --format=simple
|
289
|
+
purged backups/2016-01-27T1112
|
290
|
+
purged backups/2019-12-24T1200
|
291
|
+
keeping backups/2021-01-19T1113
|
292
|
+
keeping backups/2021-01-26T1111
|
293
|
+
purged backups/2021-01-27T1111
|
294
|
+
keeping backups/2021-01-27T1112
|
295
|
+
```
|
296
|
+
|
297
|
+
#### `--from-now-keep-<adjective>-for`
|
298
|
+
|
299
|
+
The *from now adjective for rules* work similar to *adjective for rules*,
|
300
|
+
expect they **base their calculations on the current time**, not the timestamp of the newest backup.
|
301
|
+
|
302
|
+
There are five *from now adjective for rules*:
|
303
|
+
|
304
|
+
- `--from-now-keep-hourly-for`
|
305
|
+
- `--from-now-keep-daily-for`
|
306
|
+
- `--from-now-keep-weekly-for`
|
307
|
+
- `--from-now-keep-monthly-for`
|
308
|
+
- `--from-now-keep-yearly-for`
|
309
|
+
|
310
|
+
Assuming today is the 28th January 2021 the option `--from-now-most-recent-for=5.days`
|
311
|
+
would act like this:
|
312
|
+
|
313
|
+
```shell
|
314
|
+
$ expire purge backups --from-now-keep-daily-for='3 months' --format=simple
|
315
|
+
purged backups/2016-01-27T1112
|
316
|
+
purged backups/2019-12-24T1200
|
317
|
+
keeping backups/2021-01-19T1113
|
318
|
+
keeping backups/2021-01-26T1111
|
319
|
+
purged backups/2021-01-27T1111
|
320
|
+
keeping backups/2021-01-27T1112
|
321
|
+
```
|
322
|
+
|
323
|
+
#### Time ranges
|
324
|
+
|
325
|
+
Some rules take a time range as argument.
|
326
|
+
Time ranges can be expressed like this:
|
327
|
+
|
328
|
+
```shell
|
329
|
+
1 hour
|
330
|
+
2.weeks
|
331
|
+
3 months
|
332
|
+
1_000 years
|
333
|
+
```
|
334
|
+
|
335
|
+
As you can see, a range is expressed as a combination of an **integer** and a **unit**.
|
336
|
+
The integer portion can include underscores (`_`) **between** the digits.
|
337
|
+
Possible values for the unit portion are:
|
338
|
+
|
339
|
+
- `hour` and `hours`
|
340
|
+
- `day` and `days`
|
341
|
+
- `week` and `weeks`
|
342
|
+
- `moth` and `months`
|
343
|
+
- `year` and `years`
|
344
|
+
|
345
|
+
Units are case-insensitive, so `Year` and `yEaR` are valid too.
|
346
|
+
|
347
|
+
### `--rules-file`
|
348
|
+
|
349
|
+
To read the rules form a YAML-file use the `--rules-file` option.
|
350
|
+
The rules have to be specified with an underscore instead of a hyphen.
|
351
|
+
|
352
|
+
Here is an example rules-file called `rules.yml`:
|
353
|
+
|
354
|
+
```yml
|
355
|
+
keep_most_recent: 3
|
356
|
+
```
|
357
|
+
|
358
|
+
With this rules-file we can `expire` with the `--rules-file` option:
|
359
|
+
|
360
|
+
```shell
|
361
|
+
$ expire purge backups --rules-file rules.yml --format=simple
|
362
|
+
purged backups/2016-01-27T1112
|
363
|
+
purged backups/2019-12-24T1200
|
364
|
+
purged backups/2021-01-19T1113
|
365
|
+
keeping backups/2021-01-26T1111
|
366
|
+
keeping backups/2021-01-27T1111
|
367
|
+
keeping backups/2021-01-27T1112
|
368
|
+
```
|
369
|
+
|
370
|
+
There is also a shortcut for the `--rules-file` option: `-r`.
|
371
|
+
|
372
|
+
### The `--purge-command`, `--cmd` option
|
373
|
+
|
374
|
+
The `expire` program can remove files and directories,
|
375
|
+
but it doesn't know how to deal with logical volumes or subvolumes.
|
376
|
+
This is where the `--purge-command` option comes in.
|
377
|
+
|
378
|
+
The `--purge-command` option takes a command as argument.
|
379
|
+
For each expired backup this command is executed with the backup-path as argument.
|
380
|
+
|
381
|
+
```shell
|
382
|
+
bundle exec exe/expire purge backups --keep-most-recent 3 --format=simple --purge-command='rm -rf'
|
383
|
+
purged backups/2016-01-27T1112
|
384
|
+
purged backups/2019-12-24T1200
|
385
|
+
purged backups/2021-01-19T1113
|
386
|
+
keeping backups/2021-01-26T1111
|
387
|
+
keeping backups/2021-01-27T1111
|
388
|
+
keeping backups/2021-01-27T1112
|
389
|
+
```
|
390
|
+
|
391
|
+
The previous example has called these shell commands:
|
392
|
+
|
393
|
+
```shell
|
394
|
+
rm -rf backups/2016-01-27T1112
|
395
|
+
rm -rf backups/2019-12-24T1200
|
396
|
+
rm -rf backups/2021-01-19T1113
|
397
|
+
```
|
398
|
+
|
399
|
+
## How backup timestamps are detected
|
400
|
+
|
401
|
+
`expire` recognizes the date of a backup by its file name (or directory name).
|
402
|
+
This file name must consist of twelve or 14 digits and can optionally contain other characters.
|
403
|
+
The digits are considered as `YYYYmmddHHMMSS`, where,
|
404
|
+
|
405
|
+
- `YYYY` denotes the year of the backup such as `2021`
|
406
|
+
- `mm` denotes the month the backups was created such as `01` or `11`
|
407
|
+
- `dd` denotes the day of month such as `07` or `28`
|
408
|
+
- `HH` denotes the hour (`00`..`23`)
|
409
|
+
- `MM` denotes the minute
|
410
|
+
- `SS` denotes the second; seconds are optional
|
411
|
+
|
412
|
+
Some valid filenames:
|
413
|
+
|
414
|
+
```shell
|
415
|
+
2021-01-19T1113 # with arbitrary characters
|
416
|
+
2021-01-19T111345 # with arbitrary characters and seconds
|
417
|
+
202101191113 # no arbitrary characters
|
418
|
+
20210119111345 # with seconds and no arbitrary characters
|
419
|
+
```
|
420
|
+
|
421
|
+
Some **invalid** filenames:
|
422
|
+
|
423
|
+
```shell
|
424
|
+
2021-01-19 # just a date, no time
|
425
|
+
2021-02-31T1113 # February 31
|
426
|
+
2101191113 # year 2101, only 10 digits
|
427
|
+
2021011911134501 # 16 digits are too much
|
428
|
+
```
|
429
|
+
|
430
|
+
Date detection via ctime or mtime is planned for a future release.
|
431
|
+
|
432
|
+
## Newest
|
433
|
+
|
434
|
+
The `newest` command shows the newest backup:
|
435
|
+
|
436
|
+
```shell
|
437
|
+
$ expire newest backups
|
438
|
+
backups/2021-01-27T1112
|
439
|
+
```
|
440
|
+
|
441
|
+
## Oldest
|
442
|
+
|
443
|
+
The `oldest` command shows the oldest backup:
|
444
|
+
|
445
|
+
```shell
|
446
|
+
$ expire oldest backups
|
447
|
+
backups/2016-01-27T1112
|
448
|
+
```
|
449
|
+
|
450
|
+
## Remove
|
451
|
+
|
452
|
+
The `remove` command can be used to remove files or directories:
|
453
|
+
|
454
|
+
```shell
|
455
|
+
$ expire remove /tmp/stuff
|
456
|
+
removed /tmp/stuff
|
457
|
+
```
|
458
|
+
|
459
|
+
## Rule classes
|
460
|
+
|
461
|
+
The `rule-classes` command returns a list of all rule-classes:
|
462
|
+
|
463
|
+
```shell
|
464
|
+
$ expire rule-classes
|
465
|
+
Expire::KeepMostRecentRule
|
466
|
+
Expire::KeepMostRecentForRule
|
467
|
+
Expire::FromNowKeepMostRecentForRule
|
468
|
+
Expire::KeepHourlyRule
|
469
|
+
Expire::KeepDailyRule
|
470
|
+
Expire::KeepWeeklyRule
|
471
|
+
Expire::KeepMonthlyRule
|
472
|
+
Expire::KeepYearlyRule
|
473
|
+
Expire::KeepHourlyForRule
|
474
|
+
Expire::KeepDailyForRule
|
475
|
+
Expire::KeepWeeklyForRule
|
476
|
+
Expire::KeepMonthlyForRule
|
477
|
+
Expire::KeepYearlyForRule
|
478
|
+
Expire::FromNowKeepHourlyForRule
|
479
|
+
Expire::FromNowKeepDailyForRule
|
480
|
+
Expire::FromNowKeepWeeklyForRule
|
481
|
+
Expire::FromNowKeepMonthlyForRule
|
482
|
+
Expire::FromNowKeepYearlyForRule
|
483
|
+
```
|
484
|
+
|
485
|
+
## Rule names
|
486
|
+
|
487
|
+
The `rule-names` command shows a list of all rule-names:
|
488
|
+
|
489
|
+
```shell
|
490
|
+
$ expire rule-names
|
491
|
+
keep_most_recent
|
492
|
+
keep_most_recent_for
|
493
|
+
from_now_keep_most_recent_for
|
494
|
+
keep_hourly
|
495
|
+
keep_daily
|
496
|
+
keep_weekly
|
497
|
+
keep_monthly
|
498
|
+
keep_yearly
|
499
|
+
keep_hourly_for
|
500
|
+
keep_daily_for
|
501
|
+
keep_weekly_for
|
502
|
+
keep_monthly_for
|
503
|
+
keep_yearly_for
|
504
|
+
from_now_keep_hourly_for
|
505
|
+
from_now_keep_daily_for
|
506
|
+
from_now_keep_weekly_for
|
507
|
+
from_now_keep_monthly_for
|
508
|
+
from_now_keep_yearly_for
|
509
|
+
```
|
510
|
+
|
511
|
+
## Rule option names
|
512
|
+
|
513
|
+
To get a list of all rule option-names call:
|
514
|
+
|
515
|
+
```shell
|
516
|
+
$ expire rule-option-names
|
517
|
+
--keep-most-recent
|
518
|
+
--keep-most-recent-for
|
519
|
+
--from-now-keep-most-recent-for
|
520
|
+
--keep-hourly
|
521
|
+
--keep-daily
|
522
|
+
--keep-weekly
|
523
|
+
--keep-monthly
|
524
|
+
--keep-yearly
|
525
|
+
--keep-hourly-for
|
526
|
+
--keep-daily-for
|
527
|
+
--keep-weekly-for
|
528
|
+
--keep-monthly-for
|
529
|
+
--keep-yearly-for
|
530
|
+
--from-now-keep-hourly-for
|
531
|
+
--from-now-keep-daily-for
|
532
|
+
--from-now-keep-weekly-for
|
533
|
+
--from-now-keep-monthly-for
|
534
|
+
--from-now-keep-yearly-for
|
535
|
+
```
|
536
|
+
|
537
|
+
## Development
|
538
|
+
|
539
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
540
|
+
|
541
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
542
|
+
|
543
|
+
## Contributing
|
544
|
+
|
545
|
+
Bug reports and pull requests are welcome on
|
546
|
+
GitHub at [thomasregnet/expire](https://github.com/thomasregnet/expire.)
|
547
|
+
|
548
|
+
## License
|
549
|
+
|
550
|
+
The gem is available as open source under the terms of the
|
551
|
+
[MIT License](https://opensource.org/licenses/MIT).
|