timetrap-redmine 1.0.0 → 1.0.2

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: d5f6cee22e1012dcc1cf95d22f304fbe8bf9e706
4
- data.tar.gz: 33ee86493d9738b420c9ca017d1a466068d6bb03
3
+ metadata.gz: 6913f704186a34da0aec3115d5cc64b08b3a201b
4
+ data.tar.gz: 98472b53e1c182ca441ae243463c4c5a917706b8
5
5
  SHA512:
6
- metadata.gz: 31111a325d2089ccc08f56e71f09f0f7da398fed4926f1a73f776db59b354d2558d9f0281ea9be6257df1c71a45375776e8ffa86aff45b5d909a285b55c228e7
7
- data.tar.gz: 8a547a5e3cde4972b5c781ae6283871b037f7054d4270d413542b5400f83ab579700e4778cca1cffaedf2eaa45b35ee650033d9a2c54ac48b64b36d6b9f09cf1
6
+ metadata.gz: 482d6892626d1fa3d5f4b150eaa5b3daddee2ac676c7848a466b2b6949232038553f26810471a204d8dac4db505fc7e42a804d66d695d5e8cb85083ae5bf7092
7
+ data.tar.gz: f731577b249d2f2b28ca524d59be9a3a2fd04d2a28c15eba25ad19258ce1fb289b86c8c7777f8524299c53309c314286ee2c7bcca51b2da0561f3b803537e6b1
@@ -0,0 +1,127 @@
1
+ require 'thread'
2
+
3
+ require_relative './timetrap_redmine/api'
4
+
5
+ class Timetrap::Formatters::Redmine
6
+ attr_reader :entries
7
+
8
+ def initialize(entries)
9
+ TimetrapRedmine::API::Resource.site = Timetrap::Config['redmine']['url']
10
+ TimetrapRedmine::API::Resource.user = Timetrap::Config['redmine']['user']
11
+ TimetrapRedmine::API::Resource.password = Timetrap::Config['redmine']['password']
12
+
13
+ @entries = entries
14
+
15
+ threads = []
16
+
17
+ threads << Thread.new do
18
+ @issues = {}
19
+ TimetrapRedmine::API::Issue.find(:all, :params => {
20
+ :f => ['status'],
21
+ :op => [:status => '*'],
22
+ :sort => 'id:desc',
23
+ :limit => 100,
24
+ }).each do |i|
25
+ @issues[i.id] = i
26
+ end
27
+ end
28
+
29
+ threads << Thread.new do
30
+ @rm_entries = TimetrapRedmine::API::TimeEntry.find(:all, :params => {
31
+ :f => ['comments', 'user_id'],
32
+ :op => {:comments => '~', 'user_id' => '='},
33
+ :v => {:comments => ['[tt '], 'user_id' => ['me']},
34
+ :sort => 'id:desc',
35
+ :limit => 100,
36
+ })
37
+ end
38
+
39
+ threads.each(&:join)
40
+ end
41
+
42
+ def output
43
+ status = Hash.new(0)
44
+ entries.each {|e| status[process(e)] += 1}
45
+
46
+ STDERR.puts "" if status.length
47
+
48
+ STDERR.puts "error unchanged created updated"
49
+ STDERR.puts "%5d %9d %7d %7d" % [status[:error], status[:unchanged], status[:created], status[:updated]]
50
+
51
+ exit
52
+ end
53
+
54
+ private
55
+
56
+ def process(entry)
57
+ return unless match = /^([0-9]+)(?:\s+(.+?))?\s*$/.match(entry.note)
58
+
59
+ issue_id = match[1]
60
+ comments = match[2] || ''
61
+
62
+ prefix = "[tt #{entry.id}]"
63
+
64
+ info = entry.end ? '' : ' (incomplete)'
65
+
66
+ time_entry = {
67
+ :issue_id => issue_id,
68
+ :comments => "#{prefix}#{info} #{comments}",
69
+ :spent_on => entry.start.strftime("%Y-%m-%d"),
70
+ :hours => entry.duration / 3600.0,
71
+ }
72
+
73
+ redmine_entry = find_entry(prefix)
74
+
75
+ begin
76
+ issue = find_issue(issue_id)
77
+ rescue ActiveResource::ResourceNotFound
78
+ STDERR.puts "Error: no such issue: #{issue_id}"
79
+ return :error
80
+ rescue ActiveResource::ForbiddenAccess
81
+ STDERR.puts "Error: inaccessible issue: #{issue_id}"
82
+ return :error
83
+ end
84
+
85
+ if redmine_entry &&
86
+ redmine_entry.issue.id == time_entry[:issue_id] &&
87
+ redmine_entry.comments == time_entry[:comments] &&
88
+ redmine_entry.spent_on == time_entry[:spent_on] &&
89
+ ((redmine_entry.hours || '0.0').to_f - time_entry[:hours]).abs < 0.01
90
+ operation = :unchanged
91
+ elsif redmine_entry
92
+ operation = :updated
93
+ else
94
+ operation = :created
95
+ end
96
+
97
+ line = "% 3s %s % 5.2f " % [
98
+ {:unchanged => '', :updated => 'upd', :created => 'add'}[operation],
99
+ time_entry[:spent_on],
100
+ time_entry[:hours]
101
+ ]
102
+ line += "##{issue.id}: #{issue.subject}"[0, 80 - line.length]
103
+ STDERR.puts(line)
104
+
105
+ unless operation == :unchanged
106
+ redmine_entry = TimetrapRedmine::API::TimeEntry.new unless redmine_entry
107
+ redmine_entry.update_attributes(time_entry)
108
+ end
109
+
110
+ return operation
111
+ end
112
+
113
+ def find_entry(prefix)
114
+ match = lambda {|e| e.comments.start_with?(prefix)}
115
+
116
+ @rm_entries.find(&match) || TimetrapRedmine::API::TimeEntry.find(:all, :params => {
117
+ :f => ['comments', 'user_id'],
118
+ :op => {:comments => '~', 'user_id' => '='},
119
+ :v => {:comments => [prefix], 'user_id' => ['me']},
120
+ :sort => 'id',
121
+ }).find(&match)
122
+ end
123
+
124
+ def find_issue(issue_id)
125
+ return @issues[issue_id] ||= TimetrapRedmine::API::Issue.find(issue_id)
126
+ end
127
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'active_resource'
3
+
4
+ module TimetrapRedmine
5
+ module API
6
+ class Resource < ActiveResource::Base
7
+ self.format = ActiveResource::Formats::XmlFormat
8
+ end
9
+
10
+ class Issue < Resource
11
+ end
12
+
13
+ class TimeEntry < Resource
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timetrap-redmine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert Peschar
@@ -15,7 +15,9 @@ email: albert@peschar.net
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
- files: []
18
+ files:
19
+ - lib/timetrap-redmine.rb
20
+ - lib/timetrap_redmine/api.rb
19
21
  homepage: http://github.com/apeschar/timetrap-redmine
20
22
  licenses:
21
23
  - MIT