cleaner 0.0.1 → 0.0.3
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 +2 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE +20 -0
- data/README.md +65 -0
- data/bin/cleaner +4 -0
- data/cleaner.gemspec +18 -3
- data/examples/cleaner.rb +18 -0
- data/lib/cleaner.rb +11 -4
- data/lib/cleaner/action.rb +17 -0
- data/lib/cleaner/actions/copy.rb +13 -0
- data/lib/cleaner/actions/delete.rb +9 -0
- data/lib/cleaner/actions/move.rb +11 -0
- data/lib/cleaner/cli.rb +75 -0
- data/lib/cleaner/directory.rb +35 -0
- data/lib/cleaner/file_extension.rb +15 -0
- data/lib/cleaner/file_filter.rb +58 -0
- data/lib/cleaner/runner.rb +21 -0
- data/lib/cleaner/version.rb +1 -1
- data/spec/cleaner/action_spec.rb +26 -0
- data/spec/cleaner/actions/copy_spec.rb +42 -0
- data/spec/cleaner/actions/delete_spec.rb +25 -0
- data/spec/cleaner/actions/move_spec.rb +30 -0
- data/spec/cleaner/cli_spec.rb +115 -0
- data/spec/cleaner/directory_spec.rb +85 -0
- data/spec/cleaner/file_extension_spec.rb +23 -0
- data/spec/cleaner/file_filter_spec.rb +76 -0
- data/spec/cleaner/integration_spec.rb +107 -0
- data/spec/cleaner/runner_spec.rb +37 -0
- data/spec/helpers/example_dir_helper.rb +20 -0
- data/spec/spec_helper.rb +14 -0
- metadata +149 -8
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--format documentation
|
data/Gemfile
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
+
gem "fakefs", :git => "git://github.com/wijet/fakefs.git"
|
4
|
+
gem "guard", :git => "git://github.com/guard/guard.git"
|
5
|
+
gem "guard-rspec", :git => "git://github.com/guard/guard-rspec.git"
|
6
|
+
|
3
7
|
# Specify your gem's dependencies in cleaner.gemspec
|
4
8
|
gemspec
|
data/Guardfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
guard 'rspec', :version => 2, :cli => '--color --format documentation' do
|
2
|
+
watch(%r{^spec/.+_spec\.rb$})
|
3
|
+
watch(%r{^lib/cleaner/(.+)\.rb$}) { |m| "spec/cleaner/#{m[1]}_spec.rb" }
|
4
|
+
watch(%r{^lib/cleaner/actions/(.+)\.rb$}) { |m| "spec/cleaner/actions/#{m[1]}_spec.rb" }
|
5
|
+
watch('spec/spec_helper.rb') { "spec" }
|
6
|
+
watch(%r{spec/helpers/.*\.rb}) { "spec" }
|
7
|
+
watch('lib/cleaner.rb') { "rspec" }
|
8
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Mariusz Pietrzyk
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Cleaner
|
2
|
+
---
|
3
|
+
|
4
|
+
Tool for automatic management of directories on your disk with simple DSL.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
$ gem install cleaner
|
9
|
+
|
10
|
+
## Example configuration file
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
manage '~/Downloads' do
|
14
|
+
# Move avi's and audio files to right places
|
15
|
+
move :avi, :to => '~/Movies/inbox'
|
16
|
+
move %w(mp3 ogg), :to => '~/Music/inbox'
|
17
|
+
|
18
|
+
# Remove zip files if file without zip extension exists (uncompressed files)
|
19
|
+
delete :zip, :if => proc { |file| File.exists?(file.path_without_ext) }
|
20
|
+
|
21
|
+
# Move all VAT invoices to a special place
|
22
|
+
move :pdf, :if => proc { |file| file.name =~ /VAT/ }, :to => '~/Documents/invoices'
|
23
|
+
|
24
|
+
# You've probably installed it already
|
25
|
+
delete :dmg, :after => 10.hours
|
26
|
+
|
27
|
+
# Delete everything older than 1 month.
|
28
|
+
# Was here for so long? Doesn't deserve to exist!
|
29
|
+
delete :after => 1.month
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Generate sample configuration file (~/.cleaner.rb)
|
36
|
+
|
37
|
+
$ cleaner init
|
38
|
+
|
39
|
+
Run cleaner in the background. By default it will run every 1 hour.
|
40
|
+
|
41
|
+
$ cleaner start
|
42
|
+
|
43
|
+
You can specify cleaning interval with "rails like" syntax: 20.minutes, 4.hours, 1.day
|
44
|
+
|
45
|
+
$ cleaner start 4.hours
|
46
|
+
|
47
|
+
Stop cleaner daemon
|
48
|
+
|
49
|
+
$ cleaner stop
|
50
|
+
|
51
|
+
## Contributions
|
52
|
+
|
53
|
+
To fetch & test the library for development, do:
|
54
|
+
|
55
|
+
$ git clone https://github.com/wijet/cleaner
|
56
|
+
$ cd cleaner
|
57
|
+
$ bundle
|
58
|
+
$ bundle exec rspec
|
59
|
+
|
60
|
+
If you wont to contribute, please:
|
61
|
+
|
62
|
+
* Fork the project.
|
63
|
+
* Make your feature addition or bug fix.
|
64
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
65
|
+
* Send me a pull request on Github.
|
data/bin/cleaner
ADDED
data/cleaner.gemspec
CHANGED
@@ -7,9 +7,12 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Cleaner::VERSION
|
8
8
|
s.authors = ["Mariusz Pietrzyk"]
|
9
9
|
s.email = ["wijet@wijet.pl"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{
|
12
|
-
s.description =
|
10
|
+
s.homepage = "http://github.com/wijet/cleaner"
|
11
|
+
s.summary = %q{Tool for cleaning up your directories with friendly DSL}
|
12
|
+
s.description = <<desc
|
13
|
+
Cleaner is a small tool which helps you keep your directories clean.
|
14
|
+
With simple DSL you define set of rules, which are then periodically executed against specified directory.
|
15
|
+
desc
|
13
16
|
|
14
17
|
s.rubyforge_project = "cleaner"
|
15
18
|
|
@@ -17,4 +20,16 @@ Gem::Specification.new do |s|
|
|
17
20
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
21
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
22
|
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_dependency "activesupport", "2.3.14"
|
25
|
+
s.add_dependency "filelist"
|
26
|
+
s.add_dependency "thor"
|
27
|
+
s.add_dependency "daemons"
|
28
|
+
s.add_development_dependency "rspec"
|
29
|
+
s.add_development_dependency "simplecov"
|
30
|
+
s.add_development_dependency "timecop"
|
31
|
+
if RUBY_PLATFORM =~ /darwin/
|
32
|
+
s.add_development_dependency "rb-fsevent"
|
33
|
+
s.add_development_dependency "ruby_gntp"
|
34
|
+
end
|
20
35
|
end
|
data/examples/cleaner.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
manage '~/Downloads' do
|
2
|
+
# Move avi's and audio files to right places
|
3
|
+
# move :avi, :to => '~/Movies/inbox'
|
4
|
+
# move %w(mp3 ogg), :to => '~/Music/inbox'
|
5
|
+
|
6
|
+
# Remove zip files if file without zip extension exists (uncompressed files)
|
7
|
+
# delete :zip, :if => proc { |file| File.exists?(file.path_without_ext) }
|
8
|
+
|
9
|
+
# Move all VAT invoices to a special place
|
10
|
+
# move :pdf, :if => proc { |file| file.name =~ /VAT/ }, :to => '~/Documents/invoices'
|
11
|
+
|
12
|
+
# You've probably installed it already
|
13
|
+
# delete :dmg, :after => 10.hours
|
14
|
+
|
15
|
+
# Delete everything older than 1 month.
|
16
|
+
# Was here for so long? Doesn't deserve to exist!
|
17
|
+
# delete :after => 1.month
|
18
|
+
end
|
data/lib/cleaner.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
require "
|
1
|
+
require "active_support/all"
|
2
|
+
require "filelist"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
4
|
+
require "cleaner/action"
|
5
|
+
require "cleaner/actions/delete"
|
6
|
+
require "cleaner/actions/move"
|
7
|
+
require "cleaner/actions/copy"
|
8
|
+
require "cleaner/file_extension"
|
9
|
+
require "cleaner/directory"
|
10
|
+
require "cleaner/runner"
|
11
|
+
require "cleaner/file_filter"
|
12
|
+
require "cleaner/version"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Cleaner
|
2
|
+
class Action
|
3
|
+
attr_reader :files, :options
|
4
|
+
|
5
|
+
def initialize(files, options = {})
|
6
|
+
@files = files
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute
|
11
|
+
raise NotImplementedException.new("#execute should be implemented in your Action class")
|
12
|
+
end
|
13
|
+
|
14
|
+
class UnknownActionException < Exception; end
|
15
|
+
class NotImplementedException < Exception; end
|
16
|
+
end
|
17
|
+
end
|
data/lib/cleaner/cli.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "daemons"
|
3
|
+
|
4
|
+
module Cleaner
|
5
|
+
class CLI < Thor
|
6
|
+
include Thor::Actions
|
7
|
+
attr_reader :interval
|
8
|
+
source_root("#{File.dirname(__FILE__)}/../../examples")
|
9
|
+
|
10
|
+
desc 'init', 'Create sample config file in ~/.cleaner.rb'
|
11
|
+
def init
|
12
|
+
copy_file "cleaner.rb", "~/.cleaner.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'start [INTERVAL]', %q{
|
16
|
+
Start cleaner in background. It cleans directories every 1 hour
|
17
|
+
}
|
18
|
+
def start(interval = "1.hour")
|
19
|
+
@interval = eval(interval)
|
20
|
+
daemon.start
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'stop', 'Stop cleaner in background'
|
24
|
+
def stop
|
25
|
+
daemon.stop
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'cleanup', 'Run cleaner ad hoc'
|
29
|
+
def cleanup
|
30
|
+
run_cleaner
|
31
|
+
end
|
32
|
+
|
33
|
+
no_tasks do
|
34
|
+
def daemon
|
35
|
+
group = Daemons::ApplicationGroup.new('cleaner', daemon_options)
|
36
|
+
group.new_application(daemon_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def daemon_options
|
40
|
+
{
|
41
|
+
:mode => :proc,
|
42
|
+
:proc => runner_proc,
|
43
|
+
:dir_mode => :normal,
|
44
|
+
:dir => "/tmp"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def runner_proc
|
49
|
+
Proc.new do
|
50
|
+
loop do
|
51
|
+
run_cleaner
|
52
|
+
sleep interval
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_cleaner
|
58
|
+
cleaner = Cleaner::Runner.new(load_rules)
|
59
|
+
cleaner.start
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_rules
|
63
|
+
File.read(config_file_path)
|
64
|
+
rescue Errno::ENOENT
|
65
|
+
say "Config file #{config_file_path} doesn't exist", :red
|
66
|
+
say "Generate sample config using `cleaner init`", :green
|
67
|
+
exit 1
|
68
|
+
end
|
69
|
+
|
70
|
+
def config_file_path
|
71
|
+
File.expand_path("~/.cleaner.rb")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Cleaner
|
2
|
+
class Directory
|
3
|
+
attr_reader :path, :block
|
4
|
+
|
5
|
+
def initialize(path, block)
|
6
|
+
@path = path
|
7
|
+
@block = block
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean
|
11
|
+
instance_eval(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def method_missing(method, *args, &block)
|
17
|
+
action_class = construct_action_class(method)
|
18
|
+
# FIXME: refactor this argument parsing
|
19
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
20
|
+
options = options.merge(
|
21
|
+
:pattern => args.first.is_a?(Hash) ? nil : args.first,
|
22
|
+
:path => path
|
23
|
+
)
|
24
|
+
filter = FileFilter.new(options)
|
25
|
+
action = action_class.new(filter.filterize, options)
|
26
|
+
action.execute
|
27
|
+
end
|
28
|
+
|
29
|
+
def construct_action_class(method)
|
30
|
+
Cleaner::Actions::const_get(method.to_s.capitalize)
|
31
|
+
rescue NameError => e
|
32
|
+
raise Action::UnknownActionException.new("Action '#{method}' is unknown")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Cleaner
|
2
|
+
# Provides helper methods for File object which is passed to conditions.
|
3
|
+
# With this module we can write file.name insted of File.basename(file)
|
4
|
+
#
|
5
|
+
module FileExtension
|
6
|
+
def name
|
7
|
+
File.basename(path)
|
8
|
+
end
|
9
|
+
|
10
|
+
def path_without_ext
|
11
|
+
pathname = Pathname.new(path)
|
12
|
+
pathname.sub_ext("").to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Cleaner
|
2
|
+
class FileFilter
|
3
|
+
CONDITIONS = [:after, :if]
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@options = options
|
9
|
+
@pattern = options[:pattern]
|
10
|
+
end
|
11
|
+
|
12
|
+
def filterize
|
13
|
+
paths = filter_by_name
|
14
|
+
conditions_provided? ? filter_by_conditions(paths) : paths
|
15
|
+
end
|
16
|
+
|
17
|
+
def search_pattern
|
18
|
+
case @pattern
|
19
|
+
when NilClass; "#{path}/*"
|
20
|
+
when String; "#{path}/#{@pattern}"
|
21
|
+
when Symbol; "#{path}/*.#{@pattern}"
|
22
|
+
when Array; @pattern.map { |ext| "#{path}/*.#{ext}" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def filter_by_conditions(paths)
|
29
|
+
paths.select do |path|
|
30
|
+
after_condition?(path) && if_condition?(path)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def conditions_provided?
|
35
|
+
options.keys.any? { |c| CONDITIONS.include?(c) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def after_condition?(path)
|
39
|
+
return true unless options.has_key?(:after)
|
40
|
+
File.ctime(path) < options[:after].ago
|
41
|
+
end
|
42
|
+
|
43
|
+
def if_condition?(path)
|
44
|
+
return true unless options.has_key?(:if)
|
45
|
+
file = File.new(path)
|
46
|
+
file.extend(FileExtension)
|
47
|
+
options[:if].call(file)
|
48
|
+
end
|
49
|
+
|
50
|
+
def path
|
51
|
+
File.expand_path(options[:path])
|
52
|
+
end
|
53
|
+
|
54
|
+
def filter_by_name
|
55
|
+
FileList[search_pattern]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Cleaner
|
2
|
+
class Runner
|
3
|
+
attr_reader :rules, :directories
|
4
|
+
|
5
|
+
def initialize(rules)
|
6
|
+
@rules = rules
|
7
|
+
@directories = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
instance_eval(rules)
|
12
|
+
directories.each(&:clean)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def manage(path, &block)
|
18
|
+
@directories << Directory.new(path, block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cleaner/version.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Action do
|
4
|
+
let(:files) { %w(file1 file2) }
|
5
|
+
let(:options) { {:to => '~/foo'} }
|
6
|
+
let(:action) { Cleaner::Action.new(files, options) }
|
7
|
+
|
8
|
+
describe "being initialized" do
|
9
|
+
it "should have files" do
|
10
|
+
action.files.should be(files)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have options" do
|
14
|
+
action.options.should be(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#execute" do
|
19
|
+
it "should raise exception" do
|
20
|
+
lambda {
|
21
|
+
action.execute
|
22
|
+
}.should raise_error(Cleaner::Action::NotImplementedException,
|
23
|
+
"#execute should be implemented in your Action class")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Actions::Copy do
|
4
|
+
before do
|
5
|
+
example_dir '/foo' do
|
6
|
+
%w(a.zip c.zip).each { |name| touch name }
|
7
|
+
touch 'b.txt', :content => 'btext'
|
8
|
+
end
|
9
|
+
|
10
|
+
example_dir '/foo/bar' do
|
11
|
+
touch 'barfile', :content => 'bartext'
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir.chdir('/foo')
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:copy) { Cleaner::Actions::Copy.new(%w(b.txt bar), :to => "/somewhere/dest") }
|
18
|
+
|
19
|
+
context "destination doesn't exist" do
|
20
|
+
it "should create it" do
|
21
|
+
File.exists?("/somewhere/dest").should be_false
|
22
|
+
copy.execute
|
23
|
+
File.exists?("/somewhere/dest").should be_true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should copy files to destination" do
|
28
|
+
copy.execute
|
29
|
+
File.read("/somewhere/dest/b.txt").should == "btext"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should copy directories to destination" do
|
33
|
+
copy.execute
|
34
|
+
File.read("/somewhere/dest/bar/barfile").should == "bartext"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should leave source files" do
|
38
|
+
copy.execute
|
39
|
+
File.read("/foo/b.txt").should == "btext"
|
40
|
+
File.read("/foo/bar/barfile").should == "bartext"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Actions::Delete do
|
4
|
+
before do
|
5
|
+
example_dir '/foo' do
|
6
|
+
%w(a.zip b.txt c.zip).each { |name| touch name }
|
7
|
+
example_dir '/foo/bar'
|
8
|
+
end
|
9
|
+
Dir.chdir('/foo')
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:delete) { Cleaner::Actions::Delete.new(%w(a.zip c.zip bar)) }
|
13
|
+
|
14
|
+
it "should delete given files and directories" do
|
15
|
+
delete.execute
|
16
|
+
File.exists?('a.zip').should be_false
|
17
|
+
File.exists?('c.zip').should be_false
|
18
|
+
File.exists?('bar').should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should leave other files" do
|
22
|
+
delete.execute
|
23
|
+
File.exists?('b.txt').should be_true
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Actions::Move do
|
4
|
+
before do
|
5
|
+
example_dir '/foo' do
|
6
|
+
%w(a.zip b.txt).each { |name| touch name }
|
7
|
+
end
|
8
|
+
Dir.chdir('/foo')
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:move) { Cleaner::Actions::Move.new(%w(a.zip), :to => "~/zip-files") }
|
12
|
+
|
13
|
+
context "destination dir doesn't exist" do
|
14
|
+
it "should create it" do
|
15
|
+
move.execute
|
16
|
+
File.exists?(File.expand_path("~/zip-files")).should be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should move files" do
|
21
|
+
move.execute
|
22
|
+
File.exists?("a.zip").should be_false
|
23
|
+
File.exists?(File.expand_path("~/zip-files/a.zip")).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should leave other files" do
|
27
|
+
move.execute
|
28
|
+
File.exists?("b.txt").should be_true
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
require "cleaner/cli"
|
3
|
+
|
4
|
+
describe Cleaner::CLI do
|
5
|
+
let(:rules) { "manage('~/Downloads') {}" }
|
6
|
+
let(:cli) { Cleaner::CLI.new }
|
7
|
+
before do
|
8
|
+
@home_path = File.expand_path("~")
|
9
|
+
@config_path = File.join(@home_path, ".cleaner.rb")
|
10
|
+
FileUtils.mkdir_p(@home_path)
|
11
|
+
File.open(@config_path, "w") do |file|
|
12
|
+
file << "manage('~/Downloads') {}"
|
13
|
+
end
|
14
|
+
@app = mock(:start => nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#init" do
|
18
|
+
it "should copy sample config to ~/.cleaner.rb" do
|
19
|
+
cli.should_receive("copy_file").with("cleaner.rb", "~/.cleaner.rb")
|
20
|
+
cli.init
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#start" do
|
25
|
+
before do
|
26
|
+
cli.stub(:daemon).and_return(@app)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should invoke start on daemon" do
|
30
|
+
@app.should_receive(:start)
|
31
|
+
cli.should_receive(:daemon).and_return(@app)
|
32
|
+
cli.start
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should assign and eval time interval" do
|
36
|
+
cli.start
|
37
|
+
cli.interval.should == 1.hour
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should accept custom interval" do
|
41
|
+
cli.start("20.minutes")
|
42
|
+
cli.interval.should == 20.minutes
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#stop" do
|
47
|
+
it "should invoke stop on daemon" do
|
48
|
+
@app.should_receive(:stop)
|
49
|
+
cli.should_receive(:daemon).and_return(@app)
|
50
|
+
cli.stop
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#cleanup" do
|
55
|
+
it "should invoke run_cleaner" do
|
56
|
+
cli.should_receive(:run_cleaner)
|
57
|
+
cli.cleanup
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#run_cleaner" do
|
62
|
+
before do
|
63
|
+
@runner = mock(:start => nil)
|
64
|
+
Cleaner::Runner.stub(:new).and_return(@runner)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should initialize runner with rules" do
|
68
|
+
Cleaner::Runner.should_receive(:new).with(rules)
|
69
|
+
cli.run_cleaner
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should start the runner" do
|
73
|
+
@runner.should_receive(:start)
|
74
|
+
cli.run_cleaner
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#daemon" do
|
79
|
+
it "should construct daemon application" do
|
80
|
+
proc = Proc.new {}
|
81
|
+
cli.stub(:runner_proc).and_return(proc)
|
82
|
+
group = mock
|
83
|
+
options = {:mode => :proc, :proc => proc, :dir_mode => :normal, :dir => "/tmp"}
|
84
|
+
group.should_receive(:new_application).with(options)
|
85
|
+
Daemons::ApplicationGroup.should_receive(:new).with('cleaner', options).and_return(group)
|
86
|
+
cli.daemon
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#load_rules" do
|
91
|
+
it "should load config file" do
|
92
|
+
cli.load_rules.should == rules
|
93
|
+
end
|
94
|
+
|
95
|
+
context "on missing file" do
|
96
|
+
before do
|
97
|
+
FileUtils.rm_rf(@config_path)
|
98
|
+
$stdout.stub(:puts)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should display error message" do
|
102
|
+
$stdout.should_receive(:puts).with("\e[31mConfig file #{@config_path} doesn't exist\e[0m")
|
103
|
+
lambda {
|
104
|
+
cli.load_rules
|
105
|
+
}.should raise_error(SystemExit)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should exit with 1" do
|
109
|
+
lambda {
|
110
|
+
cli.load_rules
|
111
|
+
}.should raise_error { |error| error.status.should be(1) }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Directory do
|
4
|
+
let(:block) do
|
5
|
+
Proc.new do
|
6
|
+
delete :dmg, :after => 10.days
|
7
|
+
delete :download
|
8
|
+
delete :after => 100.days
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:directory) { Cleaner::Directory.new('~/downloads', block)}
|
13
|
+
|
14
|
+
describe "being initialize" do
|
15
|
+
it "should have path" do
|
16
|
+
directory.path.should == '~/downloads'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have block" do
|
20
|
+
directory.block.should == block
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#clean" do
|
25
|
+
it "should eval block in its own context" do
|
26
|
+
block = Proc.new {}
|
27
|
+
directory = Cleaner::Directory.new('~/downloads', block)
|
28
|
+
directory.should_receive(:instance_eval).with(&block)
|
29
|
+
directory.clean
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#method_missing" do
|
34
|
+
before do
|
35
|
+
@filter = mock(:filterize => %w(file1))
|
36
|
+
Cleaner::FileFilter.stub(:new).and_return(@filter)
|
37
|
+
@action = mock(:execute => true)
|
38
|
+
Cleaner::Actions::Delete.stub(:new).and_return(@action)
|
39
|
+
end
|
40
|
+
|
41
|
+
context "on unknown action" do
|
42
|
+
it "should raise Action::UnknownActionException" do
|
43
|
+
lambda {
|
44
|
+
block = Proc.new { fooooo :txt }
|
45
|
+
directory = Cleaner::Directory.new('~/downloads', block)
|
46
|
+
directory.clean
|
47
|
+
}.should raise_error(Cleaner::Action::UnknownActionException, "Action 'fooooo' is unknown")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should initialize FileFilter object" do
|
52
|
+
Cleaner::FileFilter.should_receive(:new).with(
|
53
|
+
:pattern => :dmg,
|
54
|
+
:path => '~/downloads',
|
55
|
+
:after => 10.days
|
56
|
+
)
|
57
|
+
directory.clean
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should initialize action class with files and options" do
|
61
|
+
Cleaner::Actions::Delete.should_receive(:new).with(%w(file1),
|
62
|
+
:pattern => :dmg,
|
63
|
+
:path => '~/downloads',
|
64
|
+
:after => 10.days
|
65
|
+
)
|
66
|
+
directory.clean
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when no pattern is given" do
|
70
|
+
it "should initialize action with nil as pattern" do
|
71
|
+
Cleaner::Actions::Delete.should_receive(:new).with(%w(file1),
|
72
|
+
:pattern => nil,
|
73
|
+
:path => '~/downloads',
|
74
|
+
:after => 100.days
|
75
|
+
)
|
76
|
+
directory.clean
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should execute action" do
|
81
|
+
@action.should_receive(:execute)
|
82
|
+
directory.clean
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::FileExtension do
|
4
|
+
before do
|
5
|
+
example_dir '/foo' do
|
6
|
+
touch 'bar.txt'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:file) { File.new("/foo/bar.txt").extend(Cleaner::FileExtension) }
|
11
|
+
|
12
|
+
describe "#name" do
|
13
|
+
it "should return file name" do
|
14
|
+
file.name.should == "bar.txt"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#path_without_ext" do
|
19
|
+
it "should return file path name without file extension" do
|
20
|
+
file.path_without_ext.should == "/foo/bar"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::FileFilter do
|
4
|
+
before do
|
5
|
+
example_dir '/foo' do
|
6
|
+
touch 'b-0.zip', :mtime => 10.days.ago
|
7
|
+
touch 'b-1.zip', :ctime => 2.days.ago
|
8
|
+
touch 'cc.txt', :ctime => 3.days.ago
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def filter(options = {})
|
13
|
+
options = {:path => '/foo', :pattern => :zip}.merge(options)
|
14
|
+
Cleaner::FileFilter.new(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "being initialize" do
|
18
|
+
it "should have options" do
|
19
|
+
filter.options.should == {:path => '/foo', :pattern => :zip}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#filterize" do
|
24
|
+
it "should return files filtered by name" do
|
25
|
+
filter.filterize.should == %w(/foo/b-0.zip /foo/b-1.zip)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return files filtered by :after condition (using change time)" do
|
29
|
+
filter(:after => 1.day).filterize.should == %w(/foo/b-1.zip)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return files filtered by :if option" do
|
33
|
+
filter(
|
34
|
+
:if => proc { |file| file.name =~ /\w\w\.txt$/ },
|
35
|
+
:pattern => nil
|
36
|
+
).filterize.should == %w(/foo/cc.txt)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return files filtered by two conditions :if and :after" do
|
40
|
+
filter(
|
41
|
+
:after => 1.day,
|
42
|
+
:if => proc { |file| file.name =~ /c/ },
|
43
|
+
:pattern => nil
|
44
|
+
).filterize.should == %w(/foo/cc.txt)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#search_pattern" do
|
49
|
+
context "when nil given" do
|
50
|
+
it "should use '*' as filename pattern" do
|
51
|
+
filter = Cleaner::FileFilter.new(:path => '/some', :pattern => nil)
|
52
|
+
filter.search_pattern.should == '/some/*'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when symbol given" do
|
57
|
+
it "should be used as file extension" do
|
58
|
+
filter.search_pattern.should == '/foo/*.zip'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when string given" do
|
63
|
+
it "should be used as filename pattern" do
|
64
|
+
filter = Cleaner::FileFilter.new(:path => '/some', :pattern => 'foo.*')
|
65
|
+
filter.search_pattern.should == '/some/foo.*'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when Array given" do
|
70
|
+
it "should use every element as file extension pattern" do
|
71
|
+
filter = Cleaner::FileFilter.new(:path => '/some', :pattern => %w(pdf doc))
|
72
|
+
filter.search_pattern.should == %w(/some/*.pdf /some/*.doc)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe "Cleaner: integration spec" do
|
4
|
+
let(:config) do %q{
|
5
|
+
manage '~/Downloads' do
|
6
|
+
delete :if => proc { |file| file.name =~ /secret-\d\.txt/ }
|
7
|
+
move :avi, :to => '~/Movies'
|
8
|
+
delete :zip, :if => proc { |file| File.exists?(file.path_without_ext) }
|
9
|
+
delete :dmg, :after => 5.days
|
10
|
+
delete %w(rar gz)
|
11
|
+
delete :after => 1.month
|
12
|
+
end
|
13
|
+
|
14
|
+
manage '/foo/bar' do
|
15
|
+
copy %w(pdf), :to => '~/Documents'
|
16
|
+
delete "abc.*"
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:runner) { Cleaner::Runner.new(config) }
|
22
|
+
|
23
|
+
before do
|
24
|
+
example_dir '~/Downloads' do
|
25
|
+
touch 'Firefox99.dmg', :ctime => 7.days.ago
|
26
|
+
touch 'growl.dmg', :ctime => 2.days.ago
|
27
|
+
touch 'something-old', :ctime => 2.months.ago
|
28
|
+
touch 'lol-cat.avi'
|
29
|
+
touch 'something.rar'
|
30
|
+
touch 'another-thing.gz'
|
31
|
+
touch 'thing.dmg.zip'
|
32
|
+
touch 'thing.dmg'
|
33
|
+
touch 'thing2.zip'
|
34
|
+
2.times do |i|
|
35
|
+
touch "important-#{i}.doc"
|
36
|
+
touch "secret-#{i}.txt"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
example_dir '/foo/bar' do
|
41
|
+
%w(abc.txt abc.mp3 ddd.doc doc.pdf).each { |name| touch name }
|
42
|
+
end
|
43
|
+
|
44
|
+
runner.start
|
45
|
+
end
|
46
|
+
|
47
|
+
context "~/Downloads directory" do
|
48
|
+
before { Dir.chdir("~/Downloads") }
|
49
|
+
|
50
|
+
it "should delete :dmg files older than 5 days" do
|
51
|
+
File.exists?("Firefox99.dmg").should be_false
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should leave :dmg files younger than 5 days" do
|
55
|
+
File.exists?("growl.dmg").should be_true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should leave :doc files" do
|
59
|
+
File.exists?("important-0.doc").should be_true
|
60
|
+
File.exists?("important-1.doc").should be_true
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should delete everything that is older than 1 month" do
|
64
|
+
File.exists?("something-old").should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should move :avi files to ~/Movies" do
|
68
|
+
file = File.expand_path("~/Movies/lol-cat.avi")
|
69
|
+
File.exists?(file).should be_true
|
70
|
+
File.exists?("lol-cat.avi").should be_false
|
71
|
+
end
|
72
|
+
|
73
|
+
it "shoud remove rar and gz files given as Array of extensions" do
|
74
|
+
File.exists?("something.rar").should be_false
|
75
|
+
File.exists?("another-thing.gz").should be_false
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should delete files by :if condition" do
|
79
|
+
File.exists?("secret-1.txt").should be_false
|
80
|
+
File.exists?("secret-2.txt").should be_false
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should delete zip archives if uncompressed file exist" do
|
84
|
+
# File thing.dmg exists
|
85
|
+
File.exists?("thing.dmg.zip").should be_false
|
86
|
+
# File thing2 doesn't exist
|
87
|
+
File.exists?("thing2.zip").should be_true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "/foo/bar directory" do
|
92
|
+
before { Dir.chdir("/foo/bar") }
|
93
|
+
|
94
|
+
it "should delete all files maching abc.*" do
|
95
|
+
File.exists?("abc.txt").should be_false
|
96
|
+
File.exists?("abc.mp3").should be_false
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should leave not matching abc.*" do
|
100
|
+
File.exists?("ddd.doc").should be_true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should copy file to destination" do
|
104
|
+
File.exists?(File.expand_path("~/Documents/doc.pdf")).should be_true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Cleaner::Runner do
|
4
|
+
let(:rules) do
|
5
|
+
"manage '~/Downloads' do
|
6
|
+
end"
|
7
|
+
end
|
8
|
+
let(:runner) { Cleaner::Runner.new(rules) }
|
9
|
+
|
10
|
+
describe "being initialize" do
|
11
|
+
it "should have rules" do
|
12
|
+
runner.rules.should == rules
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#start" do
|
17
|
+
it "should instance eval rules" do
|
18
|
+
runner.should_receive(:instance_eval).with(rules)
|
19
|
+
runner.start
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should run #clean on all directories" do
|
23
|
+
directory = mock
|
24
|
+
directory.should_receive(:clean)
|
25
|
+
runner.stub(:directories).and_return([directory])
|
26
|
+
runner.start
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#manage" do
|
31
|
+
it "should initialize new directory" do
|
32
|
+
runner.start
|
33
|
+
directory = runner.directories.first
|
34
|
+
directory.path.should == "~/Downloads"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
|
3
|
+
module ExampleDirHelper
|
4
|
+
def example_dir(name, &block)
|
5
|
+
path = File.expand_path(name)
|
6
|
+
FileUtils.mkdir_p(path)
|
7
|
+
Dir.chdir(path) { block.call } if block
|
8
|
+
end
|
9
|
+
|
10
|
+
def touch(name, options = {})
|
11
|
+
options[:mtime] ||= Time.now
|
12
|
+
options[:atime] ||= Time.now
|
13
|
+
options[:ctime] ||= Time.now
|
14
|
+
Timecop.freeze(options[:ctime]) do
|
15
|
+
FileUtils.touch(name)
|
16
|
+
end
|
17
|
+
File.utime(options[:atime], options[:mtime], name)
|
18
|
+
File.open(name, "w") { |f| f << options[:content] } if options[:content]
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
require 'rspec'
|
7
|
+
require 'fakefs/spec_helpers'
|
8
|
+
require 'helpers/example_dir_helper'
|
9
|
+
require 'cleaner'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include FakeFS::SpecHelpers
|
13
|
+
config.include ExampleDirHelper
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cleaner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,151 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
12
|
+
date: 2012-01-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70196097750240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - =
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.3.14
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70196097750240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: filelist
|
27
|
+
requirement: &70196097749820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70196097749820
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: thor
|
38
|
+
requirement: &70196097749360 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70196097749360
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: daemons
|
49
|
+
requirement: &70196097748940 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70196097748940
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rspec
|
60
|
+
requirement: &70196097748520 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70196097748520
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: &70196097748100 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70196097748100
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: timecop
|
82
|
+
requirement: &70196097747680 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70196097747680
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rb-fsevent
|
93
|
+
requirement: &70196097747220 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70196097747220
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: ruby_gntp
|
104
|
+
requirement: &70196097746800 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70196097746800
|
113
|
+
description: ! " Cleaner is a small tool which helps you keep your directories clean.\n
|
114
|
+
\ With simple DSL you define set of rules, which are then periodically executed
|
115
|
+
against specified directory.\n"
|
15
116
|
email:
|
16
117
|
- wijet@wijet.pl
|
17
|
-
executables:
|
118
|
+
executables:
|
119
|
+
- cleaner
|
18
120
|
extensions: []
|
19
121
|
extra_rdoc_files: []
|
20
122
|
files:
|
21
123
|
- .gitignore
|
124
|
+
- .rspec
|
22
125
|
- Gemfile
|
126
|
+
- Guardfile
|
127
|
+
- LICENSE
|
128
|
+
- README.md
|
23
129
|
- Rakefile
|
130
|
+
- bin/cleaner
|
24
131
|
- cleaner.gemspec
|
132
|
+
- examples/cleaner.rb
|
25
133
|
- lib/cleaner.rb
|
134
|
+
- lib/cleaner/action.rb
|
135
|
+
- lib/cleaner/actions/copy.rb
|
136
|
+
- lib/cleaner/actions/delete.rb
|
137
|
+
- lib/cleaner/actions/move.rb
|
138
|
+
- lib/cleaner/cli.rb
|
139
|
+
- lib/cleaner/directory.rb
|
140
|
+
- lib/cleaner/file_extension.rb
|
141
|
+
- lib/cleaner/file_filter.rb
|
142
|
+
- lib/cleaner/runner.rb
|
26
143
|
- lib/cleaner/version.rb
|
27
|
-
|
144
|
+
- spec/cleaner/action_spec.rb
|
145
|
+
- spec/cleaner/actions/copy_spec.rb
|
146
|
+
- spec/cleaner/actions/delete_spec.rb
|
147
|
+
- spec/cleaner/actions/move_spec.rb
|
148
|
+
- spec/cleaner/cli_spec.rb
|
149
|
+
- spec/cleaner/directory_spec.rb
|
150
|
+
- spec/cleaner/file_extension_spec.rb
|
151
|
+
- spec/cleaner/file_filter_spec.rb
|
152
|
+
- spec/cleaner/integration_spec.rb
|
153
|
+
- spec/cleaner/runner_spec.rb
|
154
|
+
- spec/helpers/example_dir_helper.rb
|
155
|
+
- spec/spec_helper.rb
|
156
|
+
homepage: http://github.com/wijet/cleaner
|
28
157
|
licenses: []
|
29
158
|
post_install_message:
|
30
159
|
rdoc_options: []
|
@@ -47,5 +176,17 @@ rubyforge_project: cleaner
|
|
47
176
|
rubygems_version: 1.8.10
|
48
177
|
signing_key:
|
49
178
|
specification_version: 3
|
50
|
-
summary:
|
51
|
-
test_files:
|
179
|
+
summary: Tool for cleaning up your directories with friendly DSL
|
180
|
+
test_files:
|
181
|
+
- spec/cleaner/action_spec.rb
|
182
|
+
- spec/cleaner/actions/copy_spec.rb
|
183
|
+
- spec/cleaner/actions/delete_spec.rb
|
184
|
+
- spec/cleaner/actions/move_spec.rb
|
185
|
+
- spec/cleaner/cli_spec.rb
|
186
|
+
- spec/cleaner/directory_spec.rb
|
187
|
+
- spec/cleaner/file_extension_spec.rb
|
188
|
+
- spec/cleaner/file_filter_spec.rb
|
189
|
+
- spec/cleaner/integration_spec.rb
|
190
|
+
- spec/cleaner/runner_spec.rb
|
191
|
+
- spec/helpers/example_dir_helper.rb
|
192
|
+
- spec/spec_helper.rb
|