git-recommend 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/bin/git-recommend +1 -104
- data/bin/git-test +4 -0
- data/git-recommend.gemspec +2 -2
- data/lib/git_recommend.rb +101 -0
- data/lib/git_test.rb +57 -0
- data/lib/helper.rb +9 -0
- data/lib/{git/recommend/version.rb → version.rb} +1 -1
- metadata +8 -4
- data/lib/git/recommend.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b3bb536c881bc0b202f0abedb9a06375422634a
|
4
|
+
data.tar.gz: 605d94d353fb38ff29e1d4a05fd732ad82b1a1e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 055b3a5cc3a1013ce5d493429f7c97883e4b3424a5d987393f219858fc756350b788fde6296c5059bf04a86b8ff15869ce8f5283ace77ae24499d647c987b707
|
7
|
+
data.tar.gz: 253345f3bfe244c11be6ca1449334c226f9a4ecfe7e7715da5ad8b26f133917bebeed87cfadf85ba97764c37ff956e2068159caa29e8f88b63b842099ac61dac
|
data/.gitignore
CHANGED
data/bin/git-recommend
CHANGED
@@ -1,108 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'evoc'
|
4
|
-
require 'vcs2json'
|
5
|
-
require 'highline'
|
6
|
-
|
7
|
-
class GitRecommend < Thor
|
8
|
-
|
9
|
-
DEFAULT_HISTORY = '.history'
|
10
|
-
@@in_git_repo = File.exist?('.git')
|
11
|
-
|
12
|
-
default_task :change
|
13
|
-
# history options
|
14
|
-
method_option :number, :aliases => '-n', type: :numeric, default: 10000, :desc => "The number of commits to dump"
|
15
|
-
# recommendation options
|
16
|
-
method_option :query, aliases: '-q', type: :array, required: false, desc: "Space separated list of query items"
|
17
|
-
method_option :query_from_file, aliases: '-f', type: :string, required: false, desc: "File with new-line separated list of query items"
|
18
|
-
method_option :staged, aliases: '-s', type: :boolean, required: false, desc: "Use staged files to generate recommendation"
|
19
|
-
method_option :unstaged, aliases: '-u', type: :boolean, required: false, desc: "Use unstaged files to generate recommendation"
|
20
|
-
method_option :history, :aliases => '-h', :type => :string, default: DEFAULT_HISTORY, :desc => "Path to change-history"
|
21
|
-
method_option :algorithm, :default => 'tarmaq0', :desc => "Which algorithm to use"
|
22
|
-
method_option :aggregator, :default => 'cg', :desc => "Which aggregator to use"
|
23
|
-
method_option :measures, aliases: '-m', type: :array, default: ['support','confidence'], desc: "Order rules on the given measures, presedence from left to right"
|
24
|
-
method_option :max_size, type: :numeric, default: 30, desc: "The maximum size of commits that should be considered when looking for patterns"
|
25
|
-
method_option :model_size, type: :numeric, default: 0, desc: "How many previous commits to consider when looking for patterns"
|
26
|
-
desc "change", ""
|
27
|
-
def change
|
28
|
-
# Initialize query
|
29
|
-
q = []
|
30
|
-
staged = (@@in_git_repo ? `git diff --cached --name-only`.split("\n") : [])
|
31
|
-
unstaged = (@@in_git_repo ? `git diff --name-only`.split("\n") : [])
|
32
|
-
from_command_line = (options[:query].nil? ? [] : options[:query])
|
33
|
-
from_file = if options[:query_from_file].nil?
|
34
|
-
[]
|
35
|
-
else
|
36
|
-
if File.exist?(options[:query_from_file])
|
37
|
-
File.read(options[:query_from_file]).split("\n")
|
38
|
-
else
|
39
|
-
$stderr.puts "No file found at #{options[:query_from_file]}"
|
40
|
-
[]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# default to locally changed files
|
45
|
-
if [:staged,:unstaged,:query,:query_from_file].all? {|k| options[k].nil?}
|
46
|
-
if @@in_git_repo
|
47
|
-
q = (staged | unstaged)
|
48
|
-
$stderr.puts "[default] Change recommendation based on the currently changed files\n"
|
49
|
-
end
|
50
|
-
else
|
51
|
-
staged = (options[:staged].nil? ? [] : staged)
|
52
|
-
unstaged = (options[:staged].nil? ? [] : unstaged)
|
53
|
-
q = (staged | unstaged | from_command_line | from_file)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Initialize history
|
57
|
-
if !File.exists?(options[:history])
|
58
|
-
exit unless HighLine.new.agree("To recommend changes, a history cache needs to be generated, do you want to generate the default cache now? Run 'git recommend help update' for more options.")
|
59
|
-
GitRecommend.start(["update"])
|
60
|
-
end
|
61
|
-
# could do some validation here
|
62
|
-
h = Evoc::HistoryStore.initialize(path: options[:history])
|
63
|
-
if q.size > 0
|
64
|
-
$stderr.puts "Generating change recommendation for #{q.size} items"
|
65
|
-
q_tx = Evoc::Tx.new(id: 'query',date: Time.now, items: q)
|
66
|
-
h.base_history << q_tx
|
67
|
-
|
68
|
-
s = Evoc::Scenario.new({query: q_tx.items,
|
69
|
-
tx_index: q_tx.index,
|
70
|
-
tx_id: q_tx.id,
|
71
|
-
model_size: options[:model_size],
|
72
|
-
algorithm: options[:algorithm],
|
73
|
-
aggregator: options[:aggregator],
|
74
|
-
max_size: options[:max_size],
|
75
|
-
measures: options[:measures]})
|
76
|
-
s.call
|
77
|
-
s.print
|
78
|
-
else
|
79
|
-
$stderr.puts "No changed files detected. Change some files or run with --help for more options."
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
method_option :after, :aliases => '-a', :desc => "Only include commits after this date"
|
84
|
-
method_option :before, :aliases => '-b', :desc => "Only include commits before this date"
|
85
|
-
method_option :number, :aliases => '-n', type: :numeric, default: 10000, :desc => "The number of commits to dump"
|
86
|
-
method_option :fine_grained, type: :boolean, default: true, desc: "Include fine grained change information in output"
|
87
|
-
method_option :ignore_comments, type: :boolean, default: false, desc: "Ignore comments when calculating diffs. Only in effect for fine grained changes."
|
88
|
-
method_option :ignore_whitespace, type: :boolean, default: false, desc: "Ignore whitespace when calculating diffs. Only in effect for fine grained changes."
|
89
|
-
method_option :residuals, type: :boolean, default: true, desc: "Consider changes that happen outside of methods"
|
90
|
-
desc "update", "Update/Create the history used for generating recommendations"
|
91
|
-
def update
|
92
|
-
if @@in_git_repo
|
93
|
-
if File.exists?(DEFAULT_HISTORY)
|
94
|
-
exit unless HighLine.new.agree("History already exists, do you want to replace it?")
|
95
|
-
end
|
96
|
-
$stderr.puts "Generating new history cache to #{DEFAULT_HISTORY}, this may take a while."
|
97
|
-
old_stdout = $stdout # backup old stdout
|
98
|
-
$stdout.reopen(DEFAULT_HISTORY, 'w') # redirect stdout to file
|
99
|
-
Vcs2Json::Git.new(options).parse # write history
|
100
|
-
$stdout = STDOUT # restore stdout
|
101
|
-
else
|
102
|
-
$stderr.puts "Need to be in a git repository to generate history cache."
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
2
|
+
require_relative '../lib/helper.rb'
|
106
3
|
|
107
4
|
GitRecommend.start(ARGV)
|
108
5
|
|
data/bin/git-test
ADDED
data/git-recommend.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
4
|
+
require_relative 'lib/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "git-recommend"
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
16
|
spec.bindir = "bin"
|
17
|
-
spec.executables = ["git-recommend"]
|
17
|
+
spec.executables = ["git-recommend","git-test"]
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_runtime_dependency "thor"
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class GitRecommend < Thor
|
4
|
+
|
5
|
+
DEFAULT_HISTORY = '.history'
|
6
|
+
@@in_git_repo = File.exist?('.git')
|
7
|
+
|
8
|
+
default_task :change
|
9
|
+
# history options
|
10
|
+
method_option :number, :aliases => '-n', type: :numeric, default: 10000, :desc => "The number of commits to dump"
|
11
|
+
# recommendation options
|
12
|
+
method_option :query, aliases: '-q', type: :array, required: false, desc: "Space separated list of query items"
|
13
|
+
method_option :query_from_file, aliases: '-f', type: :string, required: false, desc: "File with new-line separated list of query items"
|
14
|
+
method_option :staged, aliases: '-s', type: :boolean, required: false, desc: "Use staged files to generate recommendation"
|
15
|
+
method_option :unstaged, aliases: '-u', type: :boolean, required: false, desc: "Use unstaged files to generate recommendation"
|
16
|
+
method_option :history, :aliases => '-h', :type => :string, default: DEFAULT_HISTORY, :desc => "Path to change-history"
|
17
|
+
method_option :algorithm, :default => 'tarmaq0', :desc => "Which algorithm to use"
|
18
|
+
method_option :aggregator, :default => 'cg', :desc => "Which aggregator to use"
|
19
|
+
method_option :measures, aliases: '-m', type: :array, default: ['support','confidence'], desc: "Order rules on the given measures, presedence from left to right"
|
20
|
+
method_option :max_size, type: :numeric, default: 30, desc: "The maximum size of commits that should be considered when looking for patterns"
|
21
|
+
method_option :model_size, type: :numeric, default: 0, desc: "How many previous commits to consider when looking for patterns"
|
22
|
+
desc "change", ""
|
23
|
+
def change
|
24
|
+
# Initialize query
|
25
|
+
q = []
|
26
|
+
staged = (@@in_git_repo ? `git diff --cached --name-only`.split("\n") : [])
|
27
|
+
unstaged = (@@in_git_repo ? `git diff --name-only`.split("\n") : [])
|
28
|
+
from_command_line = (options[:query].nil? ? [] : options[:query])
|
29
|
+
from_file = if options[:query_from_file].nil?
|
30
|
+
[]
|
31
|
+
else
|
32
|
+
if File.exist?(options[:query_from_file])
|
33
|
+
File.read(options[:query_from_file]).split("\n")
|
34
|
+
else
|
35
|
+
$stderr.puts "No file found at #{options[:query_from_file]}"
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# default to locally changed files
|
41
|
+
if [:staged,:unstaged,:query,:query_from_file].all? {|k| options[k].nil?}
|
42
|
+
if @@in_git_repo
|
43
|
+
q = (staged | unstaged)
|
44
|
+
$stderr.puts "[default] Change recommendation based on the currently changed files\n"
|
45
|
+
end
|
46
|
+
else
|
47
|
+
staged = (options[:staged].nil? ? [] : staged)
|
48
|
+
unstaged = (options[:staged].nil? ? [] : unstaged)
|
49
|
+
q = (staged | unstaged | from_command_line | from_file)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Initialize history
|
53
|
+
if !File.exists?(options[:history])
|
54
|
+
exit unless HighLine.new.agree("To recommend changes, a history cache needs to be generated, do you want to generate the default cache now? Run 'git recommend help update' for more options.")
|
55
|
+
GitRecommend.start(["update"])
|
56
|
+
end
|
57
|
+
# could do some validation here
|
58
|
+
h = Evoc::HistoryStore.initialize(path: options[:history])
|
59
|
+
if q.size > 0
|
60
|
+
$stderr.puts "Generating change recommendation for #{q.size} items"
|
61
|
+
q_tx = Evoc::Tx.new(id: 'query',date: Time.now, items: q)
|
62
|
+
h.base_history << q_tx
|
63
|
+
|
64
|
+
s = Evoc::Scenario.new({query: q_tx.items,
|
65
|
+
tx_index: q_tx.index,
|
66
|
+
tx_id: q_tx.id,
|
67
|
+
model_size: options[:model_size],
|
68
|
+
algorithm: options[:algorithm],
|
69
|
+
aggregator: options[:aggregator],
|
70
|
+
max_size: options[:max_size],
|
71
|
+
measures: options[:measures]})
|
72
|
+
s.call
|
73
|
+
s.print
|
74
|
+
else
|
75
|
+
$stderr.puts "No changed files detected. Change some files or run with --help for more options."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
method_option :after, :aliases => '-a', :desc => "Only include commits after this date"
|
80
|
+
method_option :before, :aliases => '-b', :desc => "Only include commits before this date"
|
81
|
+
method_option :number, :aliases => '-n', type: :numeric, default: 10000, :desc => "The number of commits to dump"
|
82
|
+
method_option :fine_grained, type: :boolean, default: true, desc: "Include fine grained change information in output"
|
83
|
+
method_option :ignore_comments, type: :boolean, default: false, desc: "Ignore comments when calculating diffs. Only in effect for fine grained changes."
|
84
|
+
method_option :ignore_whitespace, type: :boolean, default: false, desc: "Ignore whitespace when calculating diffs. Only in effect for fine grained changes."
|
85
|
+
method_option :residuals, type: :boolean, default: true, desc: "Consider changes that happen outside of methods"
|
86
|
+
desc "update", "Update/Create the history used for generating recommendations"
|
87
|
+
def update
|
88
|
+
if @@in_git_repo
|
89
|
+
if File.exists?(DEFAULT_HISTORY)
|
90
|
+
exit unless HighLine.new.agree("History already exists, do you want to replace it?")
|
91
|
+
end
|
92
|
+
$stderr.puts "Generating new history cache to #{DEFAULT_HISTORY}, this may take a while."
|
93
|
+
old_stdout = $stdout # backup old stdout
|
94
|
+
$stdout.reopen(DEFAULT_HISTORY, 'w') # redirect stdout to file
|
95
|
+
Vcs2Json::Git.new(options).parse # write history
|
96
|
+
$stdout = STDOUT # restore stdout
|
97
|
+
else
|
98
|
+
$stderr.puts "Need to be in a git repository to generate history cache."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/git_test.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class GitTest < Thor
|
4
|
+
default_task :test
|
5
|
+
|
6
|
+
method_option :mapping, aliases: '-m', type: :string, required: true, desc: "Path to test<->code mapping file"
|
7
|
+
method_option :change_recommendation, aliases: '-c', type: :string, required: true ,desc: "Path to change recommendation"
|
8
|
+
method_option :output, aliases: '-o', enum: ['csv','dot'], default: 'csv', desc: "The output format of the test recommendation"
|
9
|
+
desc "test", ""
|
10
|
+
def test
|
11
|
+
begin
|
12
|
+
mapping = CSV.read(options[:mapping], headers: true)
|
13
|
+
change_rec = CSV.read(options[:change_recommendation], headers: true)
|
14
|
+
rescue CSV::MalformedCSVError => e
|
15
|
+
$stderr.puts "An error occured when parsing the mapping file:\n #{e}"
|
16
|
+
end
|
17
|
+
|
18
|
+
test_plan = Hash.new
|
19
|
+
covered = Set.new
|
20
|
+
uniq_impacted_items = change_rec.map {|row| row["rhs"]}.to_set
|
21
|
+
|
22
|
+
change_rec.each do |row|
|
23
|
+
lhs = row["lhs"]
|
24
|
+
rhs = row["rhs"]
|
25
|
+
support = row["support"].to_r.to_f
|
26
|
+
mapping.each do |mapping_row|
|
27
|
+
pattern = Regexp.new(mapping_row["pattern"], Regexp::IGNORECASE)
|
28
|
+
test = mapping_row["test"]
|
29
|
+
if rhs =~ pattern
|
30
|
+
covered << rhs
|
31
|
+
if test_plan[test].nil?
|
32
|
+
test_plan[test] = {impact: support, covers: 1}
|
33
|
+
else
|
34
|
+
test_plan[test][:impact] += support
|
35
|
+
test_plan[test][:covers] += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# print warnings to stderr if any
|
41
|
+
if covered.size < uniq_impacted_items.size
|
42
|
+
uncovered = uniq_impacted_items - covered
|
43
|
+
if uncovered.size < 11
|
44
|
+
$stderr.puts "The following potentially impacted items were not covered by at least 1 test:\n #{uncovered.to_a.join("\n")}"
|
45
|
+
else
|
46
|
+
$stderr.puts "#{uncovered.size} potentially impacted items were not covered by at least 1 test. The first 10 were: \n #{uncovered.take(10).join("\n")}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# print testplan to stdout
|
51
|
+
$stdout.puts "test,impact,covers"
|
52
|
+
test_plan.sort_by {|k,v| -v[:impact]}.each do |test,relevance|
|
53
|
+
$stdout.puts "#{test},#{relevance[:impact]},#{relevance[:covers]}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/lib/helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-recommend
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Rolfsnes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -113,6 +113,7 @@ email:
|
|
113
113
|
- mail@thomasrolfsnes.com
|
114
114
|
executables:
|
115
115
|
- git-recommend
|
116
|
+
- git-test
|
116
117
|
extensions: []
|
117
118
|
extra_rdoc_files: []
|
118
119
|
files:
|
@@ -126,10 +127,13 @@ files:
|
|
126
127
|
- Rakefile
|
127
128
|
- bin/console
|
128
129
|
- bin/git-recommend
|
130
|
+
- bin/git-test
|
129
131
|
- bin/setup
|
130
132
|
- git-recommend.gemspec
|
131
|
-
- lib/
|
132
|
-
- lib/
|
133
|
+
- lib/git_recommend.rb
|
134
|
+
- lib/git_test.rb
|
135
|
+
- lib/helper.rb
|
136
|
+
- lib/version.rb
|
133
137
|
homepage:
|
134
138
|
licenses:
|
135
139
|
- MIT
|