diggit 1.0.1 → 1.0.2

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: 5edef2423b0ffdd802d4c7f78b60fbf466878577
4
- data.tar.gz: fd9005d6f5acc9f4f0fc4f84677ed87bff59dddd
3
+ metadata.gz: 03b553461539e07d43eefe6c94a760b44bdf8940
4
+ data.tar.gz: a0d58fbe18d396043c68242b916d4d76ca43e45c
5
5
  SHA512:
6
- metadata.gz: 900953e9d6b740ffcce9d600b8935a70d23d5a91c81156db6820581460e880c897158e37202ac7da6a555aa0e0f9237c7f54bd0599471af423292894a4e3e343
7
- data.tar.gz: 05cbb988a51d483787f68155f296693b080c7c5c285390401b369260cd1c366d254eaf2783d27ce2c484d190196da2587f756647fc2d1f479481f88dc03673c6
6
+ metadata.gz: cc71247842cc94ee9f4cfbab0399e0a49c47503f0b2bc964a7d2216a1fef26fb8798f38d5b2dd6a6ba1a4ef5bc90c82e3e2eddfde17673c6536949ef86cb456e
7
+ data.tar.gz: 4eea49b3b12d22ea172942431a4e38a057aa75ea61264d1edb70002e150fb6fe71ec90fbfbbd36c2dc7127c23fd2484b4c058a060488bcf97761dc3243bb35f4
data/README.md CHANGED
@@ -16,7 +16,7 @@ The diggit tool is in the lib folder. Don't hesitate to create a link to diggit.
16
16
 
17
17
  ## Configuration
18
18
 
19
- The diggit tool is designed to help you analyze software repositories. Firstly you have to create a new folder in which you launch the `diggit init` command. This way, the folder becomes a diggit folder in which you can configure repositories and analyses.
19
+ 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.
20
20
 
21
21
  ### Setting-up the repositories
22
22
 
@@ -38,7 +38,7 @@ A join is performed after all analyses of all repositories have been performed.
38
38
 
39
39
  Once diggit is configured you can perform the analyses. First you have to perform the clone by using `dgit perform clones`. Then you can launch the analyses by using `dgit perform analyses`. Finally, the joins are executed via the command `dgit perform joins`.
40
40
 
41
- At all time, you can check the status of your diggit folder by using `diggit status`. If you want more info on the status of a given repository, you can use the `dgit sources info https://github.com/jrfaller/diggit.git` command.
41
+ At all time, you can check the status of your diggit folder by using `dgit status`. If you want more info on the status of a given repository, you can use the `dgit sources info https://github.com/jrfaller/diggit.git` command.
42
42
 
43
43
  ## Cleaning up
44
44
 
@@ -1,6 +1,10 @@
1
1
  # encoding: utf-8
2
2
  require 'mongo'
3
3
 
4
+ # A MongoDB addon for Diggit. The name of this addon is :db. This addon might use an :mongo hash in the global options. In this
5
+ # hash, the :database key allows to configure the name of the database.
6
+ # @!attribute [r] db
7
+ # @return [Mongo::DB] the mongo database object.
4
8
  class Db < Diggit::Addon
5
9
 
6
10
  DEFAULT_DB = 'diggit'
@@ -1,5 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
+ # A output addon for Diggit. The name of the addon is :output, and can be reached in the
4
+ # addons hash. This addon might use an :output hash in the global options. In this hash, the
5
+ # :out key allows to configure the name of the output folder and :tmp the name of the temporary output
6
+ # folder.
7
+ # @!attribute [r] out
8
+ # @return [String] the absolute path of the output folder.
9
+ # @!attribute [r] tmp
10
+ # @return [String] the absolute path of the temporary output folder.
3
11
  class Output < Diggit::Addon
4
12
 
5
13
  attr_reader :out, :tmp
@@ -2,7 +2,7 @@
2
2
 
3
3
  class DiffStats < Diggit::Analysis
4
4
 
5
- ACCEPTED_EXTENSIONS = [".java", ".c", ".h", ".js", ".javascrip" ]
5
+ ACCEPTED_EXTENSIONS = [".java", ".c", ".h", ".js", ".javascript" ]
6
6
 
7
7
  def run
8
8
  col = @addons[:db].db['diffstats']
@@ -1,18 +1,67 @@
1
1
  # encoding: utf-8
2
+ require "rinruby"
2
3
 
3
4
  class DiffSize < Diggit::Join
4
5
 
5
- ACCEPTED_EXTENSIONS = [".java", ".c", ".h", ".js", ".javascrip" ]
6
+ SAMPLE_SIZE = 10
6
7
 
7
8
  def run
8
- col = @addons[:db].db['diffstats']
9
- @sources.each do |source|
10
- diffs = col.count({:query => {"source" => source}})
11
- puts "#{source}: #{diffs}"
12
- end
9
+ @sources.map{ |s| sample(s) }
10
+ end
11
+
12
+ def sample(src)
13
+ R.src = src[:url]
14
+ R.size = SAMPLE_SIZE
15
+ R.eval <<-EOS
16
+ library(RMongo)
17
+
18
+ srcQuery <- function(src) {
19
+ return(paste('{"source": "', src, '"}', sep=""))
20
+ }
21
+
22
+ noZeros <- function(data) {
23
+ return(subset(data,changes>0))
24
+ }
25
+
26
+ rubify <- function(data) {
27
+ return(cbind(data$old_path, data$old_commit, data$new_path, data$new_commit))
28
+ }
29
+
30
+ db <- mongoDbConnect('diffstats')
31
+ d <- noZeros(dbGetQuery(db, 'diffstats', srcQuery(src), skip=0, limit=0))
32
+
33
+ q <- quantile(d$changes)
34
+
35
+ s <- subset(d,changes > 0 & changes <= q[3])
36
+ m <- subset(d,changes > q[3] & changes <= q[4])
37
+ b <- subset(d,changes > q[4])
38
+
39
+ rs <- s[sample(nrow(s), size),]
40
+ rm <- m[sample(nrow(m), size),]
41
+ rb <- b[sample(nrow(b), size),]
42
+
43
+ rs_ruby <- rubify(rs)
44
+ rm_ruby <- rubify(rm)
45
+ rb_ruby <- rubify(rb)
46
+ EOS
47
+ write_sample(src, R.rs_ruby, 'small')
48
+ write_sample(src, R.rm_ruby, 'medium')
49
+ write_sample(src, R.rb_ruby, 'big')
50
+ end
51
+
52
+ def write_sample(src, sample, type)
53
+ prefix = "#{@addons[:output].out}/#{src[:id]}/#{type}"
54
+ n = 1
55
+ sample.row_vectors.each do |row|
56
+ FileUtils.mkdir_p("#{prefix}/#{n}")
57
+ File.write("#{prefix}/#{n}/src_#{row[1]}_#{row[0].gsub(/\//,'_')}", `git -C #{src[:folder]} show #{row[1]}:#{row[0]}`)
58
+ File.write("#{prefix}/#{n}/dst_#{row[3]}_#{row[2].gsub(/\//,'_')}", `git -C #{src[:folder]} show #{row[3]}:#{row[2]}`)
59
+ n += 1
60
+ end
13
61
  end
14
62
 
15
63
  def clean
64
+ @sources.each{ |s| FileUtils.rm_rf("#{@addons[:output].out}/#{s[:id]}") }
16
65
  end
17
66
 
18
67
  end
data/lib/diggit_cli.rb CHANGED
@@ -16,9 +16,9 @@ module Diggit
16
16
  { name: e.class.name, message: e.to_s, backtrace: e.backtrace }
17
17
  end
18
18
 
19
- def class_exist?(class_name)
20
- obj = Object::const_get(class_name)
21
- return obj.is_a?(Class)
19
+ def plugin_ok?(name, type)
20
+ obj = Object::const_get(name)
21
+ return obj < type
22
22
  rescue NameError
23
23
  return false
24
24
  end
@@ -79,7 +79,7 @@ module Diggit
79
79
 
80
80
  desc "errors", "Display informations on all source that have encountered an error."
81
81
  def errors
82
- diggit.sources.get_all(nil, {error: true}).each{|s| invoke :info, [s[:url]]}
82
+ diggit.sources.get_all(nil, {error: true}).each{|s| info s[:url] }
83
83
  end
84
84
 
85
85
  desc 'import [FILE]', "Import a list of sources from a file (one URL per line)."
@@ -105,10 +105,10 @@ module Diggit
105
105
  desc "add [ADDON*]", "Add the provided addons to the list of active addons."
106
106
  def add(*addons)
107
107
  addons.each do |a|
108
- if class_exist?(a)
108
+ if plugin_ok?(a, Addon)
109
109
  diggit.config.add_addon(a)
110
110
  else
111
- say_status(ERROR, "addon #{a} not found", :red)
111
+ say_status(ERROR, "error loading addon #{a}", :red)
112
112
  end
113
113
  end
114
114
  end
@@ -127,10 +127,10 @@ module Diggit
127
127
  desc "add [JOIN*]", "Add the provided joins to the list of active joins."
128
128
  def add(*joins)
129
129
  joins.each do |j|
130
- if class_exist?(j)
130
+ if plugin_ok?(j, Join)
131
131
  diggit.config.add_join(j)
132
132
  else
133
- say_status(ERROR, "join #{j} not found", :red)
133
+ say_status(ERROR, "error loading join #{j}", :red)
134
134
  end
135
135
  end
136
136
  end
@@ -149,10 +149,10 @@ module Diggit
149
149
  desc "add [ANALYSIS*]", "Add the provided analyses to the list of active analyses."
150
150
  def add(*analyses)
151
151
  analyses.each do |a|
152
- if class_exist?(a)
152
+ if plugin_ok?(a, Analysis)
153
153
  diggit.config.add_analysis(a)
154
154
  else
155
- say_status(ERROR, "analysis #{a} not found", :red)
155
+ say_status(ERROR, "error loading analysis #{a}", :red)
156
156
  end
157
157
  end
158
158
  end
@@ -172,7 +172,11 @@ module Diggit
172
172
  def clones(*source_defs)
173
173
  diggit.sources.get_all(source_defs, {state: :new}).each do |s|
174
174
  begin
175
- Rugged::Repository::clone_at(s[:url], s[:folder])
175
+ if File.exist?(s[:folder])
176
+ Rugged::Repository::new(s[:folder])
177
+ else
178
+ Rugged::Repository::clone_at(s[:url], s[:folder])
179
+ end
176
180
  rescue => e
177
181
  s[:log][:error] = dump_error(e)
178
182
  say_status(ERROR, "error cloning #{s[:url]}", :red)
data/lib/diggit_core.rb CHANGED
@@ -3,11 +3,10 @@
3
3
 
4
4
  require 'rugged'
5
5
  require 'oj'
6
- require 'singleton'
7
6
 
8
7
  module Diggit
9
8
 
10
- DIGGIT_RC = '.dgitrrc'
9
+ DIGGIT_RC = '.dgitrc'
11
10
  DIGGIT_LOG = '.dgitlog'
12
11
  DIGGIT_SOURCES = '.dgitsources'
13
12
 
@@ -15,19 +14,53 @@ module Diggit
15
14
  INCLUDES_FOLDER = 'includes'
16
15
  DIGGIT_FOLDER = ".diggit"
17
16
 
17
+ # Base class for Diggit addons.
18
+ # @abstract Subclass and override name to implement custom Diggit addons.
19
+ #
20
+ # @!attribute [r] options
21
+ # @return [Hash] the Diggit options.
18
22
  class Addon
19
23
 
24
+ # Create a new addon.
25
+ #
26
+ # @param options [Hash] a hash containing the Diggit options.
20
27
  def initialize(options)
21
28
  @options = options
22
29
  end
23
30
 
31
+ # Returns the name of the addon.
32
+ # @abstract The name must be overrided.
33
+ #
34
+ # @return [Symbol] the name of the addon.
24
35
  def name
36
+ raise NoMethodError.new "Subclass responsability"
25
37
  end
26
38
 
27
39
  end
28
40
 
41
+ # Base class for Diggit analyses. Diggit analyses are applied on each source that has been succesfully cloned. They can access the Diggit addons through the addons attribute.
42
+ # @see Addon
43
+ # @abstract Subclass and override run and clean to implement
44
+ # a custom analysis class.
45
+ # @!attribute [r] source
46
+ # @return [String] the URL of the source to be analyzed.
47
+ # @!attribute [r] repo
48
+ # @return [Rugged::Repository] the Rugged Repository object corresponding to the source.
49
+ # @!attribute [r] options
50
+ # @return [Hash] a hash containing the Diggit options.
51
+ # @!attribute [r] addons
52
+ # @return [Hash{Symbol => Addon}] a hash containing the loaded Diggit addons, indexed by names.
53
+ # @!attribute globs
54
+ # @return [Hash] a hash shared between all analyses of a source.
29
55
  class Analysis
30
56
 
57
+ # Create a new analysis.
58
+ #
59
+ # @param source [String] the URL of the source to be analyzed.
60
+ # @param repo [Rugged::Repository] the Rugged Repository object corresponding to the source.
61
+ # @param options [Hash] a hash containing the Diggit options.
62
+ # @param addons [Hash{Symbol => Addon}] a hash containing the loaded Diggit addons, indexed by names.
63
+ # @param globs [Hash] a hash shared between all analyses of a source.
31
64
  def initialize(source, repo, options, addons, globs)
32
65
  @source = source
33
66
  @repo = repo
@@ -36,17 +69,39 @@ module Diggit
36
69
  @globs = globs
37
70
  end
38
71
 
72
+ # Run the analysis.
73
+ # @abstract
39
74
  def run
40
75
  raise NoMethodError.new "Subclass responsability"
41
76
  end
42
77
 
78
+ # Clean the data produced by the analysis.
79
+ # @abstract
43
80
  def clean
44
81
  raise NoMethodError.new "Subclass responsability"
45
82
  end
46
83
 
47
84
  end
48
85
 
86
+ # Base class for Diggit joins. Joins are applied after each source have been analyzed. They can access the Diggit addons through the addons attribute.
87
+ # @see Addon
88
+ # @abstract Subclass and override cleand and run to implement custom Diggit join.
89
+ # @!attribute [r] sources
90
+ # @return [Array] an array containing the finished sources.
91
+ # @!attribute [r] options
92
+ # @return [Hash] a hash containing the Diggit options.
93
+ # @!attribute [r] addons
94
+ # @return [Hash{Symbol => Addon}] a hash containing the loaded Diggit addons, indexed by names.
95
+ # @!attribute globs
96
+ # @return [Hash] a hash shared between all analyses of a source.
49
97
  class Join
98
+
99
+ # Create a new join.
100
+ #
101
+ # @param sources [Array] an array containing the finished sources.
102
+ # @param options [Hash] a hash containing the Diggit options.
103
+ # @param addons [Hash{Symbol => Addon}] a hash containing the loaded Diggit addons, indexed by names.
104
+ # @param globs [Hash] a hash shared between all analyses of a source.
50
105
  def initialize(sources, options, addons, globs)
51
106
  @sources = sources
52
107
  @options = options
@@ -54,10 +109,14 @@ module Diggit
54
109
  @globs = globs
55
110
  end
56
111
 
112
+ # Run the join
113
+ # @abstract
57
114
  def run
58
115
  raise NoMethodError.new "Subclass responsability"
59
116
  end
60
117
 
118
+ # Clean the data produced by the join
119
+ # @abstract
61
120
  def clean
62
121
  raise NoMethodError.new "Subclass responsability"
63
122
  end
@@ -194,9 +253,9 @@ module Diggit
194
253
 
195
254
  def url(source_def)
196
255
  url = source_def
197
- if /\d+/.match(source_def)
256
+ if /^\d+$/.match(source_def)
198
257
  idx = source_def.to_i - 1
199
- raise "Wrong source identifier" if idx < 0 || idx >= @sources.size
258
+ raise "Wrong source identifier: #{source_def}" if idx < 0 || idx >= @sources.size
200
259
  url = @sources[source_def.to_i - 1]
201
260
  end
202
261
  url
@@ -207,11 +266,15 @@ module Diggit
207
266
  end
208
267
 
209
268
  def hash(url)
210
- {url: url, folder: folder(url), log: @log.log(url)}
269
+ {url: url, id: id(url), folder: folder(url), log: @log.log(url)}
270
+ end
271
+
272
+ def id(url)
273
+ url.gsub(/[^[\w-]]+/, "_")
211
274
  end
212
275
 
213
276
  def folder(url)
214
- File.expand_path(url.gsub(/[^[\w-]]+/, "_"), SOURCES_FOLDER)
277
+ File.expand_path(id(url), SOURCES_FOLDER)
215
278
  end
216
279
 
217
280
  end
@@ -269,10 +332,10 @@ module Diggit
269
332
  Dir["#{global}/**/*.rb"].each{ |f| require f }
270
333
 
271
334
  home = File.expand_path(INCLUDES_FOLDER,File.expand_path(DIGGIT_FOLDER,Dir.home))
272
- Dir["#{home}/**/*.rb"].each{ |f| require f }
335
+ Dir["#{home}/**{,/*/**}/*.rb"].each{ |f| require f }
273
336
 
274
337
  local = File.expand_path(INCLUDES_FOLDER)
275
- Dir["#{local}/**/*.rb"].each{ |f| require f }
338
+ Dir["#{local}/**{,/*/**}/*.rb"].each{ |f| require f }
276
339
  end
277
340
 
278
341
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diggit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Rémy Falleri
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-27 00:00:00.000000000 Z
12
+ date: 2014-11-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rugged
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0.19'
56
+ - !ruby/object:Gem::Dependency
57
+ name: mongo
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.11'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.11'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: rspec
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -67,6 +81,20 @@ dependencies:
67
81
  - - "~>"
68
82
  - !ruby/object:Gem::Version
69
83
  version: '3.1'
84
+ - !ruby/object:Gem::Dependency
85
+ name: yard
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '0.8'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.8'
70
98
  description: |
71
99
  The Diggit repository analysis tool is a neat swiss knife to enable the analysis of many Git repositories.
72
100
  email: jr.falleri@gmail.com