File: github-linguist

package info (click to toggle)
ruby-github-linguist 7.27.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 14,204 kB
  • sloc: ruby: 1,872; lex: 173; ansic: 35; makefile: 9
file content (152 lines) | stat: -rwxr-xr-x 4,456 bytes parent folder | download
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
#!/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] [--breakdown] [--json]
       linguist [--rev REV] [--breakdown] [--json]
HELP

def github_linguist(args)
  breakdown = false
  json_output = false
  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("-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)

    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)