hotspots 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +16 -1
- data/LICENSE +1 -1
- data/README.md +7 -14
- data/TODO.md +1 -0
- data/bin/hotspots +9 -3
- data/lib/hotspots/configuration.rb +36 -0
- data/lib/hotspots/{option_based_exit.rb → exit.rb} +5 -5
- data/lib/hotspots/options_parser.rb +23 -41
- data/lib/hotspots/repository/git.rb +17 -0
- data/lib/hotspots/repository/git_command.rb +38 -0
- data/lib/hotspots/repository/git_driver.rb +35 -0
- data/lib/hotspots/repository/git_parser.rb +25 -0
- data/lib/hotspots/repository.rb +5 -3
- data/lib/hotspots/store.rb +3 -3
- data/lib/hotspots/version.rb +2 -2
- data/lib/hotspots.rb +46 -68
- data/test/hotspots/configuration_test.rb +65 -0
- data/test/hotspots/options_parser_test.rb +92 -120
- data/test/hotspots/repository/git_command_test.rb +39 -0
- data/test/hotspots/repository/git_parser_test.rb +88 -0
- data/test/hotspots/store_test.rb +14 -14
- data/test/minitest_helper.rb +8 -5
- metadata +52 -73
- data/lib/hotspots/logger.rb +0 -58
- data/lib/hotspots/repository/command/git.rb +0 -40
- data/lib/hotspots/repository/command.rb +0 -1
- data/lib/hotspots/repository/driver/git.rb +0 -27
- data/lib/hotspots/repository/driver.rb +0 -1
- data/lib/hotspots/repository/parser/git.rb +0 -35
- data/lib/hotspots/repository/parser.rb +0 -1
- data/test/hotspots/repository/command/git_test.rb +0 -39
- data/test/hotspots/repository/parser/git_test.rb +0 -95
metadata
CHANGED
@@ -1,89 +1,75 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotspots
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Chirantan Mitra
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2024-03-09 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: ansi
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: 1.5.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
26
|
+
version: 1.5.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
33
|
+
version: 13.1.0
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
40
|
+
version: 13.1.0
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: minitest
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - "~>"
|
52
46
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
47
|
+
version: 5.22.2
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - "~>"
|
60
53
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
54
|
+
version: 5.22.2
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: simplecov
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - "~>"
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
61
|
+
version: 0.22.0
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - "~>"
|
76
67
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
78
|
-
description:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
have a corresponding
|
83
|
-
|
84
|
-
test change.
|
85
|
-
|
86
|
-
'
|
68
|
+
version: 0.22.0
|
69
|
+
description: |
|
70
|
+
Find all files that changed over the past days for a git repository. If a file
|
71
|
+
is modified multiple times, it may require a re-design. Watch out for
|
72
|
+
implementation changes without a corresponding test change.
|
87
73
|
email:
|
88
74
|
- chirantan.mitra@gmail.com
|
89
75
|
executables:
|
@@ -91,62 +77,55 @@ executables:
|
|
91
77
|
extensions: []
|
92
78
|
extra_rdoc_files: []
|
93
79
|
files:
|
94
|
-
-
|
95
|
-
-
|
80
|
+
- CHANGELOG.md
|
81
|
+
- LICENSE
|
82
|
+
- README.md
|
83
|
+
- TODO.md
|
84
|
+
- bin/hotspots
|
85
|
+
- lib/hotspots.rb
|
86
|
+
- lib/hotspots/configuration.rb
|
87
|
+
- lib/hotspots/exit.rb
|
96
88
|
- lib/hotspots/options_parser.rb
|
97
|
-
- lib/hotspots/repository/command/git.rb
|
98
|
-
- lib/hotspots/repository/command.rb
|
99
|
-
- lib/hotspots/repository/driver/git.rb
|
100
|
-
- lib/hotspots/repository/driver.rb
|
101
|
-
- lib/hotspots/repository/parser/git.rb
|
102
|
-
- lib/hotspots/repository/parser.rb
|
103
89
|
- lib/hotspots/repository.rb
|
90
|
+
- lib/hotspots/repository/git.rb
|
91
|
+
- lib/hotspots/repository/git_command.rb
|
92
|
+
- lib/hotspots/repository/git_driver.rb
|
93
|
+
- lib/hotspots/repository/git_parser.rb
|
104
94
|
- lib/hotspots/store.rb
|
105
95
|
- lib/hotspots/version.rb
|
106
|
-
-
|
107
|
-
- bin/hotspots
|
96
|
+
- test/hotspots/configuration_test.rb
|
108
97
|
- test/hotspots/options_parser_test.rb
|
109
|
-
- test/hotspots/repository/
|
110
|
-
- test/hotspots/repository/
|
98
|
+
- test/hotspots/repository/git_command_test.rb
|
99
|
+
- test/hotspots/repository/git_parser_test.rb
|
111
100
|
- test/hotspots/store_test.rb
|
112
101
|
- test/minitest_helper.rb
|
113
|
-
- LICENSE
|
114
|
-
- README.md
|
115
|
-
- CHANGELOG.md
|
116
|
-
- TODO.md
|
117
102
|
homepage: https://github.com/chiku/hotspots
|
118
|
-
licenses:
|
119
|
-
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
120
107
|
rdoc_options: []
|
121
108
|
require_paths:
|
122
109
|
- lib
|
123
110
|
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
-
none: false
|
125
111
|
requirements:
|
126
|
-
- -
|
112
|
+
- - ">="
|
127
113
|
- !ruby/object:Gem::Version
|
128
|
-
version:
|
129
|
-
segments:
|
130
|
-
- 0
|
131
|
-
hash: 684827185202909371
|
114
|
+
version: 3.0.0
|
132
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
-
none: false
|
134
116
|
requirements:
|
135
|
-
- -
|
117
|
+
- - ">="
|
136
118
|
- !ruby/object:Gem::Version
|
137
119
|
version: '0'
|
138
|
-
segments:
|
139
|
-
- 0
|
140
|
-
hash: 684827185202909371
|
141
120
|
requirements: []
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
summary: Find all files that changed over the past in a git repository based on conditions
|
121
|
+
rubygems_version: 3.3.7
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Find the files in a git repository that changed the most in recent past
|
147
125
|
test_files:
|
126
|
+
- test/hotspots/configuration_test.rb
|
148
127
|
- test/hotspots/options_parser_test.rb
|
149
|
-
- test/hotspots/repository/
|
150
|
-
- test/hotspots/repository/
|
128
|
+
- test/hotspots/repository/git_command_test.rb
|
129
|
+
- test/hotspots/repository/git_parser_test.rb
|
151
130
|
- test/hotspots/store_test.rb
|
152
131
|
- test/minitest_helper.rb
|
data/lib/hotspots/logger.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
module Hotspots
|
2
|
-
# Should understand log levels
|
3
|
-
class Logger #:nodoc: all
|
4
|
-
module Sink
|
5
|
-
class Console
|
6
|
-
def self.<<(message)
|
7
|
-
$stdout << message
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class Null
|
12
|
-
def self.<<(message)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
module Colour
|
18
|
-
class ANSI
|
19
|
-
def self.as(colour, message)
|
20
|
-
::ANSI::Code.send(colour, message)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class Null
|
25
|
-
def self.as(colour, message)
|
26
|
-
message
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :sink, :colour
|
32
|
-
|
33
|
-
def initialize
|
34
|
-
@sink = Sink::Null
|
35
|
-
@colour = Colour::Null
|
36
|
-
end
|
37
|
-
|
38
|
-
def as_console
|
39
|
-
@sink = Sink::Console
|
40
|
-
end
|
41
|
-
|
42
|
-
def colourize
|
43
|
-
require 'ansi/code'
|
44
|
-
@colour = Colour::ANSI
|
45
|
-
end
|
46
|
-
|
47
|
-
def log(message, options = {})
|
48
|
-
sink << format(message, options)
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
# Time stampimg should be part of log level
|
54
|
-
def format(message, options = {})
|
55
|
-
colour.as(options[:as] || "black", "[#{Time.now}] #{message}\n")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Hotspots
|
2
|
-
module Repository #:nodoc: all
|
3
|
-
module Command
|
4
|
-
module Git
|
5
|
-
class Log
|
6
|
-
attr_reader :since_days, :message_filter
|
7
|
-
|
8
|
-
def initialize(options)
|
9
|
-
@since_days = options[:since_days]
|
10
|
-
@message_filter = options[:message_filter].to_s
|
11
|
-
end
|
12
|
-
|
13
|
-
def build
|
14
|
-
"git log --pretty=\"%H\" #{since_clause}#{grep_clause}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def since_clause
|
18
|
-
"--since=\"#{since_days} days ago\""
|
19
|
-
end
|
20
|
-
|
21
|
-
def grep_clause
|
22
|
-
message_filter.empty? ? "" : " --grep \"#{message_filter}\""
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Show
|
27
|
-
attr_reader :commit_hash
|
28
|
-
|
29
|
-
def initialize(options)
|
30
|
-
@commit_hash = options[:commit_hash]
|
31
|
-
end
|
32
|
-
|
33
|
-
def build
|
34
|
-
"git show --oneline --name-only #{commit_hash}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'hotspots/repository/command/git'
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Hotspots
|
2
|
-
module Repository #:nodoc: all
|
3
|
-
module Driver
|
4
|
-
class Git
|
5
|
-
attr_reader :logger
|
6
|
-
|
7
|
-
def initialize(logger)
|
8
|
-
@logger = logger
|
9
|
-
end
|
10
|
-
|
11
|
-
def pretty_log(options)
|
12
|
-
command = log_with_tag("Input", :as => :green) { Command::Git::Log.new(:since_days => options[:since_days], :message_filter => options[:message_filter]).build }
|
13
|
-
log_with_tag("Output", :as => :red) { %x(#{command}) }
|
14
|
-
end
|
15
|
-
|
16
|
-
def show_one_line_names(options)
|
17
|
-
command = log_with_tag("Input", :as => :green) { Command::Git::Show.new(:commit_hash => options[:commit_hash]).build }
|
18
|
-
log_with_tag("Output", :as => :red) { %x(#{command}) }
|
19
|
-
end
|
20
|
-
|
21
|
-
def log_with_tag(tag, options, &block)
|
22
|
-
yield.tap { |raw| logger.log("<#{tag}>\n#{raw}<#{tag}/>", :as => options[:as]) }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'hotspots/repository/driver/git'
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Hotspots
|
2
|
-
module Repository #:nodoc: all
|
3
|
-
module Parser
|
4
|
-
class Git
|
5
|
-
attr_reader :driver, :time, :message_filters
|
6
|
-
|
7
|
-
def initialize(driver, options)
|
8
|
-
@driver = driver
|
9
|
-
@time = options[:time]
|
10
|
-
@message_filters = options[:message_filters]
|
11
|
-
end
|
12
|
-
|
13
|
-
# TODO : replace with each_line
|
14
|
-
def files
|
15
|
-
filtered_commit_hashes.map do |commit_hash|
|
16
|
-
driver.show_one_line_names(:commit_hash => commit_hash).
|
17
|
-
gsub("\r\n", "\n").
|
18
|
-
gsub("\r", "\n").
|
19
|
-
split("\n")[1..-1]
|
20
|
-
end.flatten
|
21
|
-
end
|
22
|
-
|
23
|
-
# TODO : replace with each_line
|
24
|
-
def filtered_commit_hashes
|
25
|
-
message_filters.map do |filter|
|
26
|
-
driver.pretty_log(:since_days => time, :message_filter => filter).
|
27
|
-
gsub("\r\n", "\n").
|
28
|
-
gsub("\r", "\n").
|
29
|
-
split("\n")
|
30
|
-
end.flatten.uniq
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'hotspots/repository/parser/git'
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', 'minitest_helper')
|
2
|
-
|
3
|
-
module Hotspots::Repository
|
4
|
-
describe "Command::Git" do
|
5
|
-
describe "Log" do
|
6
|
-
describe "#build" do
|
7
|
-
describe "when message filter exists" do
|
8
|
-
it "includes a grep clause" do
|
9
|
-
log_command = Command::Git::Log.new :since_days => 20, :message_filter => "Foo|Bar"
|
10
|
-
log_command.build.must_equal 'git log --pretty="%H" --since="20 days ago" --grep "Foo|Bar"'
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "when message filter doesn't exist" do
|
15
|
-
it "doesn't have a grep clause" do
|
16
|
-
log_command = Command::Git::Log.new :since_days => 20
|
17
|
-
log_command.build.must_equal 'git log --pretty="%H" --since="20 days ago"'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "when message filter is set to an empty string" do
|
22
|
-
it "grep clause is ignored" do
|
23
|
-
log_command = Command::Git::Log.new :since_days => 20, :message_filter => ""
|
24
|
-
log_command.build.must_equal 'git log --pretty="%H" --since="20 days ago"'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "Show" do
|
31
|
-
describe "#build" do
|
32
|
-
it "constructs a git show with one-line format" do
|
33
|
-
show_command = Command::Git::Show.new :commit_hash => "abc123"
|
34
|
-
show_command.build.must_equal 'git show --oneline --name-only abc123'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
require File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', 'minitest_helper')
|
2
|
-
|
3
|
-
module Hotspots::Repository
|
4
|
-
describe "Parser::Git" do
|
5
|
-
it "fetches a commit hash based on filter and time" do
|
6
|
-
mock_git_driver = MiniTest::Mock.new
|
7
|
-
options = {:time => 10, :message_filters => ["Foo"]}
|
8
|
-
git_parser = Parser::Git.new mock_git_driver, options
|
9
|
-
|
10
|
-
mock_git_driver.expect(:pretty_log, "SHA1\nSHA2", [:since_days => options[:time], :message_filter => "Foo"])
|
11
|
-
|
12
|
-
git_parser.filtered_commit_hashes.must_equal(["SHA1", "SHA2"])
|
13
|
-
|
14
|
-
assert mock_git_driver.verify
|
15
|
-
end
|
16
|
-
|
17
|
-
it "fetches multiple commit hashes" do
|
18
|
-
options = {:time => 10, :message_filters => ["Foo", "Bar"]}
|
19
|
-
git_parser = Parser::Git.new StubGitDriver.new, options
|
20
|
-
|
21
|
-
git_parser.filtered_commit_hashes.must_equal(["SHA1", "SHA2", "SHA3"])
|
22
|
-
end
|
23
|
-
|
24
|
-
it "finds all affected files for a commit message" do
|
25
|
-
mock_git_driver = MiniTest::Mock.new
|
26
|
-
options = {:time => 10, :message_filters => ["Foo"]}
|
27
|
-
git_parser = Parser::Git.new mock_git_driver, options
|
28
|
-
|
29
|
-
mock_git_driver.expect(:pretty_log, "SHA1", [:since_days => options[:time], :message_filter => "Foo"])
|
30
|
-
mock_git_driver.expect(:show_one_line_names, "SHA1 CommitMessage\nfile1\nfile2", [:commit_hash => "SHA1"])
|
31
|
-
|
32
|
-
git_parser.files.must_equal(["file1", "file2"])
|
33
|
-
|
34
|
-
assert mock_git_driver.verify
|
35
|
-
end
|
36
|
-
|
37
|
-
it "finds all affected files for multiple commit messages" do
|
38
|
-
options = {:time => 10, :message_filters => ["Foo", "Bar"]}
|
39
|
-
git_parser = Parser::Git.new StubGitDriver.new, options
|
40
|
-
|
41
|
-
git_parser.files.must_equal(["file1", "file2", "file2", "file3", "file5", "file4"])
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "handles line ending" do
|
45
|
-
it "of type \r\n" do
|
46
|
-
options = {:time => 10, :message_filters => ["Foo", "Bar"]}
|
47
|
-
git_parser = Parser::Git.new StubGitDriver.new(:line_ending => "\r\n"), options
|
48
|
-
|
49
|
-
git_parser.files.must_equal(["file1", "file2", "file2", "file3", "file5", "file4"])
|
50
|
-
end
|
51
|
-
|
52
|
-
it "of type \r" do
|
53
|
-
options = {:time => 10, :message_filters => ["Foo", "Bar"]}
|
54
|
-
git_parser = Parser::Git.new StubGitDriver.new(:line_ending => "\r"), options
|
55
|
-
|
56
|
-
git_parser.files.must_equal(["file1", "file2", "file2", "file3", "file5", "file4"])
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe "git driver stub" do
|
62
|
-
it "has a sane pretty log" do
|
63
|
-
driver = StubGitDriver.new
|
64
|
-
driver.pretty_log(:time => 10, :message_filter => "Foo").must_equal "SHA1\nSHA2"
|
65
|
-
driver.pretty_log(:time => 10, :message_filter => "Bar").must_equal "SHA2\nSHA3"
|
66
|
-
end
|
67
|
-
|
68
|
-
it "has a sane show one line names" do
|
69
|
-
StubGitDriver.new.show_one_line_names(:commit_hash => "SHA2").
|
70
|
-
must_equal "SHA1 commit message\nfile2\nfile3\nfile5"
|
71
|
-
StubGitDriver.new(:line_ending => "\r\n").show_one_line_names(:commit_hash => "SHA2").
|
72
|
-
must_equal "SHA1 commit message\r\nfile2\r\nfile3\r\nfile5"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class StubGitDriver
|
77
|
-
def initialize(options = {})
|
78
|
-
line_ending = options[:line_ending] || "\n"
|
79
|
-
@pretty_log_enum = ["SHA1#{line_ending}SHA2", "SHA2#{line_ending}SHA3"].cycle
|
80
|
-
@commits = {
|
81
|
-
"SHA1" => "SHA1 commit message#{line_ending}file1#{line_ending}file2",
|
82
|
-
"SHA2" => "SHA1 commit message#{line_ending}file2#{line_ending}file3#{line_ending}file5",
|
83
|
-
"SHA3" => "SHA1 commit message#{line_ending}file4",
|
84
|
-
}
|
85
|
-
end
|
86
|
-
|
87
|
-
def pretty_log(options)
|
88
|
-
@pretty_log_enum.next
|
89
|
-
end
|
90
|
-
|
91
|
-
def show_one_line_names(options)
|
92
|
-
@commits[options[:commit_hash]]
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|