hotspots 1.0.0 → 1.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 +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
|