surrender 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode # JRuby in 1.9 mode
5
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ ruby "1.9.3"
3
+
4
+ # Specify your gem's dependencies in surrender.gemspec
5
+ gemspec
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
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :spec do
4
+ sh "rspec spec/"
5
+ end
6
+
7
+ task :default => :spec
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,9 @@
1
+ require "surrender/bucket_policy"
2
+
3
+ module Surrender
4
+ class MonthlyPolicy < BucketPolicy
5
+ def bucket(date)
6
+ Date.new(date.year, date.month, 1)
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,3 @@
1
+ module Surrender
2
+ VERSION = "0.8.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "surrender/bucket_policy"
2
+
3
+ module Surrender
4
+ class WeeklyPolicy < BucketPolicy
5
+ def bucket(date)
6
+ date - date.wday
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require "surrender/bucket_policy"
2
+
3
+ module Surrender
4
+ class YearlyPolicy < BucketPolicy
5
+ def bucket(date)
6
+ Date.new(date.year, 1, 1)
7
+ end
8
+ end
9
+ 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
@@ -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