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.
- checksums.yaml +4 -4
- data/Gemfile +18 -0
- data/README.md +46 -0
- data/ext/valgrind.rb +21 -18
- data/ext/web_validators.rb +132 -0
- data/lang/HTML.yml +2 -14
- data/lib/component.rb +41 -39
- data/lib/components/archiver.rb +105 -101
- data/lib/components/checker.rb +46 -52
- data/lib/components/extractors.rb +121 -120
- data/lib/components/generator.rb +40 -37
- data/lib/components/generators.rb +113 -109
- data/lib/components/organiser.rb +165 -153
- data/lib/config.rb +53 -35
- data/lib/criteria/code_analysis.rb +54 -0
- data/lib/criteria/compilation.rb +42 -0
- data/lib/criteria/execution.rb +78 -0
- data/lib/exec.rb +109 -94
- data/lib/helpers/criteria.rb +152 -154
- data/lib/helpers/git.rb +23 -21
- data/lib/helpers/project.rb +198 -19
- data/lib/helpers/system.rb +50 -39
- data/lib/loggers/logger.rb +39 -30
- data/lib/loggers/modes.rb +118 -54
- data/lib/reviser.rb +63 -41
- data/res/css/style_logs.css +166 -0
- data/res/css/web_validators/css-base.css +733 -0
- data/res/css/web_validators/css-results.css +257 -0
- data/res/css/web_validators/html-base.css +746 -0
- data/res/css/web_validators/html-results.css +489 -0
- data/res/labys/labfich11.txt +19 -0
- data/res/labys/test.txt +3 -0
- data/res/labys/yoda.txt +19 -0
- data/res/scss/style_logs.scss +134 -0
- data/type/JavaProject.yml +18 -0
- data/type/Pendu.yml +22 -0
- data/type/Web.yml +23 -0
- metadata +144 -10
- data/ext/html_validator.rb +0 -21
- data/lib/helpers/code_analysis.rb +0 -64
- data/lib/helpers/compilation.rb +0 -40
- data/lib/helpers/execution.rb +0 -83
- data/lib/project.rb +0 -155
@@ -1,130 +1,134 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# Each value of data is also a [Hash]:
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# @author
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
1
|
+
module Reviser
|
2
|
+
module Components
|
3
|
+
|
4
|
+
# Module containing all methods for writing results.
|
5
|
+
#
|
6
|
+
# Convention over configuration !
|
7
|
+
#
|
8
|
+
# To add a new format, you need maybe to install a gem.
|
9
|
+
# Find a gem which supports a specified format on rubygems.org.
|
10
|
+
# Add the line "gem <gem>" in the Gemfile and execute "bundle install"
|
11
|
+
#
|
12
|
+
# Now, you can write the method corresponding to the format.
|
13
|
+
# The name of the method corresponds to the format.
|
14
|
+
# For example, if you want to generate a word file (.doc), the name of the method will be: "doc"
|
15
|
+
# Don't forget to require the gem: "require <gem>" at the beginning of the method !
|
16
|
+
# the header of method looks like the following block:
|
17
|
+
#
|
18
|
+
# def <format> (ext = '<format>') require <gem> ... end
|
19
|
+
#
|
20
|
+
# To write results, you have to go through in the data instance variable.
|
21
|
+
# data is a [Hash]:
|
22
|
+
#
|
23
|
+
# - key: The person's name.
|
24
|
+
# - value: Results of analysis
|
25
|
+
#
|
26
|
+
# Each value of data is also a [Hash]:
|
27
|
+
#
|
28
|
+
# - key: the name of criterion checked.
|
29
|
+
# - value: The result of criterion.
|
30
|
+
#
|
31
|
+
#
|
32
|
+
# @author Renan Strauss
|
33
|
+
# @author Yann Prono
|
34
|
+
#
|
35
|
+
module Generators
|
36
|
+
|
37
|
+
# Generates the CSV file
|
38
|
+
def csv(ext = '.csv')
|
39
|
+
require 'csv'
|
40
|
+
CSV.open(out(ext), 'wb') do |f|
|
41
|
+
# Criterias as columns
|
42
|
+
f << (criterias).unshift('projet')
|
43
|
+
|
44
|
+
# Values for each project as rows
|
45
|
+
@data.keys.each do |proj|
|
46
|
+
f << @data[proj].values.unshift(proj)
|
47
|
+
end
|
47
48
|
end
|
48
49
|
end
|
49
|
-
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
# Generates a Excel file
|
52
|
+
def xls(ext = '.xls')
|
53
|
+
require 'spreadsheet'
|
54
|
+
Spreadsheet.client_encoding = 'UTF-8'
|
55
|
+
book = Spreadsheet::Workbook.new
|
56
|
+
sheet = book.create_worksheet :name => 'Results'
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
# header
|
59
|
+
format = Spreadsheet::Format.new :weight => :bold, :size => 14 ,
|
60
|
+
:horizontal_align => :center
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
(criterias.unshift('Projets')).each_with_index do |crit, i|
|
63
|
+
sheet[0,i] = crit
|
64
|
+
sheet.column(i).width = (crit.size * format.font.size/10) + 5
|
65
|
+
end
|
66
|
+
sheet.row(0).default_format = format
|
67
|
+
sheet.row(0).height = 18
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
# Values for each project as rows
|
70
|
+
@data.keys.each_with_index do |proj, i|
|
71
|
+
sheet.insert_row(i+1,@data[proj].values.unshift(proj))
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
74
|
+
book.write out(ext)
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
77
|
+
# Generates an HTML file
|
78
|
+
def html(ext = '.html')
|
79
|
+
out = '<!DOCTYPE html><html><head>'
|
80
|
+
out += '<meta charset= "UTF-8">'
|
81
|
+
out += "<link rel=\"stylesheet\" href=\"#{Cfg[:res_dir]}/css/component.css\" />"
|
82
|
+
out += "<link rel=\"stylesheet\" href=\"#{Cfg[:res_dir]}/css/normalize.css\" />"
|
83
|
+
out += '<script src="res/js/component.css"></script>'
|
84
|
+
out += '<title>Results</title>'
|
85
|
+
out += "</head>\n<body><table><thead>"
|
86
|
+
out += ' <tr>'
|
87
|
+
|
88
|
+
criterias.unshift('Projet').each { |crit| out += "<th>#{crit}</th>" }
|
89
|
+
|
90
|
+
out += '</tr></thead><tbody>'
|
91
|
+
# Values for each project as rows
|
92
|
+
@data.keys.each do |proj|
|
93
|
+
out += "<tr><th>#{proj}</th>"
|
94
|
+
@data[proj].each do |k, v|
|
95
|
+
if k.to_s[/(compilation|execution)/]
|
96
|
+
out += '<td class="console">'
|
97
|
+
else
|
98
|
+
out += '<td>'
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
101
|
+
# If file, generate a link, else do nothing !
|
102
|
+
out += file?(v) && "<pre><a href=\"#{v.gsub(' ','%20')}\" target=\"_blank\">#{v}</a></pre></td>" ||"<pre>#{v}</pre></td>"
|
103
103
|
|
104
|
+
end
|
105
|
+
out += '</tr>'
|
104
106
|
end
|
105
|
-
out += '</tr>'
|
106
|
-
end
|
107
107
|
|
108
|
-
|
108
|
+
out += '</tbody></table>'
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
110
|
+
out += '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>'
|
111
|
+
out += '<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-throttle-debounce/1.1/jquery.ba-throttle-debounce.min.js"></script>'
|
112
|
+
#out += "<script src=\"#{Cfg[:res_dir]}/js/jquery.stickyheader.js\"></script>"
|
113
113
|
|
114
|
-
|
114
|
+
out += '</body></html>'
|
115
115
|
|
116
|
-
|
117
|
-
|
116
|
+
File.open(out(ext), 'w') { |f| f.write(out) }
|
117
|
+
end
|
118
118
|
|
119
|
-
|
119
|
+
private
|
120
120
|
|
121
|
-
|
122
|
-
|
123
|
-
|
121
|
+
def out(ext)
|
122
|
+
Cfg[:out] + ext
|
123
|
+
end
|
124
124
|
|
125
|
-
|
126
|
-
|
127
|
-
|
125
|
+
# Checks if result is a existing file.
|
126
|
+
# @param path [String] of possible file
|
127
|
+
# @return [Boolean] True if the path is a real file.
|
128
|
+
def file? path
|
129
|
+
File.exist? path.to_s
|
130
|
+
end
|
128
131
|
|
132
|
+
end
|
129
133
|
end
|
130
134
|
end
|
data/lib/components/organiser.rb
CHANGED
@@ -1,181 +1,193 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require_relative '../helpers/git'
|
3
|
-
require_relative '../project'
|
4
|
-
|
5
|
-
|
6
|
-
module Components
|
7
|
-
|
8
|
-
# Class which organizes all directories to simplify projects' analysis.
|
9
|
-
# Organiser renames projects folders and organises the whole of projects
|
10
|
-
# in order to have a structured folder (files at the root of folder)
|
11
|
-
# During this step, a git repository will be created, with an initial commit.
|
12
|
-
#
|
13
|
-
# @author Yann Prono
|
14
|
-
# @author Renan Strauss
|
15
|
-
#
|
16
|
-
class Organiser < Component
|
17
|
-
|
18
|
-
# Include all tools
|
19
|
-
include Helpers::Git
|
20
|
-
include Project
|
21
|
-
|
22
|
-
# All entries to ignore during sort and organization
|
23
|
-
$rejected_entries = ['.', '..', '__MACOSX']
|
24
|
-
|
25
|
-
# initialize tool.
|
26
|
-
# Organiser has to :
|
27
|
-
# - get all students
|
28
|
-
# - get all groups (classes)
|
29
|
-
# - get all teams (binoms)
|
30
|
-
# - get all unknown soldiers ...
|
31
|
-
def initialize(data)
|
32
|
-
raise ArgumentError if data == nil || !data.respond_to?('each')
|
33
|
-
|
34
|
-
super data
|
35
|
-
|
36
|
-
@directory = Cfg[:dest]
|
37
|
-
@path = @directory
|
38
|
-
@git = nil
|
39
|
-
@students = []
|
40
|
-
@binoms = []
|
41
|
-
@groups = []
|
42
|
-
@unknown = []
|
43
|
-
|
44
|
-
# How many patterns are in the pseudo-regex?
|
45
|
-
@count_patterns = {}
|
46
|
-
end
|
3
|
+
require_relative '../helpers/project'
|
47
4
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
5
|
+
|
6
|
+
module Reviser
|
7
|
+
module Components
|
8
|
+
|
9
|
+
# Class which organizes all directories to simplify projects' analysis.
|
10
|
+
# Organiser renames projects folders and organises the whole of projects
|
11
|
+
# in order to have a structured folder (files at the root of folder)
|
12
|
+
# During this step, a git repository will be created, with an initial commit.
|
13
|
+
#
|
14
|
+
# The other important task of Organiser is to detect all students, all binoms and all groups,
|
15
|
+
# thank to the directory name.
|
16
|
+
#
|
17
|
+
# @author Yann Prono
|
18
|
+
# @author Renan Strauss
|
19
|
+
#
|
20
|
+
class Organiser < Component
|
21
|
+
|
22
|
+
# Include all tools
|
23
|
+
include Helpers::Git
|
24
|
+
include Helpers::Project::Naming
|
25
|
+
|
26
|
+
# All entries to ignore during sort and organization
|
27
|
+
$rejected_entries = ['.', '..', '__MACOSX']
|
28
|
+
|
29
|
+
# initializes tool.
|
30
|
+
# The initialization will prepare all to
|
31
|
+
# crate a git repo, save all detected students as well someone who
|
32
|
+
# doesn't respect convention ...
|
33
|
+
Organiser
|
34
|
+
def initialize(data)
|
35
|
+
raise ArgumentError if data == nil || !data.respond_to?('each')
|
36
|
+
|
37
|
+
super data
|
38
|
+
|
39
|
+
@directory = Cfg[:dest]
|
40
|
+
@path = @directory
|
41
|
+
@git = nil
|
42
|
+
@students = []
|
43
|
+
@binoms = []
|
44
|
+
@projects_per_group = {}
|
45
|
+
@unknown = []
|
46
|
+
@results = []
|
47
|
+
|
48
|
+
# How many patterns are in the pseudo-regex?
|
49
|
+
@count_patterns = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
# Renames directories more clearly.
|
53
|
+
# @param entry [String] path of the entry to rename.
|
54
|
+
def rename(entry)
|
55
|
+
name = format entry
|
56
|
+
if name != nil
|
57
|
+
if name != entry
|
58
|
+
new_path = File.join(@directory, name)
|
59
|
+
FileUtils.mkdir_p(new_path.split(File.basename(new_path))[0])
|
60
|
+
FileUtils.mv(File.join(@directory, entry), new_path, :force => true)
|
61
|
+
|
62
|
+
@logger.h2 Logger::INFO, "renaming #{File.basename(entry)} to #{File.basename(name)}"
|
63
|
+
else
|
64
|
+
@logger.h2 Logger::INFO, "#{entry} has not been renamed}, already formatted"
|
65
|
+
end
|
59
66
|
else
|
60
|
-
@logger.h2 Logger::
|
67
|
+
@logger.h2 Logger::ERROR, "Can't rename #{File.basename(entry)} - Datas not found in name"
|
61
68
|
end
|
62
|
-
|
63
|
-
@logger.h2 Logger::ERROR, "Can't rename #{File.basename(entry)} - Datas not found in name"
|
69
|
+
name
|
64
70
|
end
|
65
|
-
end
|
66
71
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
72
|
+
# Method which moves project's directories in order to
|
73
|
+
# have the same hierarchy for all project.
|
74
|
+
# @param entry [String] path of the entry to structure.
|
75
|
+
def structure(entry)
|
76
|
+
chdir entry
|
77
|
+
@logger.h2 Logger::INFO, "#{entry} => #{@path}"
|
78
|
+
level = 0
|
79
|
+
@logger.h2 Logger::INFO, "Files in #{@path}"
|
80
|
+
@logger.h3 Logger::INFO, "#{all}"
|
81
|
+
|
82
|
+
@logger.h2 Logger::INFO, "Dirs in #{@path}"
|
83
|
+
@logger.h3 Logger::INFO, "#{directories}"
|
84
|
+
# directory to delete if the project directory is not structured
|
85
|
+
rm = directories.first
|
86
|
+
|
87
|
+
# Loop to find the core of project
|
88
|
+
#
|
89
|
+
# Basically running through
|
90
|
+
# each level of directories
|
91
|
+
# while there are only directories
|
92
|
+
# in the current directory
|
93
|
+
#
|
94
|
+
while all == directories
|
95
|
+
level += 1
|
96
|
+
@logger.h2 Logger::DEBUG, "Level += 1\nPath = #{@path}"
|
97
|
+
chdir directories.first
|
98
|
+
@logger.h2 Logger::DEBUG, "New path = #{@path}"
|
99
|
+
end
|
95
100
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
101
|
+
# If the core of project is not at the root of directory ...
|
102
|
+
if level >= 1
|
103
|
+
Dir.glob(File.join(@path,'*')).each do |file|
|
104
|
+
FileUtils.mv(file,File.join(@directory, entry))
|
105
|
+
end
|
106
|
+
@logger.h2 Logger::INFO, "Structuring #{File.join(@path)}"
|
107
|
+
@logger.h2 Logger::INFO, "Removing #{File.join(@directory, entry, rm)}"
|
108
|
+
FileUtils.rm_rf(File.join(@directory, entry, rm))
|
100
109
|
end
|
101
|
-
@logger.h2 Logger::INFO, "Structuring #{File.join(@path)}"
|
102
|
-
@logger.h2 Logger::INFO, "Removing #{File.join(@directory, entry, rm)}"
|
103
|
-
FileUtils.rm_rf(File.join(@directory, entry, rm))
|
104
|
-
end
|
105
110
|
|
106
|
-
|
107
|
-
|
111
|
+
@path = @directory
|
112
|
+
end
|
108
113
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
114
|
+
# Initializes a git repo.
|
115
|
+
# @param entry [String] Directory to process.
|
116
|
+
def git(entry)
|
117
|
+
Dir.chdir File.join(@directory, entry) do
|
118
|
+
git_init
|
119
|
+
git_add
|
120
|
+
git_commit
|
121
|
+
end
|
116
122
|
end
|
117
|
-
end
|
118
123
|
|
119
124
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
# Method which runs the organiser.
|
126
|
+
# It will apply all importants methods of this class for each project.
|
127
|
+
def run
|
128
|
+
@data.each do |entry|
|
129
|
+
|
130
|
+
@logger.h1 Logger::INFO, "Work on #{entry}"
|
131
|
+
@logger.h1 Logger::INFO, "Structure project"
|
132
|
+
structure entry
|
127
133
|
|
128
|
-
|
129
|
-
|
134
|
+
@logger.h1 Logger::INFO, "Initializing git repo"
|
135
|
+
git entry
|
130
136
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
137
|
+
@logger.h1 Logger::INFO, "Renaming directory"
|
138
|
+
new_path = rename entry
|
139
|
+
@logger.newline
|
140
|
+
@results << new_path
|
141
|
+
end
|
135
142
|
|
136
|
-
|
137
|
-
|
138
|
-
|
143
|
+
@logger.h1 Logger::INFO, "#{@projects_per_group.keys.size} group#{'s' if @projects_per_group.keys.size > 1} have been detected"
|
144
|
+
@logger.h1 Logger::INFO, "#{@students.size} student#{'s' if @students.size > 1} have been detected"
|
145
|
+
@logger.h1 Logger::INFO, "#{@binoms.size} binom#{'s' if @binoms.size > 1} have been detected"
|
139
146
|
|
140
|
-
|
141
|
-
|
142
|
-
|
147
|
+
formalized = []
|
148
|
+
@projects_per_group.each { |k,v| formalized << "#{k.to_s}: #{v} project#{'s' if v > 1}" }
|
149
|
+
log_resume(formalized, Logger::INFO, "Groups:")
|
150
|
+
log_resume(@students, Logger::INFO, "Students:")
|
151
|
+
log_resume(@binoms, Logger::INFO, "Binoms:")
|
143
152
|
|
144
|
-
|
145
|
-
|
153
|
+
log_resume(@unknown, Logger::ERROR, "\n#{@unknown.size} projects didn't matched with regex")
|
154
|
+
|
155
|
+
@results
|
156
|
+
end
|
146
157
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
158
|
+
private
|
159
|
+
#
|
160
|
+
# Take attention : these accessors
|
161
|
+
# are meant to be used by structure
|
162
|
+
# only ! Because @path is initialized
|
163
|
+
# for that, and used only in this def
|
164
|
+
#
|
165
|
+
def all
|
166
|
+
Dir.entries(@path) - $rejected_entries
|
167
|
+
end
|
157
168
|
|
158
|
-
|
159
|
-
|
160
|
-
|
169
|
+
def directories
|
170
|
+
all.select { |e| File.directory? File.join(@path, e) }
|
171
|
+
end
|
161
172
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
173
|
+
def chdir(dir)
|
174
|
+
base = @path
|
175
|
+
@path = File.join(base, dir)
|
176
|
+
end
|
166
177
|
|
167
178
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
179
|
+
# Shortcut for logs ...
|
180
|
+
# @param data [Array] to loop.
|
181
|
+
# @param severity [Integer] Severity of the log.
|
182
|
+
# @param message [String] Message to log before writing data.
|
183
|
+
def log_resume(data ,severity, message)
|
184
|
+
unless data.empty?
|
185
|
+
@logger.newline
|
186
|
+
@logger.h1 severity, message
|
187
|
+
data.each {|d| @logger.h2 severity, "#{d}" }
|
188
|
+
end
|
177
189
|
end
|
190
|
+
|
178
191
|
end
|
179
|
-
|
180
192
|
end
|
181
193
|
end
|