reviser 0.0.1.1.pre.beta → 0.0.2.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +18 -0
  3. data/README.md +46 -0
  4. data/ext/valgrind.rb +21 -18
  5. data/ext/web_validators.rb +132 -0
  6. data/lang/HTML.yml +2 -14
  7. data/lib/component.rb +41 -39
  8. data/lib/components/archiver.rb +105 -101
  9. data/lib/components/checker.rb +46 -52
  10. data/lib/components/extractors.rb +121 -120
  11. data/lib/components/generator.rb +40 -37
  12. data/lib/components/generators.rb +113 -109
  13. data/lib/components/organiser.rb +165 -153
  14. data/lib/config.rb +53 -35
  15. data/lib/criteria/code_analysis.rb +54 -0
  16. data/lib/criteria/compilation.rb +42 -0
  17. data/lib/criteria/execution.rb +78 -0
  18. data/lib/exec.rb +109 -94
  19. data/lib/helpers/criteria.rb +152 -154
  20. data/lib/helpers/git.rb +23 -21
  21. data/lib/helpers/project.rb +198 -19
  22. data/lib/helpers/system.rb +50 -39
  23. data/lib/loggers/logger.rb +39 -30
  24. data/lib/loggers/modes.rb +118 -54
  25. data/lib/reviser.rb +63 -41
  26. data/res/css/style_logs.css +166 -0
  27. data/res/css/web_validators/css-base.css +733 -0
  28. data/res/css/web_validators/css-results.css +257 -0
  29. data/res/css/web_validators/html-base.css +746 -0
  30. data/res/css/web_validators/html-results.css +489 -0
  31. data/res/labys/labfich11.txt +19 -0
  32. data/res/labys/test.txt +3 -0
  33. data/res/labys/yoda.txt +19 -0
  34. data/res/scss/style_logs.scss +134 -0
  35. data/type/JavaProject.yml +18 -0
  36. data/type/Pendu.yml +22 -0
  37. data/type/Web.yml +23 -0
  38. metadata +144 -10
  39. data/ext/html_validator.rb +0 -21
  40. data/lib/helpers/code_analysis.rb +0 -64
  41. data/lib/helpers/compilation.rb +0 -40
  42. data/lib/helpers/execution.rb +0 -83
  43. data/lib/project.rb +0 -155
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ad369beae7c279013559eaca2a371be84de43a0
4
- data.tar.gz: d08c27df554743428484267bf53872053bf75fb0
3
+ metadata.gz: eb2455e95c3f150c2af8cb0e01b481ce485bb948
4
+ data.tar.gz: 12663cbeb09dadc6df0f608da12dc4fd28bdb1e4
5
5
  SHA512:
6
- metadata.gz: 27115ae008fd154acc4e3c0ff6ee9b7cb0da06578634d78f14817b790a3a2bf1e30ba4c376f2d90f9e8becabeccf9bc3882f64cdea7c559ee44764877a5a3181
7
- data.tar.gz: fda1bc73fb4ff4bb9d90e9a005554dab160601a9cef5a6eb8c8ed2768a9e2ea35452862b5ec9102b84c8ab25ab8f005aca23c6a1db1e3812e33ebc54926e09ee
6
+ metadata.gz: f6540ffb673966602d288d9799589ec50ba082d500e93f354e0b8b3bdf0da505ed497105fa76ce79486249d25fa7bd9716093d38926c45c44f680fe262dcd2dd
7
+ data.tar.gz: c0e78b08ca268ad9a465d10cc4de75d597fb55b0381999015d1c30c90104dd58ceae9efb134bab017f2313a588c75fa134955d478832d5c31845b84f3dffb483
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # String.scrub for ruby 1.9.x
6
+ gem 'scrub_rb' unless RUBY_VERSION.split('.')[0] == '2'
7
+
8
+ gem 'rubyzip', '~> 1.1.6'
9
+ #gem 'seven_zip_ruby', '~> 1.2.4'
10
+ #gem 'yard', '~> 0.8.7.6'
11
+ #gem 'redcarpet', '~> 3.2.2'
12
+ gem 'spreadsheet', '~> 1.0.1'
13
+ gem 'ruby-ole', '>= 1.0'
14
+ gem 'rake', '~> 10.4.2'
15
+ gem 'thor', '~> 0.19.1'
16
+ gem 'git', '~> 1.2.9.1'
17
+ gem 'rest-client', '~> 1.7.3'
18
+ gem 'colorize', '~> 0.7.5'
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ Reviser
2
+ ====================
3
+
4
+ Description
5
+ ---------------
6
+ [Reviser](https://rubygems.org/gems/reviser) is a semi-automatic tool for student's projects evaluation, written in Ruby.
7
+
8
+ Installation
9
+ ---------------
10
+
11
+ ###Gem Installation
12
+
13
+ Download and install the gem with the following command line.
14
+
15
+ gem install reviser
16
+
17
+
18
+ ###Usage
19
+
20
+ To create a new workspace, run this following:
21
+
22
+ reviser init
23
+
24
+ After this, edit the config.yml file generated by reviser. You maybe have to create a type project config file too.
25
+
26
+ To launch a complete cycle of analysis, run:
27
+
28
+ reviser work
29
+
30
+ Team
31
+ ----
32
+ [Anthony Cerf]()
33
+
34
+ [Yann Prono](https://github.com/mcdostone)
35
+
36
+ [Romain Ruez]()
37
+
38
+ [Renan Strauss](https://github.com/renan-)
39
+
40
+
41
+ Other stuff
42
+ -------------
43
+
44
+ |Question | Answer |
45
+ | ------------- | ------------------------------ |
46
+ | Requires | Ruby 2.0.0 or later |
data/ext/valgrind.rb CHANGED
@@ -1,24 +1,27 @@
1
- module Extensions
2
- module Valgrind
1
+ module Reviser
2
+ module Extensions
3
+ module Valgrind
3
4
 
4
- include Helpers::Execution
5
- include Helpers::System
5
+ include Helpers::System
6
6
 
7
- VALGRIND_FILE = "valgrind.txt"
7
+ VALGRIND_FILE = "valgrind.txt"
8
8
 
9
- #
10
- # Check memory leaks of the program
11
- # The module uses execution value written in the config file of the project
12
- #
13
- def memleaks
14
- executable = find_executable
15
- program = "#{Cfg[:program_prefix]}#{executable}"
16
- param = Cfg.has_key?(:execution_value) ? Cfg[:execution_value].first : ''
17
- cmd = "valgrind --leak-check=full --track-origins=yes --show-reachable=yes #{program} #{param}"
18
- out = exec_with_timeout cmd
19
- File.open(VALGRIND_FILE, 'w') { |f| f.write "$ #{cmd}\r#{out[:stdout]}\r#{out[:stderr]}" }
20
- File.join(FileUtils.pwd, VALGRIND_FILE)
21
- end
9
+ #
10
+ # Check memory leaks of the program
11
+ # The module uses execution value written in the config file of the project
12
+ #
13
+ # Yann, execution_count shall be taken in count imo
14
+ #
15
+ def memleaks
16
+ executable = find_executable
17
+ program = "#{Cfg[:program_prefix]}#{executable}"
18
+ param = Cfg.has_key?(:execution_value) ? Cfg[:execution_value].first : ''
19
+ cmd = "valgrind --leak-check=full --track-origins=yes --show-reachable=yes #{program} #{param}"
20
+ out = exec_with_timeout cmd
21
+ File.open(VALGRIND_FILE, 'w') { |f| f.write "$ #{cmd}\r#{out[:stdout]}\r#{out[:stderr]}" }
22
+ File.join(FileUtils.pwd, VALGRIND_FILE)
23
+ end
22
24
 
25
+ end
23
26
  end
24
27
  end
@@ -0,0 +1,132 @@
1
+ #
2
+ # @author Renan Strauss
3
+ #
4
+ # A tool to validate what we call web languages,
5
+ # in other words languages that can't be analysed
6
+ # by compilation nor by execution
7
+ # It's very simple at that point, but feel free to
8
+ # make the extension better :-)
9
+ #
10
+ require 'rest_client'
11
+
12
+ module Reviser
13
+ module Extensions
14
+ module WebValidators
15
+ include Helpers::Project
16
+
17
+ def validate_web
18
+ { html: validate(:html), css: validate(:css) }
19
+ end
20
+
21
+ def validate_html
22
+ validate :html
23
+ end
24
+
25
+ def validate_css
26
+ validate :css
27
+ end
28
+
29
+ private
30
+
31
+ #
32
+ # @returns a hash matching all files for this lang to a resultset
33
+ #
34
+ def validate lang
35
+ results = {}
36
+
37
+ files = sources.select { |s| File.extname(s) == ".#{lang}" }
38
+ files.each do |f|
39
+ response = W3C::validate(lang, f)
40
+
41
+ if response.is_a?(Hash) && response.has_key?(:exception)
42
+ results[f] = { :status => response[:exception].to_s }
43
+ else
44
+ results[f] = {
45
+ :status => response.headers.has_key?(:x_w3c_validator_status) && response.headers[:x_w3c_validator_status] || 'Not available',
46
+ :errors => response.headers.has_key?(:x_w3c_validator_errors) && response.headers[:x_w3c_validator_errors] || 'Not available',
47
+ :warnings => response.headers.has_key?(:x_w3c_validator_warnings) && response.headers[:x_w3c_validator_warnings] || 'Not available'
48
+ }
49
+ end
50
+
51
+ puts "\t\t#{f} => #{results[f][:status]}"
52
+
53
+ #
54
+ # Generate a file
55
+ # Simply add 'web_validators_save_results: true'
56
+ # in your project's type config file
57
+ #
58
+ Cfg[:web_validators_save_results] ||= false
59
+
60
+ #
61
+ # We generate only if config key is set and
62
+ # response is not a raw string
63
+ #
64
+ if Cfg[:web_validators_save_results] and not response.headers.empty?
65
+ body = response.to_str
66
+ #
67
+ # W3C uses scss so we need to replace imports by the
68
+ # actual css...
69
+ #
70
+ case lang
71
+ when :html
72
+ body.sub! '@import "./style/base";', File.read(Cfg::resource 'css/web_validators/html-base.css')
73
+ body.sub! '@import "./style/results";', File.read(Cfg::resource 'css/web_validators/html-results.css')
74
+ when :css
75
+ body.sub! 'style/base.css', Cfg::resource('css/web_validators/css-base.css').to_path
76
+ body.sub! 'style/results.css', Cfg::resource('css/web_validators/css-results.css').to_path
77
+
78
+ body.sub! 'file://localhost/TextArea', f
79
+ end
80
+
81
+ File.open(f + '.WEB_VALIDATORS.html', 'w') { |x| x.write body }
82
+ end
83
+ end
84
+
85
+ results
86
+ end
87
+
88
+ #
89
+ # This class is wrapping up
90
+ # W3C API
91
+ #
92
+ class W3C
93
+ VALIDATORS = {
94
+ :html => 'validator.w3.org/check',
95
+ :css => 'jigsaw.w3.org/css-validator/validator'
96
+ }
97
+
98
+ #
99
+ # @returns responses from the request made to the validator
100
+ #
101
+ def self::validate lang, file
102
+ raise ArgumentError unless VALIDATORS.include? lang
103
+ #
104
+ # W3C is a free service and we shall not overflow it
105
+ # with our requests so accordingly to their doc,
106
+ # we sleep 1s between each request
107
+ #
108
+ sleep 1
109
+ begin
110
+ send lang, file
111
+ rescue => e
112
+ { exception: e }
113
+ end
114
+ end
115
+
116
+ #
117
+ # W3C HTML Validator API expects a POST uploaded_file
118
+ #
119
+ def self::html file
120
+ RestClient.post(VALIDATORS[:html], :uploaded_file => File.new(file))
121
+ end
122
+
123
+ #
124
+ # Whereas W3C CSS Validator API doesn't accept uploaded
125
+ # files, so we need to pass the raw text
126
+ def self::css file
127
+ RestClient.get(VALIDATORS[:css] + '?text=' + CGI.escape(File.read(file)))
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
data/lang/HTML.yml CHANGED
@@ -21,8 +21,7 @@ compiled: false
21
21
  # the html_validator extension
22
22
  #
23
23
  extensions:
24
- html_validator:
25
- :valid: Validite HTML 5
24
+ validate_html: Validite HTML 5
26
25
 
27
26
  # Program prefix, needed especially for C
28
27
  # The execution command will look like this :
@@ -35,15 +34,4 @@ extensions:
35
34
 
36
35
  # If not specified, the first
37
36
  # executable file found will be executed
38
- # program_name: main.rb
39
-
40
- regex_comments: !ruby/regexp '/#([^{].*)$/'
41
-
42
- criteria:
43
- - all_files
44
- - src_files
45
- - lines_count
46
- - comments_count
47
-
48
- extensions:
49
- - validate_html
37
+ # program_name: main.rb
data/lib/component.rb CHANGED
@@ -4,50 +4,52 @@
4
4
  require 'yaml'
5
5
  require_relative 'loggers/logger'
6
6
 
7
- class Component
8
-
9
- # Each component has a logger (currently a txt file)
10
- # $logger
7
+ module Reviser
8
+ class Component
9
+
10
+ # Each component has a logger (currently a txt file)
11
+ # $logger
11
12
 
12
- #
13
- # Don't forget to call super in your component's initializer !
14
- # This method is all about : it stores the data from another
15
- # component accordingly to what you told to Reviser, and
16
- # creates a hash for child to easily access config file values
17
- #
18
- def initialize(data = nil)
19
- @data = data
20
- ext = options.has_key?(:log_mode) && options[:log_mode] || 'txt'
21
- log_file = File.join(options.has_key?(:log_dir) && options[:log_dir] || '.', "#{ self.class.name.split('::').last || ''}.#{ext}")
13
+ #
14
+ # Don't forget to call super in your component's initializer !
15
+ # This method is all about : it stores the data from another
16
+ # component accordingly to what you told to Reviser, and
17
+ # creates a hash for child to easily access config file values
18
+ #
19
+ def initialize(data = nil)
20
+ @data = data
21
+ ext = options.has_key?(:log_mode) && options[:log_mode] || 'txt'
22
+ log_file = File.join(options.has_key?(:log_dir) && options[:log_dir] || '.', "#{ self.class.name.split('::').last || ''}.#{ext}")
22
23
 
23
- # For now, we output to stderr if verbose option is not set
24
- # In the future, it would be a good idea to always have logs,
25
- # but to let the user change the level
26
- @logger = Loggers::Logger.new(options[:verbose] && log_file || STDERR)
27
- end
24
+ # For now, we output to stderr if verbose option is not set
25
+ # In the future, it would be a good idea to always have logs,
26
+ # but to let the user change the level
27
+ @logger = Loggers::Logger.new(options[:verbose] && log_file || STDERR)
28
+ end
28
29
 
29
- # Place-holder
30
- # Just like an abstract method
31
- def run
32
- raise NotImplementedError, 'All components must implement a run method'
33
- end
30
+ # Place-holder
31
+ # Just like an abstract method
32
+ def run
33
+ raise NotImplementedError, 'All components must implement a run method'
34
+ end
34
35
 
35
- # Method template
36
- # So that when somebody implements a custom
37
- # Component, he doesn't have to carry about
38
- # logger being closed or not.
39
- # Might be even more useful at some point
40
- def work
41
- data = run
42
- @logger.close
36
+ # Method template
37
+ # So that when somebody implements a custom
38
+ # Component, he doesn't have to carry about
39
+ # logger being closed or not.
40
+ # Might be even more useful at some point
41
+ def work
42
+ data = run
43
+ @logger.close
43
44
 
44
- data
45
- end
45
+ data
46
+ end
46
47
 
47
- protected
48
- #
49
- # @return all options for all components if they exist in config file.
50
- def options
51
- (Cfg.has_key? :options) && Cfg[:options] || { :verbose => false }
48
+ protected
49
+ #
50
+ # @return all options for all components if they exist in config file.
51
+ def options
52
+ (Cfg.has_key? :options) && Cfg[:options] || { :verbose => false }
53
+ end
52
54
  end
53
55
  end
@@ -2,117 +2,121 @@ require 'fileutils'
2
2
  require_relative 'extractors'
3
3
 
4
4
 
5
- module Components
6
-
7
- # Manages uncompression of archive.
8
- # Archiver extracts all data in a given compressed file.
9
- #
10
- # In case of the University of Lorraine,
11
- # the archive contains all computing projects, compressed too.
12
- #
13
- # @example The simple way to extract a compressed file is :
14
- # Archiver.extract(myFile, myDirectory)
15
- #
16
- # @author Yann Prono
17
- #
18
- class Archiver < Component
19
-
20
- # methods for each different archive format
21
- extend Extractors
22
-
23
- # Ignored entries
24
- $rejected = ['.','..']
25
-
26
- # Initialize archive file and the directory of destination.
27
- def initialize(data)
28
- super data
29
- @src = Cfg[:src]
30
- @destination = Cfg[:dest]
31
- @results = []
32
- end
33
-
5
+ module Reviser
6
+ module Components
34
7
 
35
- # Check if the directory destination exists.
36
- # else create it.
37
- # For the moment, if the directory exists // TODO little input to confirm
38
- # @param destination [String] the destination directory
8
+ # Manages uncompression of archive.
9
+ # Archiver extracts all data in a given compressed file.
10
+ #
11
+ # In case of the University of Lorraine,
12
+ # the archive contains all computing projects, compressed too.
13
+ #
14
+ # If you want to add support of archive format, @see Extractors.
15
+ #
16
+ # @example The simple way to extract a compressed file is :
17
+ # Archiver.extract(myFile, myDirectory)
18
+ #
19
+ # @author Yann Prono
39
20
  #
40
- def self.destination?(destination)
41
- unless $rejected.include? File.basename destination
42
- FileUtils.rm_rf(destination) if Dir.exists? destination
43
- FileUtils.mkdir_p destination, :mode => 0700
21
+ class Archiver < Component
22
+
23
+ # methods for each different archive format
24
+ extend Extractors
25
+
26
+ # Ignored entries
27
+ $rejected = ['.','..']
28
+
29
+ # Initializes archive file and the directory of destination.
30
+ def initialize(data)
31
+ super data
32
+ @src = Cfg[:src]
33
+ @destination = Cfg[:dest]
34
+ @results = []
44
35
  end
45
- end
46
-
47
36
 
48
- # Extract the archive into the destination directory.
49
- # @param file_name [String] The name of the archive.
50
- # @param destination [String] The destination directory.
51
- #
52
- def self.extract(file_name, destination = '.')
53
- raise Errno::ENOENT unless File.exist? file_name
54
37
 
55
- # Get extension of file_name to know which method calls
56
- ext = File.extname(file_name)
57
- ext = ext.delete('.')
38
+ # Checks if the destination directory exists.
39
+ # else create it.
40
+ # For the moment, if the directory exists // TODO little input to confirm
41
+ # @param destination [String] the destination directory
42
+ #
43
+ def self.destination?(destination)
44
+ unless $rejected.include? File.basename destination
45
+ FileUtils.rm_rf(destination) if Dir.exists? destination
46
+ FileUtils.mkdir_p destination, :mode => 0700
47
+ end
48
+ end
49
+
58
50
 
59
- # Raise exception if the format is unknown by Archiver
60
- raise "Unknown format '#{r}'" unless respond_to?(ext)
61
- # Check if destination exists
62
- self::destination? destination
51
+ # Extracts the archive into the destination directory.
52
+ # @param file_name [String] The name of the archive.
53
+ # @param destination [String] The destination directory.
54
+ #
55
+ def self.extract(file_name, destination = '.')
56
+ raise Errno::ENOENT unless File.exist? file_name
63
57
 
64
- # Run extraction!
65
- send(ext,file_name, destination)
66
- end
58
+ # Get extension of file_name to know which method calls
59
+ ext = File.extname(file_name)
60
+ ext = ext.delete('.')
67
61
 
62
+ # Raise exception if the format is unknown by Archiver
63
+ raise "Unknown format '#{r}'" unless respond_to?(ext)
64
+ # Check if destination exists
65
+ self::destination? destination
68
66
 
69
- # Method which extract an archive
70
- # which contains all computing projects.
71
- #
72
- # This method extracts,in first time,the archive
73
- # given in the constructor and after, all extracted files.
74
- #
75
- # Use this method in a global usage of Reviser!
76
- # Options are for the moment :verbose
77
- #
78
- def run
79
- @logger.h1 Logger::INFO,"First extraction - #{@src}"
80
- # Extract the original archive
81
- Archiver.extract(@src, @destination)
67
+ # Run extraction!
68
+ send(ext,file_name, destination)
69
+ end
82
70
 
83
- @logger.h1 Logger::INFO,'Extraction of sub archives'
84
-
85
- # Extract all sub archives
86
- entries = Dir.entries(@destination) - $rejected
87
- extracted = 0
88
-
89
- entries.each do |entry|
90
-
91
- ext = File.extname entry
92
- basename = File.basename entry, ext
93
- begin
94
- file_name = File.join(@destination,File.basename(entry))
95
- destination = File.join(@destination,basename)
96
-
97
- # Run extraction!
98
- Archiver.extract(file_name, destination)
99
- extracted += 1
100
-
101
- @logger.h2 Logger::INFO, "extracting #{file_name} to #{destination}"
102
- @results << basename
103
-
104
- # In case of it can't extract the file
105
- rescue => e
106
- @logger.h2 Logger::ERROR, "Can't extract #{entry}: #{e.message}"
107
- puts e
108
- end
109
- # Delete in all case the archive (useless after this step
110
- FileUtils.rm_rf file_name
111
- end
112
- @logger.h1 Logger::INFO, "[#{extracted}/#{entries.size}] projects have been processed"
113
-
114
- @results
71
+
72
+ # Method which extracts an archive
73
+ # which contains all computing projects.
74
+ #
75
+ # This method extracts,in first time,the archive
76
+ # given in the constructor and after, all extracted files.
77
+ #
78
+ # Use this method in a global usage of Reviser!
79
+ # Options are for the moment :verbose
80
+ #
81
+ def run
82
+ @logger.h1 Logger::INFO,"First extraction - #{@src}"
83
+ # Extract the original archive
84
+ Archiver.extract(@src, @destination)
85
+
86
+ @logger.h1 Logger::INFO,'Extraction of sub archives'
87
+
88
+ # Extract all sub archives
89
+ entries = Dir.entries(@destination) - $rejected
90
+ extracted = 0
91
+
92
+ entries.each do |entry|
93
+
94
+ ext = File.extname entry
95
+ basename = File.basename entry, ext
96
+ begin
97
+ file_name = File.join(@destination,File.basename(entry))
98
+ destination = File.join(@destination,basename)
99
+
100
+ # Run extraction!
101
+ Archiver.extract(file_name, destination)
102
+ extracted += 1
103
+
104
+ @logger.h2 Logger::INFO, "extracting #{file_name} to #{destination}"
105
+ @results << basename
106
+
107
+ # In case of it can't extract the file
108
+ rescue => e
109
+ @logger.h2 Logger::ERROR, "Can't extract #{entry}: #{e.message}"
110
+ end
111
+
112
+ # Delete in all case the archive (useless after this step)
113
+ FileUtils.rm_rf file_name
114
+ end
115
+ @logger.h1 Logger::INFO, "[#{extracted}/#{entries.size}] projects have been processed"
116
+
117
+ @results
118
+ end
115
119
  end
116
- end
117
120
 
121
+ end
118
122
  end