diggit 1.0.3 → 2.0.0

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.
@@ -1,26 +0,0 @@
1
- # encoding: utf-8
2
- require 'mongo'
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.
8
- class Db < Diggit::Addon
9
-
10
- DEFAULT_DB = 'diggit'
11
-
12
- attr_reader :db
13
-
14
- def initialize(*args)
15
- super
16
- client = Mongo::MongoClient.new
17
- database = DEFAULT_DB
18
- database = @options[:mongo][:database] if @options.has_key?(:mongo) && @options[:mongo].has_key?(:database)
19
- @db = client[database]
20
- end
21
-
22
- def name
23
- :db
24
- end
25
-
26
- end
@@ -1,37 +0,0 @@
1
- # encoding: utf-8
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.
11
- class Output < Diggit::Addon
12
-
13
- attr_reader :out, :tmp
14
-
15
- DEFAULT_OUT = 'out'
16
- DEFAULT_TMP = 'tmp'
17
-
18
- def initialize(*args)
19
- super
20
-
21
- out = DEFAULT_OUT
22
- out = @options[:output][:out] if @options.has_key?(:output) && @options[:output].has_key?(:out)
23
- tmp = DEFAULT_TMP
24
- tmp = @options[:output][:tmp] if @options.has_key?(:output) && @options[:output].has_key?(:tmp)
25
-
26
- @out = File.absolute_path(out)
27
- @tmp = File.absolute_path(tmp)
28
-
29
- FileUtils.mkdir_p(@out) unless File.exist?(@out)
30
- FileUtils.mkdir_p(@tmp) unless File.exist?(@tmp)
31
- end
32
-
33
- def name
34
- :output
35
- end
36
-
37
- end
@@ -1,21 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class SourcesOptions < Diggit::Addon
4
-
5
- SOURCES_OPTIONS_FILE = ".dgitsources-options"
6
-
7
- def initialize(*args)
8
- super
9
- @sources_options = {}
10
- @sources_options = Oj.load_file(SOURCES_OPTIONS_FILE) if File.exists? SOURCES_OPTIONS_FILE
11
- end
12
-
13
- def name
14
- :sources_options
15
- end
16
-
17
- def method_missing(meth, *args, &block)
18
- @sources_options.send meth, *args, &block
19
- end
20
-
21
- end
@@ -1,12 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class AuthorAnalysis < Diggit::Analysis
4
-
5
- def run
6
- walker = Rugged::Walker.new(@repo)
7
- walker.sorting(Rugged::SORT_DATE)
8
- walker.push(@repo.last_commit)
9
- authors = walker.collect{ |c| c.author[:name] }.uniq
10
- puts "Authors : #{authors}"
11
- end
12
- end
@@ -1,51 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'yaml'
4
-
5
- class ClocAnalysis < Diggit::Analysis
6
-
7
- def run
8
- cloc = `cloc . --progress-rate=0 --quiet --yaml`
9
- unless cloc.empty?
10
- yaml = YAML.load(cloc.lines[2..-1].join)
11
- yaml.delete('header')
12
- output = { source: @source, cloc: yaml }
13
- col = @addons[:db].db['cloc']
14
- col.insert(output)
15
- end
16
- end
17
-
18
- def clean(source)
19
- @addons[:db].db['cloc'].remove({source: source})
20
- end
21
-
22
- end
23
-
24
-
25
- class ClocPerFileAnalysis < Diggit::Analysis
26
-
27
- def run
28
- commit_oid = "HEAD"
29
- commit_oid = @addons[:sources_options][@source]["cloc-commit-id"] if @addons.has_key?(:sources_options) && @addons[:sources_options].has_key?(@source) && @addons[:sources_options][@source].has_key?("cloc-commit-id")
30
- @repo.checkout(commit_oid, {:strategy=>[:force,:remove_untracked]})
31
- cloc = `cloc . --progress-rate=0 --quiet --by-file --yaml --script-lang=Python,python`
32
- unless cloc.empty?
33
- yaml = YAML.load(cloc.lines[2..-1].join)
34
- yaml.delete('header')
35
- yaml.delete('SUM')
36
- cloc_a = []
37
- yaml.each do |key, value|
38
- # transform the hash so the filenames are not keys anymore (as they may contain a '.' it is incompatible with mongo)
39
- path = key.gsub(/^\.\//, '') # remove the './' at the start of filenames
40
- cloc_a << value.merge({:path => path})
41
- end
42
- output = { source: @source, commit_oid: commit_oid.to_s, cloc: cloc_a }
43
- col = @addons[:db].db['cloc-file']
44
- col.insert(output)
45
- end
46
- end
47
-
48
- def clean
49
- @addons[:db].db['cloc-file'].remove({source: @source})
50
- end
51
- end
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class DiffStats < Diggit::Analysis
4
-
5
- ACCEPTED_EXTENSIONS = [".java", ".c", ".h", ".js", ".javascript" ]
6
-
7
- def run
8
- col = @addons[:db].db['diffstats']
9
-
10
- walker = Rugged::Walker.new(@repo)
11
- ref = @repo.references["refs/heads/master"]
12
- walker.push(ref.target_id)
13
- walker.each do |commit|
14
- parent1 = commit.parents[0]
15
- if parent1
16
- diff1 = parent1.diff(commit)
17
- diff1.each_delta do |delta|
18
- old_path = delta.old_file[:path]
19
- new_path = delta.new_file[:path]
20
- old_ext = File.extname(old_path).downcase
21
- new_ext = File.extname(new_path).downcase
22
- if delta.status == :modified && old_ext.eql?(new_ext) && ACCEPTED_EXTENSIONS.include?(old_ext)
23
- sha_old = delta.old_file[:oid]
24
- sha_new = delta.new_file[:oid]
25
- patch = @repo.lookup(sha_new).diff(@repo.lookup(sha_old))
26
- changes = patch.changes
27
- edit = {source: @source, old_path: old_path, new_path: new_path, old_commit: commit.oid, new_commit: parent1.oid, changes: changes}
28
- col.insert(edit)
29
- end
30
- end
31
- end
32
- end
33
- end
34
-
35
- def clean
36
- @addons[:db].db['diffstats'].remove({source: @source})
37
- end
38
-
39
- end
@@ -1,40 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class MetadataAnalysis < Diggit::Analysis
4
-
5
- def run
6
- # Importing tags
7
- tags = @addons[:db].db['tags']
8
- @repo.tags.each do |t|
9
- tag = { source: @source, name: t.name, target: t.target.oid }
10
- tags.insert(tag)
11
- end
12
-
13
- # Importing branches
14
- branches = @addons[:db].db['branches']
15
- @repo.branches.each do |b|
16
- branch = { source: @source, name: b.name, target: b.target.oid }
17
- branches.insert(branch)
18
- end
19
-
20
- # Importing commits
21
- commits = @addons[:db].db['commits']
22
- walker = Rugged::Walker.new(@repo)
23
- walker.sorting(Rugged::SORT_DATE)
24
- walker.push(@repo.last_commit)
25
- walker.each do |c|
26
- commit = {
27
- source: @source, oid: c.oid, message: c.message, author: c.author,
28
- committer: c.committer, parent_ids: c.parent_ids, time: c.time
29
- }
30
- commits.insert(commit)
31
- end
32
- end
33
-
34
- def clean
35
- @addons[:db].db['tags'].remove({source: @source})
36
- @addons[:db].db['branches'].remove({source: @source})
37
- @addons[:db].db['commits'].remove({source: @source})
38
- end
39
-
40
- end
@@ -1,16 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class PomAnalysis < Diggit::Analysis
4
-
5
- def run
6
- pom_files = Dir['**/pom.xml']
7
- pom_files.each do |file|
8
- puts file
9
- git = `git --no-pager log --pretty=%H%n%an --name-status #{file}`.lines
10
- history = []
11
- git.each_slice(4) { |slice| history << [slice[0].strip, slice[1].strip, slice[3].split("\t")[0].strip] }
12
- puts history.inspect
13
- end
14
- end
15
-
16
- end
@@ -1,67 +0,0 @@
1
- # encoding: utf-8
2
- require "rinruby"
3
-
4
- class DiffSize < Diggit::Join
5
-
6
- SAMPLE_SIZE = 10
7
-
8
- def run
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
61
- end
62
-
63
- def clean
64
- @sources.each{ |s| FileUtils.rm_rf("#{@addons[:output].out}/#{s[:id]}") }
65
- end
66
-
67
- end
@@ -1,13 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class TestJoin < Diggit::Join
4
-
5
- def run
6
- p "TestJoin performed"
7
- end
8
-
9
- def clean
10
- p "TestJoin cleaned"
11
- end
12
-
13
- end
data/lib/diggit_cli.rb DELETED
@@ -1,334 +0,0 @@
1
- require 'thor'
2
- require 'fileutils'
3
-
4
- require_relative 'diggit_core'
5
-
6
- module Diggit
7
-
8
- module Utils
9
-
10
- DONE = '[done]'
11
- WARNING = '[warning]'
12
- ERROR = '[error]'
13
- INFO = '[info]'
14
-
15
- def diggit
16
- @diggit = Diggit.new if @diggit.nil?
17
- return @diggit
18
- end
19
-
20
- def dump_error(e)
21
- { name: e.class.name, message: e.to_s, backtrace: e.backtrace }
22
- end
23
-
24
- def plugin_ok?(name, type)
25
- obj = Object::const_get(name)
26
- return obj < type
27
- rescue NameError
28
- return false
29
- end
30
-
31
- def source_color(source_hash)
32
- if source_hash[:log][:error].empty?
33
- return :blue
34
- else
35
- return :red
36
- end
37
- end
38
-
39
- def status_color(status)
40
- if status == DONE
41
- return :green
42
- else
43
- return :red
44
- end
45
- end
46
-
47
- def say_error(msg)
48
- say_status(ERROR, msg, :red)
49
- end
50
-
51
- def say_info(msg)
52
- say_status(INFO, msg, :blue)
53
- end
54
-
55
- def say_done(msg)
56
- say_status(DONE, msg, :green)
57
- end
58
-
59
- end
60
-
61
- module Cli
62
-
63
- class SourcesCli < Thor
64
- include Thor::Actions
65
- include Utils
66
-
67
- desc 'list', "Display the list of sources."
68
- def list
69
- idx = 1
70
- diggit.sources.hashes.each do |s|
71
- say_status("[#{s[:log][:state]}]", "#{idx}: #{s[:url]}", source_color(s))
72
- idx += 1
73
- end
74
- errors = diggit.sources.get_all(nil, {error: true}).size
75
- status = (errors== 0 && DONE) || ERROR
76
- say_status(status, "listed #{diggit.sources.size} sources including #{errors} errors", status_color(status))
77
- end
78
-
79
- desc 'info [SOURCE_DEF]', "Display informations on the provided source definition (either source URL or id)."
80
- def info(source_def)
81
- s = diggit.sources.get(source_def)
82
- say_status("[#{s[:log][:state]}]", "#{s[:url]}", source_color(s))
83
- say_status('[folder]', "#{s[:folder]}", :blue)
84
- unless s[:log][:error].empty?
85
- say_error("#{s[:log][:error][:name]}")
86
- say_status('[message]', "#{s[:log][:error][:message]}", :red)
87
- say_status('[backtrace]', "", :red)
88
- say(s[:log][:error][:backtrace].join("\n"))
89
- end
90
- end
91
-
92
- desc "errors", "Display informations on all source that have encountered an error."
93
- def errors
94
- diggit.sources.get_all(nil, {error: true}).each{|s| info s[:url] }
95
- end
96
-
97
- desc 'import [FILE]', "Import a list of sources from a file (one URL per line)."
98
- def import(urls_file)
99
- IO.readlines(urls_file).each{ |line| diggit.sources.add(line.strip) }
100
- end
101
-
102
- desc "add [URL*]", "Add the provided urls to the list of sources."
103
- def add(*urls)
104
- urls.each{ |u| diggit.sources.add(u) }
105
- end
106
-
107
- desc "rem [SOURCE_DEF*]", "Remove the sources correspondign to the provided source definitions (id or URL) from the list of sources."
108
- def rem(*sources_defs)
109
- sources_defs.each { |s| diggit.sources.rem(s) }
110
- end
111
- end
112
-
113
- class AddonsCli < Thor
114
- include Thor::Actions
115
- include Utils
116
-
117
- desc "add [ADDON*]", "Add the provided addons to the list of active addons."
118
- def add(*addons)
119
- addons.each do |a|
120
- if plugin_ok?(a, Addon)
121
- diggit.config.add_addon(a)
122
- else
123
- say_error("error loading addon #{a}")
124
- end
125
- end
126
- end
127
-
128
- desc "rem [ADDON*]", "Remove the provided addons from the list of active addons."
129
- def rem(*addons)
130
- addons.each{ |a| diggit.config.rem_addon(a) }
131
- end
132
-
133
- end
134
-
135
- class JoinsCli < Thor
136
- include Thor::Actions
137
- include Utils
138
-
139
- desc "add [JOIN*]", "Add the provided joins to the list of active joins."
140
- def add(*joins)
141
- joins.each do |j|
142
- if plugin_ok?(j, Join)
143
- diggit.config.add_join(j)
144
- else
145
- say_error("error loading join #{j}")
146
- end
147
- end
148
- end
149
-
150
- desc "rem [JOIN*]", "Remove the provided joins from the list of active joins."
151
- def rem(*joins)
152
- joins.each{ |j| diggit.config.rem_join(j) }
153
- end
154
-
155
- end
156
-
157
- class AnalysesCli < Thor
158
- include Thor::Actions
159
- include Utils
160
-
161
- desc "add [ANALYSIS*]", "Add the provided analyses to the list of active analyses."
162
- def add(*analyses)
163
- analyses.each do |a|
164
- if plugin_ok?(a, Analysis)
165
- diggit.config.add_analysis(a)
166
- else
167
- say_error("error loading analysis #{a}")
168
- end
169
- end
170
- end
171
-
172
- desc "rem [ANALYSIS*]", "Remove the provided analyses from the list of active analyses."
173
- def rem(*analyses)
174
- analyses.each{ |a| diggit.config.rem_analysis(a) }
175
- end
176
-
177
- end
178
-
179
- class PerformCli < Thor
180
- include Thor::Actions
181
- include Utils
182
-
183
- desc "clones [SOURCE_DEFS*]", "Clone the sources corresponding to the provided source definitions (id or URL). Clone all sources if no source definitions are provided."
184
- def clones(*source_defs)
185
- diggit.sources.get_all(source_defs, {state: :new}).each do |s|
186
- begin
187
- if File.exist?(s[:folder])
188
- Rugged::Repository::new(s[:folder])
189
- else
190
- Rugged::Repository::clone_at(s[:url], s[:folder], {
191
- transfer_progress: lambda { |total_objects, indexed_objects, received_objects, local_objects, total_deltas, indexed_deltas, received_bytes|
192
- msg = "Clone of #{s[:url]} in progress : #{received_objects}/#{total_objects} objects received.\r"
193
- $stderr.print msg
194
- @last_message_length = msg.length
195
- }
196
- })
197
- print " " * @last_message_length + "\r" # clean the line used to output transfer progress
198
- end
199
- rescue => e
200
- s[:log][:error] = dump_error(e)
201
- say_error("error cloning #{s[:url]}")
202
- else
203
- s[:log][:state] = :cloned
204
- s[:log][:error] = {}
205
- say_done("#{s[:url]} cloned")
206
- ensure
207
- diggit.sources.update(s)
208
- end
209
- end
210
- end
211
-
212
- desc "analyses [SOURCE_DEFS*]", "Perform the configured analyses to the sources corresponding to the provided source definitions (id or URL). Analyze all sources if no source definitions are provided."
213
- def analyses(*source_defs)
214
- addons = diggit.config.load_addons
215
- diggit.sources.get_all(source_defs, {state: :cloned}).each do |s|
216
- FileUtils.cd(s[:folder])
217
- globs = {}
218
- performed_analyses = []
219
- begin
220
- repo = Rugged::Repository.new('.')
221
- diggit.config.load_analyses(s[:url], repo, addons, globs).each do |a|
222
- performed_analyses << a.class.to_s
223
- a.run
224
- end
225
- rescue => e
226
- s[:log][:error] = dump_error(e)
227
- s[:log][:analyses] = performed_analyses[1..-2]
228
- say_error("error performing #{performed_analyses.last} on #{s[:url]}")
229
- else
230
- s[:log][:analyses] = performed_analyses
231
- s[:log][:state] = :finished
232
- s[:log][:error] = {}
233
- say_done("source #{s[:url]} analyzed")
234
- ensure
235
- FileUtils.cd(diggit.root)
236
- diggit.sources.update(s)
237
- end
238
- end
239
- end
240
-
241
- desc "joins", "Perform the configured joins."
242
- def joins
243
- addons = diggit.config.load_addons
244
- globs = {}
245
- diggit.config.load_joins(diggit.sources.get_all([], {state: :finished, error: false}), addons, globs).each{ |j| j.run }
246
- say_done("joins performed")
247
- end
248
-
249
- end
250
-
251
- class CleanCli < Thor
252
- include Thor::Actions
253
- include Utils
254
-
255
- desc "analyses", "Clean the configured analyzes on the provided source definitions (id or URL). Clean all sources if no source definitions are provided."
256
- def analyses(*source_defs)
257
- addons = diggit.config.load_addons
258
- diggit.sources.get_all(source_defs, {state: :finished}).each do |s|
259
- globs = {}
260
- diggit.config.load_analyses(s[:url], nil, addons, globs).each{ |a| a.clean}
261
- s[:log][:state] = :cloned
262
- s[:log][:analyses] = []
263
- s[:log][:error] = {}
264
- diggit.sources.update(s)
265
- say_done("cleaned analyses on #{s[:url]}")
266
- end
267
- end
268
-
269
- desc "joins", "Clean the configured joins."
270
- def joins
271
- addons = diggit.config.load_addons
272
- globs = {}
273
- diggit.config.load_joins(diggit.sources.get_all([], {state: :finished, error: false}), addons, globs).each{ |j| j.clean }
274
- end
275
-
276
- end
277
-
278
- class DiggitCli < Thor
279
- include Thor::Actions
280
- include Utils
281
-
282
- def initialize(*args)
283
- super
284
- cmd = args[2][:current_command].name
285
- unless 'init'.eql?(cmd) || 'help'.eql?(cmd)
286
- unless File.exist?(DIGGIT_RC)
287
- say_error("this is not a diggit directory")
288
- else
289
- diggit
290
- end
291
- end
292
- end
293
-
294
- desc "init", "Initialize the current folder as a diggit folder."
295
- def init
296
- FileUtils.touch(DIGGIT_SOURCES)
297
- Oj.to_file(DIGGIT_LOG, {})
298
- Oj.to_file(DIGGIT_RC, { addons: [], analyses: [], joins: [], options: {} })
299
- say_done("Diggit folder successfully initialized")
300
- end
301
-
302
- desc 'status', "Display the status of the current diggit folder."
303
- def status
304
- color = (diggit.sources.get_all(nil, {error: true}).size > 0 && :red) || :blue
305
- say_status('[sources]', "#{diggit.sources.get_all([], {state: :new}).size} new (#{diggit.sources.get_all([], {state: :new, error: true}).size} errors), #{diggit.sources.get_all([], {state: :cloned}).size} cloned (#{diggit.sources.get_all([], {state: :cloned, error: true}).size} errors), #{diggit.sources.get_all([], {state: :finished}).size} finished", color)
306
- say_status('[addons]', "#{diggit.config.addons.join(', ')}", :blue)
307
- say_status('[analyses]', "#{diggit.config.analyses.join(', ')}", :blue)
308
- say_status('[joins]', "#{diggit.config.joins.join(', ')}", :blue)
309
- say_status('[options]', "#{diggit.config.options}", :blue)
310
- end
311
-
312
- desc "sources SUBCOMMAND ...ARGS", "manage sources for the current diggit folder."
313
- subcommand "sources", SourcesCli
314
-
315
- desc "joins SUBCOMMAND ...ARGS", "manage joins for the current diggit folder."
316
- subcommand "joins", JoinsCli
317
-
318
- desc "analyses SUBCOMMAND ...ARGS", "manage analyses for the current diggit folder."
319
- subcommand "analyses", AnalysesCli
320
-
321
- desc "addons SUBCOMMAND ...ARGS", "manage addons for the current diggit folder."
322
- subcommand "addons", AddonsCli
323
-
324
- desc "perform SUBCOMMAND ...ARGS", "perform actions in the current diggit folder."
325
- subcommand "perform", PerformCli
326
-
327
- desc "clean SUBCOMMAND ...ARGS", "clean the current diggit folder."
328
- subcommand "clean", CleanCli
329
-
330
- end
331
-
332
- end
333
-
334
- end