redpomo 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +155 -26
- data/lib/redpomo/cli.rb +8 -0
- data/lib/redpomo/entry.rb +5 -1
- data/lib/redpomo/tracker.rb +40 -8
- data/lib/redpomo/version.rb +1 -1
- data/spec/fixtures/cassettes/cli_push.yml +213 -25
- data/spec/fixtures/config.yml +1 -1
- data/spec/fixtures/printer_output.txt +4 -4
- data/spec/fixtures/timelog.csv +2 -2
- metadata +28 -28
data/README.md
CHANGED
@@ -1,47 +1,176 @@
|
|
1
|
-
# Redpomo
|
2
|
-
## Redmine, Pomodoro.app and Todo-txt. Together.
|
1
|
+
# Redpomo: Redmine, Pomodoro.app and Todo-txt. Together.
|
3
2
|
|
4
3
|
[![Build Status](https://secure.travis-ci.org/stefanoverna/redpomo.png)](http://travis-ci.org/stefanoverna/redpomo)
|
5
4
|
|
6
|
-
Redpomo is
|
5
|
+
## Redpomo is for you if...
|
7
6
|
|
8
|
-
*
|
9
|
-
|
10
|
-
*
|
11
|
-
* It can start Pomodoro.app timer on a specific Todo.txt task, and is
|
12
|
-
able to "push" the logged pomodoros as Redmine timetracks.
|
7
|
+
* You're an hopeless nerd and like CLIs;
|
8
|
+
* You (or you company) use Redmine to track issues and time spent on projects;
|
9
|
+
* You heard about [Todo.txt](http://todotxt.com/) and the [Pomodoro technique](http://www.pomodorotechnique.com/);
|
13
10
|
|
14
|
-
|
11
|
+
Still here? Great!
|
15
12
|
|
16
|
-
|
17
|
-
Tasks:
|
18
|
-
redpomo init # generates a .redpomo configuration file on your home directory
|
19
|
-
redpomo pull # imports Redmine open issues into local todo.txt
|
20
|
-
redpomo push [LOGFILE] # parses Pomodoro export file and imports to Redmine clients
|
21
|
-
redpomo add [TASK] # creates a new task on Todo.txt, forwarding it to the remote tracker
|
22
|
-
redpomo close TASK # marks a todo.txt task as complete, and closes the related Redmine issue
|
23
|
-
redpomo open TASK # opens up the Redmine issue page of the selected task
|
24
|
-
redpomo start TASK # starts a Pomodoro session for the selected task
|
25
|
-
redpomo help [TASK] # Describe available tasks or one specific task
|
13
|
+
## What Redpomo can do for me?
|
26
14
|
|
27
|
-
|
28
|
-
-c, [--config=CONFIG] # Default: ~/.redpomo
|
29
|
-
[--no-color]
|
15
|
+
Redpomo is an opinionated CLI tool that makes it darmn easy to:
|
30
16
|
|
31
|
-
|
17
|
+
* Manage multiple Redmine instances at once;
|
18
|
+
* Create, close and navigate Redmine issues assigned to you;
|
19
|
+
* Push your completed pomodoros to remote Redmine as project time-tracks;
|
20
|
+
|
21
|
+
## It integrates nicely with [Todo.txt](http://todotxt.com/)!
|
22
|
+
|
23
|
+
Instead of reinventing yet another time the weel, Redpomo talks with
|
24
|
+
your remote Redmine instances, and syncs all the issues assigned to
|
25
|
+
your user with your local machine, converting them into Todo.txt tasks.
|
26
|
+
|
27
|
+
Just launch `redpomo` from your command line, and you're done:
|
28
|
+
|
29
|
+
```
|
30
|
+
$ redpomo
|
31
|
+
Pulled 4 issues.
|
32
|
+
|
33
|
+
$ todo.sh ls
|
34
|
+
01 Write Redpomo README #1340 +redpomo @welaika
|
35
|
+
02 Publish to App Store #1140 +love-this-song @welaika
|
36
|
+
03 Meeting with client #1490 +nike @welaika
|
37
|
+
04 Call mom
|
38
|
+
--
|
39
|
+
TODO: 4 of 4 tasks shown
|
40
|
+
```
|
41
|
+
|
42
|
+
The generic syntax for the imported task will be the following (thanks to
|
43
|
+
[asciiflow](http://www.asciiflow.com/) for the drawing):
|
44
|
+
|
45
|
+
```
|
46
|
+
(A) 2012-11-25 Make some delicious coffee #1800 +next-big-project @welaika
|
47
|
+
| | | | | |
|
48
|
+
| | | | | +-> Redmine instance identifier
|
49
|
+
| | | | |
|
50
|
+
| | | | +-> Redmine project for the issue
|
51
|
+
| | | |
|
52
|
+
| | +-> Issue title +-> Issue ID
|
53
|
+
| |
|
54
|
+
| +-> Issue expiration date (if present)
|
55
|
+
|
|
56
|
+
+-> Issue priority (A means Immediate)
|
57
|
+
```
|
58
|
+
|
59
|
+
### How to create new Redmine self-assigned issues
|
60
|
+
|
61
|
+
That's so simple:
|
62
|
+
|
63
|
+
```
|
64
|
+
$ redpomo add 'quote the project +random-project @welaika'
|
65
|
+
Issue created, see it at http://code.welaika.com/issues/3659
|
66
|
+
```
|
67
|
+
|
68
|
+
* If you specify a default project on your `~/.redpomo` configuration
|
69
|
+
file, you can even left out the `+random-project` part.
|
70
|
+
* If you don't specify a task, your predefined editor will pop up and
|
71
|
+
ask you to write the title and (optionally) the description for the
|
72
|
+
issue;
|
73
|
+
* On iTerm 2 terminals, just command + click on the URL to open up the
|
74
|
+
browser!
|
75
|
+
|
76
|
+
### How to close a Redmine issue
|
77
|
+
|
78
|
+
```
|
79
|
+
$ redpomo close 3 -m "Finally done"
|
80
|
+
Issue updated, see it at http://code.welaika.com/issues/1490
|
81
|
+
```
|
82
|
+
|
83
|
+
### Opening the browser to a specific Redmine issue
|
84
|
+
|
85
|
+
```
|
86
|
+
$ redpomo open 3
|
87
|
+
# -> takes your browser to http://code.welaika.com/issues/1490
|
88
|
+
```
|
89
|
+
|
90
|
+
## It integrates nicely with [Pomodoro.app](https://github.com/ugol/pomodoro)!
|
91
|
+
|
92
|
+
If you need to start working on some Redmine issue, just use the `start`
|
93
|
+
command:
|
94
|
+
|
95
|
+
```
|
96
|
+
$ redpomo start 3
|
97
|
+
```
|
98
|
+
|
99
|
+
This will communicate via Applescript with Pomodoro.app, and will automatically
|
100
|
+
start a new pomodoro for you: the description of the pomodoro will contain both
|
101
|
+
the ID of the Redmine issue (ie. #1234), and the Redmine instance identifier
|
102
|
+
(ie. @welaika).
|
103
|
+
|
104
|
+
This is important: in this way we will be able to remap completed pomodoros back
|
105
|
+
to Redmine issues later on!
|
106
|
+
|
107
|
+
### Pushing local pomodoros as Redmine time-tracks
|
108
|
+
|
109
|
+
Here comes the best one. Open the "Pomodoro Stats" panel, and click on
|
110
|
+
the Export button. This will generate a CSV file full of all your completed
|
111
|
+
pomodoros.
|
112
|
+
|
113
|
+
Now we can pass this file to Redpomo:
|
114
|
+
|
115
|
+
```
|
116
|
+
$ redpomo push --dry-run --fuzzy ~/pomodoros.csv
|
117
|
+
|
118
|
+
+----------+------------+---------+------------------------+----------+-------+-------+
|
119
|
+
| Monday 06/18/12 - 8 hours |
|
120
|
+
+----------+------------+---------+------------------------+----------+-------+-------+
|
121
|
+
| Context | Project | Issue # | Description | Duration | From | To |
|
122
|
+
+----------+------------+---------+------------------------+----------+-------+-------+
|
123
|
+
| welaika | nike | 1392 | Project publishing | 2 hours | 08:02 | 10:49 |
|
124
|
+
| welaika | nike | 1390 | Project subtitle | 2 hours | 10:49 | 13:05 |
|
125
|
+
| cantiere | railsyard | | Resource trees | 2 hours | 13:05 | 15:30 |
|
126
|
+
| welaika | nike | 1392 | Project publishing | 32 mins | 15:30 | 16:03 |
|
127
|
+
| cantiere | railsyard | | Resource trees | 25 mins | 16:03 | 16:28 |
|
128
|
+
+----------+------------+---------+------------------------+----------+-------+-------+
|
129
|
+
```
|
130
|
+
|
131
|
+
Isn't it awesome?!
|
132
|
+
|
133
|
+
* The `--dry-run` option tells Redpomo just to print out the parsed timetracks, without
|
134
|
+
pushing timetracks to the various Redmine instances yet;
|
135
|
+
* The `--fuzzy` option merges contiguous pomodoros related to the same Redmine issue;
|
136
|
+
|
137
|
+
## Installation and setup
|
32
138
|
|
33
139
|
Install it yourself as:
|
34
140
|
|
35
|
-
|
141
|
+
```
|
142
|
+
$ gem install redpomo
|
143
|
+
```
|
36
144
|
|
37
|
-
And then configure it:
|
145
|
+
And then configure it with the following command:
|
38
146
|
|
39
|
-
|
147
|
+
```
|
148
|
+
$ redpomo init
|
149
|
+
```
|
150
|
+
|
151
|
+
This will create a new `.redpomo` skeleton file to your home directory, where
|
152
|
+
you'll need to specify all the details of your Redmine instances. Easy
|
153
|
+
stuff.
|
40
154
|
|
41
155
|
## Contributing
|
42
156
|
|
157
|
+
Redpomo is still in its early development. Any help would be much appreciated!
|
158
|
+
|
43
159
|
1. Fork it
|
44
160
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
161
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
46
162
|
4. Push to the branch (`git push origin my-new-feature`)
|
47
163
|
5. Create new Pull Request
|
164
|
+
|
165
|
+
## License
|
166
|
+
|
167
|
+
(The MIT License)
|
168
|
+
|
169
|
+
Copyright © 2011 Stefano Verna
|
170
|
+
|
171
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
172
|
+
|
173
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
174
|
+
|
175
|
+
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
176
|
+
|
data/lib/redpomo/cli.rb
CHANGED
@@ -82,6 +82,14 @@ module Redpomo
|
|
82
82
|
entries = Entry.load_from_csv(csv)
|
83
83
|
entries = FuzzyConverter.convert(entries) if @options[:fuzzy]
|
84
84
|
|
85
|
+
unpushable_entries = entries.select {|entry| !entry.pushable? }
|
86
|
+
|
87
|
+
if unpushable_entries.any?
|
88
|
+
Redpomo.ui.error "Some pomodoros cannot be associated with a proper issue/project."
|
89
|
+
EntriesPrinter.print(unpushable_entries)
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
85
93
|
if @options[:dry_run]
|
86
94
|
EntriesPrinter.print(entries)
|
87
95
|
else
|
data/lib/redpomo/entry.rb
CHANGED
data/lib/redpomo/tracker.rb
CHANGED
@@ -69,7 +69,36 @@ module Redpomo
|
|
69
69
|
post("/issues", issue: data)
|
70
70
|
end
|
71
71
|
|
72
|
+
def pushable_entry?(entry)
|
73
|
+
data = entry_data(entry)
|
74
|
+
if data[:project_id]
|
75
|
+
project_exists?(data[:project_id])
|
76
|
+
else
|
77
|
+
issue_exists?(data[:issue_id])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
72
81
|
def push_entry!(entry)
|
82
|
+
post("/time_entries", time_entry: entry_data(entry))
|
83
|
+
end
|
84
|
+
|
85
|
+
def close_issue!(id, message = nil)
|
86
|
+
issue = { status_id: @closed_status_id }
|
87
|
+
issue[:notes] = message if message.present?
|
88
|
+
put("/issues/#{id}", issue: issue)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def project_exists?(project_id)
|
94
|
+
project_identifier_for(project_id).present?
|
95
|
+
end
|
96
|
+
|
97
|
+
def issue_exists?(issue_id)
|
98
|
+
issue_identifier_for(issue_id).present?
|
99
|
+
end
|
100
|
+
|
101
|
+
def entry_data(entry)
|
73
102
|
task = entry.to_task
|
74
103
|
time_entry = {}
|
75
104
|
|
@@ -89,22 +118,25 @@ module Redpomo
|
|
89
118
|
time_entry[:activity_id] = @default_activity_id.to_i
|
90
119
|
end
|
91
120
|
|
92
|
-
|
121
|
+
time_entry
|
93
122
|
end
|
94
123
|
|
95
|
-
def
|
96
|
-
issue
|
97
|
-
|
98
|
-
|
124
|
+
def issue_identifier_for(issue_id)
|
125
|
+
Config.cache.get("#{@name}:issue:#{issue_id}:identifier") do
|
126
|
+
data = get("/issues/#{issue_id}")
|
127
|
+
data["issue"]["id"]
|
128
|
+
end
|
129
|
+
rescue RestClient::ResourceNotFound => e
|
130
|
+
nil
|
99
131
|
end
|
100
132
|
|
101
|
-
private
|
102
|
-
|
103
133
|
def project_identifier_for(project_id)
|
104
|
-
Config.cache.get("#{@name}:#{project_id}:identifier") do
|
134
|
+
Config.cache.get("#{@name}:project:#{project_id}:identifier") do
|
105
135
|
data = get("/projects/#{project_id}")
|
106
136
|
data["project"]["identifier"]
|
107
137
|
end
|
138
|
+
rescue RestClient::ResourceNotFound => e
|
139
|
+
nil
|
108
140
|
end
|
109
141
|
|
110
142
|
def current_user_id
|
data/lib/redpomo/version.rb
CHANGED
@@ -1,11 +1,151 @@
|
|
1
1
|
---
|
2
2
|
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://project.cantierecreativo.net/projects/giunti-web.json?key=CANTIERE_TOKEN
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
Content-Type:
|
15
|
+
- application/json
|
16
|
+
User-Agent:
|
17
|
+
- Ruby
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Mon, 25 Jun 2012 18:49:26 GMT
|
25
|
+
Server:
|
26
|
+
- Apache/2.2.9 (Debian) DAV/2 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_python/3.3.1
|
27
|
+
Python/2.5.2 mod_ssl/2.2.9 OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
28
|
+
X-Powered-By:
|
29
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
30
|
+
Etag:
|
31
|
+
- ! '"65d33299faf455805a802660e349d516"'
|
32
|
+
X-Runtime:
|
33
|
+
- '17'
|
34
|
+
Cache-Control:
|
35
|
+
- private, max-age=0, must-revalidate
|
36
|
+
Content-Length:
|
37
|
+
- '241'
|
38
|
+
Status:
|
39
|
+
- '200'
|
40
|
+
Content-Type:
|
41
|
+
- application/json; charset=utf-8
|
42
|
+
body:
|
43
|
+
encoding: US-ASCII
|
44
|
+
string: ! '{"project":{"parent":{"name":"LCD (Gianni Sinni)","id":55},"updated_on":"2012/03/14
|
45
|
+
21:52:12 +0100","description":"","created_on":"2012/03/14 21:52:12 +0100","identifier":"giunti-web","name":"Sito
|
46
|
+
Giunti Educational ","id":56,"homepage":""}}'
|
47
|
+
http_version:
|
48
|
+
recorded_at: Mon, 25 Jun 2012 18:49:27 GMT
|
49
|
+
- request:
|
50
|
+
method: get
|
51
|
+
uri: http://code.welaika.com/issues/3293.json?key=WELAIKA_TOKEN
|
52
|
+
body:
|
53
|
+
encoding: US-ASCII
|
54
|
+
string: ''
|
55
|
+
headers:
|
56
|
+
Accept:
|
57
|
+
- application/json
|
58
|
+
Accept-Encoding:
|
59
|
+
- gzip, deflate
|
60
|
+
Content-Type:
|
61
|
+
- application/json
|
62
|
+
User-Agent:
|
63
|
+
- Ruby
|
64
|
+
response:
|
65
|
+
status:
|
66
|
+
code: 200
|
67
|
+
message: OK
|
68
|
+
headers:
|
69
|
+
Date:
|
70
|
+
- Mon, 25 Jun 2012 18:49:27 GMT
|
71
|
+
Server:
|
72
|
+
- Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_ssl/2.2.9
|
73
|
+
OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
74
|
+
X-Powered-By:
|
75
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
76
|
+
Etag:
|
77
|
+
- ! '"e96d810afab9370460405d2b1279b664"'
|
78
|
+
X-Runtime:
|
79
|
+
- '40'
|
80
|
+
Cache-Control:
|
81
|
+
- private, max-age=0, must-revalidate
|
82
|
+
Content-Length:
|
83
|
+
- '447'
|
84
|
+
Status:
|
85
|
+
- '200'
|
86
|
+
Content-Type:
|
87
|
+
- application/json; charset=utf-8
|
88
|
+
body:
|
89
|
+
encoding: US-ASCII
|
90
|
+
string: ! '{"issue":{"status":{"name":"Closed","id":5},"updated_on":"2012/05/07
|
91
|
+
17:02:13 +0200","assigned_to":{"name":"Stefano Verna","id":4},"done_ratio":100,"description":"","tracker":{"name":"Feature","id":2},"start_date":"2012/04/27","created_on":"2012/04/27
|
92
|
+
18:15:23 +0200","spent_hours":4.2152778208256,"subject":"Ricette","author":{"name":"Stefano
|
93
|
+
Verna","id":4},"id":3293,"priority":{"name":"Normal","id":4},"project":{"name":"Olasagasti
|
94
|
+
","id":52}}}'
|
95
|
+
http_version:
|
96
|
+
recorded_at: Mon, 25 Jun 2012 18:49:27 GMT
|
97
|
+
- request:
|
98
|
+
method: get
|
99
|
+
uri: https://project.cantierecreativo.net/projects/giunti-web.json?key=CANTIERE_TOKEN
|
100
|
+
body:
|
101
|
+
encoding: US-ASCII
|
102
|
+
string: ''
|
103
|
+
headers:
|
104
|
+
Accept:
|
105
|
+
- application/json
|
106
|
+
Accept-Encoding:
|
107
|
+
- gzip, deflate
|
108
|
+
Content-Type:
|
109
|
+
- application/json
|
110
|
+
User-Agent:
|
111
|
+
- Ruby
|
112
|
+
response:
|
113
|
+
status:
|
114
|
+
code: 200
|
115
|
+
message: OK
|
116
|
+
headers:
|
117
|
+
Date:
|
118
|
+
- Mon, 25 Jun 2012 18:49:27 GMT
|
119
|
+
Server:
|
120
|
+
- Apache/2.2.9 (Debian) DAV/2 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_python/3.3.1
|
121
|
+
Python/2.5.2 mod_ssl/2.2.9 OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
122
|
+
X-Powered-By:
|
123
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
124
|
+
Etag:
|
125
|
+
- ! '"65d33299faf455805a802660e349d516"'
|
126
|
+
X-Runtime:
|
127
|
+
- '21'
|
128
|
+
Cache-Control:
|
129
|
+
- private, max-age=0, must-revalidate
|
130
|
+
Content-Length:
|
131
|
+
- '241'
|
132
|
+
Status:
|
133
|
+
- '200'
|
134
|
+
Content-Type:
|
135
|
+
- application/json; charset=utf-8
|
136
|
+
body:
|
137
|
+
encoding: US-ASCII
|
138
|
+
string: ! '{"project":{"parent":{"name":"LCD (Gianni Sinni)","id":55},"updated_on":"2012/03/14
|
139
|
+
21:52:12 +0100","description":"","created_on":"2012/03/14 21:52:12 +0100","identifier":"giunti-web","name":"Sito
|
140
|
+
Giunti Educational ","id":56,"homepage":""}}'
|
141
|
+
http_version:
|
142
|
+
recorded_at: Mon, 25 Jun 2012 18:49:27 GMT
|
3
143
|
- request:
|
4
144
|
method: post
|
5
145
|
uri: https://project.cantierecreativo.net/time_entries.json?key=CANTIERE_TOKEN
|
6
146
|
body:
|
7
|
-
encoding:
|
8
|
-
string: ! '{"time_entry":{"project_id":"giunti-web","spent_on":"2012-05-02T08:10:08+00:00","hours":0.
|
147
|
+
encoding: US-ASCII
|
148
|
+
string: ! '{"time_entry":{"project_id":"giunti-web","spent_on":"2012-05-02T08:10:08+00:00","hours":0.08333333333333333,"comments":"Layout
|
9
149
|
homepage e contatti"}}'
|
10
150
|
headers:
|
11
151
|
Accept:
|
@@ -15,7 +155,7 @@ http_interactions:
|
|
15
155
|
Content-Type:
|
16
156
|
- application/json
|
17
157
|
Content-Length:
|
18
|
-
- '
|
158
|
+
- '149'
|
19
159
|
User-Agent:
|
20
160
|
- Ruby
|
21
161
|
response:
|
@@ -24,42 +164,90 @@ http_interactions:
|
|
24
164
|
message: Created
|
25
165
|
headers:
|
26
166
|
Date:
|
27
|
-
-
|
167
|
+
- Mon, 25 Jun 2012 18:49:27 GMT
|
28
168
|
Server:
|
29
169
|
- Apache/2.2.9 (Debian) DAV/2 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_python/3.3.1
|
30
170
|
Python/2.5.2 mod_ssl/2.2.9 OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
31
171
|
X-Powered-By:
|
32
172
|
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
33
173
|
X-Runtime:
|
34
|
-
- '
|
174
|
+
- '65'
|
35
175
|
Cache-Control:
|
36
176
|
- no-cache
|
37
177
|
Set-Cookie:
|
38
|
-
- _redmine_session=
|
178
|
+
- _redmine_session=BAh7BjoPc2Vzc2lvbl9pZCIlZTlhMGZjM2RhNGJlNWZlNzgzYzA0MWRiYjdkODQ0Y2Y%3D--c177e9142b00003b7a458d3f998b8c69a011cd9a;
|
39
179
|
path=/; HttpOnly
|
40
180
|
- autologin=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
|
41
181
|
Location:
|
42
|
-
- https://project.cantierecreativo.net/time_entries/
|
182
|
+
- https://project.cantierecreativo.net/time_entries/1067
|
43
183
|
Content-Length:
|
44
|
-
- '
|
184
|
+
- '335'
|
45
185
|
Status:
|
46
186
|
- '201'
|
47
187
|
Content-Type:
|
48
188
|
- application/json; charset=utf-8
|
49
189
|
body:
|
50
190
|
encoding: US-ASCII
|
51
|
-
string: ! '{"time_entry":{"hours":0.
|
52
|
-
|
53
|
-
|
54
|
-
Giunti Educational ","id":56},"id":
|
191
|
+
string: ! '{"time_entry":{"hours":0.0833333333333333,"activity":{"name":"da
|
192
|
+
valutare","id":15},"updated_on":"2012/06/25 20:49:27 +0200","comments":"Layout
|
193
|
+
homepage e contatti","spent_on":"2012/05/02","user":{"name":"Stefano Verna","id":18},"created_on":"2012/06/25
|
194
|
+
20:49:27 +0200","project":{"name":"Sito Giunti Educational ","id":56},"id":1067}}'
|
195
|
+
http_version:
|
196
|
+
recorded_at: Mon, 25 Jun 2012 18:49:27 GMT
|
197
|
+
- request:
|
198
|
+
method: get
|
199
|
+
uri: http://code.welaika.com/issues/3293.json?key=WELAIKA_TOKEN
|
200
|
+
body:
|
201
|
+
encoding: US-ASCII
|
202
|
+
string: ''
|
203
|
+
headers:
|
204
|
+
Accept:
|
205
|
+
- application/json
|
206
|
+
Accept-Encoding:
|
207
|
+
- gzip, deflate
|
208
|
+
Content-Type:
|
209
|
+
- application/json
|
210
|
+
User-Agent:
|
211
|
+
- Ruby
|
212
|
+
response:
|
213
|
+
status:
|
214
|
+
code: 200
|
215
|
+
message: OK
|
216
|
+
headers:
|
217
|
+
Date:
|
218
|
+
- Mon, 25 Jun 2012 18:49:27 GMT
|
219
|
+
Server:
|
220
|
+
- Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_ssl/2.2.9
|
221
|
+
OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
222
|
+
X-Powered-By:
|
223
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
224
|
+
Etag:
|
225
|
+
- ! '"e96d810afab9370460405d2b1279b664"'
|
226
|
+
X-Runtime:
|
227
|
+
- '36'
|
228
|
+
Cache-Control:
|
229
|
+
- private, max-age=0, must-revalidate
|
230
|
+
Content-Length:
|
231
|
+
- '447'
|
232
|
+
Status:
|
233
|
+
- '200'
|
234
|
+
Content-Type:
|
235
|
+
- application/json; charset=utf-8
|
236
|
+
body:
|
237
|
+
encoding: US-ASCII
|
238
|
+
string: ! '{"issue":{"status":{"name":"Closed","id":5},"updated_on":"2012/05/07
|
239
|
+
17:02:13 +0200","assigned_to":{"name":"Stefano Verna","id":4},"done_ratio":100,"description":"","tracker":{"name":"Feature","id":2},"start_date":"2012/04/27","created_on":"2012/04/27
|
240
|
+
18:15:23 +0200","spent_hours":4.2152778208256,"subject":"Ricette","author":{"name":"Stefano
|
241
|
+
Verna","id":4},"id":3293,"priority":{"name":"Normal","id":4},"project":{"name":"Olasagasti
|
242
|
+
","id":52}}}'
|
55
243
|
http_version:
|
56
|
-
recorded_at:
|
244
|
+
recorded_at: Mon, 25 Jun 2012 18:49:28 GMT
|
57
245
|
- request:
|
58
246
|
method: post
|
59
247
|
uri: http://code.welaika.com/time_entries.json?key=WELAIKA_TOKEN
|
60
248
|
body:
|
61
|
-
encoding:
|
62
|
-
string: ! '{"time_entry":{"issue_id":3293,"spent_on":"2012-05-04T15:04:57+00:00","hours":0.
|
249
|
+
encoding: US-ASCII
|
250
|
+
string: ! '{"time_entry":{"issue_id":3293,"spent_on":"2012-05-04T15:04:57+00:00","hours":0.08333333333333333,"comments":"Ricette"}}'
|
63
251
|
headers:
|
64
252
|
Accept:
|
65
253
|
- application/json
|
@@ -68,7 +256,7 @@ http_interactions:
|
|
68
256
|
Content-Type:
|
69
257
|
- application/json
|
70
258
|
Content-Length:
|
71
|
-
- '
|
259
|
+
- '120'
|
72
260
|
User-Agent:
|
73
261
|
- Ruby
|
74
262
|
response:
|
@@ -77,33 +265,33 @@ http_interactions:
|
|
77
265
|
message: Created
|
78
266
|
headers:
|
79
267
|
Date:
|
80
|
-
-
|
268
|
+
- Mon, 25 Jun 2012 18:49:28 GMT
|
81
269
|
Server:
|
82
270
|
- Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_ssl/2.2.9
|
83
271
|
OpenSSL/0.9.8g Phusion_Passenger/3.0.0
|
84
272
|
X-Powered-By:
|
85
273
|
- Phusion Passenger (mod_rails/mod_rack) 3.0.0
|
86
274
|
X-Runtime:
|
87
|
-
- '
|
275
|
+
- '184'
|
88
276
|
Cache-Control:
|
89
277
|
- no-cache
|
90
278
|
Set-Cookie:
|
91
|
-
- _redmine_session=
|
279
|
+
- _redmine_session=BAh7BjoPc2Vzc2lvbl9pZCIlYzYwYzNlOWFjZmM3NjIyOThlZmEzMGE4MjE4N2IyZjE%3D--07438999f23ae8a8c673302f979759a67f640430;
|
92
280
|
path=/; HttpOnly
|
93
281
|
Location:
|
94
|
-
- http://code.welaika.com/time_entries/
|
282
|
+
- http://code.welaika.com/time_entries/4501
|
95
283
|
Content-Length:
|
96
|
-
- '
|
284
|
+
- '321'
|
97
285
|
Status:
|
98
286
|
- '201'
|
99
287
|
Content-Type:
|
100
288
|
- application/json; charset=utf-8
|
101
289
|
body:
|
102
290
|
encoding: US-ASCII
|
103
|
-
string: ! '{"time_entry":{"spent_on":"2012/05/04","updated_on":"2012/
|
104
|
-
+0200","activity":{"name":"Development","id":9},"user":{"name":"Stefano Verna","id":4},"created_on":"2012/
|
105
|
-
|
291
|
+
string: ! '{"time_entry":{"spent_on":"2012/05/04","updated_on":"2012/06/25 20:49:28
|
292
|
+
+0200","activity":{"name":"Development","id":9},"user":{"name":"Stefano Verna","id":4},"created_on":"2012/06/25
|
293
|
+
20:49:28 +0200","hours":0.0833333333333333,"comments":"Ricette","issue":{"id":3293},"id":4501,"project":{"name":"Olasagasti
|
106
294
|
","id":52}}}'
|
107
295
|
http_version:
|
108
|
-
recorded_at:
|
296
|
+
recorded_at: Mon, 25 Jun 2012 18:49:28 GMT
|
109
297
|
recorded_with: VCR 2.0.1
|
data/spec/fixtures/config.yml
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
+----------+------------+---------+----------------------------+----------+-------+-------+
|
2
|
-
|
|
2
|
+
| Wednesday 05/02/12 - 5 mins |
|
3
3
|
+----------+------------+---------+----------------------------+----------+-------+-------+
|
4
4
|
| Context | Project | Issue # | Description | Duration | From | To |
|
5
5
|
+----------+------------+---------+----------------------------+----------+-------+-------+
|
6
|
-
| cantiere | giunti-web | | Layout homepage e contatti |
|
6
|
+
| cantiere | giunti-web | | Layout homepage e contatti | 5 mins | 08:10 | 08:15 |
|
7
7
|
+----------+------------+---------+----------------------------+----------+-------+-------+
|
8
8
|
|
9
9
|
+---------+---------+---------+-------------+----------+-------+-------+
|
10
|
-
|
|
10
|
+
| Friday 05/04/12 - 5 mins |
|
11
11
|
+---------+---------+---------+-------------+----------+-------+-------+
|
12
12
|
| Context | Project | Issue # | Description | Duration | From | To |
|
13
13
|
+---------+---------+---------+-------------+----------+-------+-------+
|
14
|
-
| welaika | | 3293 | Ricette |
|
14
|
+
| welaika | | 3293 | Ricette | 5 mins | 15:04 | 15:09 |
|
15
15
|
+---------+---------+---------+-------------+----------+-------+-------+
|
16
16
|
|
data/spec/fixtures/timelog.csv
CHANGED
@@ -2,5 +2,5 @@ Export data created by Pomodoro on 2012-05-04 16:12:17 +0000
|
|
2
2
|
|
3
3
|
Description, When, Duration, externalInterruptions, internalInterruptions
|
4
4
|
|
5
|
-
Layout homepage e contatti +giunti-web @cantiere, 2012-05-02 08:10:08 +0000,
|
6
|
-
Ricette #3293 @welaika, 2012-05-04 15:04:57 +0000,
|
5
|
+
Layout homepage e contatti +giunti-web @cantiere, 2012-05-02 08:10:08 +0000, 5, 0, 0
|
6
|
+
Ricette #3293 @welaika, 2012-05-04 15:04:57 +0000, 5, 0, 0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redpomo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70282467137440 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70282467137440
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: thor
|
27
|
-
requirement: &
|
27
|
+
requirement: &70282467157100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70282467157100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: todo-txt
|
38
|
-
requirement: &
|
38
|
+
requirement: &70282467155880 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70282467155880
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rest-client
|
49
|
-
requirement: &
|
49
|
+
requirement: &70282467155240 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70282467155240
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: launchy
|
60
|
-
requirement: &
|
60
|
+
requirement: &70282467154440 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70282467154440
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: applescript
|
71
|
-
requirement: &
|
71
|
+
requirement: &70282467153560 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70282467153560
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: terminal-table
|
82
|
-
requirement: &
|
82
|
+
requirement: &70282467153140 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70282467153140
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rspec
|
93
|
-
requirement: &
|
93
|
+
requirement: &70282467152720 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70282467152720
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: vcr
|
104
|
-
requirement: &
|
104
|
+
requirement: &70282467152240 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70282467152240
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: webmock
|
115
|
-
requirement: &
|
115
|
+
requirement: &70282467151800 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70282467151800
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: mocha
|
126
|
-
requirement: &
|
126
|
+
requirement: &70282467151380 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ! '>='
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *70282467151380
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: simplecov
|
137
|
-
requirement: &
|
137
|
+
requirement: &70282467150960 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ! '>='
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: '0'
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *70282467150960
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: rake
|
148
|
-
requirement: &
|
148
|
+
requirement: &70282467150540 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ! '>='
|
@@ -153,7 +153,7 @@ dependencies:
|
|
153
153
|
version: '0'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *70282467150540
|
157
157
|
description: A nice little gem that integrates Redmine, Todo.txt and Pomodoro.app
|
158
158
|
email:
|
159
159
|
- stefano.verna@welaika.com
|