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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ffeab4df3c125edae4368f304a145fa7d76bb0f
4
- data.tar.gz: 8f362f3aa3e7010d9a871212818fa247165cea49
3
+ metadata.gz: 1ea82cda49c0d4f4aa43038029ae70b5e22b9e18
4
+ data.tar.gz: 3bf6719883563294afd3545ce02213abe468e7a5
5
5
  SHA512:
6
- metadata.gz: 75031b9762f7ecc905d2b11fbe8c16b8708b459677a58de1750bca4cb9185699f25dd006626ea85841624e0b0130324ae43eef03922ffe8459b2411cf5b95817
7
- data.tar.gz: 3a3b1bfce1f9f88da3a8bebb206c5bab6c6d6b71c81d6a8914a50ee4f74ecf216e904f03386bd95ed60b97cfb5b6eb37f706327bf22dd482d5db183f810fbf9c
6
+ metadata.gz: f0994f4ee68ce6b5adabb2de5cec31a8db29091fc02eba53929461015e639b152805ba5b42707c693a1bcf1efb200e0918f07c3b6e4522e33beb46187cda9aa8
7
+ data.tar.gz: 1749a65a4eaaaa8c580573e5dab944ae026fb057bdaa33a3ae225569f1033d9cccada2c5efd77a7c0d1e5785d38fb154ef23d8943e70db48728c3ef0ad54b41f
data/CHANGELOG CHANGED
@@ -1,5 +1,10 @@
1
1
  = Recent Changes in HCl
2
2
 
3
+ == v0.4.9 2013-12-21
4
+
5
+ * MacOS X: store password in default keychain
6
+ * abort log command when a timer is running
7
+
3
8
  == v0.4.8 2013-11-30
4
9
 
5
10
  * more fixes for 1.9.3
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
+ [![Build Status](https://travis-ci.org/zenhob/hcl.png?branch=master)](https://travis-ci.org/zenhob/hcl)
9
+ [![Gem Version](https://badge.fury.io/rb/hcl.png)](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
- $ gem install hcl
15
+ gem install hcl
13
16
 
14
17
  or you can install from source:
15
18
 
16
- $ rake install
19
+ rake install
17
20
 
18
21
  ## Usage
19
22
 
20
- $ hcl [start] @<task_alias> [+<time>] [<message>]
21
- $ hcl note <message>
22
- $ hcl stop [<message>]
23
- $ hcl resume [@<task_alias>]
24
- $ hcl log @<task_alias> [+<time>] [<message>]
25
- $ hcl show [<date>]
26
- $ hcl tasks [<project_code>]
27
- $ hcl alias <task_alias> <project_id> <task_id>
28
- $ hcl aliases
29
- $ hcl (cancel | nvm | oops)
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
- $ hcl tasks
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
- $ hcl alias tacodev 1234 5678
48
- $ hcl @tacodev Adding a new feature
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
- $ hcl @tacodev +0:15 Doing some stuff
57
- $ hcl +.25 @tacodev Doing some stuff
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
- $ hcl note Then I did something else
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
- $ hcl note
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
- $ hcl stop All done doing things
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
- $ hcl resume
85
- $ hcl resume @xdev
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
- $ hcl cancel
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
- $ hcl log @xdev +1 Worked for an hour.
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 bashrc:
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 timesheet for the specified day:
135
+ commands show the time sheet for the specified day:
117
136
 
118
- $ hcl show yesterday
119
- $ hcl show last friday
120
- $ hcl show 2 days ago
121
- $ hcl show 1 week ago
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
- STDERR.puts "Error: #{e}"
62
+ $stderr.puts "Error: #{e}"
60
63
  exit 1
61
64
  rescue SocketError => e
62
- STDERR.puts "Connection failed. (#{e.message})"
65
+ $stderr.puts "Connection failed. (#{e.message})"
63
66
  exit 1
64
67
  rescue TimesheetResource::ThrottleFailure => e
65
- STDERR.puts "Too many requests, retrying in #{e.retry_after+5} seconds..."
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
- STDERR.puts "Unable to authenticate: #{e}"
72
+ $stderr.puts "Unable to authenticate: #{e}"
70
73
  request_config
71
74
  run
72
75
  rescue TimesheetResource::Failure => e
73
- STDERR.puts "API failure: #{e}"
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 force=false
139
+ def read_config
137
140
  if File.exists? CONFIG_FILE
138
- config = YAML::load File.read(CONFIG_FILE)
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 0400, CONFIG_FILE
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
- puts "No matching tasks."
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
- puts "Failed to delete #{entry}!"
41
- exit 1
41
+ fail "Failed to delete #{entry}!"
42
42
  end
43
43
  else
44
- puts 'Nothing to cancel.'
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
- puts "Unrecognized project and task ID: #{value.inspect}"
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 ' '}" hcl]
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
- puts "Unknown task alias, try one of the following: ", aliases.join(', ')
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
- puts "No running timers found."
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
- puts "No running timers found."
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
- puts "No matching timer found."
151
- exit 1
146
+ fail "No matching timer found."
152
147
  end
153
148
  end
154
149
 
data/lib/hcl/utility.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  module HCl
2
+ class CommandError < StandardError; end
2
3
  module Utility
4
+ def fail *message
5
+ raise CommandError, message.join(' ')
6
+ end
7
+
3
8
  def get_task_ids ident, args
4
9
  if @settings.key? "task.#{ident}"
5
10
  @settings["task.#{ident}"].split(/\s+/)
data/lib/hcl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HCl
2
- VERSION = '0.4.8'
2
+ VERSION = '0.4.9'
3
3
  end
data/test/app_test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'test_helper'
2
- class AppTest < Test::Unit::TestCase
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 test_report_generic_failure
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 test_report_socket_error
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 < Test::Unit::TestCase
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,
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class DayEntryTest < Test::Unit::TestCase
3
+ class DayEntryTest < HCl::TestCase
4
4
  def test_from_xml
5
5
  entries = HCl::DayEntry.from_xml(<<-EOD)
6
6
  <daily>
@@ -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
@@ -1,5 +1,5 @@
1
1
 
2
- class Task < Test::Unit::TestCase
2
+ class Task < HCl::TestCase
3
3
  def test_cache_file
4
4
  assert_equal "#{HCl::App::HCL_DIR}/cache/tasks.yml", HCl::Task.cache_file
5
5
  end
data/test/test_helper.rb CHANGED
@@ -1,20 +1,35 @@
1
1
  require 'bundler'
2
- require 'simplecov'
3
- SimpleCov.start do
4
- add_filter '/test/'
5
- add_filter do |source_file|
6
- source_file.lines.count < 15
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
 
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class TimesheetResourceTest < Test::Unit::TestCase
3
+ class TimesheetResourceTest < HCl::TestCase
4
4
 
5
5
  def setup
6
6
  FakeWeb.allow_net_connect = false
data/test/utility_test.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class UtilityTest < Test::Unit::TestCase
3
+ class UtilityTest < HCl::TestCase
4
4
  include HCl::Utility
5
5
 
6
6
  def test_time2float_decimal
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.8
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-30 00:00:00.000000000 Z
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