Skip to content

Commit 22280f8

Browse files
author
uu59
committed
added core scripts
1 parent eebd734 commit 22280f8

File tree

9 files changed

+435
-6
lines changed

9 files changed

+435
-6
lines changed

Gemfile.lock

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
GEM
2+
remote: http://rubygems.org/
3+
specs:
4+
diff-lcs (1.1.2)
5+
git (1.2.5)
6+
jeweler (1.5.2)
7+
bundler (~> 1.0.0)
8+
git (>= 1.2.5)
9+
rake
10+
rake (0.8.7)
11+
rcov (0.9.9)
12+
reek (1.2.8)
13+
ruby2ruby (~> 1.2)
14+
ruby_parser (~> 2.0)
15+
sexp_processor (~> 3.0)
16+
rspec (2.1.0)
17+
rspec-core (~> 2.1.0)
18+
rspec-expectations (~> 2.1.0)
19+
rspec-mocks (~> 2.1.0)
20+
rspec-core (2.1.0)
21+
rspec-expectations (2.1.0)
22+
diff-lcs (~> 1.1.2)
23+
rspec-mocks (2.1.0)
24+
ruby2ruby (1.2.5)
25+
ruby_parser (~> 2.0)
26+
sexp_processor (~> 3.0)
27+
ruby_parser (2.0.5)
28+
sexp_processor (~> 3.0)
29+
sexp_processor (3.0.5)
30+
31+
PLATFORMS
32+
ruby
33+
34+
DEPENDENCIES
35+
bundler (~> 1.0.0)
36+
jeweler (~> 1.5.1)
37+
rcov
38+
reek (~> 1.2.8)
39+
rspec (~> 2.1.0)

Rakefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ require 'rake'
1212
require 'jeweler'
1313
Jeweler::Tasks.new do |gem|
1414
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15-
gem.name = "crontab-ruby"
16-
gem.homepage = "https://github.com/tt25/crontab-ruby"
15+
gem.name = "crontab-parser"
16+
gem.homepage = "https://github.com/tt25/crontab-parser"
1717
gem.license = "MIT"
1818
gem.summary = %Q{TODO: one-line summary of your gem}
1919
gem.description = %Q{TODO: longer description of your gem}
@@ -51,7 +51,7 @@ Rake::RDocTask.new do |rdoc|
5151
version = File.exist?('VERSION') ? File.read('VERSION') : ""
5252

5353
rdoc.rdoc_dir = 'rdoc'
54-
rdoc.title = "crontab-ruby #{version}"
54+
rdoc.title = "crontab-parser#{version}"
5555
rdoc.rdoc_files.include('README*')
5656
rdoc.rdoc_files.include('lib/**/*.rb')
5757
end

benchmark/test.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# -- coding: utf-8
2+
3+
require File.expand_path(File.dirname(__FILE__) + '/../spec/spec_helper')
4+
require "benchmark"
5+
require "ruby-prof"
6+
7+
crontab = <<-CRON
8+
# should ignore comment only line and blank line
9+
10+
#m h d m w cmd
11+
* * * * * foo # always run. this comment was ignored
12+
3 * * * * bar
13+
*/1 0-22 * * * baz
14+
CRON
15+
crontab *= 64
16+
range = {
17+
0 => 0..59,
18+
1 => 0..23,
19+
2 => 1..31,
20+
3 => 1..12,
21+
4 => 0..6,
22+
}
23+
24+
5000.times{
25+
line = ""
26+
5.times {|n|
27+
ra = range[n].to_a.shuffle
28+
line << case rand(10)
29+
when 0..7
30+
ra.first.to_s
31+
when 8
32+
x,y = [ra.first, ra.last].sort
33+
"#{x}-#{y}"
34+
else
35+
ra.take(rand(ra.length - 1) + 1).sort.join(",")
36+
end
37+
if rand(2) == 1
38+
line << "/" + (rand(range[n].last) + 1).to_s
39+
end
40+
line << " "
41+
}
42+
line << "cmd" + Time.now.to_f.to_s
43+
line << "\n"
44+
crontab += line
45+
}
46+
crontab += "k k k k k"
47+
File.open('foo.txt', 'w'){|f| f.puts crontab}
48+
49+
now = Time.utc(2010,1,1,0,0,0)
50+
c = CrontabParser.new("foo.txt")
51+
52+
GC.disable
53+
RubyProf.start
54+
puts c.find_all{|row| row.times}.length
55+
result = RubyProf.stop
56+
GC.enable
57+
RubyProf::FlatPrinter.new(result).print

crontab-parser.gemspec

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Generated by jeweler
2+
# DO NOT EDIT THIS FILE DIRECTLY
3+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4+
# -*- encoding: utf-8 -*-
5+
6+
Gem::Specification.new do |s|
7+
s.name = %q{crontab-parser}
8+
s.version = "0.1.0"
9+
10+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11+
s.authors = ["uu59"]
12+
s.date = %q{2011-01-08}
13+
s.description = %q{crontab parser for ruby}
14+
s.email = %q{a@tt25.org}
15+
s.extra_rdoc_files = [
16+
"LICENSE.txt",
17+
"README.rdoc"
18+
]
19+
s.files = [
20+
".document",
21+
".rspec",
22+
"Gemfile",
23+
"LICENSE.txt",
24+
"README.rdoc",
25+
"Rakefile",
26+
"VERSION",
27+
"benchmark/test.rb",
28+
"lib/crontab-parser.rb",
29+
"lib/crontab-parser/record.rb",
30+
"lib/crontab-parser/time_parser.rb",
31+
"spec/crontab-ruby_spec.rb",
32+
"spec/spec_helper.rb"
33+
]
34+
s.homepage = %q{https://github.com/tt25/crontab-parser}
35+
s.licenses = ["MIT"]
36+
s.require_paths = ["lib"]
37+
s.rubygems_version = %q{1.3.7}
38+
s.summary = %q{crontab parser for ruby}
39+
s.test_files = [
40+
"spec/crontab-ruby_spec.rb",
41+
"spec/spec_helper.rb"
42+
]
43+
44+
if s.respond_to? :specification_version then
45+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46+
s.specification_version = 3
47+
48+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49+
s.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
50+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
51+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
52+
s.add_development_dependency(%q<rcov>, [">= 0"])
53+
s.add_development_dependency(%q<reek>, ["~> 1.2.8"])
54+
else
55+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
56+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
57+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
58+
s.add_dependency(%q<rcov>, [">= 0"])
59+
s.add_dependency(%q<reek>, ["~> 1.2.8"])
60+
end
61+
else
62+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
63+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
65+
s.add_dependency(%q<rcov>, [">= 0"])
66+
s.add_dependency(%q<reek>, ["~> 1.2.8"])
67+
end
68+
end
69+

lib/crontab-parser.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -- coding: utf-8
2+
3+
require "stringio"
4+
require "crontab-parser/record.rb"
5+
require "crontab-parser/time_parser.rb"
6+
7+
class CrontabParser
8+
include Enumerable
9+
10+
def initialize(crontab, options={})
11+
@crontab = crontab
12+
@options = options
13+
end
14+
15+
def each
16+
io = if File.exists?(@crontab)
17+
open(@crontab, 'r')
18+
else
19+
StringIO.new(@crontab)
20+
end
21+
until io.eof?
22+
line = io.gets
23+
line.strip!
24+
if line.length > 0 && line.index('#') != 0
25+
yield Record.new(line, @options)
26+
end
27+
end
28+
end
29+
end

lib/crontab-parser/record.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -- coding: utf-8
2+
3+
class CrontabParser
4+
class Record
5+
attr_reader :line
6+
7+
def initialize(line, options={})
8+
@line = line
9+
@options = options
10+
end
11+
12+
def cmd
13+
times
14+
@cmd
15+
end
16+
17+
def to_s
18+
@line
19+
end
20+
21+
def should_run?(time)
22+
time.utc
23+
times[:min].include?(time.min) &&
24+
times[:hour].include?(time.hour) &&
25+
times[:day].include?(time.day) &&
26+
times[:month].include?(time.month) &&
27+
times[:week].include?(time.wday)
28+
end
29+
30+
def times
31+
@times ||= begin
32+
base = @line.strip.gsub(/#.*/, "").gsub(%r!^@(yearly|annually|monthly|weekly|daily|midnight|hourly)!){|m|
33+
case $1
34+
when 'yearly','annually'
35+
'0 0 1 1 *'
36+
when 'monthly'
37+
'0 0 1 * *'
38+
when 'weekly'
39+
'0 0 * * 0'
40+
when 'daily','midnight'
41+
'0 0 * * *'
42+
when 'hourly'
43+
'0 * * * *'
44+
end
45+
}.strip
46+
min,hour,day,month,week,@cmd = *base.split(/[\t\s]+/, 6)
47+
base = [min,hour,day,month,week].join(" ")
48+
if week.nil?
49+
if @options[:silent]
50+
return nil
51+
else
52+
raise "invalid line #{@line}"
53+
end
54+
end
55+
{
56+
:month => TimeParser.parse(month, 1, 12),
57+
:day => TimeParser.parse(day, 1, 31),
58+
:hour => TimeParser.parse(hour, 0, 23),
59+
:min => TimeParser.parse(min, 0, 59),
60+
:week => TimeParser.parse(week, 0, 6),
61+
}
62+
end
63+
end
64+
end
65+
end

lib/crontab-parser/time_parser.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# -- coding: utf-8
2+
3+
class CrontabParser
4+
class TimeParser
5+
CACHE = {}
6+
7+
def self.parse(column, first=0, last=59)
8+
base = column + "_#{first}-#{last}"
9+
if CACHE[base]
10+
return CACHE[base]
11+
end
12+
column = column.gsub(%r!/1$!,"").gsub('*', "#{first}-#{last}")
13+
if column.index('/')
14+
times,filter = *column.split("/")
15+
else
16+
times = column
17+
filter = nil
18+
end
19+
20+
result = if times.index(',')
21+
times.split(',').map{|col| separetor(col)}
22+
else
23+
separetor(times)
24+
end.flatten
25+
26+
if filter
27+
result = result.find_all{|n| n % filter.to_i == 0}
28+
end
29+
30+
CACHE[base] = result
31+
end
32+
33+
def self.separetor(col)
34+
if col.index('-')
35+
m,n = *col.split("-").map{|n| n.to_i}
36+
(m..n).to_a
37+
else
38+
[col.to_i]
39+
end
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)