File: commit_stats.rb

package info (click to toggle)
ruby-grit 2.8.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 336 kB
  • sloc: ruby: 3,643; makefile: 4
file content (128 lines) | stat: -rw-r--r-- 3,416 bytes parent folder | download | duplicates (3)
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
module Grit

  class CommitStats

    attr_reader :id, :files, :additions, :deletions, :total

    # Instantiate a new CommitStats
    #   +id+ is the id of the commit
    #   +files+ is an array of :
    #     [ [filename, adds, deletes, total],
    #       [filename, adds, deletes, total],
    #       [filename, adds, deletes, total] ]
    #
    # Returns Grit::CommitStats (baked)
    def initialize(repo, id, files)
      @repo = repo
      @id = id
      @files = files
      @additions  = files.inject(0) { |total, a| total += a[1] }
      @deletions  = files.inject(0) { |total, a| total += a[2] }
      @total  = files.inject(0) { |total, a| total += a[3] }
    end

    # Find all commit stats matching the given criteria.
    #   +repo+ is the Repo
    #   +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
    #   +options+ is a Hash of optional arguments to git
    #     :max_count is the maximum number of commits to fetch
    #     :skip is the number of commits to skip
    #
    # Returns assoc array [sha, Grit::Commit[] (baked)]
    def self.find_all(repo, ref, options = {})
      allowed_options = [:max_count, :skip, :since]

      default_options = {:numstat => true}
      actual_options = default_options.merge(options)

      if ref
        output = repo.git.log(actual_options, ref)
      else
        output = repo.git.log(actual_options.merge(:all => true))
      end

      self.list_from_string(repo, output)
    end

    # Parse out commit information into an array of baked Commit objects
    #   +repo+ is the Repo
    #   +text+ is the text output from the git command (raw format)
    #
    # Returns assoc array [sha, Grit::Commit[] (baked)]
    def self.list_from_string(repo, text)
      lines = text.split("\n")

      commits = []

      while !lines.empty?
        id = lines.shift.split.last

        lines.shift
        lines.shift
        lines.shift

        message_lines = []
        message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/ || lines.first == ''

        lines.shift while lines.first && lines.first.empty?

        files = []
        while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
          (additions, deletions, filename) = lines.shift.split(nil, 3)
          additions = additions.to_i
          deletions = deletions.to_i
          total = additions + deletions
          files << [filename, additions, deletions, total]
        end

        lines.shift while lines.first && lines.first.empty?

        commits << [id, CommitStats.new(repo, id, files)]
      end

      commits
    end

    # Pretty object inspection
    def inspect
      %Q{#<Grit::CommitStats "#{@id}">}
    end

    # Convert to an easy-to-traverse structure
    def to_diffstat
      files.map do |metadata|
        DiffStat.new(*metadata)
      end
    end

    # private

    def to_hash
      {
        'id'        => id,
        'files'     => files,
        'additions' => additions,
        'deletions' => deletions,
        'total'     => total
      }
    end

  end # CommitStats

  class DiffStat
    attr_reader :filename, :additions, :deletions

    def initialize(filename, additions, deletions, total=nil)
      @filename, @additions, @deletions = filename, additions, deletions
    end

    def net
      additions - deletions
    end

    def inspect
      "#{filename}: +#{additions} -#{deletions}"
    end
  end

end # Grit