timetrap-redmine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []