diggit 2.1.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2fa14be04009f4668ce08541bcc05aa050308de7
4
- data.tar.gz: 2f956728d1a7d6e2ea999a0d2aa59d60ecbad58a
3
+ metadata.gz: 60e58099916b06eceaa99f9bad1f18822ac74106
4
+ data.tar.gz: 5568fc8c3a6bd36f09f25d7ceeb9233da126ffea
5
5
  SHA512:
6
- metadata.gz: 53da80f0affd555bb133b5b36129772d1a915fb5d04661f1d5b7a7c94d00a1cf347d092d5775f05372bd7b434ee28a21e6b3c0822d4a84485e4d94c4e2c20d7c
7
- data.tar.gz: 44488dca2f0ad7d39b788012e73c1ee17c608d958bde77be62cdb1cd6d20c5f84f11a6ac022e0e8663d0ad054a63f6bd89ce730e0a8d16d760ef477adbb82d90
6
+ metadata.gz: 84dd036f313699556b0fafc8604d56b45ceb7441dc7f4530061c98816973f6bb0c71406245b3569dcfa9cf244caab20d96702ba16e9f802dafce94994f6ea2e5
7
+ data.tar.gz: d82cc5a83c57e774af69f367df32dc695b72cb2807963e687502f3de309d7bf4ea784b4fa7bad6216484feab48e2c1e675f3120fefb99af444784e92c98217b3
@@ -1,5 +1,11 @@
1
1
  # Changelog of Diggit
2
2
 
3
+ ### Version 2.1.1
4
+ * Fixed small bugs in the CLI
5
+ * Fixed source error not showing up in case of clone error
6
+ * Now urls can have a trailing |id to enable checkout a tag, branch or commit with a specific id
7
+ * Out addon have more utility methods
8
+
3
9
  ### Version 2.1.0
4
10
  * Now repositories are reseted to master by default
5
11
  * Journal infrastructure has been vastly improved
data/README.md CHANGED
@@ -8,9 +8,20 @@ A ruby tool to analyze Git repositories
8
8
 
9
9
  Just run `gem install diggit`.
10
10
 
11
- ## From the source
11
+ ## From the source, with bundler
12
12
 
13
- Clone diggit using the following command: `git clone https://github.com/jrfaller/diggit.git`. The `dgit` tool is in the `bin` folder.
13
+ Install diggit using the following commands:
14
+ ```
15
+ git clone https://github.com/jrfaller/diggit.git
16
+ cd diggit
17
+ gem install bundler --user-install
18
+ bundler install
19
+ ```
20
+ Beware, the gem bin directory must be in your path. Also, the `dgit` command is in the `bin` folder of diggit.
21
+
22
+ ## From the source, with vagrant
23
+
24
+ You can automatically get a working VM with all required dependencies with only one command, how cool is that? For this, just install [vagrant](https://www.vagrantup.com/) and [virtualbox](https://www.virtualbox.org/), and `vagrant up` in a freshly cloned diggit folder (see previous section). Beware, this magic only works on Mac OS and Linux because it uses NFS shared folders.
14
25
 
15
26
  # Usage
16
27
 
@@ -26,15 +37,15 @@ You can add some repositories to be analyzed with the following command: `dgit s
26
37
 
27
38
  ### Using addons
28
39
 
29
- Addons add features the the diggit tool: for instance capability of writing to a MongoDB database, etc. To enable addons for your current diggit folder you can use the following command: `dgit addons add TestAddon`.
40
+ Addons add features the the diggit tool: for instance capability of writing to a MongoDB database, etc. To enable addons for your current diggit folder you can use the following command: `dgit addons add test_addon`.
30
41
 
31
42
  ### Setting-up analyses
32
43
 
33
- An analysis is applied to each repository. You can configure the analyses to be performed with the following command: `dgit analyses add TestAnalysis`. Analyses are performed in the order they have been added.
44
+ An analysis is applied to each repository. You can configure the analyses to be performed with the following command: `dgit analyses add test_analysis`. Analyses are performed in the order they have been added.
34
45
 
35
46
  ### Setting-up joins
36
47
 
37
- A join is performed after all analyses of all repositories have been performed. You can configure the joins to be performed with the following command: `dgit joins add TestJoin`. Joins are performed in the order they have been added.
48
+ A join is performed after all analyses of all repositories have been performed. You can configure the joins to be performed with the following command: `dgit joins add test_join`. Joins are performed in the order they have been added.
38
49
 
39
50
  ## Running analyses
40
51
 
data/bin/dgit CHANGED
@@ -49,8 +49,8 @@ module Diggit
49
49
  c.action do |_global_options, _options, _args|
50
50
  Log.info "Config"
51
51
  Log.info "======"
52
- Log.info "- Analyses: #{Diggit::Dig.it.config.get_analyses.join(', ')}"
53
- Log.info "- Joins: #{Diggit::Dig.it.config.get_joins.join(', ')}"
52
+ Log.info "- Analyses: #{Diggit::Dig.it.config.get_analyses.map(&:name).join(', ')}"
53
+ Log.info "- Joins: #{Diggit::Dig.it.config.get_joins.map(&:name).join(', ')}"
54
54
  Log.info ""
55
55
  Log.info "Journal"
56
56
  Log.info "======="
@@ -64,6 +64,20 @@ module Diggit
64
64
  Log.ok "* Ok: #{Diggit::Dig.it.journal.sources_by_state(:cloned).size}"
65
65
  Log.error "* Error: #{Diggit::Dig.it.journal.sources_by_state(:cloned, true).size}"
66
66
  end
67
+ Log.info "- Performed joins:" unless Diggit::Dig.it.journal.workspace.performed.empty?
68
+ Diggit::Dig.it.journal.workspace.performed.each do |e|
69
+ Log.indent { Log.info "#{e.name}, time: #{e.duration}" }
70
+ end
71
+ Log.info "- Canceled joins:" unless Diggit::Dig.it.journal.workspace.canceled.empty?
72
+ Diggit::Dig.it.journal.workspace.canceled.each do |e|
73
+ Log.indent do
74
+ Log.info "#{e.name}, time: #{e.duration}"
75
+ Log.indent do
76
+ Log.error e.error.message
77
+ Log.error e.error.backtrace.join("\n")
78
+ end
79
+ end
80
+ end
67
81
  end
68
82
  end
69
83
 
@@ -74,7 +88,7 @@ module Diggit
74
88
  list.action do |_global_options, _options, _args|
75
89
  sources = Diggit::Dig.it.journal.sources
76
90
  sources.each_index do |idx|
77
- msg = "#{idx} #{sources[idx].url} (#{sources[idx].state})"
91
+ msg = "#{idx} #{sources[idx].url} (#{sources[idx].entry.state})"
78
92
  sources[idx].entry.error? ? Log.error(msg) : Log.ok(msg)
79
93
  end
80
94
  end
@@ -86,11 +100,18 @@ module Diggit
86
100
  Diggit::Dig.it.journal.add_source args[0]
87
101
  end
88
102
  end
103
+ c.desc 'Delete a source.'
104
+ c.arg_name 'id'
105
+ c.command :del do |del|
106
+ del.action do |_global_options, _options, args|
107
+ Diggit::Dig.it.journal.del_source args[0]
108
+ end
109
+ end
89
110
  c.desc 'Import sources from a file.'
90
111
  c.arg_name 'file'
91
112
  c.command :import do |import|
92
113
  import.action do |_global_options, _options, args|
93
- File.open(args[0]).each { |line| Diggit::Dig.it.journal.add_source(line) }
114
+ File.open(args[0]).each { |line| Diggit::Dig.it.journal.add_source(line.strip) }
94
115
  end
95
116
  end
96
117
  c.desc 'Display all sources in error.'
@@ -110,11 +131,13 @@ module Diggit
110
131
  src = Diggit::Dig.it.journal.sources_by_ids(args[0].to_i)[0]
111
132
  Log.info "URL: #{src.url}"
112
133
  Log.info "State: #{src.entry.state}"
134
+ unless src.entry.error.nil?
135
+ Log.error src.entry.error.message
136
+ Log.error src.entry.error.backtrace.join("\n")
137
+ end
113
138
  Log.info "Performed analyses:" unless src.entry.performed.empty?
114
139
  src.entry.performed.each do |e|
115
- Log.indent do
116
- Log.info "#{e.name}, time: #{e.duration}"
117
- end
140
+ Log.indent { Log.info "#{e.name}, time: #{e.duration}" }
118
141
  end
119
142
  Log.info "Canceled analyses:" unless src.entry.canceled.empty?
120
143
  src.entry.canceled.each do |e|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
2
3
  #
3
4
  # This file is part of Diggit.
@@ -28,8 +29,7 @@ class String
28
29
  # Returns a underscore cased version of the string.
29
30
  # @return [String]
30
31
  def underscore
31
- gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
32
- .gsub(/([a-z\d])([A-Z])/, '\1_\2'). tr("-", "_").downcase
32
+ gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2'). tr("-", "_").downcase
33
33
  end
34
34
 
35
35
  # Returns a camel cased version of the string.
@@ -57,10 +57,14 @@ end
57
57
 
58
58
  module Diggit
59
59
  class Source
60
- attr_reader :url, :repository, :entry
60
+ DEFAULT_BRANCH = "origin/master".freeze
61
+
62
+ attr_reader :url, :repository, :entry, :oid
61
63
 
62
64
  def initialize(url)
63
- @url = url
65
+ infos = url.split(/\|/)
66
+ @url = infos[0]
67
+ @oid = infos.size > 1 ? infos[1] : DEFAULT_BRANCH
64
68
  @entry = SourceEntry.new
65
69
  @repository = nil
66
70
  end
@@ -75,21 +79,19 @@ module Diggit
75
79
 
76
80
  def clone
77
81
  @entry.error = nil
78
- if File.exist?(folder)
79
- Rugged::Repository.new(folder)
80
- else
81
- Rugged::Repository.clone_at(url, folder)
82
- end
82
+ @repository = File.exist?(folder) ? Rugged::Repository.new(folder) : Rugged::Repository.clone_at(url, folder)
83
+ @repository.checkout(@oid, { strategy: :force })
83
84
  @entry.state = :cloned
84
85
  rescue => e
85
- Log.error "Error cloning #{url}."
86
+ Log.error "Error cloning #{url}: #{e}"
87
+ e.backtrace.each { |l| Log.debug(l) }
86
88
  @entry.error = e
87
89
  end
88
90
 
89
91
  def load_repository
90
- fail "Source not cloned #{url}." if @entry.new?
92
+ raise "Source not cloned #{url}." if @entry.new?
91
93
  @repository = Rugged::Repository.new(folder)
92
- @repository.checkout("origin/master")
94
+ @repository.checkout(@oid, { strategy: :force })
93
95
  end
94
96
  end
95
97
 
@@ -114,7 +116,7 @@ module Diggit
114
116
  source_array = sources
115
117
  result = []
116
118
  ids.each do |id|
117
- fail "No such source index #{id}." if id >= source_array.length
119
+ raise "No such source index #{id}." if id >= source_array.length
118
120
  result << source_array[id]
119
121
  end
120
122
  result
@@ -125,7 +127,14 @@ module Diggit
125
127
  end
126
128
 
127
129
  def add_source(url)
128
- @sources[url] = Source.new(url) unless @sources.key?(url)
130
+ key = url.split(/\|/)[0]
131
+ @sources[key] = Source.new(url) unless @sources.key?(key)
132
+ Dig.it.save_journal
133
+ end
134
+
135
+ def del_source(id)
136
+ source = sources_by_ids(id).first
137
+ @sources.delete(source.url)
129
138
  Dig.it.save_journal
130
139
  end
131
140
  end
@@ -207,7 +216,7 @@ module Diggit
207
216
  class PluginLoader
208
217
  include Singleton
209
218
 
210
- PLUGINS_TYPES = [:addon, :analysis, :join]
219
+ PLUGINS_TYPES = [:addon, :analysis, :join].freeze
211
220
 
212
221
  # Load the plugin with the given name and type.
213
222
  # @param name [String] the name of the plugin
@@ -216,15 +225,9 @@ module Diggit
216
225
  # @return [Plugin, Class] the instance or class of the plugin.
217
226
  def load_plugin(name, type, instance = false)
218
227
  plugin = search_plugin(name, type)
219
- if plugin
220
- if instance
221
- return plugin.new(Dig.it.options)
222
- else
223
- return plugin
224
- end
225
- else
226
- fail "Plugin #{name} not found."
227
- end
228
+ raise "Plugin #{name} not found." unless plugin
229
+ return plugin.new(Dig.it.options) if instance
230
+ plugin
228
231
  end
229
232
 
230
233
  def self.plugin_paths(name, type, root)
@@ -241,13 +244,13 @@ module Diggit
241
244
 
242
245
  def search_plugin(name, type)
243
246
  return @plugins[name] if @plugins.key?(name)
244
- fail "Unknown plugin type #{type}." unless PLUGINS_TYPES.include?(type)
245
- fail "File #{name}.rb in #{type} directories not found." unless load_file(name, type)
247
+ raise "Unknown plugin type #{type}." unless PLUGINS_TYPES.include?(type)
248
+ raise "File #{name}.rb in #{type} directories not found." unless load_file(name, type)
246
249
 
247
250
  base_class = Object.const_get("Diggit::#{type.to_s.camel_case}")
248
251
  plugins = ObjectSpace.each_object(Class).select { |c| c < base_class && c.simple_name == name }
249
252
 
250
- fail "No plugin #{name} of kind #{type} found." if plugins.empty?
253
+ raise "No plugin #{name} of kind #{type} found." if plugins.empty?
251
254
  warn "Ambiguous plugin name: several plugins of kind #{type} named #{name} were found." if plugins.size > 1
252
255
 
253
256
  @plugins[name] = plugins[0]
@@ -291,11 +294,11 @@ module Diggit
291
294
  # @!attribute [r] plugin_loader
292
295
  # @return [PluginLoader] utility classes to load plugins.
293
296
  class Dig
294
- DGIT_FOLDER = ".dgit"
295
- DGIT_SOURCES = "sources"
296
- DGIT_CONFIG = "config"
297
- DGIT_OPTIONS = "options"
298
- DGIT_JOURNAL = "journal"
297
+ DGIT_FOLDER = ".dgit".freeze
298
+ DGIT_SOURCES = "sources".freeze
299
+ DGIT_CONFIG = "config".freeze
300
+ DGIT_OPTIONS = "options".freeze
301
+ DGIT_JOURNAL = "journal".freeze
299
302
 
300
303
  private_constant :DGIT_SOURCES, :DGIT_CONFIG, :DGIT_OPTIONS, :DGIT_JOURNAL
301
304
 
@@ -306,7 +309,7 @@ module Diggit
306
309
  # Returns the diggit instance.
307
310
  # @return [Dig] the instance.
308
311
  def self.it
309
- fail "Diggit has not been initialized." if @diggit.nil?
312
+ raise "Diggit has not been initialized." if @diggit.nil?
310
313
  @diggit
311
314
  end
312
315
 
@@ -338,12 +341,11 @@ module Diggit
338
341
  Oj.to_file(File.expand_path(DGIT_JOURNAL, dgit_folder), Journal.new)
339
342
  end
340
343
  FileUtils.mkdir(File.expand_path('sources', folder)) unless File.exist?(File.expand_path('sources', folder))
341
- unless File.exist?(File.expand_path("plugins", folder))
342
- FileUtils.mkdir_p(File.expand_path("plugins", folder))
343
- FileUtils.mkdir_p(File.expand_path("plugins/analysis", folder))
344
- FileUtils.mkdir_p(File.expand_path("plugins/addon", folder))
345
- FileUtils.mkdir_p(File.expand_path("plugins/join", folder))
346
- end
344
+ return if File.exist?(File.expand_path("plugins", folder))
345
+ FileUtils.mkdir_p(File.expand_path("plugins", folder))
346
+ FileUtils.mkdir_p(File.expand_path("plugins/analysis", folder))
347
+ FileUtils.mkdir_p(File.expand_path("plugins/addon", folder))
348
+ FileUtils.mkdir_p(File.expand_path("plugins/join", folder))
347
349
  end
348
350
 
349
351
  # Return the path of the given config file
@@ -364,7 +366,7 @@ module Diggit
364
366
  # Use {.init} and {.it} instead.
365
367
  # @return [Dig] a diggit object.
366
368
  def initialize(folder)
367
- fail "Folder #{folder} is not a diggit folder." unless File.exist?(File.expand_path(DGIT_FOLDER, folder))
369
+ raise "Folder #{folder} is not a diggit folder." unless File.exist?(File.expand_path(DGIT_FOLDER, folder))
368
370
  @plugin_loader = PluginLoader.instance
369
371
  @folder = folder
370
372
  end
@@ -474,7 +476,8 @@ module Diggit
474
476
  entry.toc
475
477
  entry.error = e
476
478
  placeholder.canceled << entry
477
- Log.error "Error cleaning #{runnable.name}"
479
+ Log.error "Error cleaning #{runnable.name}: #{e}"
480
+ e.backtrace.each { |l| Log.debug(l) }
478
481
  ensure
479
482
  save_journal
480
483
  end
@@ -488,7 +491,8 @@ module Diggit
488
491
  entry.toc
489
492
  entry.error = e
490
493
  placeholder.canceled << entry
491
- Log.error "Error running #{runnable.name}"
494
+ Log.error "Error running #{runnable.name}: #{e}"
495
+ e.backtrace.each { |l| Log.debug(l) }
492
496
  else
493
497
  entry.toc
494
498
  placeholder.performed << entry
@@ -29,11 +29,7 @@ module Diggit
29
29
  # @param e [Exception, nil] the error, to indicate an absence of error, pass +nil+.
30
30
  # @return [void]
31
31
  def error=(e)
32
- if e.nil?
33
- @error = nil
34
- else
35
- @error = ErrorEntry.new(e)
36
- end
32
+ @error = e.nil? ? nil : ErrorEntry.new(e)
37
33
  end
38
34
  end
39
35
 
@@ -54,7 +50,7 @@ module Diggit
54
50
  # Error status of the element.
55
51
  # @return [Boolean]
56
52
  def error?
57
- @canceled.size > 0
53
+ !@canceled.empty?
58
54
  end
59
55
 
60
56
  # Check if a runnable has been performed or canceled.
@@ -63,13 +59,9 @@ module Diggit
63
59
  # @return [Boolean]
64
60
  def has?(runnable_or_string, state = :all)
65
61
  name = retrieve_name(runnable_or_string)
66
- if state == :performed
67
- return @performed.count { |e| e.name == name } > 0
68
- elsif state == :canceled
69
- return @canceled.count { |e| e.name == name } > 0
70
- elsif state == :all
71
- return (@performed + @canceled).count { |e| e.name == name } > 0
72
- end
62
+ return @performed.count { |e| e.name == name } > 0 if state == :performed
63
+ return @canceled.count { |e| e.name == name } > 0 if state == :canceled
64
+ return (@performed + @canceled).count { |e| e.name == name } > 0 if state == :all
73
65
  end
74
66
 
75
67
  # Remove a runnable from all the entries.
@@ -84,11 +76,8 @@ module Diggit
84
76
  private
85
77
 
86
78
  def retrieve_name(runnable_or_string)
87
- if runnable_or_string.is_a? String
88
- return runnable_or_string
89
- else
90
- return runnable_or_string.name
91
- end
79
+ return runnable_or_string if runnable_or_string.is_a? String
80
+ runnable_or_string.name
92
81
  end
93
82
  end
94
83
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
2
3
  #
3
4
  # This file is part of Diggit.
@@ -18,5 +19,5 @@
18
19
  # Copyright 2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
19
20
 
20
21
  module Diggit
21
- VERSION = '2.1.0'
22
+ VERSION = '2.1.1'.freeze
22
23
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
2
3
  #
3
4
  # This file is part of Diggit.
@@ -25,8 +26,8 @@ require 'mongo'
25
26
  # @!attribute [r] db
26
27
  # @return [Mongo::DB] the mongo database object.
27
28
  class Db < Diggit::Addon
28
- DEFAULT_SERVER = '127.0.0.1:27017'
29
- DEFAULT_DB = 'diggit'
29
+ DEFAULT_SERVER = '127.0.0.1:27017'.freeze
30
+ DEFAULT_DB = 'diggit'.freeze
30
31
 
31
32
  attr_reader :client
32
33
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
2
3
  #
3
4
  # This file is part of Diggit.
@@ -17,7 +18,7 @@
17
18
  #
18
19
  # Copyright 2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
19
20
 
20
- # A output addon for Diggit. The name of the addon is :output, and can be reached in the
21
+ # An output addon for Diggit. The name of the addon is :output, and can be reached in the
21
22
  # addons hash. This addon might use an :output hash in the global options. In this hash, the
22
23
  # :out key allows to configure the name of the output folder and :tmp the name of the temporary output
23
24
  # folder.
@@ -28,8 +29,8 @@
28
29
  class Out < Diggit::Addon
29
30
  attr_reader :out, :tmp
30
31
 
31
- DEFAULT_OUT = 'out'
32
- DEFAULT_TMP = 'tmp'
32
+ DEFAULT_OUT = 'out'.freeze
33
+ DEFAULT_TMP = 'tmp'.freeze
33
34
 
34
35
  def initialize(*args)
35
36
  super
@@ -45,4 +46,25 @@ class Out < Diggit::Addon
45
46
  FileUtils.mkdir_p(@out) unless File.exist?(@out)
46
47
  FileUtils.mkdir_p(@tmp) unless File.exist?(@tmp)
47
48
  end
49
+
50
+ # Get an output path for a file/directory.
51
+ # @param paths [Array<String>] the different folders of the path.
52
+ # @return [String] the absolute path.
53
+ def out_path(*paths)
54
+ File.join(@out, *paths)
55
+ end
56
+
57
+ # Get a temporary path for a file/directory.
58
+ # @param paths [Array<String>] the different folders of the path.
59
+ # @return [String] the absolute path.
60
+ def tmp_path(*paths)
61
+ File.join(@tmp, *paths)
62
+ end
63
+
64
+ # Clean the output and temporary folders.
65
+ # @return [void]
66
+ def clean
67
+ FileUtils.rm_rf(@out)
68
+ FileUtils.rm_rf(@tmp)
69
+ end
48
70
  end