git-health-check 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/git-health-check.gemspec +7 -7
- data/lib/git-health-check.rb +1 -1
- data/lib/git-health-check/cli/git_health_check_command.rb +5 -5
- data/lib/git-health-check/cli/options.rb +4 -4
- data/lib/git-health-check/git_lib.rb +16 -0
- data/lib/git-health-check/history.rb +15 -15
- data/lib/git-health-check/report.rb +3 -3
- data/lib/git-health-check/report/report.erb +30 -12
- data/lib/git-health-check/version.rb +1 -1
- data/lib/git-health-check/working_copy.rb +14 -25
- metadata +2 -2
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/git-health-check.gemspec
CHANGED
@@ -4,20 +4,20 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'git-health-check/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
7
|
+
gem.name = 'git-health-check'
|
8
8
|
gem.version = GitHealthCheck::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
9
|
+
gem.authors = ['Ben Snape']
|
10
|
+
gem.email = ['bsnape@gmail.com']
|
11
11
|
gem.description = %q{Git Health Check}
|
12
12
|
gem.summary = %q{Git Health Check}
|
13
|
-
gem.homepage =
|
13
|
+
gem.homepage = 'http://wwww.bensnape.com'
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = [
|
18
|
+
gem.require_paths = ['lib']
|
19
19
|
|
20
|
-
gem.add_dependency(
|
21
|
-
gem.add_development_dependency(
|
20
|
+
gem.add_dependency('ruport')
|
21
|
+
gem.add_development_dependency('rake')
|
22
22
|
|
23
23
|
end
|
data/lib/git-health-check.rb
CHANGED
@@ -12,18 +12,18 @@ module GitHealthCheck
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def execute(view)
|
15
|
-
history = GitHealthCheck::History.new(@repository,
|
15
|
+
history = GitHealthCheck::History.new(@repository, @threshold)
|
16
16
|
working_copy = GitHealthCheck::WorkingCopy.new @repository
|
17
17
|
packfile = GitHealthCheck::Packfile.new(@repository)
|
18
18
|
packfile.packfile_stats
|
19
19
|
|
20
|
-
working_copy_output = working_copy.
|
20
|
+
working_copy_output = working_copy.find_in_working_copy
|
21
21
|
history_output = history.search
|
22
22
|
|
23
|
-
working_copy_report = Table(
|
24
|
-
history_report = Table(
|
23
|
+
working_copy_report = Table('object sha', 'size (MB)', 'path')
|
24
|
+
history_report = Table('object sha', 'size (MB)', 'path', 'commit details', 'author')
|
25
25
|
|
26
|
-
working_copy_output.each { |sha,
|
26
|
+
working_copy_output.each { |sha, size, path| working_copy_report << [sha, size, path] }
|
27
27
|
history_output.each { |sha, size, path, where, who| history_report << [sha, size, path, where, who] }
|
28
28
|
|
29
29
|
report = GitHealthCheck::Report.new(working_copy_report.to_html, history_report.to_html, packfile)
|
@@ -29,13 +29,13 @@ EOB
|
|
29
29
|
def set_parser_options
|
30
30
|
@parser.banner = banner
|
31
31
|
|
32
|
-
@parser.separator
|
32
|
+
@parser.separator 'Options:'
|
33
33
|
|
34
|
-
@parser.on(
|
34
|
+
@parser.on('-v', '--version', 'Displays the gem version') { @command_class = VersionCommand }
|
35
35
|
|
36
|
-
@parser.on(
|
36
|
+
@parser.on('-h', '--help', 'Displays this help message') { @command_class = HelpCommand }
|
37
37
|
|
38
|
-
@parser.on(
|
38
|
+
@parser.on('-t', '--threshold THRESHOLD', Float, 'Specify history size threshold in MB (default 0.5)') do |n|
|
39
39
|
@threshold = n
|
40
40
|
end
|
41
41
|
end
|
@@ -38,5 +38,21 @@ module GitHealthCheck
|
|
38
38
|
`git count-objects -v`
|
39
39
|
end
|
40
40
|
|
41
|
+
def get_largest_files(number=10)
|
42
|
+
`git ls-files -z | xargs -0 ls -l | sort -nrk5 | head -n #{number}`
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_object_sha_from_path(path)
|
46
|
+
`git ls-files -s #{path} | cut -d ' ' -f 2`
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_revision_list(head='HEAD')
|
50
|
+
`git rev-list #{head}`
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_treeish_contents(treeish)
|
54
|
+
`git ls-tree -zrl #{treeish}`
|
55
|
+
end
|
56
|
+
|
41
57
|
end
|
42
58
|
end
|
@@ -5,36 +5,36 @@ module GitHealthCheck
|
|
5
5
|
|
6
6
|
class History
|
7
7
|
|
8
|
-
MEGABYTE =
|
8
|
+
MEGABYTE = 1024 ** 2
|
9
9
|
|
10
|
-
def initialize(repository,
|
11
|
-
@
|
10
|
+
def initialize(repository, threshold)
|
11
|
+
@repository = repository
|
12
12
|
@bytes_threshold = threshold.to_f * MEGABYTE
|
13
13
|
Dir.chdir repository
|
14
14
|
@git_lib = GitHealthCheck::GitLib.new repository
|
15
15
|
end
|
16
16
|
|
17
17
|
def search
|
18
|
-
|
18
|
+
revision_list = @git_lib.get_revision_list.split "\n"
|
19
19
|
big_files = {}
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
size = size.to_i
|
28
|
-
big_files[sha] = [path, size, commit] if size >= @bytes_threshold
|
29
|
-
end
|
21
|
+
revision_list.each do |commit|
|
22
|
+
@git_lib.get_treeish_contents(commit).split("\0").each do |object|
|
23
|
+
bits, type, sha, size, path = object.split
|
24
|
+
next if File.exist?("#@repository/#{path}")
|
25
|
+
size = size.to_f
|
26
|
+
big_files[path] = [sha, size, commit] if size >= @bytes_threshold
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
|
-
big_files.map do |
|
30
|
+
big_files = big_files.map do |path, (sha, size, commit_sha)|
|
34
31
|
where = @git_lib.get_commit_details commit_sha
|
35
32
|
who = @git_lib.get_commit_author commit_sha
|
36
|
-
[sha, size
|
33
|
+
[sha, (size / MEGABYTE).round(2), path, where, who]
|
37
34
|
end
|
35
|
+
|
36
|
+
big_files.sort_by! { |a| [a[1], a[2]] }.reverse!
|
37
|
+
|
38
38
|
end
|
39
39
|
|
40
40
|
end
|
@@ -8,7 +8,7 @@ module GitHealthCheck
|
|
8
8
|
@working_copy = working_copy
|
9
9
|
@history = history
|
10
10
|
@packfile = packfile
|
11
|
-
@report_directory = Dir.pwd +
|
11
|
+
@report_directory = Dir.pwd + '/healthcheck'
|
12
12
|
@repository = Dir.pwd
|
13
13
|
end
|
14
14
|
|
@@ -17,7 +17,7 @@ module GitHealthCheck
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def get_template
|
20
|
-
File.read(File.dirname(__FILE__) +
|
20
|
+
File.read(File.dirname(__FILE__) + '/report/report.erb')
|
21
21
|
end
|
22
22
|
|
23
23
|
def create
|
@@ -26,7 +26,7 @@ module GitHealthCheck
|
|
26
26
|
|
27
27
|
Dir.mkdir @report_directory unless File.directory? @report_directory
|
28
28
|
|
29
|
-
File.open(@report_directory +
|
29
|
+
File.open(@report_directory + '/report.html', 'w+') do |f|
|
30
30
|
f.write output
|
31
31
|
end
|
32
32
|
end
|
@@ -39,14 +39,15 @@
|
|
39
39
|
|
40
40
|
h3 {
|
41
41
|
font-size: 16px;
|
42
|
+
padding: 0 0 0 20px;
|
42
43
|
}
|
43
44
|
|
44
45
|
#history {
|
45
|
-
padding: 0 0 0
|
46
|
+
padding: 0 0 0 30px;
|
46
47
|
}
|
47
48
|
|
48
49
|
#working-copy {
|
49
|
-
padding: 0 0 0
|
50
|
+
padding: 0 0 0 30px;
|
50
51
|
}
|
51
52
|
</style>
|
52
53
|
</head>
|
@@ -64,11 +65,11 @@
|
|
64
65
|
<li><strong>Total packfile size: </strong>
|
65
66
|
<% size = @packfile.size_of_pack[0].to_f %>
|
66
67
|
<% if size >= 1048576 %>
|
67
|
-
<%= size / 1048576 %> GB
|
68
|
+
<%= (size / 1048576).round 2 %> GB
|
68
69
|
<% elsif size >= 1024 %>
|
69
|
-
<%= size / 1024 %> MB
|
70
|
+
<%= (size / 1024).round 2 %> MB
|
70
71
|
<% else %>
|
71
|
-
<%= size %> kB
|
72
|
+
<%= size.round 2 %> kB
|
72
73
|
<% end %>
|
73
74
|
</li>
|
74
75
|
</ul>
|
@@ -78,24 +79,41 @@
|
|
78
79
|
|
79
80
|
<h2>Repository Size</h2>
|
80
81
|
|
82
|
+
<h3>Working Copy</h3>
|
83
|
+
|
81
84
|
<div id="working-copy">
|
82
85
|
|
83
|
-
<
|
86
|
+
<h4>Description</h4>
|
87
|
+
|
88
|
+
<p>This metric inspects your repository's working copy using
|
89
|
+
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-ls-files.html">git ls-files</a> to identify the
|
90
|
+
<em>n</em> (default 10) largest files - and consequently the <strong>largest objects</strong>.</p>
|
84
91
|
|
85
|
-
<p>
|
86
|
-
|
87
|
-
|
92
|
+
<p>In some cases the same object hash will be displayed for multiple paths. <strong>This is not a bug.</strong>
|
93
|
+
The way git stores <a href="http://git-scm.com/book/en/Git-Internals-Git-Objects">blob objects</a> - i.e. bytes on
|
94
|
+
the filesystem that could be anything (e.g. a text file, source code, an image) - means that if you have
|
95
|
+
<em>exactly</em> the same file in multiple places in your repository - perhaps a static test file - then the
|
96
|
+
report will correctly output <em>all the paths on the filesystem where the object is referenced</em>.</p>
|
97
|
+
|
98
|
+
<h4>Statistics</h4>
|
88
99
|
|
89
100
|
<p><%= @working_copy %></p>
|
90
101
|
|
91
102
|
</div>
|
92
103
|
|
104
|
+
<br>
|
105
|
+
|
106
|
+
<h3>History</h3>
|
107
|
+
|
93
108
|
<div id="history">
|
94
|
-
|
109
|
+
|
110
|
+
<h4>Description</h4>
|
95
111
|
|
96
112
|
<p>This metric thoroughly inspects your repository's history and identifies the largest files over a configurable
|
97
|
-
threshold (defaults at 0.5 MB) that have been committed in the past <strong>but are
|
98
|
-
|
113
|
+
threshold (defaults at 0.5 MB) that have been committed in the past <strong>but are no longer part of the working
|
114
|
+
copy</strong>.</p>
|
115
|
+
|
116
|
+
<h4>Statistics</h4>
|
99
117
|
|
100
118
|
<p><%= @history %></p>
|
101
119
|
</div>
|
@@ -7,34 +7,23 @@ module GitHealthCheck
|
|
7
7
|
@git_lib = GitHealthCheck::GitLib.new repository
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
sha =
|
21
|
-
|
22
|
-
path
|
23
|
-
# an empty path means you need to do a garbage collection
|
24
|
-
next unless File.exist?("#@repository/#{path}")
|
25
|
-
|
26
|
-
sha, type, size, size_in_pack, offset = object.split
|
27
|
-
|
28
|
-
# convert from byte to kilobyte
|
29
|
-
size = (size.to_f / 1024).round 2
|
30
|
-
size_in_pack = (size_in_pack.to_f / 1024).round 2
|
31
|
-
|
32
|
-
test[sha] = [size, size_in_pack, path]
|
10
|
+
def find_in_working_copy(number=10)
|
11
|
+
largest_files = @git_lib.get_largest_files number
|
12
|
+
largest_files = largest_files.split "\n"
|
13
|
+
|
14
|
+
files = []
|
15
|
+
|
16
|
+
largest_files.each do |file|
|
17
|
+
split = file.split
|
18
|
+
size = split[4]
|
19
|
+
path = split[8]
|
20
|
+
sha = @git_lib.get_object_sha_from_path path
|
21
|
+
size = (size.to_f * 9.53674e-7).round 2 # bytes to MB
|
22
|
+
files << [sha, size, path] # no hash in case of blob-reuse in various paths
|
33
23
|
end
|
34
24
|
|
35
|
-
|
25
|
+
files
|
36
26
|
end
|
37
27
|
|
38
|
-
|
39
28
|
end
|
40
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-health-check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruport
|