-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
github-linguist
executable file
·155 lines (135 loc) · 4.62 KB
/
github-linguist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env ruby
$LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
require 'linguist'
require 'rugged'
require 'json'
require 'optparse'
require 'pathname'
HELP_TEXT = <<~HELP
Linguist v#{Linguist::VERSION}
Detect language type and determine language breakdown for a given Git repository.
Usage: linguist <path>
linguist <path> [--rev REV] [--tree-size] [--breakdown] [--json]
linguist [--rev REV] [--tree-size] [--breakdown] [--json]
HELP
def github_linguist(args)
breakdown = false
json_output = false
tree_size = Linguist::Repository::MAX_TREE_SIZE
rev = 'HEAD'
path = Dir.pwd
parser = OptionParser.new do |opts|
opts.banner = HELP_TEXT
opts.version = Linguist::VERSION
opts.on("-b", "--breakdown", "Analyze entire repository and display detailed usage statistics") { breakdown = true }
opts.on("-j", "--json", "Output results as JSON") { json_output = true }
opts.on("-r", "--rev REV", String,
"Analyze specific git revision",
"defaults to HEAD, see gitrevisions(1) for alternatives") { |r| rev = r }
opts.on("-t", "--tree-size=NUMBER", Integer,
"Maximum number of files scanned to detect languages (default: #{Linguist::Repository::MAX_TREE_SIZE})") { |t| tree_size = t }
opts.on("-h", "--help", "Display a short usage summary, then exit") do
puts opts
exit
end
end
parser.parse!(args)
if !args.empty?
if File.directory?(args[0]) || File.file?(args[0])
path = args[0]
else
abort HELP_TEXT
end
end
if File.directory?(path)
rugged = Rugged::Repository.new(path)
begin
target_oid = rugged.rev_parse_oid(rev)
rescue
puts "invalid revision '#{rev}' for repo '#{path}'"
exit 1
end
repo = Linguist::Repository.new(rugged, target_oid, tree_size)
full_results = {}
repo.languages.each do |language, size|
percentage = ((size / repo.size.to_f) * 100)
percentage = sprintf '%.2f' % percentage
full_results.merge!({"#{language}": { size: size, percentage: percentage } })
end
if !json_output
full_results.sort_by { |_, v| v[:size] }.reverse.each do |language, details|
puts "%-7s %-10s %s" % ["#{details[:percentage]}%", details[:size], language]
end
if breakdown
puts
file_breakdown = repo.breakdown_by_file
file_breakdown.each do |lang, files|
puts "#{lang}:"
files.each do |file|
puts file
end
puts
end
end
else
if !breakdown
puts JSON.dump(full_results)
else
combined_results = full_results.merge({})
repo.breakdown_by_file.each do |language, files|
combined_results[language.to_sym].update({"files": files})
end
puts JSON.dump(combined_results)
end
end
elsif File.file?(path)
begin
# Check if this file is inside a git repository so we have things like
# `.gitattributes` applied.
file_full_path = File.realpath(path)
rugged = Rugged::Repository.discover(file_full_path)
file_rel_path = file_full_path.sub(rugged.workdir, '')
oid = -> { rugged.head.target.tree.walk_blobs { |r, b| return b[:oid] if r + b[:name] == file_rel_path } }
blob = Linguist::LazyBlob.new(rugged, oid.call, file_rel_path)
rescue Rugged::RepositoryError
blob = Linguist::FileBlob.new(path, Dir.pwd)
end
type = if blob.text?
'Text'
elsif blob.image?
'Image'
else
'Binary'
end
if json_output
puts JSON.generate( { path => {
:lines => blob.loc,
:sloc => blob.sloc,
:type => type,
:mime_type => blob.mime_type,
:language => blob.language,
:large => blob.large?,
:generated => blob.generated?,
:vendored => blob.vendored?,
}
} )
else
puts "#{path}: #{blob.loc} lines (#{blob.sloc} sloc)"
puts " type: #{type}"
puts " mime type: #{blob.mime_type}"
puts " language: #{blob.language}"
if blob.large?
puts " blob is too large to be shown"
end
if blob.generated?
puts " appears to be generated source code"
end
if blob.vendored?
puts " appears to be a vendored file"
end
end
else
abort HELP_TEXT
end
end
github_linguist(ARGV)