watch_tower 0.0.1.beta11 → 0.0.1.beta12

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.
data/README.md CHANGED
@@ -88,6 +88,8 @@ to update the path to the WatchTower binary in the boot loader.
88
88
 
89
89
  # Usage
90
90
 
91
+ ## Opening the web interface
92
+
91
93
  The installation process creates a launcher on login that starts
92
94
  __WatchTower__. You can view your WatchTower Home Page via the web interface
93
95
  by going to http://localhost:9282, or from the command line:
@@ -96,6 +98,14 @@ by going to http://localhost:9282, or from the command line:
96
98
  $ watchtower open
97
99
  ```
98
100
 
101
+ ## Rehash
102
+
103
+ If for some reason, you think that the elapsed time of any of your
104
+ projects is wrong (c.f #9) then you can recalculate the elapsed time of
105
+ all projects and all their files by visiting
106
+ [http://localhost:9282/rehash](http://localhost:9282/rehash), but please
107
+ keep in mind that this can take a long time to process.
108
+
99
109
  # Commands
100
110
 
101
111
  For more information on available commands, you can take a look at the
@@ -73,7 +73,7 @@ module WatchTower
73
73
  version = nil
74
74
  Open3.popen2 "#{editor_command} --version" do |stdin, stdout, wait_thr|
75
75
  parsed_stdout = stdout.read.scan(/^VIM - Vi IMproved (\d+\.\d+).*/)
76
- LOG.info "#{__FILE__}:#{__LINE__ - 1}: Parsed vim --version: #{parsed_stdout.inspect}"
76
+ LOG.debug "#{__FILE__}:#{__LINE__ - 1}: Parsed vim --version: #{parsed_stdout.inspect}"
77
77
  version = parsed_stdout.try(:first).try(:first)
78
78
  end
79
79
 
@@ -85,7 +85,7 @@ module WatchTower
85
85
  else
86
86
  LOG.debug("#{__FILE__}:#{__LINE__}: #{editor.to_s} is not running")
87
87
  end
88
- end
88
+ end unless $pause_eye
89
89
 
90
90
  # If $stop global is set, please stop, otherwise sleep for 10 seconds.
91
91
  if $close_eye
@@ -16,6 +16,7 @@ module WatchTower
16
16
 
17
17
  # Routes
18
18
  paths :root => '/'
19
+ paths :rehash => '/rehash'
19
20
  paths :project => '/project/:id'
20
21
 
21
22
  # Enable sessions
@@ -48,7 +49,7 @@ module WatchTower
48
49
  get :root do
49
50
  @title = "Projects"
50
51
  @durations = Duration.date_range(session[:date_filtering][:from_date], session[:date_filtering][:to_date])
51
- @projects = @durations.collect(&:file).collect(&:project).uniq
52
+ @projects = @durations.collect(&:file).collect(&:project).uniq.sort_by { |p| p.elapsed_time }.reverse
52
53
 
53
54
  haml :index, layout: (request.xhr? ? false : :layout)
54
55
  end
@@ -58,10 +59,24 @@ module WatchTower
58
59
  @project = Project.find(params[:id])
59
60
  @title = "Project - #{@project.name.camelcase}"
60
61
  @durations = @project.durations.date_range(session[:date_filtering][:from_date], session[:date_filtering][:to_date])
61
- @files = @durations.collect(&:file).uniq
62
+ @files = @durations.collect(&:file).uniq.sort_by { |f| f.elapsed_time }.reverse
62
63
 
63
64
  haml :project, layout: (request.xhr? ? false : :layout)
64
65
  end
66
+
67
+ # Rehash the elapsed_times
68
+ get :rehash do
69
+ # Pause the eye to avoid conflicts
70
+ $pause_eye = true
71
+ # Iterate over all projects and recalculate_elapsed_time
72
+ Project.all.each do |p|
73
+ p.recalculate_elapsed_time
74
+ end
75
+ # Resume the eye
76
+ $pause_eye = false
77
+ # Redirect back to the home page.
78
+ redirect path_to(:root)
79
+ end
65
80
  end
66
81
  end
67
- end
82
+ end
@@ -42,6 +42,28 @@ module WatchTower
42
42
  def self.sum_elapsed_time
43
43
  sum(:elapsed_time)
44
44
  end
45
+
46
+ # Recalucate the elapsed time
47
+ def recalculate_elapsed_time
48
+ # Reset the elapsed_time of the project
49
+ self.elapsed_time = 0
50
+ # Save the project
51
+ self.save!
52
+ # Operate on all files
53
+ files.each do |f|
54
+ # Reset the elapsed_time of the files
55
+ f.elapsed_time = 0
56
+ # Save the file
57
+ f.save!
58
+ # Delete all durations
59
+ f.durations.delete_all
60
+ # Send calculate_elapsed_time to all time_entries ordered by
61
+ # their id
62
+ f.time_entries.order('id ASC').each do |t|
63
+ t.send(:calculate_elapsed_time)
64
+ end
65
+ end
66
+ end
45
67
  end
46
68
  end
47
- end
69
+ end
@@ -43,7 +43,7 @@ module WatchTower
43
43
  if this_time_entry_date == last_time_entry_date
44
44
  # Calculate the time
45
45
  time_entry_elapsed = this_time_entry.mtime - last_time_entry.mtime rescue 0
46
- unless time_entry_elapsed > pause_time
46
+ if time_entry_elapsed <= pause_time && time_entry_elapsed >= 0
47
47
  # Update the file elapsed time
48
48
  file.elapsed_time += time_entry_elapsed
49
49
  # Update the project's elapsed time
@@ -66,4 +66,4 @@ module WatchTower
66
66
  end
67
67
  end
68
68
  end
69
- end
69
+ end
@@ -4,7 +4,7 @@ module WatchTower
4
4
  MAJOR = 0
5
5
  MINOR = 0
6
6
  TINY = 1
7
- PRE = 'beta11'
7
+ PRE = 'beta12'
8
8
 
9
9
  def self.version
10
10
  # Init the version
@@ -23,4 +23,7 @@ RSpec.configure do |config|
23
23
  # config.mock_with :flexmock
24
24
  # config.mock_with :rr
25
25
  # config.mock_with :rspec
26
- end
26
+
27
+ # Treat symbols as metadata keys with true values
28
+ config.treat_symbols_as_metadata_keys_with_true_values = true
29
+ end
@@ -164,4 +164,20 @@ describe Eye do
164
164
  -> { subject.start }.should_not raise_error
165
165
  end
166
166
  end
167
+
168
+ describe "#pause" do
169
+ before(:each) do
170
+ Editor.expects(:editors).never
171
+ $pause_eye = true
172
+ end
173
+
174
+ after(:each) do
175
+ $pause_eye = false
176
+ end
177
+
178
+ it "should not run if it is paused" do
179
+
180
+ subject.start
181
+ end
182
+ end
167
183
  end
@@ -1,7 +1,14 @@
1
1
  require 'spec_helper'
2
+ require 'rack/test'
2
3
 
3
4
  module Server
4
5
  describe App do
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ Server::App
10
+ end
11
+
5
12
  before(:each) do
6
13
  @projects = {
7
14
  empty: {files: [], time_entries:[] },
@@ -50,6 +57,10 @@ module Server
50
57
  visit '/'
51
58
  end
52
59
 
60
+ it "should assings @durations"
61
+ it "should assigns @projects"
62
+ it "should return the projects sorted by their elapsed_time"
63
+
53
64
  it "should render the layout" do
54
65
  page.should have_selector :xpath, '//html/head/title'
55
66
  end
@@ -138,6 +149,10 @@ module Server
138
149
  visit "/project/#{@projects[:not_empty][:project].id}"
139
150
  end
140
151
 
152
+ it "should assings @durations"
153
+ it "should assigns @files"
154
+ it "should return the files sorted by their elapsed_time"
155
+
141
156
  it "should render the layout" do
142
157
  page.should have_selector :xpath, '//html/head/title'
143
158
  end
@@ -232,5 +247,23 @@ module Server
232
247
  page.should have_content "No files available for the selected date range."
233
248
  end
234
249
  end
250
+
251
+ describe "#rehash" do
252
+ before(:each) do
253
+ get '/rehash'
254
+ end
255
+
256
+ it "should send :recalculate_elapsed_time to all projects" do
257
+ Project.all do |p|
258
+ p.expects(:recalculate_elapsed_time).once
259
+ end
260
+ end
261
+
262
+ it "should redirect to the root_path" do
263
+ last_response.should be_redirect
264
+ follow_redirect!
265
+ last_request.url.should =~ /.+\//
266
+ end
267
+ end
235
268
  end
236
- end
269
+ end
@@ -184,6 +184,22 @@ module Server
184
184
  @file.file_hash.should == t1.file_hash
185
185
  end
186
186
 
187
+ it "should not record a negative diff, which can result from a git revert." do
188
+ # Freeze the time
189
+ Timecop.freeze(Time.now)
190
+ # Create two time entries to get an elapsed time
191
+ FactoryGirl.create :time_entry, file: @file, mtime: Time.now
192
+ FactoryGirl.create :time_entry, file: @file, mtime: Time.now + 1.minute
193
+ # Make sure we have the correct elapsed time at this point
194
+ @file.reload.elapsed_time.should == 1.minute
195
+ # Travel 1h behind
196
+ Timecop.travel(Time.now - 1.hour)
197
+ # Create a new time_entry
198
+ FactoryGirl.create :time_entry, file: @file, mtime: Time.now
199
+ # Make sure we did not add a negative elapsed_time
200
+ @file.reload.elapsed_time.should == 1.minute
201
+ end
202
+
187
203
  end
188
204
 
189
205
  describe "scopes" do
@@ -345,4 +361,4 @@ module Server
345
361
  end
346
362
  end
347
363
  end
348
- end
364
+ end
@@ -290,6 +290,50 @@ module Server
290
290
  @projects.first.percent.should == 50
291
291
  end
292
292
  end
293
+
294
+ describe "#recalculate_elapsed_time" do
295
+ before(:each) do
296
+ @project = FactoryGirl.create(:project)
297
+ @files = []
298
+ Timecop.freeze(Time.now)
299
+ 2.times do
300
+ @files << FactoryGirl.create(:file, project: @project)
301
+ 2.times do |n|
302
+ FactoryGirl.create :time_entry, file: @files.last, mtime: Time.now + 2 * n
303
+ end
304
+ end
305
+ Timecop.return
306
+
307
+ @project.reload
308
+ @elapsed_time = @project.elapsed_time
309
+ @durations = @files.collect(&:durations).flatten
310
+ end
311
+
312
+ subject { @project }
313
+
314
+ it { should respond_to(:recalculate_elapsed_time) }
315
+
316
+ it "should calculate the correct elapsed_time" do
317
+ subject.elapsed_time = -56456
318
+ subject.save
319
+
320
+ subject.recalculate_elapsed_time
321
+ subject.reload.elapsed_time.should == @elapsed_time
322
+ end
323
+
324
+ it "should generate the same durations" do
325
+ subject.elapsed_time = -56454
326
+ subject.save
327
+
328
+ subject.recalculate_elapsed_time
329
+ subject.reload
330
+ durations = subject.files.collect(&:durations).flatten
331
+ durations.each_with_index do |duration, index|
332
+ duration.date.should == @durations[index].date
333
+ duration.duration.should == @durations[index].duration
334
+ end
335
+ end
336
+ end
293
337
  end
294
338
  end
295
- end
339
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watch_tower
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta11
4
+ version: 0.0.1.beta12
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &5402520 !ruby/object:Gem::Requirement
16
+ requirement: &5090600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *5402520
24
+ version_requirements: *5090600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: i18n
27
- requirement: &4966260 !ruby/object:Gem::Requirement
27
+ requirement: &5044080 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.6.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *4966260
35
+ version_requirements: *5044080
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activerecord
38
- requirement: &5093740 !ruby/object:Gem::Requirement
38
+ requirement: &5437320 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.1.1
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *5093740
46
+ version_requirements: *5437320
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sinatra
49
- requirement: &5092860 !ruby/object:Gem::Requirement
49
+ requirement: &5524100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.3.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *5092860
57
+ version_requirements: *5524100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: sinatra-snap
60
- requirement: &5092160 !ruby/object:Gem::Requirement
60
+ requirement: &5519840 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.3.2
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *5092160
68
+ version_requirements: *5519840
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: haml
71
- requirement: &5089700 !ruby/object:Gem::Requirement
71
+ requirement: &5608420 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 3.1.3
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *5089700
79
+ version_requirements: *5608420
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: grit
82
- requirement: &5048100 !ruby/object:Gem::Requirement
82
+ requirement: &5607880 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 2.4.1
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *5048100
90
+ version_requirements: *5607880
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: coffee-script
93
- requirement: &5439660 !ruby/object:Gem::Requirement
93
+ requirement: &5607240 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 2.2.0
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *5439660
101
+ version_requirements: *5607240
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: uglifier
104
- requirement: &5523540 !ruby/object:Gem::Requirement
104
+ requirement: &5606200 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 1.0.3
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *5523540
112
+ version_requirements: *5606200
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: sass
115
- requirement: &5608600 !ruby/object:Gem::Requirement
115
+ requirement: &5605060 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 3.1.10
121
121
  type: :runtime
122
122
  prerelease: false
123
- version_requirements: *5608600
123
+ version_requirements: *5605060
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: sprockets
126
- requirement: &5608120 !ruby/object:Gem::Requirement
126
+ requirement: &5604100 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 2.0.2
132
132
  type: :runtime
133
133
  prerelease: false
134
- version_requirements: *5608120
134
+ version_requirements: *5604100
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: cronedit
137
- requirement: &5607480 !ruby/object:Gem::Requirement
137
+ requirement: &5602760 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 0.3.0
143
143
  type: :runtime
144
144
  prerelease: false
145
- version_requirements: *5607480
145
+ version_requirements: *5602760
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: guard
148
- requirement: &5606940 !ruby/object:Gem::Requirement
148
+ requirement: &5601660 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: 0.8.4
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *5606940
156
+ version_requirements: *5601660
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: guard-bundler
159
- requirement: &5606120 !ruby/object:Gem::Requirement
159
+ requirement: &5600700 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ~>
@@ -164,10 +164,10 @@ dependencies:
164
164
  version: 0.1.3
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *5606120
167
+ version_requirements: *5600700
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: guard-rspec
170
- requirement: &5604680 !ruby/object:Gem::Requirement
170
+ requirement: &5677640 !ruby/object:Gem::Requirement
171
171
  none: false
172
172
  requirements:
173
173
  - - ~>
@@ -175,10 +175,10 @@ dependencies:
175
175
  version: 0.4.5
176
176
  type: :development
177
177
  prerelease: false
178
- version_requirements: *5604680
178
+ version_requirements: *5677640
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: guard-sprockets2
181
- requirement: &5603880 !ruby/object:Gem::Requirement
181
+ requirement: &5676620 !ruby/object:Gem::Requirement
182
182
  none: false
183
183
  requirements:
184
184
  - - ~>
@@ -186,10 +186,10 @@ dependencies:
186
186
  version: 0.0.5
187
187
  type: :development
188
188
  prerelease: false
189
- version_requirements: *5603880
189
+ version_requirements: *5676620
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: yard
192
- requirement: &5603200 !ruby/object:Gem::Requirement
192
+ requirement: &5674520 !ruby/object:Gem::Requirement
193
193
  none: false
194
194
  requirements:
195
195
  - - ~>
@@ -197,10 +197,10 @@ dependencies:
197
197
  version: 0.7.2
198
198
  type: :development
199
199
  prerelease: false
200
- version_requirements: *5603200
200
+ version_requirements: *5674520
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: rspec
203
- requirement: &5602120 !ruby/object:Gem::Requirement
203
+ requirement: &5670780 !ruby/object:Gem::Requirement
204
204
  none: false
205
205
  requirements:
206
206
  - - ~>
@@ -208,10 +208,10 @@ dependencies:
208
208
  version: 2.6.0
209
209
  type: :development
210
210
  prerelease: false
211
- version_requirements: *5602120
211
+ version_requirements: *5670780
212
212
  - !ruby/object:Gem::Dependency
213
213
  name: rspec-rails
214
- requirement: &5601240 !ruby/object:Gem::Requirement
214
+ requirement: &5723420 !ruby/object:Gem::Requirement
215
215
  none: false
216
216
  requirements:
217
217
  - - ~>
@@ -219,10 +219,10 @@ dependencies:
219
219
  version: 2.6.1
220
220
  type: :development
221
221
  prerelease: false
222
- version_requirements: *5601240
222
+ version_requirements: *5723420
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: capybara
225
- requirement: &5678180 !ruby/object:Gem::Requirement
225
+ requirement: &5721240 !ruby/object:Gem::Requirement
226
226
  none: false
227
227
  requirements:
228
228
  - - ~>
@@ -230,10 +230,10 @@ dependencies:
230
230
  version: 1.1.1
231
231
  type: :development
232
232
  prerelease: false
233
- version_requirements: *5678180
233
+ version_requirements: *5721240
234
234
  - !ruby/object:Gem::Dependency
235
235
  name: launchy
236
- requirement: &5677000 !ruby/object:Gem::Requirement
236
+ requirement: &5719060 !ruby/object:Gem::Requirement
237
237
  none: false
238
238
  requirements:
239
239
  - - ~>
@@ -241,10 +241,10 @@ dependencies:
241
241
  version: 2.0.5
242
242
  type: :development
243
243
  prerelease: false
244
- version_requirements: *5677000
244
+ version_requirements: *5719060
245
245
  - !ruby/object:Gem::Dependency
246
246
  name: mocha
247
- requirement: &5674720 !ruby/object:Gem::Requirement
247
+ requirement: &5717740 !ruby/object:Gem::Requirement
248
248
  none: false
249
249
  requirements:
250
250
  - - ~>
@@ -252,10 +252,10 @@ dependencies:
252
252
  version: 0.10.0
253
253
  type: :development
254
254
  prerelease: false
255
- version_requirements: *5674720
255
+ version_requirements: *5717740
256
256
  - !ruby/object:Gem::Dependency
257
257
  name: factory_girl
258
- requirement: &5672560 !ruby/object:Gem::Requirement
258
+ requirement: &5731960 !ruby/object:Gem::Requirement
259
259
  none: false
260
260
  requirements:
261
261
  - - ~>
@@ -263,10 +263,10 @@ dependencies:
263
263
  version: 2.1.2
264
264
  type: :development
265
265
  prerelease: false
266
- version_requirements: *5672560
266
+ version_requirements: *5731960
267
267
  - !ruby/object:Gem::Dependency
268
268
  name: timecop
269
- requirement: &5671000 !ruby/object:Gem::Requirement
269
+ requirement: &5729440 !ruby/object:Gem::Requirement
270
270
  none: false
271
271
  requirements:
272
272
  - - ~>
@@ -274,10 +274,10 @@ dependencies:
274
274
  version: 0.3.5
275
275
  type: :development
276
276
  prerelease: false
277
- version_requirements: *5671000
277
+ version_requirements: *5729440
278
278
  - !ruby/object:Gem::Dependency
279
279
  name: pry
280
- requirement: &5724100 !ruby/object:Gem::Requirement
280
+ requirement: &5726660 !ruby/object:Gem::Requirement
281
281
  none: false
282
282
  requirements:
283
283
  - - ~>
@@ -285,7 +285,7 @@ dependencies:
285
285
  version: 0.9.6.2
286
286
  type: :development
287
287
  prerelease: false
288
- version_requirements: *5724100
288
+ version_requirements: *5726660
289
289
  description: ! 'Did you ever want to keep track of how much time you _really_ spend
290
290
  on all of
291
291