maid 0.1.0.beta2 → 0.1.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -17,4 +17,3 @@ tmtags
17
17
  doc/*
18
18
  *.gem
19
19
  .bundle
20
- Gemfile.lock
data/CONTRIBUTING.rdoc ADDED
@@ -0,0 +1,12 @@
1
+ = Contributing
2
+
3
+ This is a Ruby Gem, built using Bundler. For a walkthrough of how that works, see http://railscasts.com/episodes/245-new-gem-with-bundler.
4
+
5
+ == Notes
6
+
7
+ * `rake install` builds and installs the gem, but you'll probably need to do `sudo rake install`.
8
+ * Keep in mind that the gemspec only looks at files in the VCS (git).
9
+
10
+ == Guidelines
11
+
12
+ * Whenever possible, retain compatibility with Ruby 1.8.
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ maid (0.1.0.beta.3)
5
+ thor (~> 0.14.6)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ ZenTest (4.4.2)
11
+ diff-lcs (1.1.2)
12
+ rake (0.8.7)
13
+ rspec (2.5.0)
14
+ rspec-core (~> 2.5.0)
15
+ rspec-expectations (~> 2.5.0)
16
+ rspec-mocks (~> 2.5.0)
17
+ rspec-core (2.5.2)
18
+ rspec-expectations (2.5.0)
19
+ diff-lcs (~> 1.1.2)
20
+ rspec-mocks (2.5.0)
21
+ thor (0.14.6)
22
+ timecop (0.3.5)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ ZenTest (~> 4.4.2)
29
+ maid!
30
+ rake (~> 0.8.7)
31
+ rspec (~> 2.5.0)
32
+ timecop (~> 0.3.5)
data/Maidfile ADDED
@@ -0,0 +1,4 @@
1
+ Maid.rules do
2
+ rule('documentation') { trash('doc') }
3
+ rule('built gems') { trash('pkg') }
4
+ end
data/README.rdoc CHANGED
@@ -1,10 +1,10 @@
1
1
  = Maid
2
2
 
3
- Maid cleans up after you, based on rules you define.
3
+ Be lazy! Let Maid clean up after you, based on rules you define.
4
4
 
5
- Your maid keeps files from sitting around too long, untouched. Many of the downloads and other files you collect can easily be categorized and handled appropriately by rules you define. Let the maid in your computer take care of the easy stuff, so you can spend more of your time on what matters.
5
+ Maid keeps files from sitting around too long, untouched. Many of the downloads and other files you collect can easily be categorized and handled appropriately by rules you define. Let the maid in your computer take care of the easy stuff, so you can spend more of your time on what matters.
6
6
 
7
- Worried about things happening that you don't expect? Your maid doesn't overwrite files and actions are logged so you can tell what happened.
7
+ Think of it like the email filters you might already have, but for files. Worried about things happening that you don't expect? Maid doesn't overwrite files and actions are logged so you can tell what happened.
8
8
 
9
9
  Maid is inspired by the Mac OS X shareware program Hazel[http://www.noodlesoft.com/hazel.php]. This tool was created on Mac OS X 10.6, but should be generally portable to other systems. (Some of the more advanced features such as <tt>downloaded_from</tt> require OS X, however.)
10
10
 
@@ -12,23 +12,43 @@ Your rules are defined in Ruby, so easy rules are easy and difficult rules are p
12
12
 
13
13
  == Installation
14
14
 
15
- If you have RubyGems installed (default on OS X and most Ruby installations):
15
+ Maid is currently in beta, but I encourage you to give it a try. I'm using it on several computers daily.
16
16
 
17
- gem install maid
17
+ If you have RubyGems installed (default on Mac OS X and many Ruby installations):
18
18
 
19
- If you want to install the executable into <tt>/usr/bin</tt>, you may need to give root access:
19
+ gem install maid --pre
20
20
 
21
- sudo gem install maid
21
+ If you want to install the executable for all users, you may need to give root access:
22
22
 
23
- Maid is currently in beta, but I encourage you to give it a try. I'm using it on several computers daily.
23
+ sudo gem install maid --pre
24
+
25
+ === Ubuntu, et al.
26
+
27
+ As you might expect, you need Ruby and RubyGems installed to do the above.
28
+
29
+ sudo apt-get install ruby
30
+ sudo apt-get install rubygems
31
+
32
+ You might also need to add the RubyGems <tt>bin</tt> directory to your <tt>$PATH</tt>. For example, on Ubuntu you might need to add something like this to your <tt>~/.bashrc</tt>:
33
+
34
+ export PATH="/var/lib/gems/1.8/bin:$PATH"
24
35
 
25
36
  == Tutorial
26
37
 
27
- Maid can be used in several ways.
38
+ Maid rules are defined using Ruby, with some common operations made easier with a small DSL (Domain Specific Language). Here's a sample:
39
+
40
+ Maid.rules do
41
+ rule 'Old files downloaded while developing/testing' do
42
+ dir('~/Downloads/*').each do |path|
43
+ if downloaded_from(path).any? {|u| u.match 'http://localhost'} && 1.week.since? last_accessed(path)
44
+ trash(path)
45
+ end
46
+ end
47
+ end
48
+ end
28
49
 
29
- Before you start running your rules, you'll likely want to test them using one of the following forms:
50
+ Before you start running your rules, you'll likely want to be able to test them. Here's how:
30
51
 
31
- # Do a "dry run" of your rules.
32
52
  # No actions are taken; you just see what would happen with your rules as defined.
33
53
  maid --dry-run
34
54
  maid --noop
@@ -42,9 +62,9 @@ To run your rules on demand, you can run <tt>maid</tt> manually:
42
62
  So, for example, if this is <tt>some_rules.rb</tt>:
43
63
 
44
64
  Maid.rules do
45
- rule 'pdf files' do
65
+ rule 'downloaded PDF books' do
46
66
  dir('~/Downloads/*.pdf').each do |path|
47
- move(path, path) # Intentionally does nothing
67
+ move(path, '~/Books')
48
68
  end
49
69
  end
50
70
  end
@@ -52,26 +72,25 @@ So, for example, if this is <tt>some_rules.rb</tt>:
52
72
  This is the command to test, as well as some sample output:
53
73
 
54
74
  $ maid -nr some_rules.rb
55
- Started
56
- Rule: pdf files
57
- mv "/Users/ben/Downloads/bill.pdf" "/Users/ben/Downloads/bill.pdf"
58
- mv "/Users/ben/Downloads/book.pdf" "/Users/ben/Downloads/book.pdf"
59
- mv "/Users/ben/Downloads/issue12.pdf" "/Users/ben/Downloads/issue12.pdf"
60
- mv "/Users/ben/Downloads/spring2011newsletter.pdf" "/Users/ben/Downloads/spring2011newsletter.pdf"
61
- Finished
75
+ Rule: downloaded PDF books
76
+ mv "/Users/ben/Downloads/book.pdf" "/Users/ben/Books/"
77
+ mv "/Users/ben/Downloads/issue12.pdf" "/Users/ben/Books/"
78
+ mv "/Users/ben/Downloads/spring2011newsletter.pdf" "/Users/ben/Books/"
62
79
 
63
- For more helper methods, please see the documentation of Maid::Tools.
80
+ For more DSL helper methods, please see the documentation of Maid::Tools.
64
81
 
65
82
  === Automation
66
83
 
67
- Once you get a hang for what you can do with Maid, the easiest way is to let Maid do its stuff automatically throughout the day. You'll find your computer stays a little tidier with as you teach it how to handle your common files.
84
+ Once you get a hang for what you can do with Maid, let it do its stuff automatically throughout the day. You'll find your computer stays a little tidier with as you teach it how to handle your common files.
68
85
 
69
86
  To do this, edit your crontab in your tool of choice and have it invoke the <tt>maid</tt> command. The <tt>--silent</tt> option is provided to keep this from emailing you, if desired. A log of the actions taken is kept at <tt>~/.maid/maid.log</tt>.
70
87
 
71
88
  Example for every day at 1am:
72
89
 
73
90
  # minute hour day_of_month month day_of_week command_to_execute
74
- 0 1 * * * bash -li -c "maid --silent"
91
+ 0 1 * * * /bin/bash -li -c "maid --silent"
92
+
93
+ Both Mac OS X and Linux support callbacks when folders are changed, and that may be a forthcoming feature in Maid. That said, I find cron to take care of most of my needs.
75
94
 
76
95
  == Sample and Ideas
77
96
 
data/lib/maid.rb CHANGED
@@ -26,6 +26,4 @@ class Numeric
26
26
  include Maid::NumericExtensions
27
27
  end
28
28
 
29
- if __FILE__ == $PROGRAM_NAME
30
- Maid::App.start
31
- end
29
+ # TODO Is there a no-conflict way of including the extensions?
data/lib/maid/app.rb CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'thor'
3
3
 
4
4
  class Maid::App < Thor
5
+ check_unknown_options!
5
6
  default_task 'clean'
6
7
 
7
8
  desc 'clean', 'Clean based on rules'
@@ -10,11 +11,13 @@ class Maid::App < Thor
10
11
  method_option :silent, :type => :boolean, :aliases => %w[-s]
11
12
  def clean
12
13
  maid = Maid::Maid.new(maid_options(options))
13
- say "Logging actions to #{maid.log_path.inspect}" unless options.silent? || options.noop?
14
+ unless options.silent? || options.noop?
15
+ say "Logging actions to #{maid.log_device.inspect}"
16
+ end
14
17
  maid.clean
15
18
  end
16
19
 
17
- desc 'version', 'print version number'
20
+ desc 'version', 'Print version number'
18
21
  def version
19
22
  say Maid::VERSION
20
23
  end
@@ -26,7 +29,7 @@ class Maid::App < Thor
26
29
  if options['noop']
27
30
  # You're testing, so a simple log goes to STDOUT and no actions are taken
28
31
  h[:file_options] = {:noop => true}
29
- h[:log_path] = STDOUT
32
+ h[:log_device] = STDOUT
30
33
  h[:log_formatter] = lambda { |_, _, _, msg| "#{msg}\n" }
31
34
  end
32
35
 
data/lib/maid/maid.rb CHANGED
@@ -4,33 +4,33 @@ require 'logger'
4
4
  # Maid cleans up according to the given rules, logging what it does.
5
5
  class Maid::Maid
6
6
  DEFAULTS = {
7
- :progname => 'Maid',
8
- :log_path => File.expand_path('~/.maid/maid.log'),
9
- :rules_path => File.expand_path('~/.maid/rules.rb'),
10
- :trash_path => File.expand_path('~/.Trash'),
7
+ :progname => 'Maid',
8
+ :log_device => File.expand_path('~/.maid/maid.log'),
9
+ :rules_path => File.expand_path('~/.maid/rules.rb'),
10
+ :trash_path => File.expand_path('~/.Trash'),
11
11
  :file_options => {:noop => true}, # for FileUtils
12
12
  }.freeze
13
13
 
14
+ attr_reader :file_options, :log_device, :rules, :rules_path, :trash_path
14
15
  include ::Maid::Tools
15
- attr_reader :file_options, :log_path, :rules, :rules_path, :trash_path
16
16
 
17
17
  # Make a new Maid, setting up paths for the log and trash.
18
18
  #
19
19
  # Sane defaults for a log and trash path are set for Mac OS X, but they can easily be overridden like so:
20
20
  #
21
- # Maid::Maid.new(:log_path => '/home/username/log/maid.log', :trash_path => '/home/username/.local/share/Trash/files/')
21
+ # Maid::Maid.new(:log_device => '/home/username/log/maid.log', :trash_path => '/home/username/.local/share/Trash/files/')
22
22
  #
23
23
  def initialize(options = {})
24
24
  options = DEFAULTS.merge(options.reject { |k, v| v.nil? })
25
25
 
26
- @log_path = options[:log_path]
27
- FileUtils.mkdir_p(File.dirname(@log_path)) unless @log_path.kind_of?(IO)
28
- @logger = Logger.new(@log_path)
29
- @logger.progname = options[:progname]
26
+ @log_device = options[:log_device]
27
+ FileUtils.mkdir_p(File.dirname(@log_device)) unless @log_device.kind_of?(IO)
28
+ @logger = Logger.new(@log_device)
29
+ @logger.progname = options[:progname]
30
30
  @logger.formatter = options[:log_formatter] if options[:log_formatter]
31
31
 
32
- @rules_path = options[:rules_path]
33
- @trash_path = options[:trash_path]
32
+ @rules_path = options[:rules_path]
33
+ @trash_path = options[:trash_path]
34
34
  @file_options = options[:file_options]
35
35
 
36
36
  @rules = []
@@ -38,18 +38,28 @@ class Maid::Maid
38
38
 
39
39
  # Start cleaning, based on the rules defined at rules_path.
40
40
  def clean
41
- @logger.info 'Started'
41
+ unless @log_device.kind_of?(IO)
42
+ @logger.info "v#{Maid::VERSION}"
43
+ @logger.info 'Started'
44
+ end
45
+
42
46
  add_rules(@rules_path)
43
47
  follow_rules
44
- @logger.info 'Finished'
48
+
49
+ unless @log_device.kind_of?(IO)
50
+ @logger.info 'Finished'
51
+ end
45
52
  end
46
53
 
47
54
  # Add the rules at path.
48
55
  def add_rules(path)
49
56
  Maid.with_instance(self) do
50
57
  # Using 'Kernel' here to help with testability
51
- Kernel.require(path)
58
+ # Kernel.load must be used for non-".rb" files to be required, it seems.
59
+ Kernel.load(path)
52
60
  end
61
+ rescue LoadError => e
62
+ STDERR.puts e.message
53
63
  end
54
64
 
55
65
  # Register a rule with a description and instructions (lambda function).
@@ -64,4 +74,26 @@ class Maid::Maid
64
74
  rule.follow
65
75
  end
66
76
  end
77
+
78
+ # Run a shell command.
79
+ #--
80
+ # Delegates to Kernel.`. Made primarily for testing other commands and some error handling.
81
+ def cmd(command) #:nodoc:
82
+ if supported_command?(command)
83
+ %x(#{command})
84
+ else
85
+ raise ArgumentError, "Unsupported command: #{command.inspect}"
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ # Does the OS support this command?
92
+ def supported_command?(command) #:nodoc:
93
+ @@supported_commands ||= {}
94
+
95
+ command_name = command.strip.split(/\s+/)[0]
96
+ supported = @@supported_commands[command_name]
97
+ @@supported_commands[command_name] = supported ? supported : !%x(which #{command_name}).empty?
98
+ end
67
99
  end
@@ -73,4 +73,17 @@ module Maid::NumericExtensions
73
73
 
74
74
  # Reads best without arguments: 10.minutes.from_now
75
75
  alias :from_now :since
76
+
77
+ ######################
78
+ ### Maid additions ###
79
+ ######################
80
+
81
+ # TODO find a better place for these to live?
82
+
83
+ # Reads well in a case like:
84
+ #
85
+ # 1.week.since? last_accessed('filename')
86
+ def since?(other_time)
87
+ other_time < self.ago
88
+ end
76
89
  end
data/lib/maid/tools.rb CHANGED
@@ -5,6 +5,8 @@ require 'time'
5
5
  # Collection of utility methods included in Maid::Maid (and thus available in the rules DSL).
6
6
  #
7
7
  # In general, all paths are automatically expanded (e.g. '~/Downloads/foo.zip' becomes '/home/username/Downloads/foo.zip').
8
+ #
9
+ # Some methods are not available on all platforms. An <tt>ArgumentError</tt> is raised when a command is not available. See tags: [Mac OS X]
8
10
  module Maid::Tools
9
11
  # Move from <tt>from</tt> to <tt>to</tt>.
10
12
  #
@@ -62,14 +64,16 @@ module Maid::Tools
62
64
  Find.find(File.expand_path(path), &block)
63
65
  end
64
66
 
65
- # Run a shell command.
67
+ # [Mac OS X] Use Spotlight to locate all files matching the given filename.
66
68
  #
67
- # Delegates to Kernel.`. Made primarily for testing other commands.
68
- def cmd(command) #:nodoc:
69
- %x(#{command})
69
+ # locate('foo.zip') # => ['/a/foo.zip', '/b/foo.zip']
70
+ #--
71
+ # TODO use `locate` elsewhere -- it isn't available by default on OS X starting with OS X Leopard.
72
+ def locate(name)
73
+ cmd("mdfind -name #{name.inspect}").split("\n")
70
74
  end
71
75
 
72
- # Use Spotlight metadata to determine the site from which a file was downloaded.
76
+ # [Mac OS X] Use Spotlight metadata to determine the site from which a file was downloaded.
73
77
  #
74
78
  # downloaded_from('foo.zip') # => ['http://www.site.com/foo.zip', 'http://www.site.com/']
75
79
  def downloaded_from(path)
@@ -78,20 +82,13 @@ module Maid::Tools
78
82
  clean.split(/,\s+/).map { |s| t = s.strip; t[1, t.length - 2] }
79
83
  end
80
84
 
81
- # Use Spotlight metadata to determine audio length.
85
+ # [Mac OS X] Use Spotlight metadata to determine audio length.
82
86
  #
83
87
  # duration_s('foo.mp3') # => 235.705
84
88
  def duration_s(path)
85
89
  cmd("mdls -raw -name kMDItemDurationSeconds #{path.inspect}").to_f
86
90
  end
87
91
 
88
- # Use Spotlight to locate all files matching the given filename
89
- #
90
- # locate('foo.zip') # => ['/a/foo.zip', '/b/foo.zip']
91
- def locate(name)
92
- cmd("mdfind -name #{name.inspect}").split("\n")
93
- end
94
-
95
92
  # Inspect the contents of a .zip file.
96
93
  #
97
94
  # zipfile_contents('foo.zip') # => ['foo/foo.exe', 'foo/README.txt']
@@ -108,12 +105,19 @@ module Maid::Tools
108
105
  raw.split(/\s+/).first.to_i
109
106
  end
110
107
 
108
+ # In Unix speak, "atime".
109
+ #
110
+ # last_accessed('foo.zip') # => Sat Apr 09 10:50:01 -0400 2011
111
+ def last_accessed(path)
112
+ File.atime(File.expand_path(path))
113
+ end
114
+
111
115
  # Pulls and pushes the given git repository.
112
116
  #
113
117
  # git_piston('~/code/projectname')
114
118
  def git_piston(path)
115
119
  full_path = File.expand_path(path)
116
120
  stdout = cmd("cd #{full_path.inspect} && git pull && git push 2>&1")
117
- @logger.info "Fired piston on #{full_path.inspect}. STDOUT:\n\n#{stdout}"
121
+ @logger.info "Fired git piston on #{full_path.inspect}. STDOUT:\n\n#{stdout}"
118
122
  end
119
123
  end
data/lib/maid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Maid
2
- VERSION = "0.1.0.beta2"
2
+ VERSION = "0.1.0.beta.3"
3
3
  end
data/maid.gemspec CHANGED
@@ -9,12 +9,13 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Benjamin Oakes"]
10
10
  s.email = ["hello@benjaminoakes.com"]
11
11
  s.homepage = "http://github.com/benjaminoakes/maid"
12
- s.summary = %q{Maid cleans up after you, based on rules you define.}
12
+ s.summary = %q{Be lazy. Let Maid clean up after you, based on rules you define.}
13
13
  s.description = s.summary
14
14
 
15
15
  s.rubyforge_project = "maid"
16
16
 
17
17
  s.add_dependency('thor', '~> 0.14.6')
18
+ s.add_development_dependency('rake', '~> 0.8.7')
18
19
  s.add_development_dependency('rspec', '~> 2.5.0')
19
20
  s.add_development_dependency('timecop', '~> 0.3.5')
20
21
  s.add_development_dependency('ZenTest', '~> 4.4.2')
@@ -1,15 +1,35 @@
1
1
  require 'spec_helper'
2
+ require 'stringio'
2
3
 
3
4
  module Maid
4
5
  describe App, '#clean' do
6
+ def capture_stdout
7
+ out = StringIO.new
8
+ $stdout = out
9
+ yield
10
+ return out
11
+ ensure
12
+ $stdout = STDOUT
13
+ end
14
+
15
+ def capture_stderr
16
+ out = StringIO.new
17
+ $stderr = out
18
+ yield
19
+ return out
20
+ ensure
21
+ $stderr = STDERR
22
+ end
23
+
5
24
  before :each do
6
25
  @app = App.new
7
26
  @app.stub!(:maid_options)
8
27
  @app.stub!(:say)
9
28
 
29
+ # NOTE It's pretty important that this is stubbed, unless you want your rules to be run over and over when you test!
10
30
  @maid = mock('Maid')
11
31
  @maid.stub!(:clean)
12
- @maid.stub!(:log_path)
32
+ @maid.stub!(:log_device)
13
33
  Maid.stub!(:new).and_return(@maid)
14
34
  end
15
35
 
@@ -24,6 +44,19 @@ module Maid
24
44
  @maid.should_receive(:clean)
25
45
  @app.clean
26
46
  end
47
+
48
+ it 'should be silent if given the --silent option' do
49
+ # TODO It might even make sense to wrap "maid.clean" in capture_stdout { }...
50
+ capture_stdout { App.start(['clean', '--silent']) }.string.should == ''
51
+ end
52
+
53
+ it 'should complain about a MISSPELLED option' do
54
+ capture_stderr { App.start(['clean', '--slient']) }.string.should match(/Unknown/)
55
+ end
56
+
57
+ it 'should complain about an undefined task' do
58
+ capture_stderr { App.start(['rules.rb']) }.string.should match(/Could not find/)
59
+ end
27
60
  end
28
61
 
29
62
  describe App, '#version' do
@@ -42,7 +75,7 @@ module Maid
42
75
  it 'should log to STDOUT for testing purposes when given noop' do
43
76
  opts = @app.maid_options('noop' => true)
44
77
  opts[:file_options][:noop].should be_true
45
- opts[:log_path].should == STDOUT
78
+ opts[:log_device].should == STDOUT
46
79
  opts[:log_formatter].call(nil, nil, nil, 'hello').should == "hello\n"
47
80
  end
48
81
 
@@ -10,19 +10,19 @@ module Maid
10
10
 
11
11
  describe '.new' do
12
12
  it 'should set up a logger with the default path' do
13
- Logger.should_receive(:new).with(Maid::DEFAULTS[:log_path])
13
+ Logger.should_receive(:new).with(Maid::DEFAULTS[:log_device])
14
14
  Maid.new
15
15
  end
16
16
 
17
17
  it 'should set up a logger with the given path, if provided' do
18
- log_path = '/var/log/maid.log'
19
- Logger.should_receive(:new).with(log_path)
20
- Maid.new(:log_path => log_path)
18
+ log_device = '/var/log/maid.log'
19
+ Logger.should_receive(:new).with(log_device)
20
+ Maid.new(:log_device => log_device)
21
21
  end
22
22
 
23
23
  it 'should make the log directory in case it does not exist' do
24
24
  FileUtils.should_receive(:mkdir_p).with('/home/username/log')
25
- Maid.new(:log_path => '/home/username/log/maid.log')
25
+ Maid.new(:log_device => '/home/username/log/maid.log')
26
26
  end
27
27
 
28
28
  it 'should set the trash to the default path' do
@@ -99,7 +99,7 @@ module Maid
99
99
 
100
100
  describe '#add_rules' do
101
101
  before :each do
102
- Kernel.stub!(:require)
102
+ Kernel.stub!(:load)
103
103
  @maid = Maid.new
104
104
  end
105
105
 
@@ -108,11 +108,17 @@ module Maid
108
108
  @maid.add_rules('path')
109
109
  end
110
110
 
111
- it 'should require the path' do
111
+ it 'should load the path' do
112
112
  path = 'rules.rb'
113
- Kernel.should_receive(:require).with(path)
113
+ Kernel.should_receive(:load).with(path)
114
114
  @maid.add_rules(path)
115
115
  end
116
+
117
+ it 'should give an error on STDERR if there is a LoadError' do
118
+ Kernel.stub!(:load).and_raise(LoadError)
119
+ STDERR.should_receive(:puts)
120
+ @maid.add_rules('path')
121
+ end
116
122
  end
117
123
 
118
124
  describe '#rule' do
@@ -147,5 +153,19 @@ module Maid
147
153
  maid.follow_rules
148
154
  end
149
155
  end
156
+
157
+ describe '#cmd' do
158
+ before :each do
159
+ @maid = Maid.new
160
+ end
161
+
162
+ it 'should report `not-a-real-command` as not being a supported command' do
163
+ lambda { @maid.cmd('not-a-real-command arg1 arg2') }.should raise_error(ArgumentError)
164
+ end
165
+
166
+ it 'should report `echo` as a real command' do
167
+ lambda { @maid.cmd('echo .') }.should_not raise_error(ArgumentError)
168
+ end
169
+ end
150
170
  end
151
171
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Maid::NumericExtensions, '#since?' do
4
+ it 'should tell you that 1 week ago happened after 2 weeks ago' do
5
+ (1.week.since? 2.weeks.ago).should be_true
6
+ end
7
+
8
+ it 'should tell you that 2 weeks ago was not after 1 week ago' do
9
+ (2.week.since? 1.weeks.ago).should be_false
10
+ end
11
+ end
@@ -72,41 +72,49 @@ module Maid
72
72
  end
73
73
  end
74
74
 
75
+ describe '#locate' do
76
+ it 'should locate a file by name' do
77
+ @maid.should_receive(:cmd).and_return("/a/foo.zip\n/b/foo.zip\n")
78
+ @maid.locate('foo.zip').should == ['/a/foo.zip', '/b/foo.zip']
79
+ end
80
+ end
81
+
75
82
  describe '#downloaded_from' do
76
- it 'should use Spotlight metadata to determine the download site' do
83
+ it 'should determine the download site' do
77
84
  @maid.should_receive(:cmd).and_return(%Q{(\n "http://www.site.com/foo.zip",\n"http://www.site.com/"\n)})
78
85
  @maid.downloaded_from('foo.zip').should == ['http://www.site.com/foo.zip', 'http://www.site.com/']
79
86
  end
80
87
  end
81
88
 
82
89
  describe '#duration_s' do
83
- it 'should use Spotlight metadata to determine audio length' do
90
+ it 'should determine audio length' do
84
91
  @maid.should_receive(:cmd).and_return('235.705')
85
92
  @maid.duration_s('foo.mp3').should == 235.705
86
93
  end
87
94
  end
88
95
 
89
- describe '#locate' do
90
- it 'should use Spotlight to locate a file by name' do
91
- @maid.should_receive(:cmd).and_return("/a/foo.zip\n/b/foo.zip\n")
92
- @maid.locate('foo.zip').should == ['/a/foo.zip', '/b/foo.zip']
93
- end
94
- end
95
-
96
96
  describe '#zipfile_contents' do
97
- it 'should use unzip to inspect the contents of a .zip file' do
97
+ it 'should inspect the contents of a .zip file' do
98
98
  @maid.should_receive(:cmd).and_return("foo/foo.exe\nfoo/README.txt\n")
99
99
  @maid.zipfile_contents('foo.zip').should == ['foo/foo.exe', 'foo/README.txt']
100
100
  end
101
101
  end
102
102
 
103
103
  describe '#disk_usage' do
104
- it 'should use du to find the disk usage of a file' do
104
+ it 'should give the disk usage of a file' do
105
105
  @maid.should_receive(:cmd).and_return("136 foo.zip")
106
106
  @maid.disk_usage('foo.zip').should == 136
107
107
  end
108
108
  end
109
109
 
110
+ describe '#last_accessed' do
111
+ it 'should give the last accessed time of the file' do
112
+ time = Time.now
113
+ File.should_receive(:atime).with("#@home/foo.zip").and_return(time)
114
+ @maid.last_accessed('~/foo.zip').should == time
115
+ end
116
+ end
117
+
110
118
  describe '#git_piston' do
111
119
  it 'should pull and push the given git repository, logging the action' do
112
120
  @maid.should_receive(:cmd).with(%Q{cd "#@home/code/projectname" && git pull && git push 2>&1})
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196407
4
+ hash: 62196405
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
9
  - 0
10
10
  - beta
11
- - 2
12
- version: 0.1.0.beta2
11
+ - 3
12
+ version: 0.1.0.beta.3
13
13
  platform: ruby
14
14
  authors:
15
15
  - Benjamin Oakes
@@ -17,8 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-05-24 00:00:00 -04:00
21
- default_executable:
20
+ date: 2011-06-02 00:00:00 Z
22
21
  dependencies:
23
22
  - !ruby/object:Gem::Dependency
24
23
  name: thor
@@ -37,9 +36,25 @@ dependencies:
37
36
  type: :runtime
38
37
  version_requirements: *id001
39
38
  - !ruby/object:Gem::Dependency
40
- name: rspec
39
+ name: rake
41
40
  prerelease: false
42
41
  requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 49
47
+ segments:
48
+ - 0
49
+ - 8
50
+ - 7
51
+ version: 0.8.7
52
+ type: :development
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
43
58
  none: false
44
59
  requirements:
45
60
  - - ~>
@@ -51,11 +66,11 @@ dependencies:
51
66
  - 0
52
67
  version: 2.5.0
53
68
  type: :development
54
- version_requirements: *id002
69
+ version_requirements: *id003
55
70
  - !ruby/object:Gem::Dependency
56
71
  name: timecop
57
72
  prerelease: false
58
- requirement: &id003 !ruby/object:Gem::Requirement
73
+ requirement: &id004 !ruby/object:Gem::Requirement
59
74
  none: false
60
75
  requirements:
61
76
  - - ~>
@@ -67,11 +82,11 @@ dependencies:
67
82
  - 5
68
83
  version: 0.3.5
69
84
  type: :development
70
- version_requirements: *id003
85
+ version_requirements: *id004
71
86
  - !ruby/object:Gem::Dependency
72
87
  name: ZenTest
73
88
  prerelease: false
74
- requirement: &id004 !ruby/object:Gem::Requirement
89
+ requirement: &id005 !ruby/object:Gem::Requirement
75
90
  none: false
76
91
  requirements:
77
92
  - - ~>
@@ -83,8 +98,8 @@ dependencies:
83
98
  - 2
84
99
  version: 4.4.2
85
100
  type: :development
86
- version_requirements: *id004
87
- description: Maid cleans up after you, based on rules you define.
101
+ version_requirements: *id005
102
+ description: Be lazy. Let Maid clean up after you, based on rules you define.
88
103
  email:
89
104
  - hello@benjaminoakes.com
90
105
  executables:
@@ -96,8 +111,11 @@ extra_rdoc_files: []
96
111
  files:
97
112
  - .gitignore
98
113
  - .rspec
114
+ - CONTRIBUTING.rdoc
99
115
  - Gemfile
116
+ - Gemfile.lock
100
117
  - LICENSE
118
+ - Maidfile
101
119
  - README.rdoc
102
120
  - Rakefile
103
121
  - bin/maid
@@ -111,11 +129,11 @@ files:
111
129
  - maid.gemspec
112
130
  - spec/lib/maid/app_spec.rb
113
131
  - spec/lib/maid/maid_spec.rb
132
+ - spec/lib/maid/numeric_extensions_spec.rb
114
133
  - spec/lib/maid/rule_spec.rb
115
134
  - spec/lib/maid/tools_spec.rb
116
135
  - spec/lib/maid_spec.rb
117
136
  - spec/spec_helper.rb
118
- has_rdoc: true
119
137
  homepage: http://github.com/benjaminoakes/maid
120
138
  licenses: []
121
139
 
@@ -147,13 +165,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
165
  requirements: []
148
166
 
149
167
  rubyforge_project: maid
150
- rubygems_version: 1.6.2
168
+ rubygems_version: 1.7.2
151
169
  signing_key:
152
170
  specification_version: 3
153
- summary: Maid cleans up after you, based on rules you define.
171
+ summary: Be lazy. Let Maid clean up after you, based on rules you define.
154
172
  test_files:
155
173
  - spec/lib/maid/app_spec.rb
156
174
  - spec/lib/maid/maid_spec.rb
175
+ - spec/lib/maid/numeric_extensions_spec.rb
157
176
  - spec/lib/maid/rule_spec.rb
158
177
  - spec/lib/maid/tools_spec.rb
159
178
  - spec/lib/maid_spec.rb