@@ -9,7 +9,9 @@ module KGrader | |||
@root = @fs.assignment @course.name, @name | |||
@config = @fs.load @fs.assignment_config(@course.name, @name) | |||
@manifest = build_manifest | |||
verify_config | |||
@manifest = get_manifest | |||
rescue FilesystemError | |||
raise AssignmentError, "unknown assignment: #{name}" | |||
end | |||
@@ -18,22 +20,44 @@ module KGrader | |||
@config['id'] || @name | |||
end | |||
def build_manifest | |||
unless @config.include? 'manifest' | |||
raise AssignmentError, "missing manifest: #{@name}" | |||
def build_steps | |||
@config['build'] | |||
end | |||
def tests | |||
@config['grade'] | |||
end | |||
def report | |||
@config['commit']['report'] || "report.txt" | |||
end | |||
def commit_message(student) | |||
default = "adding grade report for #{name}: {student}" | |||
template = @config['commit']['message'].clone || default | |||
template['{student}'] = student | |||
template | |||
end | |||
private | |||
def verify_config | |||
%w(stage build grade).each do |key| | |||
unless @config.include? key | |||
raise AssignmentError, "missing #{key} section in config: #{@name}" | |||
end | |||
end | |||
end | |||
def get_manifest | |||
stage = @config['stage'] | |||
raise AssignmentError, "chroot is not supported yet" if stage['chroot'] | |||
manifest = @config['manifest'] | |||
provided = manifest['provided'].map do |fn| | |||
provided = stage['provided'].map do |fn| | |||
{ :name => fn, :path => File.join(@root, 'provided', fn) } | |||
end | |||
graded = manifest['graded'].map { |fn| { :name => fn } } | |||
graded = stage['graded'].map { |fn| { :name => fn } } | |||
{ | |||
:provided => provided, | |||
:graded => graded, | |||
:report => manifest['report'] | |||
} | |||
{ :provided => provided, :graded => graded } | |||
end | |||
end | |||
end |
@@ -5,16 +5,25 @@ module KGrader | |||
@root = root | |||
end | |||
def reset | |||
FileUtils.rm_rf @root | |||
end | |||
def init | |||
FileUtils.mkdir_p @root | |||
end | |||
def reset | |||
FileUtils.rm_rf @root | |||
def stage(source, target) | |||
FileUtils.cp source, File.join(@root, target) | |||
end | |||
def stage(source, target) | |||
puts "[chroot::stage] #{source} -> (jail)/#{target}" | |||
def exec(command) | |||
pid = Process.fork do | |||
Dir.chdir @root | |||
# TODO: rlimit in exec, umask? | |||
Process.exec command | |||
end | |||
Process.waitpid pid, 0 | |||
end | |||
end | |||
end |
@@ -48,30 +48,24 @@ module KGrader | |||
end | |||
def grade | |||
# TODO: | |||
# self.status = :ungraded | |||
self.status = :ungraded | |||
stage | |||
# [grade the stuff] | |||
# [save report to gradefile] | |||
# @fs.jail.reset | |||
# FileUtils.touch pendingfile | |||
# self.status = :graded | |||
# return grade summary string | |||
sleep rand / 2 | |||
'100%' | |||
build | |||
test | |||
save | |||
# self.status = :graded # UNCOMMENT | |||
# @fs.jail.reset # UNCOMMENT | |||
# TODO: return grade summary string | |||
end | |||
def commit | |||
# TODO: | |||
# if status == :graded && File.exists? pendingfile | |||
# [copy gradefile to repo] | |||
# @course.backend.commit repo, <message>, <gradefile path> | |||
# FileUtils.rm pendingfile | |||
# end | |||
sleep rand / 2 | |||
nil | |||
if status == :graded && File.exists?(pendingfile) | |||
target = File.join(repo, @assignment.report) | |||
message = @assignment.commit_message @student | |||
FileUtils.cp gradefile, target | |||
@course.backend.commit repo, message, target | |||
FileUtils.rm pendingfile | |||
end | |||
end | |||
private | |||
@@ -118,5 +112,22 @@ module KGrader | |||
@fs.jail.stage File.join(repo, entry[:name]), entry[:name] | |||
end | |||
end | |||
def build | |||
@assignment.build_steps.each do |command| | |||
@fs.jail.exec command | |||
end | |||
end | |||
def test | |||
@assignment.tests.each do |script| | |||
# TODO: execute script in jail | |||
end | |||
end | |||
def save | |||
# TODO: save gradefile | |||
FileUtils.touch pendingfile | |||
end | |||
end | |||
end |
@@ -1 +1 @@ | |||
Subproject commit 438e509e4c9097894f275dd66a5ae37bbcb62c24 | |||
Subproject commit f9cb0aabbe48368ef7a8db6c43e7d81e71d2c4fa |