reviser 0.0.1.1.pre.beta
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 +7 -0
- data/bin/reviser +6 -0
- data/config.yml +80 -0
- data/ext/html_validator.rb +21 -0
- data/ext/valgrind.rb +24 -0
- data/labels.yml +8 -0
- data/lang/C.yml +22 -0
- data/lang/HTML.yml +49 -0
- data/lang/Java.yml +15 -0
- data/lang/Ruby.yml +26 -0
- data/lib/component.rb +53 -0
- data/lib/components/archiver.rb +118 -0
- data/lib/components/checker.rb +78 -0
- data/lib/components/extractors.rb +139 -0
- data/lib/components/generator.rb +47 -0
- data/lib/components/generators.rb +130 -0
- data/lib/components/organiser.rb +181 -0
- data/lib/config.rb +48 -0
- data/lib/exec.rb +136 -0
- data/lib/helpers/code_analysis.rb +64 -0
- data/lib/helpers/compilation.rb +40 -0
- data/lib/helpers/criteria.rb +186 -0
- data/lib/helpers/execution.rb +83 -0
- data/lib/helpers/git.rb +37 -0
- data/lib/helpers/project.rb +39 -0
- data/lib/helpers/system.rb +56 -0
- data/lib/loggers/logger.rb +41 -0
- data/lib/loggers/modes.rb +74 -0
- data/lib/project.rb +155 -0
- data/lib/reviser.rb +68 -0
- data/res/css/component.css +115 -0
- data/res/css/normalize.css +1 -0
- data/res/js/jquery.stickyheader.js +149 -0
- data/type/CProject.yml +32 -0
- data/type/HelloWorldRuby.yml +2 -0
- data/type/HtmlASRALL.yml +1 -0
- data/type/Labyrinthe.yml +42 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ad369beae7c279013559eaca2a371be84de43a0
|
4
|
+
data.tar.gz: d08c27df554743428484267bf53872053bf75fb0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 27115ae008fd154acc4e3c0ff6ee9b7cb0da06578634d78f14817b790a3a2bf1e30ba4c376f2d90f9e8becabeccf9bc3882f64cdea7c559ee44764877a5a3181
|
7
|
+
data.tar.gz: fda1bc73fb4ff4bb9d90e9a005554dab160601a9cef5a6eb8c8ed2768a9e2ea35452862b5ec9102b84c8ab25ab8f005aca23c6a1db1e3812e33ebc54926e09ee
|
data/bin/reviser
ADDED
data/config.yml
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
################################################
|
4
|
+
# Config file #
|
5
|
+
################################################
|
6
|
+
|
7
|
+
|
8
|
+
######## Archiver config ########
|
9
|
+
|
10
|
+
# File name of the archive containing all projects
|
11
|
+
src: projects.zip
|
12
|
+
|
13
|
+
# The destination directory for these projects
|
14
|
+
dest: projects
|
15
|
+
|
16
|
+
|
17
|
+
######## Organiser config ########
|
18
|
+
|
19
|
+
# Conventiong naming of projects, useful to rename folders
|
20
|
+
# You have to write a pseudo-regex with some constants:
|
21
|
+
# [ GROUP, FIRSTN, NAME ]
|
22
|
+
#
|
23
|
+
# '^GROUP_NAME_NAME' => Project starts with GROUP (S2A for example) and contains two names.
|
24
|
+
# '^GROUP_NAME(_NAME)*' => Project starts with GROUP and contains minimum one name.
|
25
|
+
# '^TP_html_NAME_FIRSTN' => name starts by 'TP_html_' and contains a name and firstname.
|
26
|
+
projects_names: '^FIRSTN NAME'
|
27
|
+
|
28
|
+
|
29
|
+
######## Generator config ########
|
30
|
+
|
31
|
+
# The file name for results which will be generated
|
32
|
+
out: results
|
33
|
+
|
34
|
+
# The type/format of the previous file => currently supported: [csv, html, xls]
|
35
|
+
out_format:
|
36
|
+
- csv
|
37
|
+
- html
|
38
|
+
|
39
|
+
# Ressources directory
|
40
|
+
# (needed for html format)
|
41
|
+
res_dir: res
|
42
|
+
|
43
|
+
|
44
|
+
######## Reviser config ########
|
45
|
+
|
46
|
+
# The type of project (<type>.yml must exists)
|
47
|
+
type: Labyrinthe
|
48
|
+
|
49
|
+
# Default timeout
|
50
|
+
# shall be overriden in sorts
|
51
|
+
timeout: 5
|
52
|
+
|
53
|
+
|
54
|
+
######## Global config ########
|
55
|
+
|
56
|
+
# Criteria you want for analysis
|
57
|
+
# Can be overriden or declared in
|
58
|
+
# project's config file
|
59
|
+
#
|
60
|
+
# Basics criteria, available in lib/helpers
|
61
|
+
criteria:
|
62
|
+
- all_files
|
63
|
+
- src_files
|
64
|
+
- lines_count
|
65
|
+
- comments_count
|
66
|
+
- compile
|
67
|
+
- execute
|
68
|
+
|
69
|
+
# Extensions you want to use, available in ext/
|
70
|
+
extensions:
|
71
|
+
- memleaks
|
72
|
+
|
73
|
+
|
74
|
+
# Options of all components
|
75
|
+
# For the moment, there is just verbose option (for logger)
|
76
|
+
options:
|
77
|
+
:verbose: true
|
78
|
+
:log_dir: logs
|
79
|
+
# mode of logger => [org, txt ...]
|
80
|
+
:log_mode: org
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'html5_validator/validator'
|
2
|
+
|
3
|
+
module Extensions
|
4
|
+
module HtmlValidator
|
5
|
+
include Helpers::CodeAnalysis
|
6
|
+
|
7
|
+
def validate_html
|
8
|
+
validator = Html5Validator::Validator.new
|
9
|
+
|
10
|
+
results = {}
|
11
|
+
# Might need to take care of other extensions
|
12
|
+
sources.each do |f|
|
13
|
+
validator.validate_text File.read(f)
|
14
|
+
results.store f, validator.errors
|
15
|
+
end
|
16
|
+
|
17
|
+
results
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/ext/valgrind.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Extensions
|
2
|
+
module Valgrind
|
3
|
+
|
4
|
+
include Helpers::Execution
|
5
|
+
include Helpers::System
|
6
|
+
|
7
|
+
VALGRIND_FILE = "valgrind.txt"
|
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
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/labels.yml
ADDED
data/lang/C.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
# C language
|
3
|
+
|
4
|
+
# List of source files extensions
|
5
|
+
extension:
|
6
|
+
- .c
|
7
|
+
- .h
|
8
|
+
|
9
|
+
# Whether it's a compiled or an interpreted language
|
10
|
+
compiled: true
|
11
|
+
|
12
|
+
# Program prefix, needed especially for C
|
13
|
+
# The execution command will look like this :
|
14
|
+
# [execute_command=(java, ruby, python, ...)] [program_prefix]<program> [args]
|
15
|
+
# [] are optionals, whereas <> mandatory
|
16
|
+
program_prefix: ./
|
17
|
+
|
18
|
+
# Fallback if no command is specified in project type
|
19
|
+
default_build_command: gcc -ansi -pedantic -Wall -g *.c
|
20
|
+
|
21
|
+
# Ruby regex to find C-style comments
|
22
|
+
regex_comments: !ruby/regexp '/(\/\/(.*?)^)|(\/\*(.*?)\*\/)/m'
|
data/lang/HTML.yml
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
# HTML language
|
4
|
+
|
5
|
+
# List of source files extensions
|
6
|
+
# !!!!! Recent changes make me think
|
7
|
+
# we should actually think about
|
8
|
+
# renaming it to ext for instance !!!!!!!!
|
9
|
+
|
10
|
+
# HTML
|
11
|
+
|
12
|
+
# List of source files extensions
|
13
|
+
extension:
|
14
|
+
- .html
|
15
|
+
|
16
|
+
# Whether it's a compiled or an interpreted language
|
17
|
+
compiled: false
|
18
|
+
|
19
|
+
#
|
20
|
+
# In all HTML projects, we'll need
|
21
|
+
# the html_validator extension
|
22
|
+
#
|
23
|
+
extensions:
|
24
|
+
html_validator:
|
25
|
+
:valid: Validite HTML 5
|
26
|
+
|
27
|
+
# Program prefix, needed especially for C
|
28
|
+
# The execution command will look like this :
|
29
|
+
# [execute_command=(java, ruby, python, ...)] [program_prefix]<program> [args]
|
30
|
+
# [] are optionals, whereas <> mandatory
|
31
|
+
# program_prefix:
|
32
|
+
|
33
|
+
# For interpreted languages
|
34
|
+
# execute_command: ruby
|
35
|
+
|
36
|
+
# If not specified, the first
|
37
|
+
# 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
|
data/lang/Java.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
# Java language
|
3
|
+
|
4
|
+
# List of source files extensions
|
5
|
+
extension:
|
6
|
+
- .java
|
7
|
+
|
8
|
+
# Whether it's a compiled or an interpreted language
|
9
|
+
compiled: true
|
10
|
+
|
11
|
+
# Fallback if no command is specified in project type
|
12
|
+
default_build_command: javac *.java
|
13
|
+
|
14
|
+
# Ruby regex to find C-style comments
|
15
|
+
regex_comments: !ruby/regexp '/(\/\/(.*?)^)|(\/\*(.*?)\*\/)/m'
|
data/lang/Ruby.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
# Ruby language
|
3
|
+
|
4
|
+
# List of source files extensions
|
5
|
+
extension:
|
6
|
+
- .rb
|
7
|
+
|
8
|
+
# Whether it's a compiled or an interpreted language
|
9
|
+
compiled: false
|
10
|
+
|
11
|
+
# Program prefix, needed especially for C
|
12
|
+
# The execution command will look like this :
|
13
|
+
# [execute_command=(java, ruby, python, ...)] [program_prefix]<program> [args]
|
14
|
+
# [] are optionals, whereas <> mandatory
|
15
|
+
# program_prefix:
|
16
|
+
|
17
|
+
# For interpreted languages
|
18
|
+
execute_command: ruby
|
19
|
+
|
20
|
+
# If not specified, the first
|
21
|
+
# executable file found will be executed
|
22
|
+
program_name: main.rb
|
23
|
+
|
24
|
+
regex_comments: !ruby/regexp '/#([^{].*)$/'
|
25
|
+
|
26
|
+
timeout: 1
|
data/lib/component.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Renan Strauss
|
3
|
+
#
|
4
|
+
require 'yaml'
|
5
|
+
require_relative 'loggers/logger'
|
6
|
+
|
7
|
+
class Component
|
8
|
+
|
9
|
+
# Each component has a logger (currently a txt file)
|
10
|
+
# $logger
|
11
|
+
|
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}")
|
22
|
+
|
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
|
28
|
+
|
29
|
+
# Place-holder
|
30
|
+
# Just like an abstract method
|
31
|
+
def run
|
32
|
+
raise NotImplementedError, 'All components must implement a run method'
|
33
|
+
end
|
34
|
+
|
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
|
43
|
+
|
44
|
+
data
|
45
|
+
end
|
46
|
+
|
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 }
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require_relative 'extractors'
|
3
|
+
|
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
|
+
|
34
|
+
|
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
|
39
|
+
#
|
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
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
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
|
+
|
55
|
+
# Get extension of file_name to know which method calls
|
56
|
+
ext = File.extname(file_name)
|
57
|
+
ext = ext.delete('.')
|
58
|
+
|
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
|
63
|
+
|
64
|
+
# Run extraction!
|
65
|
+
send(ext,file_name, destination)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
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)
|
82
|
+
|
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
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Renan Strauss
|
3
|
+
#
|
4
|
+
# The Checker is a component that wraps
|
5
|
+
# all required tools to do the analysis.
|
6
|
+
# It adapts itself dynamically
|
7
|
+
# to the language Cfg.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
require 'open3'
|
11
|
+
|
12
|
+
require_relative '../helpers/criteria'
|
13
|
+
|
14
|
+
module Components
|
15
|
+
class Checker < Component
|
16
|
+
include Helpers::Criteria
|
17
|
+
|
18
|
+
def initialize(data)
|
19
|
+
super data
|
20
|
+
|
21
|
+
init_criteria_helper
|
22
|
+
|
23
|
+
@results = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# Yann : je ne recupere pas les datas de l'organiser,
|
27
|
+
# Je considere que tous les projets sont dans le dossier courant.
|
28
|
+
# TODO a voir si cela marche dans certains cas particuliers
|
29
|
+
def run
|
30
|
+
# We'll work in the dest directory
|
31
|
+
Dir.chdir Cfg[:dest] do
|
32
|
+
projects = Dir.entries('.') - ['.','..']
|
33
|
+
projects.each_with_index do |proj, i|
|
34
|
+
puts "\t[#{i+1}/#{projects.size}]\t#{proj}"
|
35
|
+
Dir.chdir(proj) { check proj }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
@results
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
#
|
45
|
+
# Being called in the project's directory,
|
46
|
+
# this methods maps all the criterias to
|
47
|
+
# their analysis value
|
48
|
+
#
|
49
|
+
def check(proj)
|
50
|
+
# Init results
|
51
|
+
@results[proj] = {}
|
52
|
+
|
53
|
+
# for each method asked by user with its label
|
54
|
+
@output.each do |meth, label|
|
55
|
+
if @criteria.has_key? meth
|
56
|
+
@results[proj][label] = call meth
|
57
|
+
else
|
58
|
+
@logger.h1(Logger::ERROR, "Unknown method '#{meth}'' for project #{proj}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# This method is what would be the constructor
|
65
|
+
# of criteria_helper if it was a class
|
66
|
+
#
|
67
|
+
def init_criteria_helper
|
68
|
+
@criteria = Hash.new
|
69
|
+
@output = Hash.new
|
70
|
+
@logger.h1 Logger::INFO, "Loading modules"
|
71
|
+
load PWD, '../helpers/*'
|
72
|
+
load EXT, '*'
|
73
|
+
@logger.h1 Logger::INFO, "Loading labels"
|
74
|
+
[:criteria, :extensions].each { |x| load_labels x }
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Components
|
5
|
+
|
6
|
+
# The module contains all methods to extract an archive
|
7
|
+
# regardless the format.
|
8
|
+
#
|
9
|
+
# Convention over configuration !
|
10
|
+
#
|
11
|
+
# To add a new format, maybe you need to install the a gem.
|
12
|
+
# Find your gem which uncompress a specified format on rubygems.org.
|
13
|
+
# Add the line "gem <gem>" in the Gemfile and execute "bundle install"
|
14
|
+
#
|
15
|
+
# Now, you can write the method corresponding to the format.
|
16
|
+
# The name of the method corresponds to the format.
|
17
|
+
# For example, if you want to use 'rar' format, the name of the method will be: "rar"
|
18
|
+
# Don't forget to require the gem: "require <gem>" at the beginning of the method!
|
19
|
+
# the header of method looks like the following block:
|
20
|
+
#
|
21
|
+
# def <format> (archive, destination)
|
22
|
+
# require <gem>
|
23
|
+
# ...
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @author Anthony Cerf
|
27
|
+
# @author Yann Prono
|
28
|
+
#
|
29
|
+
module Extractors
|
30
|
+
|
31
|
+
# Method which unzip a file.
|
32
|
+
# @param zip_file [String] the zip file.
|
33
|
+
# @param destination [String] Destination of extracted data.
|
34
|
+
def zip zip_file, destination
|
35
|
+
require 'zip'
|
36
|
+
# Cfg the gem
|
37
|
+
Zip.on_exists_proc = true
|
38
|
+
Zip.continue_on_exists_proc = true
|
39
|
+
|
40
|
+
Zip::File.open(zip_file) do |archive|
|
41
|
+
#Entry = file or directory
|
42
|
+
archive.each do |entry|
|
43
|
+
#Create filepath
|
44
|
+
filepath = File.join(destination, entry.name)
|
45
|
+
|
46
|
+
# Check if it doesn't exist because of directories (overwrite)
|
47
|
+
unless File.exist?(filepath)
|
48
|
+
# Create directories to access file
|
49
|
+
FileUtils.mkdir_p(File.dirname(filepath))
|
50
|
+
entry.extract(filepath)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Method which ungz a file.
|
57
|
+
# @param gz_file [String] the gz file.
|
58
|
+
# @param destination [String] Destination of extracted data.
|
59
|
+
def gz gz_file, destination
|
60
|
+
require 'zlib'
|
61
|
+
file = Zlib::GzipReader.open(gz_file)
|
62
|
+
unzipped = StringIO.new(file.read)
|
63
|
+
file.close
|
64
|
+
tar(unzipped, destination)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Alias for format shortcut
|
68
|
+
# CC Dominique Colnet!
|
69
|
+
alias :tgz :gz
|
70
|
+
|
71
|
+
# Method which untar a tarfile.
|
72
|
+
# @param tar_file [String] the tar file.
|
73
|
+
# @param destination [String] Destination of extracted data.
|
74
|
+
def tar tar_file, destination
|
75
|
+
require 'rubygems/package'
|
76
|
+
# test if src is String (filename) or IO stream
|
77
|
+
if tar_file.is_a? String
|
78
|
+
stream = File.open(tar_file)
|
79
|
+
else
|
80
|
+
stream = tar_file
|
81
|
+
end
|
82
|
+
|
83
|
+
Gem::Package::TarReader.new(stream) do |tar|
|
84
|
+
tar.each do |tarfile|
|
85
|
+
destination_file = File.join destination, tarfile.full_name
|
86
|
+
if tarfile.directory?
|
87
|
+
FileUtils.mkdir_p destination_file
|
88
|
+
else
|
89
|
+
destination_directory = File.dirname(destination_file)
|
90
|
+
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
|
91
|
+
File.open destination_file, 'wb' do |f|
|
92
|
+
f.print tarfile.read
|
93
|
+
end
|
94
|
+
end
|
95
|
+
tarfile.close unless tarfile.closed?
|
96
|
+
end
|
97
|
+
tar.close
|
98
|
+
end
|
99
|
+
stream.close
|
100
|
+
end
|
101
|
+
|
102
|
+
# Method which unrar a rar file, if it is possible (proprietary format grr ...)
|
103
|
+
# @param rar_file [String] the rar file.
|
104
|
+
# @param destination [String] Destination of extracted data.
|
105
|
+
def rar rar_file, destination
|
106
|
+
require 'shellwords'
|
107
|
+
`which unrar`
|
108
|
+
if $?.success?
|
109
|
+
src = Shellwords.escape(rar_file)
|
110
|
+
destination = Shellwords.escape(destination)
|
111
|
+
`unrar e #{src} #{destination}`
|
112
|
+
else
|
113
|
+
puts 'Please install unrar : sudo apt-get install unrar'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Method which un7zip a 7zip file.
|
118
|
+
# @param seven_zip_file [String] the 7zip file.
|
119
|
+
# @param destination [String] Destination of extracted data.
|
120
|
+
def seven_zip seven_zip_file, destination
|
121
|
+
require 'seven_zip_ruby'
|
122
|
+
File.open(seven_zip_file, 'rb') do |file|
|
123
|
+
SevenZipRuby::Reader.open(file) do |szr|
|
124
|
+
szr.extract_all destination
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Use first of all for seven zip format (little tip, can't call it directly).
|
130
|
+
def method_missing(m, *args, &block)
|
131
|
+
if (ext = File.extname(args[0]).delete('.') == '7z')
|
132
|
+
seven_zip(args[0], args[1])
|
133
|
+
else
|
134
|
+
raise "Format '#{ext.delete('.')}' not supported"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|