hcl 0.4.8 → 0.4.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG +5 -0
- data/Gemfile +9 -0
- data/HACKING.markdown +4 -0
- data/README.markdown +49 -30
- data/lib/hcl/app.rb +43 -8
- data/lib/hcl/commands.rb +14 -19
- data/lib/hcl/utility.rb +5 -0
- data/lib/hcl/version.rb +1 -1
- data/test/app_test.rb +23 -3
- data/test/command_test.rb +6 -1
- data/test/day_entry_test.rb +1 -1
- data/test/ext/capture_output.rb +23 -0
- data/test/task_test.rb +1 -1
- data/test/test_helper.rb +25 -10
- data/test/timesheet_resource_test.rb +1 -1
- data/test/utility_test.rb +1 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ea82cda49c0d4f4aa43038029ae70b5e22b9e18
|
4
|
+
data.tar.gz: 3bf6719883563294afd3545ce02213abe468e7a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0994f4ee68ce6b5adabb2de5cec31a8db29091fc02eba53929461015e639b152805ba5b42707c693a1bcf1efb200e0918f07c3b6e4522e33beb46187cda9aa8
|
7
|
+
data.tar.gz: 1749a65a4eaaaa8c580573e5dab944ae026fb057bdaa33a3ae225569f1033d9cccada2c5efd77a7c0d1e5785d38fb154ef23d8943e70db48728c3ef0ad54b41f
|
data/CHANGELOG
CHANGED
data/Gemfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
gemspec
|
3
|
+
# XXX this is dumb but it's crazy hard to get platform specfic deps into a gemspec
|
4
|
+
gem 'rubysl-abbrev', platform:'rbx'
|
5
|
+
gem 'rubysl-singleton', platform:'rbx'
|
6
|
+
gem 'rubysl-rexml', platform:'rbx'
|
7
|
+
gem 'rubysl-coverage', platform:'rbx', group:'test'
|
8
|
+
gem 'rubinius-coverage', platform:'rbx', group:'test'
|
9
|
+
gem 'yajl-ruby', platform:'rbx', group:'test'
|
data/HACKING.markdown
CHANGED
@@ -8,6 +8,10 @@ Use Bundler to install dependencies before you run the tests:
|
|
8
8
|
bundle
|
9
9
|
rake test
|
10
10
|
|
11
|
+
Coverage is tested automatically. To view the test coverage report:
|
12
|
+
|
13
|
+
open coverage/index.html
|
14
|
+
|
11
15
|
## Running HCl during development
|
12
16
|
|
13
17
|
To run HCl in place (e.g. for testing out local changes) you can use bundle exec:
|
data/README.markdown
CHANGED
@@ -5,28 +5,31 @@ HCl is a command-line tool for interacting with Harvest time sheets using the
|
|
5
5
|
|
6
6
|
[htt]: http://www.getharvest.com/api/time_tracking
|
7
7
|
|
8
|
+
[](https://travis-ci.org/zenhob/hcl)
|
9
|
+
[](http://badge.fury.io/rb/hcl)
|
10
|
+
|
8
11
|
## Quick Start
|
9
12
|
|
10
13
|
You can install hcl directly from rubygems.org:
|
11
14
|
|
12
|
-
|
15
|
+
gem install hcl
|
13
16
|
|
14
17
|
or you can install from source:
|
15
18
|
|
16
|
-
|
19
|
+
rake install
|
17
20
|
|
18
21
|
## Usage
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
hcl [start] @<task_alias> [+<time>] [<message>]
|
24
|
+
hcl note <message>
|
25
|
+
hcl stop [<message>]
|
26
|
+
hcl resume [@<task_alias>]
|
27
|
+
hcl log @<task_alias> [+<time>] [<message>]
|
28
|
+
hcl show [<date>]
|
29
|
+
hcl tasks [<project_code>]
|
30
|
+
hcl alias <task_alias> <project_id> <task_id>
|
31
|
+
hcl aliases
|
32
|
+
hcl (cancel | nvm | oops)
|
30
33
|
|
31
34
|
### Available Projects and Tasks
|
32
35
|
|
@@ -34,7 +37,7 @@ To start a new timer you need to identify the project and task.
|
|
34
37
|
The tasks command displays a list of available tasks with their
|
35
38
|
project and task IDs.
|
36
39
|
|
37
|
-
|
40
|
+
hcl tasks
|
38
41
|
|
39
42
|
You can also pass a project code (this is the short optional code associated
|
40
43
|
with each project) to list only the tasks for that project.
|
@@ -44,8 +47,8 @@ with each project) to list only the tasks for that project.
|
|
44
47
|
Since it's not practical to enter two long numbers every time you want to
|
45
48
|
identify a task, HCl supports task aliases:
|
46
49
|
|
47
|
-
|
48
|
-
|
50
|
+
hcl alias tacodev 1234 5678
|
51
|
+
hcl @tacodev Adding a new feature
|
49
52
|
|
50
53
|
### Starting a Timer with Initial Time
|
51
54
|
|
@@ -53,20 +56,20 @@ You can also provide an initial time when starting a new timer.
|
|
53
56
|
This can be expressed in floating-point or HH:MM. The following two
|
54
57
|
commands are equivalent:
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
hcl @tacodev +0:15 Doing some stuff
|
60
|
+
hcl +.25 @tacodev Doing some stuff
|
58
61
|
|
59
62
|
### Adding Notes to a Running Task
|
60
63
|
|
61
64
|
While a task is running you can append lines to the task notes:
|
62
65
|
|
63
|
-
|
66
|
+
hcl note Then I did something else
|
64
67
|
|
65
68
|
**Note** that `show` only displays the last line of the timer notes.
|
66
69
|
You can list all the notes for a running timer by issuing the note
|
67
70
|
command without any arguments:
|
68
71
|
|
69
|
-
|
72
|
+
hcl note
|
70
73
|
|
71
74
|
### Stopping a Timer
|
72
75
|
|
@@ -74,22 +77,22 @@ The following command will stop a running timer (currently only one timer at
|
|
74
77
|
a time is supported). You can provide a message when stopping a timer as
|
75
78
|
well:
|
76
79
|
|
77
|
-
|
80
|
+
hcl stop All done doing things
|
78
81
|
|
79
82
|
### Resuming a Timer
|
80
83
|
|
81
84
|
You can resume a stopped timer. Specify a task to resume the last timer
|
82
85
|
for that task:
|
83
86
|
|
84
|
-
|
85
|
-
|
87
|
+
hcl resume
|
88
|
+
hcl resume @xdev
|
86
89
|
|
87
90
|
### Canceling a Timer
|
88
91
|
|
89
92
|
If you accidentally started a timer that you didn't mean to, you can cancel
|
90
93
|
it:
|
91
94
|
|
92
|
-
|
95
|
+
hcl cancel
|
93
96
|
|
94
97
|
This will delete the running timer, or the last-updated timer if one isn't
|
95
98
|
running. You can also use `nvm` or `oops` instead of `cancel`.
|
@@ -99,26 +102,42 @@ running. You can also use `nvm` or `oops` instead of `cancel`.
|
|
99
102
|
You can log time and notes without leaving a timer running. It takes
|
100
103
|
the same arguments as start:
|
101
104
|
|
102
|
-
|
105
|
+
hcl log @xdev +1 Worked for an hour.
|
103
106
|
|
104
107
|
The above starts and immediately stops a one-hour timer with the given note.
|
105
108
|
|
109
|
+
## Advanced Usage
|
110
|
+
|
106
111
|
### Bash Auto-completion of Task Aliases
|
107
112
|
|
108
|
-
You can enable auto-completion of task aliases by adding this to your
|
113
|
+
You can enable auto-completion of task aliases by adding this to your shell
|
114
|
+
configuration:
|
109
115
|
|
110
116
|
eval `hcl completion`
|
111
117
|
|
118
|
+
### Configuration Profiles
|
119
|
+
|
120
|
+
You can specify an alternate configuration directory in the environment as
|
121
|
+
`HCL_DIR`. This can be used to easily interact with multiple harvest accounts.
|
122
|
+
Here is a shell alias `myhcl` with a separate configuration from the
|
123
|
+
main `hcl` command, including alias completion:
|
124
|
+
|
125
|
+
alias myhcl="env HCL_DIR=~/.myhcl hcl"
|
126
|
+
eval `myhcl completion myhcl`
|
127
|
+
|
128
|
+
When using `myhcl` you can use different credentials and aliases, while
|
129
|
+
`hcl` will continue to function with your original configuration.
|
130
|
+
|
112
131
|
### Date Formats
|
113
132
|
|
114
133
|
Dates can be expressed in a variety of ways. See the [Chronic documentation][cd]
|
115
134
|
for more information about available date input formats. The following
|
116
|
-
commands show the
|
135
|
+
commands show the time sheet for the specified day:
|
117
136
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
137
|
+
hcl show yesterday
|
138
|
+
hcl show last friday
|
139
|
+
hcl show 2 days ago
|
140
|
+
hcl show 1 week ago
|
122
141
|
|
123
142
|
[cd]: http://chronic.rubyforge.org/
|
124
143
|
|
data/lib/hcl/app.rb
CHANGED
@@ -55,22 +55,25 @@ module HCl
|
|
55
55
|
else
|
56
56
|
puts show
|
57
57
|
end
|
58
|
+
rescue CommandError => e
|
59
|
+
$stderr.puts e
|
60
|
+
exit 1
|
58
61
|
rescue RuntimeError => e
|
59
|
-
|
62
|
+
$stderr.puts "Error: #{e}"
|
60
63
|
exit 1
|
61
64
|
rescue SocketError => e
|
62
|
-
|
65
|
+
$stderr.puts "Connection failed. (#{e.message})"
|
63
66
|
exit 1
|
64
67
|
rescue TimesheetResource::ThrottleFailure => e
|
65
|
-
|
68
|
+
$stderr.puts "Too many requests, retrying in #{e.retry_after+5} seconds..."
|
66
69
|
sleep e.retry_after+5
|
67
70
|
run
|
68
71
|
rescue TimesheetResource::AuthFailure => e
|
69
|
-
|
72
|
+
$stderr.puts "Unable to authenticate: #{e}"
|
70
73
|
request_config
|
71
74
|
run
|
72
75
|
rescue TimesheetResource::Failure => e
|
73
|
-
|
76
|
+
$stderr.puts "API failure: #{e}"
|
74
77
|
exit 1
|
75
78
|
end
|
76
79
|
end
|
@@ -133,9 +136,12 @@ EOM
|
|
133
136
|
|
134
137
|
private
|
135
138
|
|
136
|
-
def read_config
|
139
|
+
def read_config
|
137
140
|
if File.exists? CONFIG_FILE
|
138
|
-
config = YAML::load
|
141
|
+
config = YAML::load(File.read(CONFIG_FILE)) || {}
|
142
|
+
if has_security_command?
|
143
|
+
load_password config
|
144
|
+
end
|
139
145
|
TimesheetResource.configure config
|
140
146
|
elsif File.exists? OLD_CONFIG_FILE
|
141
147
|
config = YAML::load File.read(OLD_CONFIG_FILE)
|
@@ -159,10 +165,13 @@ EOM
|
|
159
165
|
|
160
166
|
def write_config config
|
161
167
|
puts "Writing configuration to #{CONFIG_FILE}."
|
168
|
+
if has_security_command?
|
169
|
+
save_password config
|
170
|
+
end
|
162
171
|
File.open(CONFIG_FILE, 'w') do |f|
|
163
172
|
f.write config.to_yaml
|
164
173
|
end
|
165
|
-
FileUtils.chmod
|
174
|
+
FileUtils.chmod 0600, CONFIG_FILE
|
166
175
|
end
|
167
176
|
|
168
177
|
def read_settings
|
@@ -182,6 +191,32 @@ EOM
|
|
182
191
|
end
|
183
192
|
nil
|
184
193
|
end
|
194
|
+
|
195
|
+
def has_security_command?
|
196
|
+
if @has_security.nil?
|
197
|
+
@has_security = File.exists?('/usr/bin/security') &&
|
198
|
+
(`/usr/bin/security error 1` =~ /CSSM_ERRCODE_INTERNAL_ERROR/)
|
199
|
+
else
|
200
|
+
@has_security
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def load_password config
|
205
|
+
cmd = "security find-internet-password -l hcl -a '%s' -s '%s.harvestapp.com' -w" % [
|
206
|
+
config['login'],
|
207
|
+
config['subdomain'],
|
208
|
+
]
|
209
|
+
password = `#{cmd}`
|
210
|
+
config.update('password'=>password.chomp) if $?.success?
|
211
|
+
end
|
212
|
+
|
213
|
+
def save_password config
|
214
|
+
if system("security add-internet-password -U -l hcl -a '%s' -s '%s.harvestapp.com' -w '%s'" % [
|
215
|
+
config['login'],
|
216
|
+
config['subdomain'],
|
217
|
+
config['password'],
|
218
|
+
]) then config.delete('password') end
|
219
|
+
end
|
185
220
|
end
|
186
221
|
end
|
187
222
|
|
data/lib/hcl/commands.rb
CHANGED
@@ -3,6 +3,8 @@ require 'highline'
|
|
3
3
|
|
4
4
|
module HCl
|
5
5
|
module Commands
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
6
8
|
def tasks project_code=nil
|
7
9
|
tasks = Task.all
|
8
10
|
if tasks.empty? # cache tasks
|
@@ -11,8 +13,7 @@ module HCl
|
|
11
13
|
end
|
12
14
|
tasks.select! {|t| t.project.code == project_code } if project_code
|
13
15
|
if tasks.empty?
|
14
|
-
|
15
|
-
exit 1
|
16
|
+
fail "No matching tasks."
|
16
17
|
end
|
17
18
|
tasks.map { |task| "#{task.project.id} #{task.id}\t#{task}" }.join("\n")
|
18
19
|
end
|
@@ -37,12 +38,10 @@ module HCl
|
|
37
38
|
if entry.cancel
|
38
39
|
"Deleted entry #{entry}."
|
39
40
|
else
|
40
|
-
|
41
|
-
exit 1
|
41
|
+
fail "Failed to delete #{entry}!"
|
42
42
|
end
|
43
43
|
else
|
44
|
-
|
45
|
-
exit 1
|
44
|
+
fail 'Nothing to cancel.'
|
46
45
|
end
|
47
46
|
end
|
48
47
|
alias_method :oops, :cancel
|
@@ -64,13 +63,12 @@ module HCl
|
|
64
63
|
set "task.#{task_name}", *value
|
65
64
|
"Added alias @#{task_name} for #{task}."
|
66
65
|
else
|
67
|
-
|
68
|
-
exit 1
|
66
|
+
fail "Unrecognized project and task ID: #{value.inspect}"
|
69
67
|
end
|
70
68
|
end
|
71
69
|
|
72
|
-
def completion
|
73
|
-
%[complete -W "#{aliases.join ' '}"
|
70
|
+
def completion command=$PROGRAM_NAME
|
71
|
+
%[complete -W "#{aliases.join ' '}" #{command}]
|
74
72
|
end
|
75
73
|
|
76
74
|
def aliases
|
@@ -81,8 +79,7 @@ module HCl
|
|
81
79
|
starting_time = get_starting_time args
|
82
80
|
task = get_task args
|
83
81
|
if task.nil?
|
84
|
-
|
85
|
-
exit 1
|
82
|
+
fail "Unknown task alias, try one of the following: ", aliases.join(', ')
|
86
83
|
end
|
87
84
|
timer = task.start \
|
88
85
|
:starting_time => starting_time,
|
@@ -91,6 +88,7 @@ module HCl
|
|
91
88
|
end
|
92
89
|
|
93
90
|
def log *args
|
91
|
+
fail "There is already a timer running." if DayEntry.with_timer
|
94
92
|
start *args
|
95
93
|
stop
|
96
94
|
end
|
@@ -102,8 +100,7 @@ module HCl
|
|
102
100
|
entry.toggle
|
103
101
|
"Stopped #{entry} (at #{current_time})"
|
104
102
|
else
|
105
|
-
|
106
|
-
exit 1
|
103
|
+
fail "No running timers found."
|
107
104
|
end
|
108
105
|
end
|
109
106
|
|
@@ -117,8 +114,7 @@ module HCl
|
|
117
114
|
"Added note to #{entry}."
|
118
115
|
end
|
119
116
|
else
|
120
|
-
|
121
|
-
exit 1
|
117
|
+
fail "No running timers found."
|
122
118
|
end
|
123
119
|
end
|
124
120
|
|
@@ -128,7 +124,7 @@ module HCl
|
|
128
124
|
result = ''
|
129
125
|
DayEntry.all(date).each do |day|
|
130
126
|
running = day.running? ? '(running) ' : ''
|
131
|
-
columns = HighLine::SystemExtensions.terminal_size[0]
|
127
|
+
columns = HighLine::SystemExtensions.terminal_size[0] rescue 80
|
132
128
|
result << "\t#{day.formatted_hours}\t#{running}#{day.project}: #{day.notes.lines.to_a.last}\n"[0..columns-1]
|
133
129
|
total_hours = total_hours + day.hours.to_f
|
134
130
|
end
|
@@ -147,8 +143,7 @@ module HCl
|
|
147
143
|
if entry
|
148
144
|
entry.toggle
|
149
145
|
else
|
150
|
-
|
151
|
-
exit 1
|
146
|
+
fail "No matching timer found."
|
152
147
|
end
|
153
148
|
end
|
154
149
|
|
data/lib/hcl/utility.rb
CHANGED
data/lib/hcl/version.rb
CHANGED
data/test/app_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
class AppTest <
|
2
|
+
class AppTest < HCl::TestCase
|
3
3
|
|
4
4
|
def setup
|
5
5
|
# touch config to avoid triggering manual config
|
@@ -30,18 +30,38 @@ class AppTest < Test::Unit::TestCase
|
|
30
30
|
app.process_args('show').run
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
33
|
+
def test_generic_failure
|
34
34
|
app = HCl::App.new
|
35
35
|
app.expects(:show).raises(RuntimeError)
|
36
36
|
app.expects(:exit).with(1)
|
37
37
|
app.process_args('show').run
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
40
|
+
def test_socket_error
|
41
41
|
app = HCl::App.new
|
42
42
|
app.expects(:show).raises(SocketError)
|
43
43
|
app.expects(:exit).with(1)
|
44
44
|
app.process_args('show').run
|
45
|
+
assert_match /connection failed/i, error_output
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_configure_on_auth_failure
|
49
|
+
app = HCl::App.new
|
50
|
+
configured = states('configured').starts_as(false)
|
51
|
+
app.expects(:show).raises(HCl::TimesheetResource::AuthFailure).when(configured.is(false))
|
52
|
+
app.expects(:ask).returns('xxx').times(4).when(configured.is(false))
|
53
|
+
app.expects(:write_config).then(configured.is(true))
|
54
|
+
app.expects(:show).when(configured.is(true))
|
55
|
+
app.process_args('show').run
|
56
|
+
assert_match /unable to authenticate/i, error_output
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_api_failure
|
60
|
+
app = HCl::App.new
|
61
|
+
app.expects(:show).raises(HCl::TimesheetResource::Failure)
|
62
|
+
app.expects(:exit).with(1)
|
63
|
+
app.process_args('show').run
|
64
|
+
assert_match /API failure/i, error_output
|
45
65
|
end
|
46
66
|
|
47
67
|
end
|
data/test/command_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
class CommandTest <
|
2
|
+
class CommandTest < HCl::TestCase
|
3
3
|
include HCl::Commands
|
4
4
|
include HCl::Utility
|
5
5
|
|
@@ -18,6 +18,11 @@ class CommandTest < Test::Unit::TestCase
|
|
18
18
|
@settings
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_log_failure
|
22
|
+
HCl::DayEntry.expects(:with_timer).returns(stub)
|
23
|
+
assert_raises(HCl::CommandError) { log "stuff" }
|
24
|
+
end
|
25
|
+
|
21
26
|
def test_tasks
|
22
27
|
HCl::Task.expects(:all).returns([HCl::Task.new(
|
23
28
|
id:123,
|
data/test/day_entry_test.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module CaptureOutput
|
2
|
+
def before_setup
|
3
|
+
super
|
4
|
+
$stderr = @stderr = StringIO.new
|
5
|
+
$stdout = @stdout = StringIO.new
|
6
|
+
end
|
7
|
+
def after_teardown
|
8
|
+
super
|
9
|
+
$stderr = STDERR
|
10
|
+
$stdout = STDOUT
|
11
|
+
end
|
12
|
+
def error_output
|
13
|
+
@stderr.string
|
14
|
+
end
|
15
|
+
def standard_output
|
16
|
+
@stdout.string
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class MiniTest::Unit::TestCase
|
20
|
+
include CaptureOutput
|
21
|
+
end
|
22
|
+
|
23
|
+
|
data/test/task_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,20 +1,35 @@
|
|
1
1
|
require 'bundler'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter '/test/'
|
7
|
+
add_filter '/vendor/' # for travis-ci
|
8
|
+
add_filter do |source_file|
|
9
|
+
source_file.lines.count < 15
|
10
|
+
end
|
11
|
+
# source: https://travis-ci.org/zenhob/hcl
|
12
|
+
minimum_coverage case RUBY_ENGINE
|
13
|
+
when "rbx" then 84
|
14
|
+
when "jruby" then 73
|
15
|
+
else 78
|
16
|
+
end
|
7
17
|
end
|
18
|
+
rescue LoadError => e
|
19
|
+
$stderr.puts 'No test coverage tools found, skipping coverage check.'
|
8
20
|
end
|
9
21
|
|
10
|
-
require 'test/unit'
|
11
|
-
require 'mocha/setup'
|
12
|
-
require 'fileutils'
|
13
|
-
require 'fakeweb'
|
14
|
-
|
15
22
|
# override the default hcl dir
|
16
23
|
ENV['HCL_DIR'] = File.dirname(__FILE__)+"/dot_hcl"
|
17
24
|
|
18
25
|
require 'hcl'
|
26
|
+
require 'minitest/autorun'
|
27
|
+
require 'mocha/setup'
|
28
|
+
require 'fileutils'
|
29
|
+
require 'fakeweb'
|
30
|
+
|
31
|
+
# require test extensions/helpers
|
32
|
+
Dir[File.dirname(__FILE__) + '/ext/*.rb'].each { |ext| require ext }
|
19
33
|
|
34
|
+
class HCl::TestCase < MiniTest::Unit::TestCase; end
|
20
35
|
|
data/test/utility_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hcl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zack Hobson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trollop
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rubygems-tasks
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +136,20 @@ dependencies:
|
|
122
136
|
- - '>='
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: minitest
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
125
153
|
description: HCl is a command-line client for manipulating Harvest time sheets.
|
126
154
|
email: zack@zackhobson.com
|
127
155
|
executables:
|
@@ -132,6 +160,7 @@ files:
|
|
132
160
|
- CHANGELOG
|
133
161
|
- LICENSE
|
134
162
|
- Rakefile
|
163
|
+
- Gemfile
|
135
164
|
- HACKING.markdown
|
136
165
|
- README.markdown
|
137
166
|
- bin/hcl
|
@@ -147,6 +176,7 @@ files:
|
|
147
176
|
- test/app_test.rb
|
148
177
|
- test/command_test.rb
|
149
178
|
- test/day_entry_test.rb
|
179
|
+
- test/ext/capture_output.rb
|
150
180
|
- test/task_test.rb
|
151
181
|
- test/test_helper.rb
|
152
182
|
- test/timesheet_resource_test.rb
|