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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab5b0bd0d5959100238fb8bdcd2d6471a660bc94
4
- data.tar.gz: 41bcf9e0cea8e6110faded4f51b37caa8475adf2
3
+ metadata.gz: 9fbc5e12f3c7806df481b5627dc5f904f89428c5
4
+ data.tar.gz: 6600fc64a91b44b386795d16a792caa11f12d932
5
5
  SHA512:
6
- metadata.gz: 2d11da8a99ed2706e882bbdaf9a95e011f46fb3f3e1941c6728311de15b7796ab624ce62ac0220e778094f6a8f29e0b798e79efa6c5916de8cce471a8f9b0b8f
7
- data.tar.gz: f7272bb6679af26829ee4ccbc1b013f2f6d6c1e2026b01e0501335a0cd726e82b117c42fc8f2a28fbc24bae2ef988c86b37fd54f06581f3b78520cee010850a1
6
+ metadata.gz: 5defc137d1d9cd066c730c4c2d01b2da01bd7f848866cd01888caf6b97fea24377e293ddfc66ade5f03f9b6742ca3bc177b611762a30deb697b9fe6ff894f326
7
+ data.tar.gz: 535718d8f71f8f088f08c08bab2edb33e8e270db0e928a208d26c273c4a71b445863060ec2157175adb33fc33292e8120ba4d0df94931f96a1589db783a800ed
@@ -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
- desc 'Display errors.'
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|
@@ -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/formatador"
24
+ require_relative "dgit/log"
@@ -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 'formatador'
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 add_performed_analysis(name)
72
- @entry[:performed_analyses] << name
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 analyses_performed?(*names)
80
- (names - @entry[:performed_analyses]).empty?
108
+ def performed_analyses
109
+ @entry[:performed_analyses]
81
110
  end
82
111
 
83
- def del_performed_analysis(name)
84
- @entry[:performed_analyses].delete_if { |a| a == name }
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
- plugin = nil
291
- if @plugins.key?(name)
292
- plugin = @plugins[name]
293
- else
294
- fail "Unknown plugin type #{type}." unless PLUGINS_TYPES.include?(type)
295
- if load_file(name, type)
296
- plugin = Object.const_get(name.camel_case)
297
- base_class = Object.const_get("Diggit::#{type.to_s.camel_case}")
298
- if plugin < base_class
299
- @plugins[name] = plugin
300
- else
301
- fail "Plugin #{name} not of kind #{type}."
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.plugin_path(name, type, File.expand_path('../..', File.dirname(File.realpath(__FILE__))))
310
- f_home = PluginLoader.plugin_path(name, type, File.expand_path(Dig::DGIT_FOLDER, Dir.home))
311
- f_local = PluginLoader.plugin_path(name, type, Dig.it.folder)
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 File.exist?(f_local)
314
- require f_local
315
- elsif File.exist?(f_home)
316
- require f_home
317
- elsif File.exist?(f_glob)
318
- require f_glob
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
- FileUtils.mkdir(dgit_folder)
361
- Oj.to_file(File.expand_path(DGIT_CONFIG, dgit_folder), Config.empty_config)
362
- Oj.to_file(File.expand_path(DGIT_OPTIONS, dgit_folder), {})
363
- FileUtils.touch(File.expand_path(DGIT_SOURCES, dgit_folder))
364
- Oj.to_file(File.expand_path(DGIT_JOURNAL, dgit_folder), {})
365
- FileUtils.mkdir(File.expand_path('sources', folder))
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.analysis?(a.name)
418
- run_analysis(s, a) if run_mode?(mode) && !s.analysis_performed?(a.name)
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.add_ongoing_analysis(a.name)
550
+ s.ongoing_analyses << a.name
440
551
  a.run
441
- s.del_ongoing_analysis(a.name)
442
- s.add_performed_analysis(a.name)
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