git-recommend 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd37e6d5a0899d26e9477ae487f378b70e823f00
4
- data.tar.gz: 2bf08d57c099aa33531424a8866f2a8506f78588
3
+ metadata.gz: 2b3bb536c881bc0b202f0abedb9a06375422634a
4
+ data.tar.gz: 605d94d353fb38ff29e1d4a05fd732ad82b1a1e2
5
5
  SHA512:
6
- metadata.gz: d73be1af4a07f28df93d165294d75b4a5099915b0b2145941beb43b137439006fd9429c2d8b147984f01a64599308ecaa003e00b813fd8d03be5d1dbcb4040da
7
- data.tar.gz: b927bed5b8af7e4c8e67504ad92cfe4a2b530cdcc72b603b4a2e890efb3e48727581768bf89e48f2ebe62a9fd7da189b1fd6cfdf57fb83cd059dfa5d880e20ad
6
+ metadata.gz: 055b3a5cc3a1013ce5d493429f7c97883e4b3424a5d987393f219858fc756350b788fde6296c5059bf04a86b8ff15869ce8f5283ace77ae24499d647c987b707
7
+ data.tar.gz: 253345f3bfe244c11be6ca1449334c226f9a4ecfe7e7715da5ad8b26f133917bebeed87cfadf85ba97764c37ff956e2068159caa29e8f88b63b842099ac61dac
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *~
data/bin/git-recommend CHANGED
@@ -1,108 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require 'thor'
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/helper.rb'
3
+
4
+ GitTest.start(ARGV)
@@ -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
- require 'git/recommend/version'
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
@@ -0,0 +1,9 @@
1
+ require 'thor'
2
+ require 'evoc'
3
+ require 'vcs2json'
4
+ require 'highline'
5
+ require 'csv'
6
+ require 'set'
7
+
8
+ require 'git_recommend'
9
+ require 'git_test'
@@ -1,5 +1,5 @@
1
1
  module Git
2
2
  module Recommend
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
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.1.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-14 00:00:00.000000000 Z
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/git/recommend.rb
132
- - lib/git/recommend/version.rb
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
data/lib/git/recommend.rb DELETED
@@ -1,7 +0,0 @@
1
- require "git/recommend/version"
2
-
3
- module Git
4
- module Recommend
5
- # Your code goes here...
6
- end
7
- end