diggit 2.0.0 → 2.0.1
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/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 [](https://travis-ci.org/jrfaller/diggit) [](https://coveralls.io/r/jrfaller/diggit?branch=master) [](http://inch-ci.org/github/jrfaller/diggit) [](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
|