Class: TimeCost::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/timecost/cli.rb

Instance Method Summary collapse

Constructor Details

#initializeCLI

Returns a new instance of CLI.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/timecost/cli.rb', line 3

def initialize
  # FIXME: accept multiple authors
  @config = {
    :author_filter_enable => false,
    :author_filter => ".*?",

    :date_filter_enable => false,
    :date_filter => [],

    :branches_filter_enable => true,

    :input_dump => [],
    :output_dump => nil,

    :range_granularity => 0.5, # in decimal hours

    :verbose => false
  }
  @rangelist = {}
  @authorlist = nil
end

Instance Method Details

#analyzeObject



193
194
195
196
197
198
199
# File 'lib/timecost/cli.rb', line 193

def analyze
  if @config[:input_dump].empty? then
    analyze_git
  else
    analyze_dumps
  end
end

#analyze_dumpsObject



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/timecost/cli.rb', line 175

def analyze_dumps
  #read ranges

  @config[:input_dump].each do |filename|
    filelists = YAML::load(File.open(filename,"r"))
    # require 'pry'
    # binding.pry
    filelists.each do |author, rangelist|
      # create list if author is new
      @rangelist[author] ||= RangeList.new

      rangelist.each do |range|
        @rangelist[author].add range
      end
    end
  end
end

#analyze_gitObject



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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/timecost/cli.rb', line 92

def analyze_git
  # git log
  # foreach, create time range (before) + logs

  cmd = [
    "git", "log",
      "--date=iso", 
      "--no-patch"
  ]
  if not @config[:branches_filter_enable] then  
    cmd << "--all"
  end
  cmd.concat ["--", "."]
  process = IO.popen cmd

  @rangelist = {}
  commit = nil
  loop do
    line = process.gets
    break if line.nil?
    # utf-8 fix ?
    # line.encode!( line.encoding, "binary", :invalid => :replace, :undef => :replace)
    line.strip!

    case line
    when /^commit (.*)$/ then
      id = $1
      # merge ranges & push
      unless commit.nil? then
        range = Range.new commit, granularity: @config[:range_granularity]

        if not @rangelist.include? commit.author then
          @rangelist[commit.author] = RangeList.new
        end
        @rangelist[commit.author].add range
      end
      commit = Commit.new id
      # puts "commit #{id}"

    when /^Author:\s*(.*?)\s*$/ then
      unless commit.nil? then
        commit.author = $1 

        if @config[:author_filter_enable] and 
          (not commit.author =~ /#{@config[:author_filter]}/) then
          commit = nil
          # reject
        end

      end

    when /^Date:\s*(.*?)\s*$/ then
      unless commit.nil? then
        commit.date = $1

        # reject if a some filter does not validate date
        filter_keep = true
        filters = @config[:date_filter]
        filters.each do |f|
          filter_keep &= f.call(DateTime.parse(commit.date))
        end

        if not filter_keep then
          commit = nil
        end
      end

    when /^\s*$/ then
      # skip

    else 
      # add as note
      unless commit.nil? then
        commit.note = if commit.note.nil? then line
                  else commit.note + "\n" + line
                  end
      end
    end

  end

end

#exportObject



201
202
203
204
205
206
207
# File 'lib/timecost/cli.rb', line 201

def export
  return if @config[:output_dump].nil?
  puts "Exporting to %s" % @config[:output_dump]
  File.open(@config[:output_dump], "w") do |file|
    file.puts YAML::dump(@rangelist)
  end
end

#parse_cmdline(args) ⇒ Object



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
# File 'lib/timecost/cli.rb', line 25

def parse_cmdline args
  options = OptionParser.new do |opts|
    opts.banner = "Usage: #{File.basename $0} [options]"

    opts.on_tail("-v","--verbose", "Run verbosely") do |v|
      @config[:verbose] = true
    end

    opts.on_tail("-h","--help", "Show this help") do
      puts opts
      exit 0
    end


    opts.on("-i","--input FILE", "Set input dump file") do |file|
      @config[:input_dump] << file
    end

    opts.on("-o","--output FILE", "Set output dump file") do |file|
      @config[:output_dump] = file
    end

    opts.on("--before DATE", "Keep only commits before DATE") do |date|
      puts "set date filter to <= #{date}"
      @config[:date_filter] << lambda { |other|
        return (other <= DateTime.parse(date))
      }
      @config[:date_filter_enable] = true
    end

    opts.on("--after DATE", "Keep only commits after DATE") do |date|
      puts "set date filter to >= #{date}"
      @config[:date_filter] << lambda { |other|
        return (other >= DateTime.parse(date))
      }
      @config[:date_filter_enable] = true
    end

    opts.on("-t","--time TIME", "Keep only commits on last TIME days") do |time|
      puts "set time filter to latest #{time} days"
      @config[:date_filter] = DateTime.now - time.to_f;
      puts "set date filter to date = #{@config[:date_filter]}"
      @config[:date_filter_enable] = true
    end

    opts.on("-a","--author AUTHOR", "Keep only commits by AUTHOR") do |author|
      puts "set author filter to #{author}"
      @config[:author_filter] = author
      @config[:author_filter_enable] = true
    end

    opts.on_tail("--all", "Collect from all branches and refs") do
      @config[:branches_filter_enable] = false
    end

    # overlap : 
    #
    opts.on("-s","--scotch GRANULARITY", "Use GRANULARITY (decimal hours) to merge ranges") do |granularity|
      puts "set scotch to #{granularity}"
      @config[:range_granularity] = granularity.to_f
    end
  end
  options.parse! args

end

#reportObject



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/timecost/cli.rb', line 209

def report
  return if not @config[:output_dump].nil?

  @rangelist.each do |author,rangelist|
    rangelist.each do |range|
      puts range.to_s(!@config[:author_filter_enable]) + "\n"
    end
  end
  total = 0
  @rangelist.each do |author,rangelist|
    puts "SUB-TOTAL for %s: %.2f hours\n" % [author, rangelist.sum]
    total += rangelist.sum
  end
  puts "TOTAL: %.2f hours" % total
end