clockout 0.1 → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/bin/clock +73 -51
  2. data/lib/clockout.rb +80 -32
  3. metadata +2 -2
data/bin/clock CHANGED
@@ -3,16 +3,16 @@
3
3
  require 'clockout'
4
4
 
5
5
  HELP_BANNER = <<-EOS
6
- Clockout v0.1
6
+ Clockout v0.2
7
7
  Usage:
8
- $ clock [options]
8
+ $ clock [options]
9
9
 
10
10
  Options:
11
- --estimations, -e: Show estimations made for first commit of each block
12
- --condensed, -c: Condense output (don't show the timeline for each day)
13
- --generate-clock, -g: Generate .clock file
14
- --see-clock, -s: See options specified in .clock file
15
- --help, -h: Show this message
11
+ --estimations, -e: Show estimations made for first commit of each block
12
+ --condensed, -c: Condense output (don't show the timeline for each day)
13
+ --generate-clock, -g: Generate .clock file
14
+ --see-clock, -s: See options specified in .clock file
15
+ --help, -h: Show this message
16
16
  EOS
17
17
 
18
18
  TEMPLATE_CLOCKFILE = <<-EOF
@@ -41,7 +41,7 @@ TEMPLATE_CLOCKFILE = <<-EOF
41
41
  ; that you don't want to report as your own work.
42
42
  ; Below is an example regex that will only calculate changes made to files with those extensions
43
43
 
44
- ;my_files = /\.(m|h|rb|txt)$/
44
+ ;my_files = /\\.(m|h|rb|txt)$/
45
45
 
46
46
  ; Diffs of files matched by this regex will NOT be included in commit time estimation
47
47
  ; Type: Regex (Ruby)
@@ -50,7 +50,7 @@ TEMPLATE_CLOCKFILE = <<-EOF
50
50
  ; You also have the option of defining a negative regex match, to ignore certain files.
51
51
  ; For example, if you added an external library or something, you should ignore those additions
52
52
 
53
- ;not_my_files = /(ThisFile\.cpp | SomeOtherClass\.*)/
53
+ ;not_my_files = /(ThisFile\\.cpp | SomeOtherClass\\.*)/
54
54
 
55
55
  ; Completion time overrides for commit estimations
56
56
  ; Type: Int (in minutes)
@@ -76,8 +76,8 @@ def parse_options(args)
76
76
  opts[:condensed] = true
77
77
  elsif (arg == "-g" || arg == "--generate-clock")
78
78
  opts[:generate_clock] = true
79
- elsif (arg[0] == "-")
80
- puts "Error: invalid option '#{arg}'."
79
+ else
80
+ puts "#{colorize("Error:", RED)} invalid option '#{arg}'."
81
81
  puts "Try --help for help."
82
82
  exit
83
83
  end
@@ -86,51 +86,73 @@ def parse_options(args)
86
86
  opts
87
87
  end
88
88
 
89
+ def generate_clock_file(path)
90
+ clock_path = Clockout.clock_path(path)
91
+ if (File.exists?(clock_path))
92
+ false
93
+ else
94
+ File.open(clock_path, "w") do |file|
95
+ file.write(TEMPLATE_CLOCKFILE)
96
+ end
97
+ true
98
+ end
99
+ end
100
+
89
101
  path = Dir.pwd
90
102
 
91
- # Default options
92
- opts = {time_cutoff:120, my_files:"/.*/"}
93
- opts.merge!(parse_options(ARGV))
94
-
95
- if opts[:generate_clock]
96
- clock_path = path+"/.clock"
97
- if (File.exists?(clock_path))
98
- puts "#{colorize("Error:", RED)} .clock file already exists, ignoring --generate-clock option.\n"
99
- else
100
- File.open(clock_path, "w") do |file|
101
- file.write(TEMPLATE_CLOCKFILE)
102
- end
103
- puts "Generated .clock file at #{clock_path}.\n"
104
- end
105
- end
103
+ if (ARGV[0] == "in" || ARGV[0] == "out")
104
+ # Generate a clock file if one doesn't already exist
105
+ generate_clock_file(path)
106
106
 
107
- clock = Clockout.new(path, opts)
107
+ # Append "in <current date>" or "out <current date>" to the clockfile
108
+ File.open(Clockout.clock_path(path), "a") do |file|
109
+ file.puts ARGV[0] + " " + Time.new.to_s
110
+ end
111
+ else
112
+ opts = parse_options(ARGV)
113
+
114
+ if opts[:help]
115
+ puts HELP_BANNER
116
+ exit
117
+ end
108
118
 
109
- if opts[:see_clock]
110
- if !clock.clock_opts
111
- puts "No .clock file found. Run `clock -g` to generate one."
112
- else
113
- if clock.clock_opts.size == 0
114
- puts "No clock options."
115
- else
116
- puts "Clock options:"
117
- clock.clock_opts.each do |k, v|
118
- key = k[0..19]
119
- puts " #{key}:#{' '*(20-key.length)}#{v}"
120
- end
121
- end
119
+ if opts[:generate_clock]
120
+ if generate_clock_file(path)
121
+ puts "Generated .clock file at #{Clockout.clock_path(path)}.\n"
122
+ else
123
+ puts "#{colorize("Error:", RED)} .clock file already exists for this repo.\n"
124
+ end
125
+ exit
122
126
  end
123
- exit
124
- end
125
127
 
126
- if opts[:help]
127
- puts HELP_BANNER
128
- exit
129
- end
128
+ if opts[:see_clock]
129
+ clock_opts = Clockout.parse_clockfile(Clockout.clock_path(path))
130
+ if !clock_opts
131
+ puts "No .clock file found. Run `clock -g` to generate one."
132
+ else
133
+ if clock_opts.size == 0
134
+ puts "No clock options."
135
+ else
136
+ puts "Clock options:"
137
+ clock_opts.each do |k, v|
138
+ space = 23
139
+ width = space-6
140
+ key = k[0..width]
141
+ key += "..." if k.length > width
142
+ # For clockins/outs, display the number of them instead of all the dates
143
+ v = v.length if k == :clockins || k == :clockouts
144
+ puts " #{key}:#{' '*(space-key.length)}#{v}"
145
+ end
146
+ end
147
+ end
148
+ exit
149
+ end
130
150
 
131
- if (opts[:estimations])
132
- clock.print_estimations
133
- else
134
- clock.print_chart
135
- end
151
+ clock = Clockout.new(path)
136
152
 
153
+ if (opts[:estimations])
154
+ clock.print_estimations
155
+ else
156
+ clock.print_chart(opts[:condensed])
157
+ end
158
+ end
data/lib/clockout.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'grit'
2
+ require 'time'
2
3
 
3
4
  class Commit
4
5
  attr_accessor :message, :minutes, :date, :diffs, :sha
@@ -16,7 +17,7 @@ class Clockout
16
17
  COLS = 80
17
18
  DAY_FORMAT = '%B %e, %Y'
18
19
 
19
- attr_accessor :blocks, :time_per_day, :clock_opts
20
+ attr_accessor :blocks
20
21
 
21
22
  def diffs(commit)
22
23
  plus, minus = 0, 0
@@ -43,6 +44,7 @@ class Clockout
43
44
 
44
45
  total_diffs, total_mins = 0, 0
45
46
 
47
+ prev = nil
46
48
  commits.each do |commit|
47
49
 
48
50
  c = Commit.new
@@ -52,7 +54,17 @@ class Clockout
52
54
  c.sha = commit.id[0..7]
53
55
 
54
56
  if block.size > 0
55
- time_since_last = (block.last.date - commit.committed_date).abs/60
57
+ last_date = block.last.date
58
+
59
+ @clockins.each do |clockin|
60
+ if clockin > last_date && clockin < c.date
61
+ last_date = clockin
62
+ @clockins.delete(clockin)
63
+ break
64
+ end
65
+ end
66
+
67
+ time_since_last = (last_date - commit.committed_date).abs/60
56
68
 
57
69
  if (time_since_last > $opts[:time_cutoff])
58
70
  blocks << block
@@ -82,22 +94,21 @@ class Clockout
82
94
  elsif ($opts[:ignore_initial] && block == blocks.first) || total_diffs == 0
83
95
  first.minutes = 0
84
96
  else
85
- # Underestimate by a factor of 0.9
86
- first.minutes = 0.9*first.diffs*(1.0*total_mins/total_diffs)
97
+ first.minutes = $opts[:estimation_factor]*first.diffs*(1.0*total_mins/total_diffs)
87
98
  end
88
99
 
89
100
  @time_per_day[first.date.strftime(DAY_FORMAT)] += first.minutes
90
101
  end
91
102
  end
92
103
 
93
- def print_chart
94
- cols = ($opts[:condensed] ? 30 : COLS)
104
+ def print_chart(condensed)
105
+ cols = (condensed ? 30 : COLS)
95
106
  total_sum = 0
96
107
  current_day = nil
97
108
  @blocks.each do |block|
98
109
  date = block.first.date.strftime(DAY_FORMAT)
99
110
  if date != current_day
100
- puts if (!$opts[:condensed])
111
+ puts if (!condensed)
101
112
 
102
113
  current_day = date
103
114
 
@@ -111,7 +122,7 @@ class Clockout
111
122
  puts
112
123
  end
113
124
 
114
- print_timeline(block) if (!$opts[:condensed])
125
+ print_timeline(block) if (!condensed)
115
126
  end
116
127
 
117
128
  puts " "*(cols-10) + colorize("-"*10,MAGENTA)
@@ -184,15 +195,16 @@ class Clockout
184
195
  begin
185
196
  return Grit::Repo.new(path)
186
197
  rescue Exception => e
198
+ print colorize("Error: ", RED)
187
199
  if e.class == Grit::NoSuchPathError
188
- puts "Error: Path '#{path}' could not be found."
200
+ puts "Path '#{path}' could not be found."
189
201
  else
190
- puts "Error: '#{path}' is not a Git repository."
202
+ puts "'#{path}' is not a Git repository."
191
203
  end
192
204
  end
193
205
  end
194
206
 
195
- def parse_clockfile(file)
207
+ def self.parse_clockfile(file)
196
208
  return nil if !File.exists?(file)
197
209
 
198
210
  opts = {}
@@ -200,42 +212,78 @@ class Clockout
200
212
  line_num = 0
201
213
  File.foreach(file) do |line|
202
214
  line_num += 1
215
+ #Strip whitespace
203
216
  line.strip!
217
+ #Strip comments
218
+ line = line.split(";",2)[0]
204
219
 
205
- next if line[0] == ";" || line.length == 0
220
+ next if !line || line.length == 0
206
221
 
207
222
  sides = line.split("=",2)
208
223
 
209
- if sides.length != 2
210
- puts "Error: bad syntax on line #{line_num} of .clock file:"
211
- puts " #{line}"
212
- puts ""
213
- puts "Line must be of form:"
214
- puts " KEY = VALUE"
224
+ clock_split = sides[0].split(" ",2)
225
+ if (clock_split[0] == "in" || clock_split[0] == "out")
215
226
 
216
- exit
217
- end
227
+ begin
228
+ date = Time.parse(clock_split[1])
229
+ rescue Exception => e
230
+ puts "#{colorize("Error:", RED)} invalid date for '#{clock_split[0]}' on line #{line_num} of .clock file:"
231
+ puts " #{line}"
218
232
 
219
- left = sides[0].strip
220
- right = sides[1].strip
233
+ exit
234
+ end
221
235
 
222
- if left == "ignore_initial"
223
- right = (right != "0")
224
- elsif left == "time_cutoff"
225
- right = right.to_i
226
- end
236
+ key = (clock_split[0] == "out") ? :clockouts : :clockins
227
237
 
228
- opts[left.to_sym] = right
238
+ opts[key] ||= []
239
+ opts[key] << date
240
+ else
241
+ if sides.length != 2
242
+ puts "#{colorize("Error:", RED)} bad syntax on line #{line_num} of .clock file:"
243
+ puts " #{line}"
244
+ puts ""
245
+ puts "Line must be of form:"
246
+ puts " KEY = VALUE"
247
+
248
+ exit
249
+ end
250
+
251
+ left = sides[0].strip
252
+ right = sides[1].strip
253
+
254
+ if left == "ignore_initial"
255
+ right = (right != "0")
256
+ elsif left == "time_cutoff"
257
+ right = right.to_i
258
+ elsif left == "estimation_factor"
259
+ right = right.to_f
260
+ end
261
+
262
+ opts[left.to_sym] = right
263
+ end
229
264
  end
230
265
 
231
266
  opts
232
267
  end
233
268
 
234
- def initialize(path, options)
235
- $opts = options
269
+ def self.clock_path(path)
270
+ path+"/.clock"
271
+ end
272
+
273
+ def initialize(path)
274
+ # Default options
275
+ $opts = {time_cutoff:120, my_files:"/.*/", estimation_factor:0.9}
276
+
277
+ # Parse .clock options
278
+ clock_opts = Clockout.parse_clockfile(Clockout.clock_path(path))
236
279
 
237
- @clock_opts = parse_clockfile(path+"/.clock")
238
- $opts.merge!(@clock_opts) if @clock_opts
280
+ if clock_opts
281
+ @clockins = clock_opts[:clockins] || []
282
+ @clockouts = clock_opts[:clockouts] || []
283
+
284
+ # Merge with .clock override options
285
+ $opts.merge!(clock_opts)
286
+ end
239
287
 
240
288
  repo = get_repo(path) || exit
241
289
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clockout
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-04 00:00:00.000000000 Z
12
+ date: 2013-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grit