javan-whenever 0.1.7 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,7 +1,17 @@
1
+ == 0.2.2 / April 30th, 2009
2
+
3
+ * Days of week jobs can now accept an :at directive (ex: every :monday, :at => '5pm'). [David Eisinger]
4
+
5
+ * Fixed command line test so it runs without a config/schedule.rb present. [Javan Makhmali]
6
+
7
+ * Raising an exception if someone tries to specify an :at with a cron shortcut (:day, :reboot, etc) so there are no false hopes. [Javan Makhmali]
8
+
9
+
1
10
  == 0.1.7 / March 5th, 2009
2
11
 
3
12
  * Added ability to update the crontab file non-destuctively instead of only overwriting it. [Javan Makhmali -- Inspired by code submitted individually from: Tien Dung (tiendung), Tom Lea (cwninja), Kyle Maxwell (fizx), and Andrew Timberlake (andrewtimberlake) on github]
4
13
 
14
+
5
15
  == 0.1.5 / February 19th, 2009
6
16
 
7
17
  * Fixed load path so Whenever's files don't conflict with anything in Rails. Thanks Ryan Koopmans. [Javan Makhmali]
data/Manifest ADDED
@@ -0,0 +1,23 @@
1
+ bin/whenever
2
+ bin/wheneverize
3
+ CHANGELOG.rdoc
4
+ lib/base.rb
5
+ lib/command_line.rb
6
+ lib/job_list.rb
7
+ lib/job_types/default.rb
8
+ lib/job_types/rake_task.rb
9
+ lib/job_types/runner.rb
10
+ lib/outputs/cron.rb
11
+ lib/version.rb
12
+ lib/whenever.rb
13
+ Rakefile
14
+ README.rdoc
15
+ test/command_line_test.rb
16
+ test/cron_test.rb
17
+ test/output_command_test.rb
18
+ test/output_env_test.rb
19
+ test/output_rake_test.rb
20
+ test/output_runner_test.rb
21
+ test/test_helper.rb
22
+ whenever.gemspec
23
+ Manifest
data/README.rdoc CHANGED
@@ -14,7 +14,7 @@ In a Rails (2.1 or greater) application:
14
14
  in your "config/environment.rb" file:
15
15
 
16
16
  Rails::Initializer.run do |config|
17
- config.gem 'javan-whenever', :lib => false, :version => '>= 0.1.7' :source => 'http://gems.github.com'
17
+ config.gem 'javan-whenever', :lib => false, :source => 'http://gems.github.com'
18
18
  end
19
19
 
20
20
  To install this gem (and all other missing gem dependencies), run rake gems:install (use sudo if necessary).
@@ -57,7 +57,7 @@ This will create an initial "config/schedule.rb" file you.
57
57
  runner "SomeModel.ladeeda"
58
58
  end
59
59
 
60
- every :sunday do # Use any day of the week or :weekend, :weekday
60
+ every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
61
61
  runner "Task.do_something_great"
62
62
  end
63
63
 
@@ -79,15 +79,15 @@ In your "config/deploy.rb" file do something like:
79
79
  namespace :deploy do
80
80
  desc "Update the crontab file"
81
81
  task :update_crontab, :roles => :db do
82
- run "cd #{release_path} && whenever --update-crontab"
82
+ run "cd #{release_path} && whenever --update-crontab #{application}"
83
83
  end
84
84
  end
85
85
 
86
- This will update your crontab file, leaving any existing entries unharmed. When using the "--update-crontab" option, Whenever will only update the entries in your crontab file related to the current schedule.rb file. This means you can use Whenever to deploy any number of apps to the same server and have them share a single crontab file peacefully.
86
+ This will update your crontab file, leaving any existing entries unharmed. When using the <code>--update-crontab</code> option, Whenever will only update the entries in your crontab file related to the current schedule.rb file. You can replace the <code>#{application}</code> with any identifying string you'd like. You can have any number of apps deploy to the same crontab file peacefully given they each use a different identifier.
87
87
 
88
- If you wish to simply overwrite your crontab file each time you deploy, use the "--write-crontab" option. This is ideal if you are only working with one app and every crontab entry is contained in a single schedule.rb file.
88
+ If you wish to simply overwrite your crontab file each time you deploy, use the <code>--write-crontab</code> option. This is ideal if you are only working with one app and every crontab entry is contained in a single schedule.rb file.
89
89
 
90
- By mixing and matching the "--load-file" and "--user" options with your various :roles in Capistrano it is entirely possible to deploy different crontab schedules under different users to all your various servers. Get creative!
90
+ By mixing and matching the <code>--load-file</code> and <code>--user</code> options with your various :roles in Capistrano it is entirely possible to deploy different crontab schedules under different users to all your various servers. Get creative!
91
91
 
92
92
  == Credit
93
93
 
@@ -97,8 +97,6 @@ While building Whenever, I learned a lot by digging through the source code of C
97
97
 
98
98
  == Feedback
99
99
 
100
- Lighthouse: http://javan.lighthouseapp.com/projects/25781-whenever/overview
101
-
102
100
  Email me: javan [at] javan (dot) us
103
101
 
104
102
  == License
data/lib/outputs/cron.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  module Whenever
2
2
  module Output
3
-
3
+
4
4
  class Cron
5
-
5
+
6
6
  attr_accessor :time, :task
7
-
7
+
8
8
  def initialize(time = nil, task = nil, at = nil)
9
9
  @time = time
10
10
  @task = task
11
11
  @at = at.is_a?(String) ? (Chronic.parse(at) || 0) : (at || 0)
12
12
  end
13
-
13
+
14
14
  def self.output(time, job)
15
15
  out = new(time, job.output, job.at)
16
16
  "#{out.time_in_cron_syntax} #{out.task}"
17
17
  end
18
-
18
+
19
19
  def time_in_cron_syntax
20
20
  case @time
21
21
  when Symbol then parse_symbol
@@ -23,11 +23,11 @@ module Whenever
23
23
  else parse_time
24
24
  end
25
25
  end
26
-
26
+
27
27
  protected
28
-
28
+
29
29
  def parse_symbol
30
- case @time
30
+ shortcut = case @time
31
31
  when :reboot then '@reboot'
32
32
  when :year, :yearly then '@annually'
33
33
  when :day, :daily then '@daily'
@@ -35,10 +35,19 @@ module Whenever
35
35
  when :month, :monthly then '@monthly'
36
36
  when :week, :weekly then '@weekly'
37
37
  when :hour, :hourly then '@hourly'
38
- else parse_as_string
38
+ end
39
+
40
+ if shortcut
41
+ if @at > 0
42
+ raise ArgumentError, "You cannot specify an ':at' when using the shortcuts for times."
43
+ else
44
+ return shortcut
45
+ end
46
+ else
47
+ parse_as_string
39
48
  end
40
49
  end
41
-
50
+
42
51
  def parse_time
43
52
  timing = Array.new(5, '*')
44
53
  case @time
@@ -49,7 +58,7 @@ module Whenever
49
58
  timing[0] = comma_separated_timing(minute_frequency, 59)
50
59
  when 1.hour...1.day
51
60
  hour_frequency = (@time / 60 / 60).round
52
- timing[0] = @at.is_a?(Time) ? @at.min : @at
61
+ timing[0] = @at.is_a?(Time) ? @at.min : @at
53
62
  timing[1] = comma_separated_timing(hour_frequency, 23)
54
63
  when 1.day...1.month
55
64
  day_frequency = (@time / 24 / 60 / 60).round
@@ -67,38 +76,42 @@ module Whenever
67
76
  end
68
77
  timing.join(' ')
69
78
  end
70
-
79
+
71
80
  def parse_as_string
72
81
  return unless @time
73
82
  string = @time.to_s
74
-
75
- return "0 0 * * mon-fri" if string.downcase.index('weekday')
76
- return "0 0 * * sat,sun" if string.downcase.index('weekend')
77
-
83
+
84
+ timing = Array.new(4, '*')
85
+ timing[0] = @at.is_a?(Time) ? @at.min : 0
86
+ timing[1] = @at.is_a?(Time) ? @at.hour : 0
87
+
88
+ return (timing << 'mon-fri') * " " if string.downcase.index('weekday')
89
+ return (timing << 'sat,sun') * " " if string.downcase.index('weekend')
90
+
78
91
  %w(sun mon tue wed thu fri sat).each do |day|
79
- return "0 0 * * #{day}" if string.downcase.index(day)
92
+ return (timing << day) * " " if string.downcase.index(day)
80
93
  end
81
-
94
+
82
95
  raise ArgumentError, "Couldn't parse: #{@time}"
83
96
  end
84
-
97
+
85
98
  def comma_separated_timing(frequency, max, start = 0)
86
99
  return start if frequency.blank? || frequency.zero?
87
100
  return '*' if frequency == 1
88
101
  return frequency if frequency > (max * 0.5).ceil
89
-
102
+
90
103
  original_start = start
91
-
104
+
92
105
  start += frequency unless (max + 1).modulo(frequency).zero? || start > 0
93
106
  output = (start..max).step(frequency).to_a
94
-
107
+
95
108
  max_occurances = (max.to_f / (frequency.to_f)).round
96
109
  max_occurances += 1 if original_start.zero?
97
-
110
+
98
111
  output[0, max_occurances].join(',')
99
112
  end
100
113
 
101
114
  end
102
-
115
+
103
116
  end
104
117
  end
data/lib/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Whenever
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 7
4
+ MINOR = 2
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -4,6 +4,7 @@ class CommandLineTest < Test::Unit::TestCase
4
4
 
5
5
  context "A command line write" do
6
6
  setup do
7
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
7
8
  @command = Whenever::CommandLine.new(:write => true, :identifier => 'My identifier')
8
9
  @task = "#{two_hours} /my/command"
9
10
  Whenever.expects(:cron).returns(@task)
@@ -27,6 +28,7 @@ class CommandLineTest < Test::Unit::TestCase
27
28
 
28
29
  context "A command line update" do
29
30
  setup do
31
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
30
32
  @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
31
33
  @task = "#{two_hours} /my/command"
32
34
  Whenever.expects(:cron).returns(@task)
@@ -85,6 +87,7 @@ class CommandLineTest < Test::Unit::TestCase
85
87
 
86
88
  context "A command line update with no identifier" do
87
89
  setup do
90
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
88
91
  Whenever::CommandLine.any_instance.expects(:default_identifier).returns('DEFAULT')
89
92
  @command = Whenever::CommandLine.new(:update => true, :file => @file)
90
93
  end
data/test/cron_test.rb CHANGED
@@ -1,18 +1,18 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
2
 
3
3
  class CronTest < Test::Unit::TestCase
4
-
4
+
5
5
  context "When parsing time in minutes" do
6
6
  should "raise if less than 1 minute" do
7
7
  assert_raises ArgumentError do
8
8
  parse_time(59.seconds)
9
9
  end
10
-
10
+
11
11
  assert_raises ArgumentError do
12
12
  parse_time(0.minutes)
13
13
  end
14
14
  end
15
-
15
+
16
16
  # For santity, do some tests on straight String
17
17
  should "parse correctly" do
18
18
  assert_equal '* * * * *', parse_time(1.minute)
@@ -22,19 +22,19 @@ class CronTest < Test::Unit::TestCase
22
22
  assert_equal '32 * * * *', parse_time(32.minutes)
23
23
  assert_not_equal '60 * * * *', parse_time(60.minutes) # 60 minutes bumps up into the hour range
24
24
  end
25
-
25
+
26
26
  # Test all minutes
27
27
  (2..59).each do |num|
28
28
  should "parse correctly for #{num} minutes" do
29
29
  start = 0
30
30
  start += num unless 60.modulo(num).zero?
31
31
  minutes = (start..59).step(num).to_a
32
-
32
+
33
33
  assert_equal "#{minutes.join(',')} * * * *", parse_time(num.minutes)
34
34
  end
35
35
  end
36
36
  end
37
-
37
+
38
38
  context "When parsing time in hours" do
39
39
  should "parse correctly" do
40
40
  assert_equal '0 * * * *', parse_time(1.hour)
@@ -44,24 +44,24 @@ class CronTest < Test::Unit::TestCase
44
44
  assert_equal '0 17 * * *', parse_time(17.hours)
45
45
  assert_not_equal '0 24 * * *', parse_time(24.hours) # 24 hours bumps up into the day range
46
46
  end
47
-
47
+
48
48
  (2..23).each do |num|
49
49
  should "parse correctly for #{num} hours" do
50
50
  start = 0
51
51
  start += num unless 24.modulo(num).zero?
52
52
  hours = (start..23).step(num).to_a
53
-
53
+
54
54
  assert_equal "0 #{hours.join(',')} * * *", parse_time(num.hours)
55
55
  end
56
56
  end
57
-
57
+
58
58
  should "parse correctly when given an 'at' with minutes as an Integer" do
59
59
  assert_minutes_equals "1", 1
60
60
  assert_minutes_equals "14", 14
61
61
  assert_minutes_equals "27", 27
62
62
  assert_minutes_equals "55", 55
63
63
  end
64
-
64
+
65
65
  should "parse correctly when given an 'at' with minutes as a Time" do
66
66
  # Basically just testing that Chronic parses some times and we get the minutes out of it
67
67
  assert_minutes_equals "1", '3:01am'
@@ -70,7 +70,7 @@ class CronTest < Test::Unit::TestCase
70
70
  assert_minutes_equals "59", '13:59'
71
71
  end
72
72
  end
73
-
73
+
74
74
  context "When parsing time in days (of month)" do
75
75
  should "parse correctly" do
76
76
  assert_equal '0 0 * * *', parse_time(1.days)
@@ -82,7 +82,7 @@ class CronTest < Test::Unit::TestCase
82
82
  assert_equal '0 0 29 * *', parse_time(29.days)
83
83
  assert_not_equal '0 0 30 * *', parse_time(30.days) # 30 days bumps into the month range
84
84
  end
85
-
85
+
86
86
  should "parse correctly when given an 'at' with hours, minutes as a Time" do
87
87
  # first param is an array with [hours, minutes]
88
88
  assert_hours_and_minutes_equals %w(3 45), '3:45am'
@@ -91,7 +91,7 @@ class CronTest < Test::Unit::TestCase
91
91
  assert_hours_and_minutes_equals %w(1 23), '1:23 AM'
92
92
  assert_hours_and_minutes_equals %w(23 59), 'March 21 11:59 pM'
93
93
  end
94
-
94
+
95
95
  should "parse correctly when given an 'at' with hours as an Integer" do
96
96
  # first param is an array with [hours, minutes]
97
97
  assert_hours_and_minutes_equals %w(1 0), 1
@@ -101,7 +101,7 @@ class CronTest < Test::Unit::TestCase
101
101
  assert_hours_and_minutes_equals %w(23 0), 23
102
102
  end
103
103
  end
104
-
104
+
105
105
  context "When parsing time in months" do
106
106
  should "parse correctly" do
107
107
  assert_equal '0 0 1 * *', parse_time(1.month)
@@ -116,7 +116,7 @@ class CronTest < Test::Unit::TestCase
116
116
  assert_equal '0 0 1 11 *', parse_time(11.months)
117
117
  assert_equal '0 0 1 12 *', parse_time(12.months)
118
118
  end
119
-
119
+
120
120
  should "parse correctly when given an 'at' with days, hours, minutes as a Time" do
121
121
  # first param is an array with [days, hours, minutes]
122
122
  assert_days_and_hours_and_minutes_equals %w(1 3 45), 'January 1st 3:45am'
@@ -124,7 +124,7 @@ class CronTest < Test::Unit::TestCase
124
124
  assert_days_and_hours_and_minutes_equals %w(22 1 1), 'march 22nd at 1:01 am'
125
125
  assert_days_and_hours_and_minutes_equals %w(23 0 0), 'march 22nd at midnight' # looks like midnight means the next day
126
126
  end
127
-
127
+
128
128
  should "parse correctly when given an 'at' with days as an Integer" do
129
129
  # first param is an array with [days, hours, minutes]
130
130
  assert_days_and_hours_and_minutes_equals %w(1 0 0), 1
@@ -132,7 +132,7 @@ class CronTest < Test::Unit::TestCase
132
132
  assert_days_and_hours_and_minutes_equals %w(29 0 0), 29
133
133
  end
134
134
  end
135
-
135
+
136
136
  context "When parsing time in days (of week)" do
137
137
  should "parse days of the week correctly" do
138
138
  {
@@ -142,25 +142,64 @@ class CronTest < Test::Unit::TestCase
142
142
  'wed' => %w(wed Wednesday WEDNESDAY WED),
143
143
  'thu' => %w(thu thurs thur Thursday THURSDAY THU),
144
144
  'fri' => %w(fri Friday FRIDAY FRI),
145
- 'sat' => %w(sat Saturday SATURDAY SAT)
145
+ 'sat' => %w(sat Saturday SATURDAY SAT)
146
146
  }.each do |day, day_tests|
147
147
  day_tests.each do |day_test|
148
148
  assert_equal "0 0 * * #{day}", parse_time(day_test)
149
149
  end
150
150
  end
151
151
  end
152
-
152
+
153
+ should "allow additional directives" do
154
+ assert_equal '30 13 * * fri', parse_time('friday', nil, "1:30 pm")
155
+ assert_equal '22 2 * * mon', parse_time('Monday', nil, "2:22am")
156
+ assert_equal '55 17 * * thu', parse_time('THU', nil, "5:55PM")
157
+ end
158
+
153
159
  should "parse weekday correctly" do
154
160
  assert_equal '0 0 * * mon-fri', parse_time('weekday')
155
161
  assert_equal '0 0 * * mon-fri', parse_time('Weekdays')
162
+ assert_equal '0 1 * * mon-fri', parse_time('Weekdays', nil, "1:00 am")
163
+ assert_equal '59 5 * * mon-fri', parse_time('Weekdays', nil, "5:59 am")
156
164
  end
157
-
165
+
158
166
  should "parse weekend correctly" do
159
167
  assert_equal '0 0 * * sat,sun', parse_time('weekend')
160
168
  assert_equal '0 0 * * sat,sun', parse_time('Weekends')
169
+ assert_equal '0 7 * * sat,sun', parse_time('Weekends', nil, "7am")
170
+ assert_equal '2 18 * * sat,sun', parse_time('Weekends', nil, "6:02PM")
161
171
  end
162
172
  end
163
173
 
174
+ context "When parsing time using the cron shortcuts" do
175
+ should "parse a :symbol into the correct shortcut" do
176
+ assert_equal '@reboot', parse_time(:reboot)
177
+ assert_equal '@annually', parse_time(:year)
178
+ assert_equal '@annually', parse_time(:yearly)
179
+ assert_equal '@daily', parse_time(:day)
180
+ assert_equal '@daily', parse_time(:daily)
181
+ assert_equal '@midnight', parse_time(:midnight)
182
+ assert_equal '@monthly', parse_time(:month)
183
+ assert_equal '@monthly', parse_time(:monthly)
184
+ assert_equal '@hourly', parse_time(:hour)
185
+ assert_equal '@hourly', parse_time(:hourly)
186
+ end
187
+
188
+ should "raise an exception if a valid shortcut is given but also an :at" do
189
+ assert_raises ArgumentError do
190
+ parse_time(:hour, nil, "1:00 am")
191
+ end
192
+
193
+ assert_raises ArgumentError do
194
+ parse_time(:reboot, nil, 5)
195
+ end
196
+
197
+ assert_raises ArgumentError do
198
+ parse_time(:day, nil, '4:20pm')
199
+ end
200
+ end
201
+ end
202
+
164
203
  private
165
204
 
166
205
  def assert_days_and_hours_and_minutes_equals(expected, time)
@@ -183,5 +222,5 @@ private
183
222
  def parse_time(time = nil, task = nil, at = nil)
184
223
  Whenever::Output::Cron.new(time, task, at).time_in_cron_syntax
185
224
  end
186
-
225
+
187
226
  end
data/whenever.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{whenever}
5
- s.version = "0.1.7"
5
+ s.version = "0.2.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Javan Makhmali"]
9
- s.date = %q{2009-03-05}
9
+ s.date = %q{2009-04-30}
10
10
  s.description = %q{Provides clean ruby syntax for defining messy cron jobs and running them Whenever.}
11
11
  s.email = %q{javan@javan.us}
12
12
  s.executables = ["whenever", "wheneverize"]
13
13
  s.extra_rdoc_files = ["bin/whenever", "bin/wheneverize", "CHANGELOG.rdoc", "lib/base.rb", "lib/command_line.rb", "lib/job_list.rb", "lib/job_types/default.rb", "lib/job_types/rake_task.rb", "lib/job_types/runner.rb", "lib/outputs/cron.rb", "lib/version.rb", "lib/whenever.rb", "README.rdoc"]
14
- s.files = ["bin/whenever", "bin/wheneverize", "CHANGELOG.rdoc", "lib/base.rb", "lib/command_line.rb", "lib/job_list.rb", "lib/job_types/default.rb", "lib/job_types/rake_task.rb", "lib/job_types/runner.rb", "lib/outputs/cron.rb", "lib/version.rb", "lib/whenever.rb", "Manifest", "Rakefile", "README.rdoc", "test/command_line_test.rb", "test/cron_test.rb", "test/output_command_test.rb", "test/output_env_test.rb", "test/output_rake_test.rb", "test/output_runner_test.rb", "test/test_helper.rb", "whenever.gemspec"]
14
+ s.files = ["bin/whenever", "bin/wheneverize", "CHANGELOG.rdoc", "lib/base.rb", "lib/command_line.rb", "lib/job_list.rb", "lib/job_types/default.rb", "lib/job_types/rake_task.rb", "lib/job_types/runner.rb", "lib/outputs/cron.rb", "lib/version.rb", "lib/whenever.rb", "Rakefile", "README.rdoc", "test/command_line_test.rb", "test/cron_test.rb", "test/output_command_test.rb", "test/output_env_test.rb", "test/output_rake_test.rb", "test/output_runner_test.rb", "test/test_helper.rb", "whenever.gemspec", "Manifest"]
15
15
  s.has_rdoc = true
16
16
  s.homepage = %q{http://github.com/javan/whenever}
17
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Whenever", "--main", "README.rdoc"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: javan-whenever
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javan Makhmali
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-05 00:00:00 -08:00
12
+ date: 2009-04-30 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -66,7 +66,6 @@ files:
66
66
  - lib/outputs/cron.rb
67
67
  - lib/version.rb
68
68
  - lib/whenever.rb
69
- - Manifest
70
69
  - Rakefile
71
70
  - README.rdoc
72
71
  - test/command_line_test.rb
@@ -77,6 +76,7 @@ files:
77
76
  - test/output_runner_test.rb
78
77
  - test/test_helper.rb
79
78
  - whenever.gemspec
79
+ - Manifest
80
80
  has_rdoc: true
81
81
  homepage: http://github.com/javan/whenever
82
82
  post_install_message: