diggit 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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