surrender 0.8.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.
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +7 -0
- data/bin/surrender +19 -0
- data/lib/surrender/bucket_policy.rb +23 -0
- data/lib/surrender/monthly_policy.rb +9 -0
- data/lib/surrender/most_recent_policy.rb +21 -0
- data/lib/surrender/version.rb +3 -0
- data/lib/surrender/weekly_policy.rb +9 -0
- data/lib/surrender/yearly_policy.rb +9 -0
- data/lib/surrender.rb +51 -0
- data/spec/backup_re_matches_filenames_spec.rb +8 -0
- data/spec/monthly_policy_spec.rb +31 -0
- data/spec/most_recent_policy_spec.rb +62 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/surrender_most_recent_spec.rb +68 -0
- data/spec/surrender_weekly_spec.rb +30 -0
- data/spec/weekly_policy_spec.rb +66 -0
- data/spec/yearly_policy_spec.rb +34 -0
- data/surrender.gemspec +22 -0
- metadata +111 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 François Beausoleil
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Surrender
|
2
|
+
|
3
|
+
Returns the list of files which should be surrendered to the ether.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'surrender'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install surrender
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Acts as a filter, returning files which should be removed from a backup scheme:
|
22
|
+
|
23
|
+
$ find /var/backup/database -type f | sort | surrender --minimum-files=7 --most-recent=2 --weekly=2 --monthly=12 --yearly=2 | xargs rm
|
24
|
+
|
25
|
+
Would keep at a minimum 4 files, but only 2 weekly (the 2 most recent weekly backups),
|
26
|
+
the 12 most recent monthly backups and the 2 most recent yearly backups. Backup dates
|
27
|
+
are determined from the file's path, which must match the following regular
|
28
|
+
expression: `/\b(?:19|2\d)\d{2}(.)?(?:0\d|1[012])\1(?:[012]\d|3[01])(?:T|\b)`.
|
29
|
+
|
30
|
+
This regular expression matches schemes like this:
|
31
|
+
|
32
|
+
* /var/backup/database/contacts-20130811T130914.sql.gz
|
33
|
+
* /var/backup/database/contacts-2013-08-11.13-09-14.sql.gz
|
34
|
+
* /var/backup/database/contacts/2013/08/11.sql.gz
|
35
|
+
|
36
|
+
which seems to be common enough.
|
37
|
+
|
38
|
+
No attempt is made to validate the date: 2013-02-31 is a perfectly valid date for surrender.
|
39
|
+
|
40
|
+
Anything that does not match the regular expression is reported as a warning on STDERR, and filtered from
|
41
|
+
STDOUT, implying the file must be kept.
|
42
|
+
|
43
|
+
Incidentally, all parameters to surrender are optional. The default values are the ones expressed above.
|
44
|
+
surrender uses a constant amount of memory, related to the total number of files in the input stream.
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/surrender
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "surrender"
|
3
|
+
|
4
|
+
options = ARGV.each_with_object(Surrender::DEFAULT_ARGUMENTS) do |arg, memo|
|
5
|
+
case arg
|
6
|
+
when /^--most-recent=(\d+)$/
|
7
|
+
memo[:most_recent] = Integer($1)
|
8
|
+
when /^--weekly=(\d+)$/
|
9
|
+
memo[:weekly] = Integer($1)
|
10
|
+
when /^--monthly=(\d+)$/
|
11
|
+
memo[:monthly] = Integer($1)
|
12
|
+
when /^--yearly=(\d+)$/
|
13
|
+
memo[:yearly] = Integer($1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
unprocessable, deleteable = Surrender.reject(ARGF, options)
|
18
|
+
STDERR.puts unprocessable.map{|filename| "WARN: Filename #{filename.inspect} did not match the filter expression"}
|
19
|
+
STDOUT.puts deleteable
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Surrender
|
2
|
+
class BucketPolicy
|
3
|
+
def initialize(count)
|
4
|
+
@count = count
|
5
|
+
@memo = Hash.new
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :count, :memo
|
9
|
+
|
10
|
+
def add(filename, date)
|
11
|
+
memo[bucket(date)] = filename
|
12
|
+
memo.delete(memo.keys.first) if memo.size > count
|
13
|
+
end
|
14
|
+
|
15
|
+
def deleteable?(filename)
|
16
|
+
!memo.values.include?(filename)
|
17
|
+
end
|
18
|
+
|
19
|
+
def keys
|
20
|
+
memo.keys
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Surrender
|
2
|
+
class MostRecentPolicy
|
3
|
+
def initialize(count)
|
4
|
+
@count = count
|
5
|
+
@memo = []
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :count, :memo
|
9
|
+
|
10
|
+
def add(filename, _)
|
11
|
+
memo << filename
|
12
|
+
memo.shift if memo.size > count
|
13
|
+
end
|
14
|
+
|
15
|
+
def deleteable?(filename)
|
16
|
+
!memo.include?(filename)
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :keys, :memo
|
20
|
+
end
|
21
|
+
end
|
data/lib/surrender.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "surrender/version"
|
2
|
+
require "surrender/most_recent_policy"
|
3
|
+
require "surrender/weekly_policy"
|
4
|
+
require "surrender/monthly_policy"
|
5
|
+
require "surrender/yearly_policy"
|
6
|
+
require "date"
|
7
|
+
|
8
|
+
module Surrender
|
9
|
+
DEFAULT_ARGUMENTS = {
|
10
|
+
most_recent: 7,
|
11
|
+
weekly: 5,
|
12
|
+
monthly: 2,
|
13
|
+
yearly: 2
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
# @return [Array<String>, Array<String>] The first argument returns filenames which did not match the regular expression.
|
17
|
+
# The second argument returns filenames which matched the regular expression and
|
18
|
+
# are candidates to be deleted.
|
19
|
+
def self.reject(filenames, options={})
|
20
|
+
options = DEFAULT_ARGUMENTS.merge(options)
|
21
|
+
extra_keys = options.keys - DEFAULT_ARGUMENTS.keys
|
22
|
+
raise ArgumentError, "Unknown keys: #{extra_keys.inspect} -- won't proceed" unless extra_keys.empty?
|
23
|
+
|
24
|
+
policies = [
|
25
|
+
Surrender::MostRecentPolicy.new(options.fetch(:most_recent)),
|
26
|
+
Surrender::WeeklyPolicy.new(options.fetch(:weekly)),
|
27
|
+
Surrender::MonthlyPolicy.new(options.fetch(:monthly)),
|
28
|
+
Surrender::YearlyPolicy.new(options.fetch(:yearly)),
|
29
|
+
]
|
30
|
+
|
31
|
+
all_files = filenames.map(&:to_s)
|
32
|
+
valid_filenames = all_files.select{|fn| fn =~ BACKUP_RE}
|
33
|
+
unprocessable = all_files - valid_filenames
|
34
|
+
valid_filenames.each do |filename|
|
35
|
+
filename =~ BACKUP_RE
|
36
|
+
date = Date.new($1.to_i, $3.to_i, $4.to_i)
|
37
|
+
|
38
|
+
policies.each do |policy|
|
39
|
+
policy.add(filename, date)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
deleteable = valid_filenames.select do |filename|
|
44
|
+
policies.all?{|policy| policy.deleteable?(filename)}
|
45
|
+
end
|
46
|
+
|
47
|
+
[unprocessable, deleteable]
|
48
|
+
end
|
49
|
+
|
50
|
+
BACKUP_RE = /\b((?:19|2\d)\d{2})(.)?(0\d|1[012])\2?([012]\d|3[01])(?:T|\b)/
|
51
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Surrender, "BACKUP_RE" do
|
4
|
+
subject { Surrender::BACKUP_RE }
|
5
|
+
|
6
|
+
it { subject.match("/var/backup/database/base-20130809.sql.gz").inspect.should == "#<MatchData \"20130809\" 1:\"2013\" 2:nil 3:\"08\" 4:\"09\">" }
|
7
|
+
it { subject.match("/var/backup/database/base-20130810.sql.gz").inspect.should == "#<MatchData \"20130810\" 1:\"2013\" 2:nil 3:\"08\" 4:\"10\">" }
|
8
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "surrender/monthly_policy"
|
3
|
+
|
4
|
+
describe Surrender::MonthlyPolicy do
|
5
|
+
context "when count = 3" do
|
6
|
+
subject { Surrender::MonthlyPolicy.new(3) }
|
7
|
+
|
8
|
+
it "keeps the latest backup of the last three months" do
|
9
|
+
subject.add "a", Date.new(2013, 3, 1)
|
10
|
+
subject.add "b", Date.new(2013, 3, 15)
|
11
|
+
|
12
|
+
subject.add "c", Date.new(2013, 4, 1)
|
13
|
+
subject.add "d", Date.new(2013, 4, 15)
|
14
|
+
|
15
|
+
subject.add "e", Date.new(2013, 5, 1)
|
16
|
+
subject.add "f", Date.new(2013, 5, 15)
|
17
|
+
|
18
|
+
subject.add "g", Date.new(2013, 6, 1)
|
19
|
+
subject.add "h", Date.new(2013, 6, 15)
|
20
|
+
|
21
|
+
subject.deleteable?("a").should == true
|
22
|
+
subject.deleteable?("b").should == true
|
23
|
+
subject.deleteable?("c").should == true
|
24
|
+
subject.deleteable?("d").should == false
|
25
|
+
subject.deleteable?("e").should == true
|
26
|
+
subject.deleteable?("f").should == false
|
27
|
+
subject.deleteable?("g").should == true
|
28
|
+
subject.deleteable?("h").should == false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "surrender/most_recent_policy"
|
3
|
+
|
4
|
+
describe Surrender::MostRecentPolicy do
|
5
|
+
context "when count = 1" do
|
6
|
+
subject { Surrender::MostRecentPolicy.new(1) }
|
7
|
+
|
8
|
+
it "keeps the last entry only" do
|
9
|
+
filename1 = "/var/backups/20130801.sql.gz"
|
10
|
+
subject.add filename1, Date.new(2013, 8, 1)
|
11
|
+
subject.deleteable?(filename1).should == false
|
12
|
+
|
13
|
+
filename2 = "/var/backups/20130802.sql.gz"
|
14
|
+
subject.add filename2, Date.new(2013, 8, 2)
|
15
|
+
subject.deleteable?(filename1).should == true # previous file is deleteable
|
16
|
+
subject.deleteable?(filename2).should == false
|
17
|
+
end
|
18
|
+
|
19
|
+
it "preserves memory by only keeping N files in memory" do
|
20
|
+
subject.add "/var/backups/20130801.sql.gz", Date.new(2013, 8, 1)
|
21
|
+
subject.keys.size.should == 1
|
22
|
+
|
23
|
+
subject.add "/var/backups/20130802.sql.gz", Date.new(2013, 8, 2)
|
24
|
+
subject.keys.size.should == 1
|
25
|
+
|
26
|
+
subject.add "/var/backups/20130803.sql.gz", Date.new(2013, 8, 3)
|
27
|
+
subject.keys.size.should == 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when count = 2" do
|
32
|
+
subject { Surrender::MostRecentPolicy.new(2) }
|
33
|
+
|
34
|
+
it "keeps the last entry only" do
|
35
|
+
filename1 = "/var/backups/20130801.sql.gz"
|
36
|
+
subject.add filename1, Date.new(2013, 8, 1)
|
37
|
+
subject.deleteable?(filename1).should == false
|
38
|
+
|
39
|
+
filename2 = "/var/backups/20130802.sql.gz"
|
40
|
+
subject.add filename2, Date.new(2013, 8, 2)
|
41
|
+
subject.deleteable?(filename1).should == false
|
42
|
+
subject.deleteable?(filename2).should == false
|
43
|
+
|
44
|
+
filename3 = "/var/backups/20130803.sql.gz"
|
45
|
+
subject.add filename3, Date.new(2013, 8, 3)
|
46
|
+
subject.deleteable?(filename1).should == true
|
47
|
+
subject.deleteable?(filename2).should == false
|
48
|
+
subject.deleteable?(filename3).should == false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "preserves memory by only keeping N files in memory" do
|
52
|
+
subject.add "/var/backups/20130801.sql.gz", Date.new(2013, 8, 1)
|
53
|
+
subject.keys.size.should == 1
|
54
|
+
|
55
|
+
subject.add "/var/backups/20130802.sql.gz", Date.new(2013, 8, 2)
|
56
|
+
subject.keys.size.should == 2
|
57
|
+
|
58
|
+
subject.add "/var/backups/20130803.sql.gz", Date.new(2013, 8, 3)
|
59
|
+
subject.keys.size.should == 2
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "surrender"
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Surrender, "most_recent" do
|
4
|
+
let(:options) { {weekly: 0, monthly: 0, yearly: 0} }
|
5
|
+
|
6
|
+
context "when no input filenames" do
|
7
|
+
subject { Surrender.reject([], {}) }
|
8
|
+
|
9
|
+
it { should == [[], []] }
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when 1 input filename" do
|
13
|
+
subject { Surrender.reject(["/var/backup/database/base-20130810.sql.gz"], options) }
|
14
|
+
it { should == [[], []] }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when 2 input filenames" do
|
18
|
+
let(:filenames) do
|
19
|
+
%w(
|
20
|
+
/var/backup/database/base-20130809.sql.gz
|
21
|
+
/var/backup/database/base-20130810.sql.gz
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
context "and most_recent = 1" do
|
26
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 1)) }
|
27
|
+
it { should == [[], filenames[-2..-2]] }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "and most_recent = 2" do
|
31
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 2)) }
|
32
|
+
it { should == [[], []] }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "and most_recent = 3" do
|
36
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 3)) }
|
37
|
+
it { should == [[], []] }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when 6 input filenames" do
|
42
|
+
let(:filenames) do
|
43
|
+
%w(
|
44
|
+
/var/backup/database/base-20130805.sql.gz
|
45
|
+
/var/backup/database/base-20130806.sql.gz
|
46
|
+
/var/backup/database/base-20130807.sql.gz
|
47
|
+
/var/backup/database/base-20130808.sql.gz
|
48
|
+
/var/backup/database/base-20130809.sql.gz
|
49
|
+
/var/backup/database/base-20130810.sql.gz
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
context "and most_recent = 1" do
|
54
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 1)) }
|
55
|
+
it { should == [[], filenames.sort - filenames.sort[-1..-1]] }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "and most_recent = 2" do
|
59
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 2)) }
|
60
|
+
it { should == [[], filenames.sort - filenames.sort[-2..-1]] }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "and most_recent = 3" do
|
64
|
+
subject { Surrender.reject(filenames, options.merge(most_recent: 3)) }
|
65
|
+
it { should == [[], filenames.sort - filenames.sort[-3..-1]] }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Surrender, "weekly" do
|
4
|
+
context "when 2 files present, weekly=1" do
|
5
|
+
let(:filenames) do
|
6
|
+
%w(
|
7
|
+
/var/backup/database/base-20130809.sql.gz
|
8
|
+
/var/backup/database/base-20130810.sql.gz
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { Surrender.reject(filenames, most_recent: 0, weekly: 1) }
|
13
|
+
|
14
|
+
it { should == [[], filenames.sort[-2..-2]] }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when 3 files present over 2 weeks, weekly=2" do
|
18
|
+
let(:filenames) do
|
19
|
+
%w(
|
20
|
+
/var/backup/database/base-20130801.sql.gz
|
21
|
+
/var/backup/database/base-20130809.sql.gz
|
22
|
+
/var/backup/database/base-20130810.sql.gz
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
subject { Surrender.reject(filenames, most_recent: 0, weekly: 2) }
|
27
|
+
|
28
|
+
it { should == [[], filenames[-2..-2]] }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "surrender/weekly_policy"
|
3
|
+
|
4
|
+
describe Surrender::WeeklyPolicy do
|
5
|
+
context "when count = 1" do
|
6
|
+
subject { Surrender::WeeklyPolicy.new(1) }
|
7
|
+
|
8
|
+
it "keeps the last filename per week" do
|
9
|
+
subject.add "a", Date.new(2013, 8, 4)
|
10
|
+
subject.deleteable?("a").should == false
|
11
|
+
|
12
|
+
subject.add "b", Date.new(2013, 8, 5)
|
13
|
+
subject.deleteable?("a").should == true
|
14
|
+
subject.deleteable?("b").should == false
|
15
|
+
|
16
|
+
subject.add "c", Date.new(2013, 8, 6)
|
17
|
+
subject.deleteable?("a").should == true
|
18
|
+
subject.deleteable?("b").should == true
|
19
|
+
subject.deleteable?("c").should == false
|
20
|
+
|
21
|
+
subject.add "d", Date.new(2013, 8, 10)
|
22
|
+
subject.deleteable?("a").should == true
|
23
|
+
subject.deleteable?("b").should == true
|
24
|
+
subject.deleteable?("c").should == true
|
25
|
+
subject.deleteable?("d").should == false
|
26
|
+
|
27
|
+
subject.add "e", Date.new(2013, 8, 11)
|
28
|
+
subject.deleteable?("a").should == true
|
29
|
+
subject.deleteable?("b").should == true
|
30
|
+
subject.deleteable?("c").should == true
|
31
|
+
subject.deleteable?("d").should == true
|
32
|
+
subject.deleteable?("e").should == false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when count = 2" do
|
37
|
+
subject { Surrender::WeeklyPolicy.new(2) }
|
38
|
+
|
39
|
+
it "keeps the last filename per week" do
|
40
|
+
subject.add "a", Date.new(2013, 8, 4)
|
41
|
+
subject.deleteable?("a").should == false
|
42
|
+
|
43
|
+
subject.add "b", Date.new(2013, 8, 5)
|
44
|
+
subject.deleteable?("a").should == true
|
45
|
+
subject.deleteable?("b").should == false
|
46
|
+
|
47
|
+
subject.add "c", Date.new(2013, 8, 6)
|
48
|
+
subject.deleteable?("a").should == true
|
49
|
+
subject.deleteable?("b").should == true
|
50
|
+
subject.deleteable?("c").should == false
|
51
|
+
|
52
|
+
subject.add "d", Date.new(2013, 8, 10)
|
53
|
+
subject.deleteable?("a").should == true
|
54
|
+
subject.deleteable?("b").should == true
|
55
|
+
subject.deleteable?("c").should == true
|
56
|
+
subject.deleteable?("d").should == false
|
57
|
+
|
58
|
+
subject.add "e", Date.new(2013, 8, 11)
|
59
|
+
subject.deleteable?("a").should == true
|
60
|
+
subject.deleteable?("b").should == true
|
61
|
+
subject.deleteable?("c").should == true
|
62
|
+
subject.deleteable?("d").should == false
|
63
|
+
subject.deleteable?("e").should == false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "surrender/yearly_policy"
|
3
|
+
|
4
|
+
describe Surrender::YearlyPolicy do
|
5
|
+
context "when count = 2" do
|
6
|
+
subject { Surrender::YearlyPolicy.new(2) }
|
7
|
+
|
8
|
+
it "keeps the most recent filename of the last two years" do
|
9
|
+
subject.add "a", Date.new(2011, 8, 9)
|
10
|
+
subject.add "b", Date.new(2011, 9, 9)
|
11
|
+
subject.add "c", Date.new(2011, 10, 9)
|
12
|
+
|
13
|
+
subject.add "d", Date.new(2012, 8, 9)
|
14
|
+
subject.add "e", Date.new(2012, 9, 9)
|
15
|
+
subject.add "f", Date.new(2012, 10, 9)
|
16
|
+
|
17
|
+
subject.add "g", Date.new(2013, 8, 9)
|
18
|
+
subject.add "h", Date.new(2013, 9, 9)
|
19
|
+
subject.add "i", Date.new(2013, 10, 9)
|
20
|
+
|
21
|
+
subject.deleteable?("a").should == true
|
22
|
+
subject.deleteable?("b").should == true
|
23
|
+
subject.deleteable?("c").should == true
|
24
|
+
|
25
|
+
subject.deleteable?("d").should == true
|
26
|
+
subject.deleteable?("e").should == true
|
27
|
+
subject.deleteable?("f").should == false
|
28
|
+
|
29
|
+
subject.deleteable?("g").should == true
|
30
|
+
subject.deleteable?("h").should == true
|
31
|
+
subject.deleteable?("i").should == false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/surrender.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'surrender/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "surrender"
|
8
|
+
gem.version = Surrender::VERSION
|
9
|
+
gem.authors = ["François Beausoleil"]
|
10
|
+
gem.email = ["francois@teksol.info"]
|
11
|
+
gem.description = %q{Given a list of files on STDIN, returns on STDOUT the list of files that should be rm'd - namely the list of files which don't match the retain rules.}
|
12
|
+
gem.summary = %q{Acts as a filter, returning the list of files that don't match the retain rules}
|
13
|
+
gem.homepage = "https://github.com/francois/surrender"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency "rspec", "~> 2.14"
|
21
|
+
gem.add_development_dependency "rake"
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: surrender
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- François Beausoleil
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.14'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.14'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Given a list of files on STDIN, returns on STDOUT the list of files that
|
47
|
+
should be rm'd - namely the list of files which don't match the retain rules.
|
48
|
+
email:
|
49
|
+
- francois@teksol.info
|
50
|
+
executables:
|
51
|
+
- surrender
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- .travis.yml
|
57
|
+
- Gemfile
|
58
|
+
- LICENSE.txt
|
59
|
+
- README.md
|
60
|
+
- Rakefile
|
61
|
+
- bin/surrender
|
62
|
+
- lib/surrender.rb
|
63
|
+
- lib/surrender/bucket_policy.rb
|
64
|
+
- lib/surrender/monthly_policy.rb
|
65
|
+
- lib/surrender/most_recent_policy.rb
|
66
|
+
- lib/surrender/version.rb
|
67
|
+
- lib/surrender/weekly_policy.rb
|
68
|
+
- lib/surrender/yearly_policy.rb
|
69
|
+
- spec/backup_re_matches_filenames_spec.rb
|
70
|
+
- spec/monthly_policy_spec.rb
|
71
|
+
- spec/most_recent_policy_spec.rb
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
- spec/surrender_most_recent_spec.rb
|
74
|
+
- spec/surrender_weekly_spec.rb
|
75
|
+
- spec/weekly_policy_spec.rb
|
76
|
+
- spec/yearly_policy_spec.rb
|
77
|
+
- surrender.gemspec
|
78
|
+
homepage: https://github.com/francois/surrender
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.25
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Acts as a filter, returning the list of files that don't match the retain
|
102
|
+
rules
|
103
|
+
test_files:
|
104
|
+
- spec/backup_re_matches_filenames_spec.rb
|
105
|
+
- spec/monthly_policy_spec.rb
|
106
|
+
- spec/most_recent_policy_spec.rb
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
- spec/surrender_most_recent_spec.rb
|
109
|
+
- spec/surrender_weekly_spec.rb
|
110
|
+
- spec/weekly_policy_spec.rb
|
111
|
+
- spec/yearly_policy_spec.rb
|