From 07702d9adfb4a3fe5463d391d42ce91f82914811 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 20 Apr 2016 23:27:52 -0500 Subject: [PATCH] More work on building submissions. --- lib/kgrader/assignment.rb | 48 +++++++++++++++++++++++++++++++++----------- lib/kgrader/jail.rb | 17 ++++++++++++---- lib/kgrader/submission.rb | 51 ++++++++++++++++++++++++++++------------------- spec/cs241h | 2 +- 4 files changed, 81 insertions(+), 37 deletions(-) diff --git a/lib/kgrader/assignment.rb b/lib/kgrader/assignment.rb index bf9ec3d..66c227a 100644 --- a/lib/kgrader/assignment.rb +++ b/lib/kgrader/assignment.rb @@ -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 diff --git a/lib/kgrader/jail.rb b/lib/kgrader/jail.rb index 3ee2a43..98207f5 100644 --- a/lib/kgrader/jail.rb +++ b/lib/kgrader/jail.rb @@ -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 diff --git a/lib/kgrader/submission.rb b/lib/kgrader/submission.rb index 2bcfadd..edad216 100644 --- a/lib/kgrader/submission.rb +++ b/lib/kgrader/submission.rb @@ -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, , - # 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 diff --git a/spec/cs241h b/spec/cs241h index 438e509..f9cb0aa 160000 --- a/spec/cs241h +++ b/spec/cs241h @@ -1 +1 @@ -Subproject commit 438e509e4c9097894f275dd66a5ae37bbcb62c24 +Subproject commit f9cb0aabbe48368ef7a8db6c43e7d81e71d2c4fa