diggit 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +3 -1
- data/bin/dgit +59 -32
- data/lib/dgit.rb +19 -1
- data/lib/dgit/core.rb +191 -98
- data/lib/dgit/log.rb +62 -0
- data/lib/dgit/plugins.rb +101 -8
- data/lib/dgit/version.rb +19 -1
- data/plugins/addon/db.rb +39 -0
- data/plugins/addon/out.rb +49 -0
- data/plugins/addon/r.rb +35 -0
- data/plugins/analysis/cloc.rb +42 -0
- data/spec/core_spec.rb +36 -6
- data/spec/dgit/plugins/addon/test_addon.rb +18 -0
- data/spec/dgit/plugins/analysis/duplicate_analysis.rb +28 -0
- data/spec/dgit/plugins/analysis/my_module/duplicate_analysis.rb +30 -0
- data/spec/dgit/plugins/analysis/my_module/other_analysis.rb +30 -0
- data/spec/dgit/plugins/analysis/test_analysis.rb +18 -2
- data/spec/dgit/plugins/analysis/test_analysis_with_addon.rb +18 -0
- data/spec/dgit/plugins/analysis/test_analysis_with_error.rb +19 -1
- data/spec/dgit/plugins/join/test_join.rb +18 -0
- data/spec/dgit/plugins/join/test_join_with_addon.rb +18 -0
- data/spec/spec_helper.rb +18 -0
- metadata +39 -17
- data/lib/dgit/formatador.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9fbc5e12f3c7806df481b5627dc5f904f89428c5
|
4
|
+
data.tar.gz: 6600fc64a91b44b386795d16a792caa11f12d932
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5defc137d1d9cd066c730c4c2d01b2da01bd7f848866cd01888caf6b97fea24377e293ddfc66ade5f03f9b6742ca3bc177b611762a30deb697b9fe6ff894f326
|
7
|
+
data.tar.gz: 535718d8f71f8f088f08c08bab2edb33e8e270db0e928a208d26c273c4a71b445863060ec2157175adb33fc33292e8120ba4d0df94931f96a1589db783a800ed
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Changelog of Diggit
|
2
|
+
|
3
|
+
### Version 2.0.1
|
4
|
+
* Removed `errors`command, merged with subcommands of `sources`
|
5
|
+
* Added a lot of documentation
|
6
|
+
* Now the `init` command creates the directory for plugins and skips creating already existing folders
|
7
|
+
* Fixed plugins not shipped with the gem
|
8
|
+
* Removed useless dependency on `mongo`
|
9
|
+
|
10
|
+
## Version 2.0.0 (Beardfish)
|
11
|
+
* huge refactoring of the code
|
12
|
+
* now addons are lazy loaded
|
13
|
+
* `require_addons` to include addons in analyses and joins
|
14
|
+
* addons are now accessible using a method with the name of the addon inside an analysis or a join
|
15
|
+
* improved command line: now uses the GLI library
|
16
|
+
* addition of run modes: `:run`, `:rerun` and `:clean`
|
17
|
+
* more detailed journaling
|
18
|
+
|
19
|
+
## Version 1.0.0 (Anchovy)
|
20
|
+
* initial version
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Diggit
|
1
|
+
# Diggit [![Build Status](https://travis-ci.org/jrfaller/diggit.svg?branch=master)](https://travis-ci.org/jrfaller/diggit) [![Coverage Status](https://coveralls.io/repos/jrfaller/diggit/badge.svg?branch=master)](https://coveralls.io/r/jrfaller/diggit?branch=master) [![Inline docs](http://inch-ci.org/github/jrfaller/diggit.svg?branch=master)](http://inch-ci.org/github/jrfaller/diggit) [![Dependency Status](https://gemnasium.com/jrfaller/diggit.svg)](https://gemnasium.com/jrfaller/diggit)
|
2
2
|
|
3
3
|
A ruby tool to analyze Git repositories
|
4
4
|
|
@@ -14,6 +14,8 @@ Clone diggit using the following command: `git clone https://github.com/jrfaller
|
|
14
14
|
|
15
15
|
# Usage
|
16
16
|
|
17
|
+
Don't forget that dgit binary has an associated help that can be consulted using `dgit help`.
|
18
|
+
|
17
19
|
## Configuration
|
18
20
|
|
19
21
|
The diggit tool is designed to help you analyze software repositories. Firstly you have to create a new folder in which you launch the `dgit init` command. This way, the folder becomes a diggit folder in which you can configure repositories and analyses.
|
data/bin/dgit
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
+
#
|
4
|
+
# This file is part of Diggit.
|
5
|
+
#
|
6
|
+
# Diggit is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Diggit is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Diggit. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
# Copyright 2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
|
20
|
+
#
|
3
21
|
|
4
22
|
require 'gli'
|
5
23
|
require_relative '../lib/dgit'
|
@@ -8,6 +26,8 @@ include GLI::App
|
|
8
26
|
|
9
27
|
program_desc 'A git repository analysis tool.'
|
10
28
|
|
29
|
+
switch [:v, :verbose], default_value: false, negatable: false, desc: "Indicates if the debug information are visible."
|
30
|
+
|
11
31
|
version Diggit::VERSION
|
12
32
|
|
13
33
|
subcommand_option_handling :normal
|
@@ -71,6 +91,35 @@ command :sources do |c|
|
|
71
91
|
File.open(args[0]).each { |line| Diggit::Dig.it.journal.add_source(line) }
|
72
92
|
end
|
73
93
|
end
|
94
|
+
c.desc 'Display all sources in error.'
|
95
|
+
c.command :errors do |errors|
|
96
|
+
errors.action do |_global_options, _options, _args|
|
97
|
+
sources = Diggit::Dig.it.journal.sources
|
98
|
+
sources.each_index do |idx|
|
99
|
+
msg = "#{idx} #{sources[idx].url} (#{sources[idx].state})"
|
100
|
+
Log.error msg if sources[idx].error?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
c.desc 'Display information on a source'
|
105
|
+
c.arg_name 'id'
|
106
|
+
c.command :info do |info|
|
107
|
+
info.action do |_global_options, _options, args|
|
108
|
+
src = Diggit::Dig.it.journal.sources_by_ids(args.to_i)
|
109
|
+
url = "URL: #{src.url}"
|
110
|
+
src.error? ? Log.error(url) : Log.info(url)
|
111
|
+
Log.info "State: #{src.state}"
|
112
|
+
Log.info "Performed analyses: #{src.performed_analyses.join(', ')}" unless src.performed_analyses.empty?
|
113
|
+
Log.error "Ongoing analyses: #{src.ongoing_analyses.join(', ')}" unless src.ongoing_analyses.emtpy?
|
114
|
+
if src.error?
|
115
|
+
error = src.error
|
116
|
+
Log.indent do
|
117
|
+
Log.error error[:message]
|
118
|
+
Log.info error[:backtrace].join("\n")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
74
123
|
c.default_command :list
|
75
124
|
end
|
76
125
|
|
@@ -117,6 +166,13 @@ command :analyses do |c|
|
|
117
166
|
Diggit::Dig.it.config.add_analysis args[0]
|
118
167
|
end
|
119
168
|
end
|
169
|
+
c.desc 'Delete an analysis.'
|
170
|
+
c.arg_name 'name'
|
171
|
+
c.command :del do |add|
|
172
|
+
add.action do |_global_options, _options, args|
|
173
|
+
Diggit::Dig.it.config.del_analysis args[0]
|
174
|
+
end
|
175
|
+
end
|
120
176
|
c.desc 'Perform analyses.'
|
121
177
|
c.command :perform do |perform|
|
122
178
|
perform.flag [:s, :sources], desc: "list of sources", type: Array, default_value: []
|
@@ -142,39 +198,10 @@ command :clone do |c|
|
|
142
198
|
c.default_command :perform
|
143
199
|
end
|
144
200
|
|
145
|
-
|
146
|
-
command :errors do |c|
|
147
|
-
c.desc 'Display the list of errors.'
|
148
|
-
c.command :list do |list|
|
149
|
-
list.action do |_global_options, _options, _args|
|
150
|
-
sources = Diggit::Dig.it.journal.sources
|
151
|
-
sources.each_index do |idx|
|
152
|
-
msg = "#{idx} #{sources[idx].url} (#{sources[idx].state})"
|
153
|
-
Log.error msg if sources[idx].error?
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
c.desc 'Display a source error.'
|
158
|
-
c.arg_name 'id'
|
159
|
-
c.command :show do |show|
|
160
|
-
show.action do |_global_options, _options, args|
|
161
|
-
source = Diggit::Dig.it.journal.sources_by_ids(args[0].to_i)[0]
|
162
|
-
Log.ok "Error summary for source #{args[0]}"
|
163
|
-
error = source.error
|
164
|
-
Log.info "URL: #{source.url}"
|
165
|
-
Log.info "State: #{source.state}"
|
166
|
-
Log.info "Error:"
|
167
|
-
Log.indent do
|
168
|
-
Log.error error[:message]
|
169
|
-
Log.info error[:backtrace].join("\n")
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
c.default_command :list
|
174
|
-
end
|
175
|
-
|
176
|
-
pre do |_global, _command, _options, _args|
|
201
|
+
pre do |global, _command, _options, _args|
|
177
202
|
Diggit::Dig.init
|
203
|
+
Log.level = :fine if global[:v]
|
204
|
+
true
|
178
205
|
end
|
179
206
|
|
180
207
|
post do |_global, _command, _options, _args|
|
data/lib/dgit.rb
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of Diggit.
|
4
|
+
#
|
5
|
+
# Diggit is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# Diggit is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
16
|
+
# along with Diggit. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Copyright 2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
|
19
|
+
#
|
2
20
|
|
3
21
|
require_relative "dgit/core"
|
4
22
|
require_relative "dgit/plugins"
|
5
23
|
require_relative "dgit/version"
|
6
|
-
require_relative "dgit/
|
24
|
+
require_relative "dgit/log"
|
data/lib/dgit/core.rb
CHANGED
@@ -1,26 +1,59 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of Diggit.
|
4
|
+
#
|
5
|
+
# Diggit is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# Diggit is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
16
|
+
# along with Diggit. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Copyright 2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
|
19
|
+
#
|
2
20
|
|
3
21
|
require 'oj'
|
4
22
|
require 'rugged'
|
5
23
|
require 'singleton'
|
6
|
-
require_relative '
|
24
|
+
require_relative 'log'
|
7
25
|
|
8
26
|
class String
|
27
|
+
# Returns a underscore cased version of the string.
|
28
|
+
# @return [String]
|
9
29
|
def underscore
|
10
30
|
gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
11
31
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2'). tr("-", "_").downcase
|
12
32
|
end
|
13
33
|
|
34
|
+
# Returns a camel cased version of the string.
|
35
|
+
# @return [String]
|
14
36
|
def camel_case
|
15
37
|
return self if self !~ /_/ && self =~ /[A-Z]+.*/
|
16
38
|
split('_').map(&:capitalize).join
|
17
39
|
end
|
18
40
|
|
41
|
+
# Returns a version of the string that can be safely used as a folder name.
|
42
|
+
# @return [string]
|
19
43
|
def id
|
20
44
|
gsub(/[^[\w-]]+/, "_")
|
21
45
|
end
|
22
46
|
end
|
23
47
|
|
48
|
+
class Module
|
49
|
+
# Return the simple name of a module.
|
50
|
+
# The simple name is the underscore cased name of the module without namespaces.
|
51
|
+
# FIXME: name returns module/class instead of module::class.
|
52
|
+
def simple_name
|
53
|
+
to_s.gsub(/^.*::/, '').underscore
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
24
57
|
module Diggit
|
25
58
|
class Source
|
26
59
|
attr_reader :url, :repository
|
@@ -68,45 +101,16 @@ module Diggit
|
|
68
101
|
@entry[:state] == :cloned
|
69
102
|
end
|
70
103
|
|
71
|
-
def
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
def analysis_performed?(name)
|
76
|
-
@entry[:performed_analyses].include?(name)
|
104
|
+
def all_analyses
|
105
|
+
performed_analyses + ongoing_analyses
|
77
106
|
end
|
78
107
|
|
79
|
-
def
|
80
|
-
|
108
|
+
def performed_analyses
|
109
|
+
@entry[:performed_analyses]
|
81
110
|
end
|
82
111
|
|
83
|
-
def
|
84
|
-
@entry[:
|
85
|
-
end
|
86
|
-
|
87
|
-
def add_ongoing_analysis(name)
|
88
|
-
@entry[:ongoing_analyses].include?(name)
|
89
|
-
end
|
90
|
-
|
91
|
-
def del_ongoing_analysis(name)
|
92
|
-
@entry[:ongoing_analyses].delete_if { |a| a == name }
|
93
|
-
end
|
94
|
-
|
95
|
-
def analysis_ongoing?(name)
|
96
|
-
@entry[:ongoing_analyses].include?(name)
|
97
|
-
end
|
98
|
-
|
99
|
-
def analyses_ongoing?(*names)
|
100
|
-
(names - @entry[:ongoing_analyses]).empty?
|
101
|
-
end
|
102
|
-
|
103
|
-
def analysis?(name)
|
104
|
-
analysis_ongoing?(name) || analysis_performed?(name)
|
105
|
-
end
|
106
|
-
|
107
|
-
def del_analysis(name)
|
108
|
-
del_ongoing_analysis(name)
|
109
|
-
del_performed_analysis(name)
|
112
|
+
def ongoing_analyses
|
113
|
+
@entry[:ongoing_analyses]
|
110
114
|
end
|
111
115
|
|
112
116
|
def clone
|
@@ -268,11 +272,23 @@ module Diggit
|
|
268
272
|
end
|
269
273
|
end
|
270
274
|
|
275
|
+
# Class to handle loading of diggit plugins.
|
276
|
+
# Diggit plugins are defined in camel cased classes derived from Plugin.
|
277
|
+
# Their name is the underscore cased version of the class name (example +MyPlugin+ becomes +my_plugin+).
|
278
|
+
# It uses a singleton pattern, so you have to create an instance like that:
|
279
|
+
# @example
|
280
|
+
# PluginLoader.instance
|
281
|
+
# @see Plugin
|
271
282
|
class PluginLoader
|
272
283
|
include Singleton
|
273
284
|
|
274
285
|
PLUGINS_TYPES = [:addon, :analysis, :join]
|
275
286
|
|
287
|
+
# Load the plugin with the given name and type.
|
288
|
+
# @param name [String] the name of the plugin
|
289
|
+
# @param type [Symbol] the type of the plugin: +:addon+, +:analysis+ or +:join+.
|
290
|
+
# @param instance [Boolean] +true+ for retrieving an instance or +false+ for retrieving the class.
|
291
|
+
# @return [Plugin, Class] the instance or class of the plugin.
|
276
292
|
def load_plugin(name, type, instance = false)
|
277
293
|
plugin = search_plugin(name, type)
|
278
294
|
if plugin
|
@@ -286,51 +302,69 @@ module Diggit
|
|
286
302
|
end
|
287
303
|
end
|
288
304
|
|
305
|
+
def self.plugin_paths(name, type, root)
|
306
|
+
Dir.glob(File.join(root, 'plugins', type.to_s, '**', "#{name}.rb"))
|
307
|
+
end
|
308
|
+
|
309
|
+
# Constructor. Should not be called directly. Use {.instance} instead.
|
310
|
+
# @return [PluginLoader]
|
311
|
+
def initialize
|
312
|
+
@plugins = {}
|
313
|
+
end
|
314
|
+
|
315
|
+
private
|
316
|
+
|
289
317
|
def search_plugin(name, type)
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
305
|
-
plugin
|
318
|
+
return @plugins[name] if @plugins.key?(name)
|
319
|
+
fail "Unknown plugin type #{type}." unless PLUGINS_TYPES.include?(type)
|
320
|
+
fail "File #{name}.rb in #{type} directories not found." unless load_file(name, type)
|
321
|
+
|
322
|
+
base_class = Object.const_get("Diggit::#{type.to_s.camel_case}")
|
323
|
+
plugins = ObjectSpace.each_object(Class).select { |c| c < base_class && c.simple_name == name }
|
324
|
+
|
325
|
+
fail "No plugin #{name} of kind #{type} found." if plugins.empty?
|
326
|
+
warn "Ambiguous plugin name: several plugins of kind #{type} named #{name} were found." if plugins.size > 1
|
327
|
+
|
328
|
+
@plugins[name] = plugins[0]
|
329
|
+
plugins[0]
|
306
330
|
end
|
307
331
|
|
308
332
|
def load_file(name, type)
|
309
|
-
f_glob = PluginLoader.
|
310
|
-
f_home = PluginLoader.
|
311
|
-
f_local = PluginLoader.
|
333
|
+
f_glob = PluginLoader.plugin_paths(name, type, File.expand_path('../..', File.dirname(File.realpath(__FILE__))))
|
334
|
+
f_home = PluginLoader.plugin_paths(name, type, File.join(Dir.home, Dig::DGIT_FOLDER))
|
335
|
+
f_local = PluginLoader.plugin_paths(name, type, Dig.it.folder)
|
336
|
+
Log.debug "Plugin files in global: #{f_glob}."
|
337
|
+
Log.debug "Plugin files in home: #{f_home}."
|
338
|
+
Log.debug "Plugin files in local directory: #{f_local}."
|
312
339
|
found = true
|
313
|
-
if
|
314
|
-
require
|
315
|
-
elsif
|
316
|
-
require
|
317
|
-
elsif
|
318
|
-
require
|
340
|
+
if !f_local.empty?
|
341
|
+
f_local.each { |f| require File.expand_path(f) }
|
342
|
+
elsif !f_home.empty?
|
343
|
+
f_home.each { |f| require File.expand_path(f) }
|
344
|
+
elsif !f_glob.empty?
|
345
|
+
f_glob.each { |f| require File.expand_path(f) }
|
319
346
|
else
|
320
347
|
found = false
|
321
348
|
end
|
322
349
|
found
|
323
350
|
end
|
324
|
-
|
325
|
-
def self.plugin_path(name, type, root)
|
326
|
-
File.expand_path("#{name}.rb", File.expand_path(type.to_s, File.expand_path('plugins', root)))
|
327
|
-
end
|
328
|
-
|
329
|
-
def initialize
|
330
|
-
@plugins = {}
|
331
|
-
end
|
332
351
|
end
|
333
352
|
|
353
|
+
# Main diggit class.
|
354
|
+
# It must be runned in a folder containing a +.dgit+ folder with a proper configuration.
|
355
|
+
# Access configuration, options, sources and journal from this object.
|
356
|
+
# It implements the singleton pattern.
|
357
|
+
# You can initialize it via {.init} and retrieve the instance via {.it}.
|
358
|
+
# @!attribute [r] config
|
359
|
+
# @return [Config] the config.
|
360
|
+
# @!attribute [r] options
|
361
|
+
# @return [Hash<String,Object>] the options.
|
362
|
+
# @!attribute [r] journal
|
363
|
+
# @return [Journal] the journal.
|
364
|
+
# @!attribute [r] folder
|
365
|
+
# @return [String] the folder in which diggit is running.
|
366
|
+
# @!attribute [r] plugin_loader
|
367
|
+
# @return [PluginLoader] utility classes to load plugins.
|
334
368
|
class Dig
|
335
369
|
DGIT_FOLDER = ".dgit"
|
336
370
|
DGIT_SOURCES = "sources"
|
@@ -338,15 +372,22 @@ module Diggit
|
|
338
372
|
DGIT_OPTIONS = "options"
|
339
373
|
DGIT_JOURNAL = "journal"
|
340
374
|
|
375
|
+
private_constant :DGIT_SOURCES, :DGIT_CONFIG, :DGIT_OPTIONS, :DGIT_JOURNAL
|
376
|
+
|
341
377
|
attr_reader :config, :options, :journal, :plugin_loader, :folder
|
342
378
|
|
343
379
|
@diggit = nil
|
344
380
|
|
381
|
+
# Returns the diggit instance.
|
382
|
+
# @return [Dig] the instance.
|
345
383
|
def self.it
|
346
384
|
fail "Diggit has not been initialized." if @diggit.nil?
|
347
385
|
@diggit
|
348
386
|
end
|
349
387
|
|
388
|
+
# Initialize and return the diggit instance into the given folder.
|
389
|
+
# @param folder the path to the folder.
|
390
|
+
# @return [Dig] the instance.
|
350
391
|
def self.init(folder = '.')
|
351
392
|
@diggit = Dig.new(folder)
|
352
393
|
@diggit.load_options
|
@@ -355,22 +396,56 @@ module Diggit
|
|
355
396
|
@diggit
|
356
397
|
end
|
357
398
|
|
399
|
+
# Initialize a folder to be a diggit folder by creating an empty configuration.
|
400
|
+
# It creates a +.dgit+ folder containing a +journal+, +config+, +options+ files.
|
401
|
+
# It creates a +sources+ folder.
|
402
|
+
# It creates a +plugins+ folder.
|
403
|
+
# Directory creation is skipped if folder already exist.
|
404
|
+
# @param folder the path to the folder.
|
405
|
+
# @return [void]
|
358
406
|
def self.init_dir(folder = '.')
|
359
407
|
dgit_folder = File.expand_path(DGIT_FOLDER, folder)
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
408
|
+
unless File.exist?(dgit_folder)
|
409
|
+
FileUtils.mkdir(dgit_folder)
|
410
|
+
Oj.to_file(File.expand_path(DGIT_CONFIG, dgit_folder), Config.empty_config)
|
411
|
+
Oj.to_file(File.expand_path(DGIT_OPTIONS, dgit_folder), {})
|
412
|
+
FileUtils.touch(File.expand_path(DGIT_SOURCES, dgit_folder))
|
413
|
+
Oj.to_file(File.expand_path(DGIT_JOURNAL, dgit_folder), {})
|
414
|
+
end
|
415
|
+
FileUtils.mkdir(File.expand_path('sources', folder)) unless File.exist?(File.expand_path('sources', folder))
|
416
|
+
unless File.exist?(File.expand_path("plugins", folder))
|
417
|
+
FileUtils.mkdir_p(File.expand_path("plugins", folder))
|
418
|
+
FileUtils.mkdir_p(File.expand_path("plugins/analysis", folder))
|
419
|
+
FileUtils.mkdir_p(File.expand_path("plugins/addon", folder))
|
420
|
+
FileUtils.mkdir_p(File.expand_path("plugins/join", folder))
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
# Return the path of the given config file
|
425
|
+
# @param name [String] name of the file
|
426
|
+
# @return [String] the path to the file.
|
427
|
+
def config_path(name)
|
428
|
+
File.expand_path(name, File.expand_path(DGIT_FOLDER, @folder))
|
366
429
|
end
|
367
430
|
|
431
|
+
# Return the path of the given file in the diggit folder
|
432
|
+
# @param name [String] name of the file
|
433
|
+
# @return [String] the path to the file.
|
434
|
+
def file_path(name)
|
435
|
+
File.expand_path(name, @folder)
|
436
|
+
end
|
437
|
+
|
438
|
+
# Constructor. Should not be called directly.
|
439
|
+
# Use {.init} and {.it} instead.
|
440
|
+
# @return [Dig] a diggit object.
|
368
441
|
def initialize(folder)
|
369
442
|
fail "Folder #{folder} is not a diggit folder." unless File.exist?(File.expand_path(DGIT_FOLDER, folder))
|
370
443
|
@plugin_loader = PluginLoader.instance
|
371
444
|
@folder = folder
|
372
445
|
end
|
373
446
|
|
447
|
+
# Load the journal from +.dgit/journal+
|
448
|
+
# @return [void]
|
374
449
|
def load_journal
|
375
450
|
url_array = []
|
376
451
|
IO.readlines(config_path(DGIT_SOURCES)).each { |l| url_array << l.strip }
|
@@ -379,47 +454,83 @@ module Diggit
|
|
379
454
|
@journal = Journal.new(hash)
|
380
455
|
end
|
381
456
|
|
457
|
+
# Save the journal to +.dgit/journal+
|
458
|
+
# @return [void]
|
382
459
|
def save_journal
|
383
460
|
hash = @journal.to_hash
|
384
461
|
File.open(config_path(DGIT_SOURCES), "w") { |f| hash[:urls].each { |u| f.puts(u) } }
|
385
462
|
Oj.to_file(config_path(DGIT_JOURNAL), { sources: hash[:sources], workspace: hash[:workspace] })
|
386
463
|
end
|
387
464
|
|
465
|
+
# Load the options from +.dgit/options+
|
466
|
+
# @return [void]
|
388
467
|
def load_options
|
389
468
|
@options = Oj.load_file(config_path(DGIT_OPTIONS))
|
390
469
|
end
|
391
470
|
|
471
|
+
# Save the options to +.dgit/options+
|
472
|
+
# @return [void]
|
392
473
|
def save_options
|
393
474
|
Oj.to_file(config_path(DGIT_OPTIONS), options)
|
394
475
|
end
|
395
476
|
|
477
|
+
# Load the config from +.dgit/config+
|
478
|
+
# @return [void]
|
396
479
|
def load_config
|
397
480
|
@config = Config.new(Oj.load_file(config_path(DGIT_CONFIG)))
|
398
481
|
end
|
399
482
|
|
483
|
+
# Save the config to +.dgit/config+
|
484
|
+
# @return [void]
|
400
485
|
def save_config
|
401
486
|
config_hash = @config.to_hash
|
402
487
|
Oj.to_file(config_path(DGIT_CONFIG), config_hash)
|
403
488
|
end
|
404
489
|
|
490
|
+
# Clone the repository of all sources with the given source ids.
|
491
|
+
# @param source_ids [Array<Integer>] the ids of the sources.
|
492
|
+
# @return [void]
|
405
493
|
def clone(*source_ids)
|
406
494
|
@journal.sources_by_ids(*source_ids).select(&:new?).each(&:clone)
|
407
495
|
ensure
|
408
496
|
save_journal
|
409
497
|
end
|
410
498
|
|
499
|
+
# Perform the given analyses on sources with the given ids using the given mode.
|
500
|
+
# @param source_ids [Array<Integer>] the ids of the sources.
|
501
|
+
# @param analyses [Array<String>] the names of the analyses.
|
502
|
+
# @param mode [Symbol] the mode: +:run+, +:rerun+ or +:clean+.
|
503
|
+
# @return [void]
|
411
504
|
def analyze(source_ids = [], analyses = [], mode = :run)
|
412
505
|
@journal.sources_by_ids(*source_ids).select(&:cloned?).each do |s|
|
413
506
|
@config.get_analyses(*analyses).each do |klass|
|
414
507
|
a = klass.new(@options)
|
415
508
|
s.load_repository
|
416
509
|
a.source = s
|
417
|
-
clean_analysis(s, a) if clean_mode?(mode) && s.
|
418
|
-
run_analysis(s, a) if run_mode?(mode) && !s.
|
510
|
+
clean_analysis(s, a) if clean_mode?(mode) && s.all_analyses.include?(a.name)
|
511
|
+
run_analysis(s, a) if run_mode?(mode) && !s.performed_analyses.include?(a.name)
|
419
512
|
end
|
420
513
|
end
|
421
514
|
end
|
422
515
|
|
516
|
+
# Perform the given joins on sources with the given ids using the given mode.
|
517
|
+
# @param source_ids [Array<Integer>] the ids of the sources.
|
518
|
+
# @param joins [Array<String>] the names of the analyses.
|
519
|
+
# @param mode [Symbol] the mode: +:run+, +:rerun+ or +:clean+.
|
520
|
+
# @return [void]
|
521
|
+
def join(source_ids = [], joins = [], mode = :run)
|
522
|
+
@config.get_joins(*joins).each do |klass|
|
523
|
+
j = klass.new(@options)
|
524
|
+
j.clean if clean_mode?(mode)
|
525
|
+
source_array = @journal.sources_by_ids(*source_ids).select do |s|
|
526
|
+
s.cloned? && (klass.required_analyses - s.performed_analyses).empty?
|
527
|
+
end
|
528
|
+
run_join(j, source_array) if run_mode?(mode) && !source_array.empty?
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
private
|
533
|
+
|
423
534
|
def clean_mode?(mode)
|
424
535
|
mode == :rerun || mode == :clean
|
425
536
|
end
|
@@ -436,10 +547,10 @@ module Diggit
|
|
436
547
|
end
|
437
548
|
|
438
549
|
def run_analysis(s, a)
|
439
|
-
s.
|
550
|
+
s.ongoing_analyses << a.name
|
440
551
|
a.run
|
441
|
-
s.
|
442
|
-
s.
|
552
|
+
s.ongoing_analyses.pop
|
553
|
+
s.performed_analyses << a.name
|
443
554
|
rescue => e
|
444
555
|
Log.error "Error applying analysis #{a.name} on #{s.url}"
|
445
556
|
s.error = Journal.dump_error(e)
|
@@ -447,16 +558,6 @@ module Diggit
|
|
447
558
|
save_journal
|
448
559
|
end
|
449
560
|
|
450
|
-
def join(source_ids = [], joins = [], mode = :run)
|
451
|
-
@config.get_joins(*joins).each do |klass|
|
452
|
-
j = klass.new(@options)
|
453
|
-
j.clean if clean_mode?(mode)
|
454
|
-
source_array = @journal.sources_by_ids(*source_ids)
|
455
|
-
.select { |s| s.cloned? && s.analyses_performed?(*klass.required_analyses) }
|
456
|
-
run_join(j, source_array) if run_mode?(mode) && !source_array.empty?
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
561
|
def run_join(j, source_array)
|
461
562
|
j.sources = source_array
|
462
563
|
j.run
|
@@ -467,13 +568,5 @@ module Diggit
|
|
467
568
|
ensure
|
468
569
|
save_journal
|
469
570
|
end
|
470
|
-
|
471
|
-
def config_path(name)
|
472
|
-
File.expand_path(name, File.expand_path(DGIT_FOLDER, @folder))
|
473
|
-
end
|
474
|
-
|
475
|
-
def file_path(name)
|
476
|
-
File.expand_path(name, @folder)
|
477
|
-
end
|
478
571
|
end
|
479
572
|
end
|