pintoscheck 0.1.0beta
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ptschk +19 -0
- data/lib/pintoscheck.rb +83 -0
- data/lib/pintoscheck/file_unzipper.rb +25 -0
- data/lib/pintoscheck/mail_checker.rb +111 -0
- data/lib/pintoscheck/pintos_runner.rb +39 -0
- data/lib/pintoscheck/pintoscheck_config.rb +46 -0
- data/tests/test_file_unzipper.rb +40 -0
- data/tests/test_mail_checker.rb +44 -0
- data/tests/test_pintos_runner.rb +24 -0
- metadata +80 -0
data/bin/ptschk
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Pintos Check program
|
3
|
+
# http://github.com/ChrisKXu/PintosCheck
|
4
|
+
# Written by Christopher Xu
|
5
|
+
|
6
|
+
require 'pintoscheck'
|
7
|
+
|
8
|
+
case ARGV[0]
|
9
|
+
when '--help' || '--usage'
|
10
|
+
help
|
11
|
+
when 'init'
|
12
|
+
init ARGV[1]
|
13
|
+
when 'run'
|
14
|
+
run ARGV[1]
|
15
|
+
when '--version' || '-v'
|
16
|
+
version
|
17
|
+
else
|
18
|
+
help
|
19
|
+
end
|
data/lib/pintoscheck.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'pintoscheck/pintoscheck_config'
|
6
|
+
require 'pintoscheck/mail_checker'
|
7
|
+
require 'pintoscheck/file_unzipper'
|
8
|
+
require 'pintoscheck/pintos_runner'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'pathname'
|
11
|
+
|
12
|
+
PTSCHK_VERSION = '0.1.0beta'
|
13
|
+
|
14
|
+
def version
|
15
|
+
puts PTSCHK_VERSION
|
16
|
+
end
|
17
|
+
|
18
|
+
def help
|
19
|
+
puts "PintosCheck -- Automatic pintos checker"
|
20
|
+
puts "Version: " + PTSCHK_VERSION
|
21
|
+
puts "Generic commands: "
|
22
|
+
puts " init <my_config_file.config>\t\t\Generates a default config file"
|
23
|
+
puts " run <my_config_file.config>\t\t\Run the tasks based on the config file"
|
24
|
+
end
|
25
|
+
|
26
|
+
def usage
|
27
|
+
help
|
28
|
+
end
|
29
|
+
|
30
|
+
# Initialize a config script
|
31
|
+
def init(file)
|
32
|
+
if file.nil?
|
33
|
+
puts 'Please specify the file name.'
|
34
|
+
help
|
35
|
+
else
|
36
|
+
PintosCheckConfig.default_config.save_to(file)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Run tasks according to the config script
|
41
|
+
def run(file)
|
42
|
+
if file.nil?
|
43
|
+
puts 'Please specify the file name.'
|
44
|
+
help
|
45
|
+
else
|
46
|
+
# Preparing ...
|
47
|
+
printf 'Reading configurations ... '
|
48
|
+
config = PintosCheckConfig.load_from(file)
|
49
|
+
puts 'done.'
|
50
|
+
|
51
|
+
# Fetch mail
|
52
|
+
printf 'Fetching mail meta-data ... '
|
53
|
+
mail_checker = MailChecker.new :host => config.host, :port => config.port, :ssl => config.ssl, :mailaddr => config.mailaddr, :username => config.username, :password => config.password
|
54
|
+
msgs = mail_checker.check_mail :mailbox => config.mailbox, :subject => config.search_options[:subject], :sender => config.search_options[:sender], :recipient => config.search_options[:recipient]
|
55
|
+
puts "got #{msgs.count} messages, done."
|
56
|
+
printf 'Fetching mail attachments ... '
|
57
|
+
files = mail_checker.fetch_attachments config.stage_path
|
58
|
+
puts "done. Attachments saved to #{config.stage_path}"
|
59
|
+
|
60
|
+
files.each do |f|
|
61
|
+
# Unzip files
|
62
|
+
rf = Pathname.new(f).relative_path_from(Pathname.new(config.stage_path))
|
63
|
+
dname = config.stage_path + '/'+ rf + '_test'
|
64
|
+
if !File.exist?(dname)
|
65
|
+
FileUtils.mkdir_p(dname)
|
66
|
+
end
|
67
|
+
printf "Unzipping #{rf} to #{dname} ... "
|
68
|
+
FileUnzipper.unzip(f, dname)
|
69
|
+
puts 'done.'
|
70
|
+
|
71
|
+
# Run test
|
72
|
+
printf "Running tests, please wait ... "
|
73
|
+
if !File.exist?(config.results_path)
|
74
|
+
FileUtils.mkdir_p(config.results_path)
|
75
|
+
end
|
76
|
+
runner = PintosRunner.new(dname, config.test_dir, config.results_path + '/result_' + rf + '_test.txt')
|
77
|
+
runner.validate_path
|
78
|
+
runner.run_tests
|
79
|
+
puts "done."
|
80
|
+
puts "Results saved to #{config.results_path + '/result_' + rf + '_test.txt'}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
class FileUnzipper
|
8
|
+
|
9
|
+
SUPPORTED_FORMATS = %w[ .zip .tgz .gz .bz2 ]
|
10
|
+
|
11
|
+
def self.unzip(from, path)
|
12
|
+
ext = File.extname(from)
|
13
|
+
if File.exist?(from) && SUPPORTED_FORMATS.include?(ext)
|
14
|
+
case ext
|
15
|
+
when '.zip'
|
16
|
+
`unzip #{from} -d #{path}`
|
17
|
+
when '.gz' || '.tar.gz' || '.tgz'
|
18
|
+
`tar zxf #{from} -C #{path}`
|
19
|
+
when '.bz2' || '.tar.bz2'
|
20
|
+
`tar jxf #{from} -C #{path}`
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'net/imap'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
# This class checks certain mailbox for special kind of mail messages
|
9
|
+
# It uses IMAP protocol
|
10
|
+
class MailChecker
|
11
|
+
attr_accessor :host, :port, :ssl, :mailaddr, :username, :password
|
12
|
+
|
13
|
+
# ctor
|
14
|
+
def initialize(options = {})
|
15
|
+
self.host = options[:host] # The imap server, e.g. mail.google.com
|
16
|
+
self.port = options[:port] || 143 # The port number, defaults to 143
|
17
|
+
self.ssl = options[:ssl] || false # Whether to use ssl
|
18
|
+
self.mailaddr = options[:mailaddr] # The email address, e.g. chriskxu@chriskxu.com
|
19
|
+
self.username = options[:username] # The username to access the email
|
20
|
+
self.password = options[:password] # The password to access the email
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a list of message numbers to investigate
|
24
|
+
def check_mail(options = {})
|
25
|
+
@mailbox = options[:mailbox] || "inbox" # Defaults to inbox
|
26
|
+
# regex = options[:regex] # The subject pattern to match
|
27
|
+
@subject = options[:subject] # The keyword in the subject to search
|
28
|
+
@recipient = options[:recipient] || self.mailaddr # The recipient to match, a string or a list of strings
|
29
|
+
@sender = options[:sender] # The sender to match, a string or a list of strings
|
30
|
+
@ret = [] # an array of message numbers
|
31
|
+
|
32
|
+
t = Thread.new do
|
33
|
+
# Now we check the email based on the parameters
|
34
|
+
imap = Net::IMAP.new(self.host, self.port, self.ssl)
|
35
|
+
imap.login(self.username, self.password)
|
36
|
+
|
37
|
+
imap.examine(@mailbox)
|
38
|
+
|
39
|
+
if !@subject.nil?
|
40
|
+
if @subject.class != Array # subject is NOT an array
|
41
|
+
@subject = [@subject]
|
42
|
+
end
|
43
|
+
@subject.each do |s|
|
44
|
+
@ret = imap.search(["SUBJECT", s])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if @recipient.class != Array # recipient is NOT an array
|
49
|
+
@recipient = [@recipient]
|
50
|
+
end
|
51
|
+
@recipient.each do |r|
|
52
|
+
@ret &= imap.search(["TO", r])
|
53
|
+
end
|
54
|
+
|
55
|
+
if !@sender.nil?
|
56
|
+
if @sender.class != Array # sender is NOT an array
|
57
|
+
@sender = [@sender]
|
58
|
+
end
|
59
|
+
@sender.each do |s|
|
60
|
+
@ret &= imap.search(["FROM", s])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
imap.logout
|
65
|
+
#imap.close
|
66
|
+
end
|
67
|
+
|
68
|
+
t.join
|
69
|
+
@ret = @ret.uniq
|
70
|
+
end
|
71
|
+
|
72
|
+
def fetch_attachments(path)
|
73
|
+
imap = Net::IMAP.new(self.host, self.port, self.ssl)
|
74
|
+
imap.login(self.username, self.password)
|
75
|
+
files = []
|
76
|
+
|
77
|
+
imap.examine(@mailbox)
|
78
|
+
t = Thread.new do
|
79
|
+
@ret.each do |mail|
|
80
|
+
message = imap.fetch(mail, ["BODY", "ENVELOPE"])[0]
|
81
|
+
body = message.attr["BODY"]
|
82
|
+
sender = message.attr["ENVELOPE"].sender[0]
|
83
|
+
i = 1
|
84
|
+
while body.parts[i] != nil && body.parts[i].media_type == "TEXT"
|
85
|
+
i += 1
|
86
|
+
end
|
87
|
+
while body.parts[i] != nil
|
88
|
+
attachment = imap.fetch(mail, "BODY[#{i + 1}]")[0].attr["BODY[#{i + 1}]"]
|
89
|
+
filename = body.parts[i].param["NAME"]
|
90
|
+
# Save the attachment to file
|
91
|
+
if !File.exist?(path)
|
92
|
+
FileUtils.mkdir_p(path)
|
93
|
+
end
|
94
|
+
filename = path + "/#{sender.mailbox}_#{filename}"
|
95
|
+
files << filename
|
96
|
+
file = File.new(filename, 'wb+')
|
97
|
+
file.write(attachment.unpack('m'))
|
98
|
+
file.close
|
99
|
+
i += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
imap.logout
|
104
|
+
end
|
105
|
+
# imap.close
|
106
|
+
|
107
|
+
t.join
|
108
|
+
files
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
class PintosRunner
|
6
|
+
attr_reader :result
|
7
|
+
|
8
|
+
def initialize(root, testpath, resultspath)
|
9
|
+
@root = root
|
10
|
+
@testpath = testpath
|
11
|
+
@resultspath = resultspath
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_path
|
15
|
+
ret = ''
|
16
|
+
if File.exist?("#{@root}/#{@testpath}")
|
17
|
+
ret = "#{@root}/#{@testpath}"
|
18
|
+
elsif File.exist?("#{@root}/src/#{@testpath}")
|
19
|
+
ret = "#{@root}/src/#{@testpath}"
|
20
|
+
elsif File.exist?("#{@root}/pintos/#{@testpath}")
|
21
|
+
ret = "#{@root}/pintos/#{@testpath}"
|
22
|
+
elsif File.exist?("#{@root}/pintos/src/#{@testpath}")
|
23
|
+
ret = "#{@root}/pintos/src/#{@testpath}"
|
24
|
+
end
|
25
|
+
|
26
|
+
@runpath = ret
|
27
|
+
end
|
28
|
+
|
29
|
+
def run_tests
|
30
|
+
t = Thread.new do
|
31
|
+
@result = `cd #{@runpath} && make check 2>/dev/null | tail -n1`
|
32
|
+
end
|
33
|
+
|
34
|
+
t.join
|
35
|
+
`cp #{@runpath}/build/results #{@resultspath} && echo "#{@result}" >> #{@resultspath}`
|
36
|
+
@result
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
class PintosCheckConfig
|
8
|
+
attr_accessor :mailaddr, :mailbox, :username, :password, :host, :port, :ssl, :stage_path, :test_dir, :results_path
|
9
|
+
attr_accessor :search_options
|
10
|
+
|
11
|
+
def self.default_config
|
12
|
+
config = PintosCheckConfig.new do |c|
|
13
|
+
c.mailaddr = 'mail@example.com'
|
14
|
+
c.mailbox = 'inbox'
|
15
|
+
c.username = 'johndoe'
|
16
|
+
c.password = 'secret'
|
17
|
+
c.host = 'imap.gmail.com'
|
18
|
+
c.port = 993
|
19
|
+
c.ssl = true
|
20
|
+
c.stage_path = '/tmp/pintoscheck'
|
21
|
+
c.test_dir = 'threads'
|
22
|
+
c.results_path = '/tmp/pintoscheck/results'
|
23
|
+
c.search_options[:subject] = 'pintos'
|
24
|
+
c.search_options[:sender] = [ 'someone@example.com', 'sometwo@example.com' ]
|
25
|
+
c.search_options[:recipient] = 'somethree@example.com'
|
26
|
+
end
|
27
|
+
|
28
|
+
config
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.load_from(filepath)
|
32
|
+
data = File.new(filepath, 'r').read
|
33
|
+
config = YAML.load(data)
|
34
|
+
end
|
35
|
+
|
36
|
+
def save_to(filepath)
|
37
|
+
save = self.to_yaml
|
38
|
+
File.new(filepath, 'w+').write(save)
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(&block)
|
42
|
+
@search_options = {}
|
43
|
+
yield(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'pintoscheck/file_unzipper'
|
6
|
+
require 'pintoscheck/mail_checker'
|
7
|
+
require 'test/unit'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
class TestFileUnzipper < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@host = 'imap.gmail.com'
|
14
|
+
@username = 'pintoscheck@chriskxu.com'
|
15
|
+
@password = 'pintoscheck'
|
16
|
+
@port = 993
|
17
|
+
@ssl = true
|
18
|
+
|
19
|
+
@mail_checker = MailChecker.new :host => @host, :port => @port, :username => @username, :password => @password, :ssl => @ssl, :mailaddr => @username
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_unzip
|
23
|
+
messages = @mail_checker.check_mail :mailbox => 'inbox', :subject => 'attachment'
|
24
|
+
assert_equal [4], messages
|
25
|
+
|
26
|
+
# Now we fetch the attachments
|
27
|
+
path = '/tmp/pintoscheck'
|
28
|
+
@mail_checker.fetch_attachments(path)
|
29
|
+
assert File.exist?(path)
|
30
|
+
# assert File.exist?(path + '/xuhotdogs@gmail.com_s3-qrc-20060301.pdf')
|
31
|
+
assert File.exist?(path + '/xuhotdogs@gmail.com_ospdf09.zip')
|
32
|
+
|
33
|
+
# Now the FileUnzipper comes in
|
34
|
+
FileUtils.mkdir_p(path + '/xuhotdogs@gmail.com_ospdf09')
|
35
|
+
FileUnzipper.unzip(path + '/xuhotdogs@gmail.com_ospdf09.zip', path + '/xuhotdogs@gmail.com_ospdf09')
|
36
|
+
assert File.exist?(path + '/xuhotdogs@gmail.com_ospdf09/ospdf09')
|
37
|
+
assert File.exist?(path + '/xuhotdogs@gmail.com_ospdf09/ospdf09/09_0.pdf')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'pintoscheck/mail_checker'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class TestMailChecker < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@host = 'imap.gmail.com'
|
11
|
+
@username = 'pintoscheck@chriskxu.com'
|
12
|
+
@password = 'pintoscheck'
|
13
|
+
@port = 993
|
14
|
+
@ssl = true
|
15
|
+
|
16
|
+
@mail_checker = MailChecker.new :host => @host, :port => @port, :username => @username, :password => @password, :ssl => @ssl, :mailaddr => @username
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize
|
20
|
+
assert_equal @host, @mail_checker.host
|
21
|
+
assert_equal @username, @mail_checker.username
|
22
|
+
assert_equal @password, @mail_checker.password
|
23
|
+
assert_equal @port, @mail_checker.port
|
24
|
+
assert_equal @username, @mail_checker.mailaddr
|
25
|
+
assert_equal @ssl, @mail_checker.ssl
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_check_mail
|
29
|
+
result1 = @mail_checker.check_mail :mailbox => 'inbox', :subject => 'gmail'
|
30
|
+
assert_equal [1, 2], result1
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_fetch_attachments
|
34
|
+
messages = @mail_checker.check_mail :mailbox => 'inbox', :subject => 'attachments'
|
35
|
+
assert_equal [3], messages
|
36
|
+
|
37
|
+
# Now we fetch the attachments
|
38
|
+
path = '/tmp/pintoscheck'
|
39
|
+
@mail_checker.fetch_attachments(path)
|
40
|
+
assert File.exist?(path)
|
41
|
+
assert File.exist?(path + '/xuhotdogs@gmail.com_s3-qrc-20060301.pdf')
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Pintos Check program
|
2
|
+
# http://github.com/ChrisKXu/PintosCheck
|
3
|
+
# Written by Christopher Xu
|
4
|
+
|
5
|
+
require 'pintoscheck/pintos_runner'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class TestPintosRunner < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@runner = PintosRunner.new '/tmp/pintos', 'threads', '/tmp/pintoscheck/results'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_validate_path
|
15
|
+
assert_equal '/tmp/pintos/threads', @runner.validate_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_run_tests
|
19
|
+
@runner.validate_path
|
20
|
+
result = @runner.run_tests
|
21
|
+
assert File.exist?('/tmp/pintoscheck/results')
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pintoscheck
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0beta
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christopher Xu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-05-05 00:00:00 +08:00
|
13
|
+
default_executable: ptschk
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: |
|
17
|
+
== PintosCheck -- Auto Pintos Checker to Save the Day ==
|
18
|
+
|
19
|
+
== Functionalities ==
|
20
|
+
The functionality of this simple script is to download pintos homework assignments from the mail inbox and then run through all the desired tests and finally generate reports in plain text or html formats, all automatically.
|
21
|
+
|
22
|
+
== Requirements For Running PintosCheck ==
|
23
|
+
Since all the scripts are written in ruby, PintosCheck require ruby installed on the system. I use ruby 1.8.7 for development, but ruby 1.9.* versions are expected to function as well. However, ruby 1.8.6 and lower versions are not supported. For information of downloading and installing ruby, see http://www.ruby-lang.org/en/downloads/.
|
24
|
+
In addition to ruby itself, RubyGems 1.3.* is also required because it hosts the installation source for this project and almost all other ruby projects as well. To download or update RubyGems, please go to http://gemcutter.org/pages/download for more information.
|
25
|
+
|
26
|
+
== Installation ==
|
27
|
+
Once you have all the requirements on your system, it's really easy to install PintosCheck. In the UNIX shell or Windows command line environment, type the following command(sudo if needed):
|
28
|
+
gem install pintoscheck --include-dependencies
|
29
|
+
Go grab a cup of coffee, and PintosCheck will automatically download and install itself onto the system.
|
30
|
+
To check the installation, type 'ptschk --version', and if something like 'PintosCheck 0.1.0' pops up then you're green to go!
|
31
|
+
|
32
|
+
== Finally, how do I check my students' pintos homework? ==
|
33
|
+
This project ships with a 'ptschk' command tool. This tool needs a task configuration file to actually do everything. The configuration file is in YAML format, which is basically a recursive key-value pair representation. If you're using PintosCheck for the first time, there's a very nice command line option to generate the skeleton for you. Just run 'ptschk init my_first_task.config' and a file named 'my_first_task.config' will be generated for you. Inside this file there is a set of the minimal options for the task to run properly, and you just have to fill in what you need. After you set up your configuration file, run 'ptschk run my_first_task.config' and the tasks will kick off immediately, and after a while the report will be generated. A detailed configuration options for advanced task setup will be available in production release of this project.
|
34
|
+
|
35
|
+
email: XuHotdogs@gmail.com
|
36
|
+
executables:
|
37
|
+
- ptschk
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- lib/pintoscheck/file_unzipper.rb
|
44
|
+
- lib/pintoscheck/mail_checker.rb
|
45
|
+
- lib/pintoscheck/pintos_runner.rb
|
46
|
+
- lib/pintoscheck/pintoscheck_config.rb
|
47
|
+
- lib/pintoscheck.rb
|
48
|
+
- bin/ptschk
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/ChrisKXu/pintoscheck
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.1
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Auto Pintos Checker to Save the Day
|
77
|
+
test_files:
|
78
|
+
- tests/test_file_unzipper.rb
|
79
|
+
- tests/test_mail_checker.rb
|
80
|
+
- tests/test_pintos_runner.rb
|