Class: Autoproj::Stats::Git

Inherits:
Object
  • Object
show all
Defined in:
lib/autoproj/stats/git.rb

Overview

Statistic generator for git-based packages

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sloc_counter: SLOCCounter.new, sanitizer: Sanitizer.new) ⇒ Git

Returns a new instance of Git.



7
8
9
10
# File 'lib/autoproj/stats/git.rb', line 7

def initialize(sloc_counter: SLOCCounter.new, sanitizer: Sanitizer.new)
    @sloc_counter = sloc_counter
    @sanitizer = sanitizer
end

Instance Attribute Details

#sanitizerObject (readonly)

Returns the value of attribute sanitizer.



6
7
8
# File 'lib/autoproj/stats/git.rb', line 6

def sanitizer
  @sanitizer
end

#sloc_counterObject (readonly)

Returns the value of attribute sloc_counter.



5
6
7
# File 'lib/autoproj/stats/git.rb', line 5

def sloc_counter
  @sloc_counter
end

Instance Method Details

#call(pkg) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/autoproj/stats/git.rb', line 12

def call(pkg)
    pkg.progress_start "processing %s", done_message: "processed %s" do
        importer = pkg.importer
        entries = importer.run_git(pkg, 'ls-tree', '-r', 'HEAD', encoding: 'UTF-8')

        progress_counter = 0
        entries.inject(PackageStats.new) do |aggregate, line|
            mode, type, sha, path = line.split(/\s+/)
            if file_counter = sloc_counter.find_counter_for_path(path)
                aggregate += process_file(pkg, path, sloc: file_counter)
            else
                pkg.warn "%s: no SLOC count counter available for #{path}"
            end
            progress_counter += 1
            pkg.progress "processing %s (#{progress_counter}/#{entries.size})"
            aggregate
        end
    end
end

#process_file(pkg, path, sloc: proc { true }) ⇒ Object



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
# File 'lib/autoproj/stats/git.rb', line 32

def process_file(pkg, path, sloc: proc { true })
    blamed = pkg.importer.run_git(pkg, 'blame', '-w', '-C', '-C', '-C', '-M', '--minimal', 'HEAD', '--', path, encoding: 'UTF-8')

    authors = Hash.new(0)
    copyrights = Hash.new(0)

    line_matcher = Regexp.new(/^\^?[0-9a-f]+.*\((.*) (\d{4})-(\d{2})-(\d{2}).*\d+\) (.*)$/)
    blamed.each do |line|
        line = line.encode('UTF-8', invalid: :replace, undef: :replace)
        if m = line_matcher.match(line)
            _, name, y, m, d, code = *m
            code = code.strip
            next if code.empty? || !sloc.(code)

            name = sanitizer.sanitize_author_name(name.strip)
            copyright = sanitizer.compute_copyright_of(
                name, Date.new(y.to_i, m.to_i, d.to_i))
            authors[name] += 1
            copyrights[copyright] += 1
        else
            raise "cannot match #{line}"
        end
    end

    sloc = authors.values.inject(0, &:+)
    PackageStats.new(sloc, authors, copyrights)
end