one_inch_punch 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/bin/punch +16 -0
- data/lib/punch.rb +13 -1
- data/lib/punch/instance.rb +6 -1
- data/lib/punch/version.rb +2 -2
- data/spec/punch_command_spec.rb +121 -1
- data/spec/punch_instance_spec.rb +54 -0
- data/spec/punch_spec.rb +78 -0
- metadata +74 -41
data/History.txt
CHANGED
data/bin/punch
CHANGED
@@ -33,6 +33,10 @@ BANNER
|
|
33
33
|
"Restrict command to only on the given date") { |date| OPTIONS[:on] = Date.parse(date) }
|
34
34
|
opts.on('--at [TIME]', '--time [TIME]', String,
|
35
35
|
"Use the given time") { |time| OPTIONS[:time] = Time.parse(time) }
|
36
|
+
opts.on('--from [TIME]', String,
|
37
|
+
"Use the given time") { |time| OPTIONS[:from] = Time.parse(time) }
|
38
|
+
opts.on('--to [TIME]', String,
|
39
|
+
"Use the given time") { |time| OPTIONS[:to] = Time.parse(time) }
|
36
40
|
opts.on('-m', '--message [MESSAGE]', String,
|
37
41
|
"Use the given log message") { |message| OPTIONS[:message] = message }
|
38
42
|
opts.on('--full',
|
@@ -104,6 +108,17 @@ commands = {
|
|
104
108
|
puts message
|
105
109
|
end
|
106
110
|
end,
|
111
|
+
'entry' => lambda do |project|
|
112
|
+
if project
|
113
|
+
if Punch.entry(project, OPTIONS)
|
114
|
+
Punch.write
|
115
|
+
else
|
116
|
+
puts "Cannot create entry for '#{project}'"
|
117
|
+
end
|
118
|
+
else
|
119
|
+
puts "Project required"
|
120
|
+
end
|
121
|
+
end,
|
107
122
|
'log' => lambda do |project|
|
108
123
|
if project
|
109
124
|
if message = OPTIONS.delete(:message) || ARGV[2]
|
@@ -136,6 +151,7 @@ commands = {
|
|
136
151
|
end
|
137
152
|
end
|
138
153
|
}
|
154
|
+
commands['clock'] = commands['entry']
|
139
155
|
|
140
156
|
if command_code = commands[command]
|
141
157
|
command_code.call(project)
|
data/lib/punch.rb
CHANGED
@@ -108,7 +108,19 @@ class Punch
|
|
108
108
|
end
|
109
109
|
true
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
|
+
def entry(project, options = {})
|
113
|
+
raise ArgumentError, 'both :from and :to time are needed' unless options[:from] and options[:to]
|
114
|
+
|
115
|
+
in_options = { :time => options[:from] }
|
116
|
+
in_options[:message] = options[:message] if options[:message]
|
117
|
+
result = self.in(project, in_options)
|
118
|
+
return result unless result
|
119
|
+
|
120
|
+
out(project, :time => options[:to])
|
121
|
+
end
|
122
|
+
alias_method :clock, :entry
|
123
|
+
|
112
124
|
def delete(project)
|
113
125
|
return nil unless data.delete(project)
|
114
126
|
true
|
data/lib/punch/instance.rb
CHANGED
@@ -24,7 +24,12 @@ class Punch
|
|
24
24
|
def out(options = {})
|
25
25
|
self.class.out(project, options)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
|
+
def entry(options = {})
|
29
|
+
self.class.entry(project, options)
|
30
|
+
end
|
31
|
+
alias_method :clock, :entry
|
32
|
+
|
28
33
|
def list(options = {})
|
29
34
|
self.class.list(project, options)
|
30
35
|
end
|
data/lib/punch/version.rb
CHANGED
data/spec/punch_command_spec.rb
CHANGED
@@ -467,7 +467,127 @@ describe 'punch command' do
|
|
467
467
|
end
|
468
468
|
end
|
469
469
|
end
|
470
|
-
|
470
|
+
|
471
|
+
describe "when the command is 'entry'" do
|
472
|
+
before do
|
473
|
+
Punch.stub!(:entry)
|
474
|
+
@from_option = '2012-04-10 14:39'
|
475
|
+
@to_option = '2012-04-10 17:43'
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'should load punch data' do
|
479
|
+
Punch.should.receive(:load)
|
480
|
+
run_command('entry', @project)
|
481
|
+
end
|
482
|
+
|
483
|
+
it 'should make a punch entry for the given project' do
|
484
|
+
from_option = '2012-04-10 14:39'
|
485
|
+
from_time = Time.local(2012, 4, 10, 14, 39)
|
486
|
+
to_option = '2012-04-10 17:43'
|
487
|
+
to_time = Time.local(2012, 4, 10, 17, 43)
|
488
|
+
|
489
|
+
Punch.should.receive(:entry) do |proj, options|
|
490
|
+
proj.should == @project
|
491
|
+
options[:from].should == from_time
|
492
|
+
options[:to ].should == to_time
|
493
|
+
end
|
494
|
+
|
495
|
+
run_command('entry', @project, '--from', from_option, '--to', to_option)
|
496
|
+
end
|
497
|
+
|
498
|
+
it 'should pass a message if specified on the command line (with --message)' do
|
499
|
+
message = 'About to do some amazing work'
|
500
|
+
|
501
|
+
Punch.should.receive(:entry) do |proj, options|
|
502
|
+
proj.should == @project
|
503
|
+
options[:message].should == message
|
504
|
+
end
|
505
|
+
|
506
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option, '--message', message)
|
507
|
+
end
|
508
|
+
|
509
|
+
it 'should pass a message if specified on the command line (with -m)' do
|
510
|
+
message = 'About to do some amazing work'
|
511
|
+
|
512
|
+
Punch.should.receive(:entry) do |proj, options|
|
513
|
+
proj.should == @project
|
514
|
+
options[:message].should == message
|
515
|
+
end
|
516
|
+
|
517
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option, '-m', message)
|
518
|
+
end
|
519
|
+
|
520
|
+
describe 'when entry created successfully' do
|
521
|
+
before do
|
522
|
+
Punch.stub!(:entry).and_return(true)
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'should write the data' do
|
526
|
+
Punch.should.receive(:write)
|
527
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option)
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'should not print anything' do
|
531
|
+
self.should.receive(:puts).never
|
532
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
describe 'when entry not created successfully' do
|
537
|
+
before do
|
538
|
+
Punch.stub!(:entry).and_return(false)
|
539
|
+
end
|
540
|
+
|
541
|
+
it 'should not write the data' do
|
542
|
+
Punch.should.receive(:write).never
|
543
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option)
|
544
|
+
end
|
545
|
+
|
546
|
+
it 'should print a message' do
|
547
|
+
self.should.receive(:puts) do |output|
|
548
|
+
output.should.match(/cannot.+entry/i)
|
549
|
+
end
|
550
|
+
run_command('entry', @project, '--from', @from_option, '--to', @to_option)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
describe 'when no project given' do
|
555
|
+
it 'should display an error message' do
|
556
|
+
self.should.receive(:puts) do |output|
|
557
|
+
output.should.match(/project.+require/i)
|
558
|
+
end
|
559
|
+
run_command('entry')
|
560
|
+
end
|
561
|
+
|
562
|
+
it 'should not create an entry' do
|
563
|
+
Punch.stub!(:write)
|
564
|
+
Punch.should.receive(:entry).never
|
565
|
+
run_command('entry')
|
566
|
+
end
|
567
|
+
|
568
|
+
it 'should not write the data' do
|
569
|
+
Punch.should.receive(:write).never
|
570
|
+
run_command('entry')
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
it "should have 'clock' as an alias" do
|
575
|
+
from_option = '2012-04-10 14:39'
|
576
|
+
from_time = Time.local(2012, 4, 10, 14, 39)
|
577
|
+
to_option = '2012-04-10 17:43'
|
578
|
+
to_time = Time.local(2012, 4, 10, 17, 43)
|
579
|
+
|
580
|
+
Punch.should.receive(:entry) do |proj, options|
|
581
|
+
proj.should == @project
|
582
|
+
options[:from].should == from_time
|
583
|
+
options[:to ].should == to_time
|
584
|
+
end
|
585
|
+
|
586
|
+
run_command('clock', @project, '--from', from_option, '--to', to_option)
|
587
|
+
end
|
588
|
+
|
589
|
+
end
|
590
|
+
|
471
591
|
describe "when the command is 'delete'" do
|
472
592
|
before do
|
473
593
|
Punch.stub!(:delete)
|
data/spec/punch_instance_spec.rb
CHANGED
@@ -220,6 +220,60 @@ describe Punch, 'instance' do
|
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
223
|
+
it 'should make a punch entry' do
|
224
|
+
@punch.should.respond_to(:entry)
|
225
|
+
end
|
226
|
+
|
227
|
+
describe 'making a punch entry' do
|
228
|
+
before do
|
229
|
+
@entry = 'entry val'
|
230
|
+
Punch.stub!(:entry).and_return(@entry)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should accept options' do
|
234
|
+
lambda { @punch.entry(:time => Time.now) }.should.not.raise(ArgumentError)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should not require options' do
|
238
|
+
lambda { @punch.entry }.should.not.raise(ArgumentError)
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'should delegate to the class' do
|
242
|
+
Punch.should.receive(:entry)
|
243
|
+
@punch.entry
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'should pass the project when delegating to the class' do
|
247
|
+
Punch.should.receive(:entry) do |proj, _|
|
248
|
+
proj.should == @project
|
249
|
+
end
|
250
|
+
@punch.entry
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should pass the options when delegating to the class' do
|
254
|
+
options = { :time => Time.now }
|
255
|
+
Punch.should.receive(:entry) do |_, opts|
|
256
|
+
opts.should == options
|
257
|
+
end
|
258
|
+
@punch.entry(options)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'should pass an empty hash if no options given' do
|
262
|
+
Punch.should.receive(:entry) do |_, opts|
|
263
|
+
opts.should == {}
|
264
|
+
end
|
265
|
+
@punch.entry
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should return the value returned by the class method' do
|
269
|
+
@punch.entry.should == @entry
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should have clock as an alias' do
|
273
|
+
@punch.clock.should == @entry
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
223
277
|
it 'should list the project data' do
|
224
278
|
@punch.should.respond_to(:list)
|
225
279
|
end
|
data/spec/punch_spec.rb
CHANGED
@@ -990,6 +990,84 @@ describe Punch do
|
|
990
990
|
end
|
991
991
|
end
|
992
992
|
|
993
|
+
it 'should create a full punch entry' do
|
994
|
+
Punch.should.respond_to(:entry)
|
995
|
+
end
|
996
|
+
|
997
|
+
describe 'creating a full punch entry' do
|
998
|
+
before do
|
999
|
+
Punch.stub!(:in)
|
1000
|
+
Punch.stub!(:out)
|
1001
|
+
|
1002
|
+
@now = Time.now
|
1003
|
+
@from_time = @now - 1000
|
1004
|
+
@to_time = @now - 100
|
1005
|
+
@project = 'myproj'
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it 'should require a project name' do
|
1009
|
+
lambda { Punch.entry }.should.raise(ArgumentError)
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
it 'should accept a project name and options' do
|
1013
|
+
lambda { Punch.entry('proj', :from => Time.now - 500, :to => Time.now - 20) }.should.not.raise(ArgumentError)
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
it 'should require :from and :to options' do
|
1017
|
+
lambda { Punch.entry('proj') }.should.raise(ArgumentError)
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
it 'should punch the project in with the given :from time' do
|
1021
|
+
Punch.should.receive(:in).with(@project, :time => @from_time)
|
1022
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time)
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
it 'should pass any given message when punching in' do
|
1026
|
+
msg = 'just some work'
|
1027
|
+
Punch.should.receive(:in).with(@project, :time => @from_time, :message => msg)
|
1028
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time, :message => msg)
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
describe 'when punching in is successful' do
|
1032
|
+
before do
|
1033
|
+
Punch.stub!(:in).and_return(true)
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it 'should punch the project out with the given :to time' do
|
1037
|
+
Punch.should.receive(:out).with(@project, :time => @to_time)
|
1038
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time)
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
it 'should return the result from punching out' do
|
1042
|
+
result = Object.new
|
1043
|
+
Punch.stub!(:out).and_return(result)
|
1044
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time).should == result
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
describe 'when punching in is unsuccesful' do
|
1049
|
+
before do
|
1050
|
+
Punch.stub!(:in).and_return(false)
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
it 'should not attempt the punch the project out' do
|
1054
|
+
Punch.should.receive(:out).never
|
1055
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time)
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
it 'should return false' do
|
1059
|
+
Punch.entry(@project, :from => @from_time, :to => @to_time).should == false
|
1060
|
+
end
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
it 'should have .clock as an alias' do
|
1064
|
+
msg = 'just some work'
|
1065
|
+
Punch.should.receive(:in).with(@project, :time => @from_time, :message => msg).and_return(true)
|
1066
|
+
Punch.should.receive(:out).with(@project, :time => @to_time)
|
1067
|
+
Punch.clock(@project, :from => @from_time, :to => @to_time, :message => msg)
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
|
993
1071
|
it 'should delete a project' do
|
994
1072
|
Punch.should.respond_to(:delete)
|
995
1073
|
end
|
metadata
CHANGED
@@ -1,57 +1,80 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: one_inch_punch
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 0
|
10
|
+
version: 0.6.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Yossef Mendelssohn
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-04-10 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: bacon
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 19
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 1
|
32
|
+
- 0
|
21
33
|
version: 1.1.0
|
22
34
|
type: :development
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
26
37
|
name: facon
|
27
|
-
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
40
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 11
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 5
|
48
|
+
- 0
|
32
49
|
version: 0.5.0
|
33
50
|
type: :development
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
37
53
|
name: timely
|
38
|
-
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
56
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 29
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
- 0
|
64
|
+
- 1
|
43
65
|
version: 0.0.1
|
44
66
|
type: :runtime
|
45
|
-
|
46
|
-
version_requirements: *2157946540
|
67
|
+
version_requirements: *id003
|
47
68
|
description: A simple time-tracking tool, compatible with Ara T. Howard's punch gem.
|
48
|
-
email:
|
69
|
+
email:
|
49
70
|
- ymendel@pobox.com
|
50
|
-
executables:
|
71
|
+
executables:
|
51
72
|
- punch
|
52
73
|
extensions: []
|
74
|
+
|
53
75
|
extra_rdoc_files: []
|
54
|
-
|
76
|
+
|
77
|
+
files:
|
55
78
|
- License.txt
|
56
79
|
- History.txt
|
57
80
|
- README.txt
|
@@ -68,26 +91,36 @@ files:
|
|
68
91
|
- bin/punch
|
69
92
|
homepage: http://github.com/ymendel/one_inch_punch/
|
70
93
|
licenses: []
|
94
|
+
|
71
95
|
post_install_message:
|
72
96
|
rdoc_options: []
|
73
|
-
|
97
|
+
|
98
|
+
require_paths:
|
74
99
|
- lib
|
75
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
101
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
110
|
none: false
|
83
|
-
requirements:
|
84
|
-
- -
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 3
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
87
118
|
requirements: []
|
119
|
+
|
88
120
|
rubyforge_project:
|
89
121
|
rubygems_version: 1.8.10
|
90
122
|
signing_key:
|
91
123
|
specification_version: 3
|
92
124
|
summary: Track your time locally.
|
93
125
|
test_files: []
|
126
|
+
|