A code autograder for student homework submissions
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

98 lignes
2.4 KiB

  1. require 'io/console'
  2. require 'nokogiri'
  3. require 'open3'
  4. require 'shellwords'
  5. module KGrader::Backend
  6. class SVN
  7. def initialize(filesystem, course, config)
  8. @fs = filesystem
  9. @course = course
  10. @config = config
  11. @password = nil
  12. end
  13. def prepare(semester, assignment)
  14. return unless @config['verify']
  15. url = @config['verify'] % {
  16. :semester => semester,
  17. :assignment => assignment
  18. }
  19. unless test_okay url
  20. print "svn: password: "
  21. @password = STDIN.noecho(&:gets).chomp
  22. puts
  23. unless test_okay url
  24. raise KGrader::SVNError, "bad password or other network issues"
  25. end
  26. end
  27. end
  28. def revision(repo)
  29. xml = Nokogiri::XML run('log', '--xml', '-l', '1', repo).first
  30. xml.css('logentry').attr('revision').value.to_i
  31. end
  32. def clone(repo, semester, assignment, student)
  33. url = get_url semester, assignment, student
  34. run 'checkout', '--ignore-externals', url, repo
  35. end
  36. def update(repo, revision = nil)
  37. args = 'update', '--ignore-externals', '--accept', 'tf'
  38. args.push "-r#{revision}" unless revision.nil?
  39. run *args, repo
  40. end
  41. def log(repo)
  42. xml = Nokogiri::XML run('log', '--xml', repo).first
  43. xml.css('logentry').map do |elem|
  44. { :rev => elem.attr('revision').to_i,
  45. :date => Time.parse(elem.css('date').text) }
  46. end
  47. end
  48. def commit(repo, message, *paths)
  49. Dir.chdir(repo) do
  50. run 'add', *paths
  51. run 'commit', '-m', message, *paths
  52. end
  53. end
  54. def commit_date(repo)
  55. xml = Nokogiri::XML run('log', '--xml', '-l', '1', repo).first
  56. Time.parse xml.css('logentry date').text
  57. end
  58. private
  59. def run(*cmd)
  60. if @password
  61. temp = '.svn_temp_' + rand(1000000000).to_s
  62. begin
  63. File.write temp, @password
  64. Open3.capture2e("cat #{temp} | xargs svn #{cmd.shelljoin} --password")
  65. ensure
  66. File.unlink temp
  67. end
  68. else
  69. Open3.capture2e('svn', *cmd)
  70. end
  71. end
  72. def get_url(semester, assignment, student)
  73. @config['url'] % {
  74. :semester => semester,
  75. :assignment => assignment,
  76. :student => student
  77. }
  78. end
  79. def test_okay(url)
  80. status = run('list', '--non-interactive', url)[1]
  81. status.exited? && status.exitstatus == 0
  82. end
  83. end
  84. end