timetrap-redmine 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 352b3d941d68011a4564be97c93289d9a158e68c
4
+ data.tar.gz: 9445d2b64bda328f43aaba63f2c09a2e89f2fba6
5
+ SHA512:
6
+ metadata.gz: b899a6903f40ebc832d9afcfb7ff31f49dc6496f697c0dde2b446b674d901af66302735687d46b2d3fa1a807ef64439c44a52e2dbd120d2a42169c82e3c853b6
7
+ data.tar.gz: ac308b8b818b8c81d45d05fa8994e0f24d37a371595310baa01a67ad22afb32f9b5c17b789d41b67cad03fa2672bee7ea5ceedb49555bad52ca99731cda97de5
@@ -0,0 +1,98 @@
1
+ require_relative './timetrap_redmine/api'
2
+
3
+ class Timetrap::Formatters::Redmine
4
+ attr_reader :entries
5
+
6
+ def initialize(entries)
7
+ TimetrapRedmine::API::Resource.site = Timetrap::Config['redmine']['url']
8
+ TimetrapRedmine::API::Resource.user = Timetrap::Config['redmine']['user']
9
+ TimetrapRedmine::API::Resource.password = Timetrap::Config['redmine']['password']
10
+
11
+ @entries = entries
12
+ @issues = {}
13
+ end
14
+
15
+ def output
16
+ status = Hash.new(0)
17
+ entries.each {|e| status[process(e)] += 1}
18
+
19
+ STDERR.puts "" if status.length
20
+
21
+ STDERR.puts "error unchanged created updated"
22
+ STDERR.puts "%5d %9d %7d %7d" % [status[:error], status[:unchanged], status[:created], status[:updated]]
23
+
24
+ exit
25
+ end
26
+
27
+ private
28
+
29
+ def process(entry)
30
+ return unless match = /^([0-9]+)(?:\s+(.+?))?\s*$/.match(entry.note)
31
+
32
+ issue_id = match[1]
33
+ comments = match[2] || ''
34
+
35
+ prefix = "[tt #{entry.id}]"
36
+
37
+ info = entry.end ? '' : ' (incomplete)'
38
+
39
+ time_entry = {
40
+ :issue_id => issue_id,
41
+ :comments => "#{prefix}#{info} #{comments}",
42
+ :spent_on => entry.start.strftime("%Y-%m-%d"),
43
+ :hours => entry.duration / 3600.0,
44
+ }
45
+
46
+ redmine_entry = find_entry(prefix)
47
+
48
+ begin
49
+ issue = find_issue(issue_id)
50
+ rescue ActiveResource::ResourceNotFound
51
+ STDERR.puts "Error: no such issue: #{issue_id}"
52
+ return :error
53
+ rescue ActiveResource::ForbiddenAccess
54
+ STDERR.puts "Error: inaccessible issue: #{issue_id}"
55
+ return :error
56
+ end
57
+
58
+ if redmine_entry &&
59
+ redmine_entry.issue.id == time_entry[:issue_id] &&
60
+ redmine_entry.comments == time_entry[:comments] &&
61
+ redmine_entry.spent_on == time_entry[:spent_on] &&
62
+ ((redmine_entry.hours || '0.0').to_f - time_entry[:hours]).abs < 0.01
63
+ operation = :unchanged
64
+ elsif redmine_entry
65
+ operation = :updated
66
+ else
67
+ operation = :created
68
+ end
69
+
70
+ line = "% 3s %s % 5.2f " % [
71
+ {:unchanged => '', :updated => 'upd', :created => 'add'}[operation],
72
+ time_entry[:spent_on],
73
+ time_entry[:hours]
74
+ ]
75
+ line += "##{issue.id}: #{issue.subject}"[0, 80 - line.length]
76
+ STDERR.puts(line)
77
+
78
+ unless operation == :unchanged
79
+ redmine_entry = TimetrapRedmine::API::TimeEntry.new unless redmine_entry
80
+ redmine_entry.update_attributes(time_entry)
81
+ end
82
+
83
+ return operation
84
+ end
85
+
86
+ def find_entry(prefix)
87
+ TimetrapRedmine::API::TimeEntry.find(:all, :params => {
88
+ :f => ['comments', 'user_id'],
89
+ :op => {:comments => '~', 'user_id' => '='},
90
+ :v => {:comments => [prefix], 'user_id' => ['me']},
91
+ :sort => 'id',
92
+ }).find {|e| e.comments.start_with?(prefix)}
93
+ end
94
+
95
+ def find_issue(issue_id)
96
+ return @issues[issue_id] ||= TimetrapRedmine::API::Issue.find(issue_id)
97
+ end
98
+ 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 ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timetrap-redmine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Albert Peschar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: This timetrap formatter creates Redmine timelog entries
14
+ email: albert@peschar.net
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/timetrap-redmine.rb
20
+ - lib/timetrap_redmine/api.rb
21
+ homepage: http://github.com/apeschar/timetrap-redmine
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.4.5
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Sync timetrap to Redmine
45
+ test_files: []