taskmapper-trac 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rbenv-gemsets ADDED
@@ -0,0 +1 @@
1
+ ticketmaster-trac
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@taskmapper-trac --create
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source :rubygems
2
+
3
+ gem "taskmapper", "~> 0.8"
4
+ gem "trac4r", "~> 1.2"
5
+ gem "nokogiri", "~> 1.5"
6
+
7
+ group :development do
8
+ gem "rspec", "~> 2.8"
9
+ gem "bundler", "~> 1.1"
10
+ gem "jeweler", "~> 1.6"
11
+ gem "simplecov", "~> 0.5", :platform => :ruby_19
12
+ gem "rcov", "~> 1.0", :platform => :ruby_18
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,75 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.3)
5
+ activesupport (= 3.2.3)
6
+ builder (~> 3.0.0)
7
+ activeresource (3.2.3)
8
+ activemodel (= 3.2.3)
9
+ activesupport (= 3.2.3)
10
+ activesupport (3.2.3)
11
+ i18n (~> 0.6)
12
+ multi_json (~> 1.0)
13
+ builder (3.0.0)
14
+ diff-lcs (1.1.3)
15
+ gash (0.1.3)
16
+ open4 (>= 0, = 0.9.6)
17
+ git (1.2.5)
18
+ gli (1.4.0)
19
+ grancher (0.1.5)
20
+ gash
21
+ hashie (1.2.0)
22
+ i18n (0.6.0)
23
+ jeweler (1.6.4)
24
+ bundler (~> 1.0)
25
+ git (>= 1.2.5)
26
+ rake
27
+ json (1.6.5)
28
+ multi_json (1.0.4)
29
+ nokogiri (1.5.0)
30
+ open4 (0.9.6)
31
+ rainbow (1.1.3)
32
+ rake (0.9.2.2)
33
+ rcov (1.0.0)
34
+ rdoc (3.12)
35
+ json (~> 1.4)
36
+ rspec (2.8.0)
37
+ rspec-core (~> 2.8.0)
38
+ rspec-expectations (~> 2.8.0)
39
+ rspec-mocks (~> 2.8.0)
40
+ rspec-core (2.8.0)
41
+ rspec-expectations (2.8.0)
42
+ diff-lcs (~> 1.1.2)
43
+ rspec-mocks (2.8.0)
44
+ sdoc (0.3.16)
45
+ json (>= 1.1.3)
46
+ rdoc (~> 3.10)
47
+ simplecov (0.5.4)
48
+ multi_json (~> 1.0.3)
49
+ simplecov-html (~> 0.5.3)
50
+ simplecov-html (0.5.3)
51
+ taskmapper (0.8.0)
52
+ activeresource (~> 3.0)
53
+ activesupport (~> 3.0)
54
+ hashie (~> 1.2)
55
+ trac4r (1.2.4)
56
+ gli
57
+ gli (>= 1.1.0)
58
+ grancher
59
+ jeweler
60
+ rainbow
61
+ rainbow (>= 1.0.4)
62
+ sdoc
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ bundler (~> 1.1)
69
+ jeweler (~> 1.6)
70
+ nokogiri (~> 1.5)
71
+ rcov (~> 1.0)
72
+ rspec (~> 2.8)
73
+ simplecov (~> 0.5)
74
+ taskmapper (~> 0.8)
75
+ trac4r (~> 1.2)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 YOU
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ NONE
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # taskmapper-trac
2
+
3
+ This is a provider for [taskmapper](http://ticketrb.com). It provides interoperability with [Trac](http://trac.edgewall.org) and it's issue tracking system through the taskmapper gem.
4
+
5
+ # Usage and Examples
6
+
7
+ First we have to instantiate a new taskmapper instance, your trac installation should have api access enable:
8
+ trac = taskmapper.new(:trac, {:username=> 'foo', :password => "bar", :url => "http://tracserver/username/project/trac"})
9
+
10
+ If you do not pass in the url, username and password, you won't get any information.
11
+
12
+ ## Finding Projects(Repositories)
13
+
14
+ Right now Trac doesn't support project handling, that's why you will use a project holder which consist of your username and url for the Trac instance.
15
+
16
+ ## Finding Tickets(Issues)
17
+
18
+ tickets = project.tickets # All tickets
19
+ ticket = project.tickets(:status => '!closed') # All non closed tickets, you can specified any type of attributes field based on Trac scheme. ex. :component => 'Web'
20
+
21
+ ## Open Tickets
22
+
23
+ ticket = project.ticket!({:summary => "New ticket", :description=> "Body for the very new ticket"}, attributes) # summary and description are mandatory fields the attributes hash will contain all the optional info that you need for your ticket, have to use the fields provided by Trac api.
24
+
25
+ ## Finding comments
26
+
27
+ comments = project.tickets.first.comments # All the tickets facility for searchs are available for comments as well
28
+
29
+
30
+ ## Requirements
31
+
32
+ * rubygems (obviously)
33
+ * taskmapper gem (latest version preferred)
34
+ * jeweler gem (only if you want to repackage and develop)
35
+ * trac4r
36
+
37
+ The taskmapper gem should automatically be installed during the installation of this gem if it is not already installed.
38
+
39
+ ## Other Notes
40
+
41
+ Since this and the taskmapper gem is still primarily a work-in-progress, minor changes may be incompatible with previous versions. Please be careful about using and updating this gem in production.
42
+
43
+ If you see or find any issues, feel free to open up an issue report.
44
+
45
+
46
+ ## Note on Patches/Pull Requests
47
+
48
+ * Fork the project.
49
+ * Make your feature addition or bug fix.
50
+ * Add tests for it. This is important so we don't break it in a
51
+ future version unintentionally.
52
+ * Commit, do not mess with rakefile, version, or history.
53
+ (if you want to have your own version, that is fine but bump version in a commit by itself so we can ignore when I pull)
54
+ * Send us a pull request. Bonus points for topic branches.
55
+
56
+ ## Copyright
57
+
58
+ Copyright (c) 2010 The Hybrid Group. See LICENSE for details.
59
+
60
+
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "taskmapper-trac"
8
+ gem.summary = %Q{taskmapper Provider for Trac}
9
+ gem.description = %Q{Allows taskmapper to interact with Your System.}
10
+ gem.email = "rafael@hybridgroup.com"
11
+ gem.homepage = "http://github.com/hybridgroup/taskmapper-trac"
12
+ gem.authors = ["Rafael George"]
13
+ gem.add_dependency "trac4r"
14
+ gem.add_dependency "nokogiri"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rspec/core'
23
+ require 'rspec/core/rake_task'
24
+ RSpec::Core::RakeTask.new(:spec) do |spec|
25
+ spec.pattern = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :default => :spec
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "taskmapper-trac #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
@@ -0,0 +1,79 @@
1
+ module TaskMapper::Provider
2
+ module Trac
3
+ # The comment class for taskmapper-yoursystem
4
+ #
5
+ # Do any mapping between taskmapper and your system's comment model here
6
+ # versions of the ticket.
7
+ #
8
+ class Comment < TaskMapper::Provider::Base::Comment
9
+ # declare needed overloaded methods here
10
+
11
+ def initialize(*object)
12
+ if object.first
13
+ object = object.first
14
+ unless object.is_a? Hash
15
+ @system_data = {:client => object}
16
+ hash = {:id => object[:id],
17
+ :author => object.author,
18
+ :body => object.body,
19
+ :ticket_id => object.ticket_id,
20
+ :created_at => object.created_at,
21
+ :updated_at => object.updated_at}
22
+ else
23
+ hash = object
24
+ end
25
+ super(hash)
26
+ end
27
+ end
28
+
29
+ def created_at
30
+ begin
31
+ Time.parse(self[:created_at])
32
+ rescue
33
+ self[:created_at]
34
+ end
35
+ end
36
+
37
+ def updated_at
38
+ begin
39
+ Time.parse(self[:updated_at])
40
+ rescue
41
+ self[:updated_at]
42
+ end
43
+ end
44
+
45
+ def id
46
+ self[:id]
47
+ end
48
+
49
+ def self.find_by_attributes(project_id, ticket_id, attributes = {})
50
+ comments = self.find_all(ticket_id)
51
+ search_by_attribute(comments, attributes)
52
+ end
53
+
54
+ def self.find(project_id, ticket_id, *options)
55
+ if options[0].first.is_a? Array
56
+ self.find_all(ticket_id).select do |comment|
57
+ comment if options[0].any? { |id| id == comment.id }
58
+ end
59
+ elsif options[0].first.is_a? Hash
60
+ self.find_by_attributes(project_id, ticket_id, options[0].first)
61
+ else
62
+ self.find_all(ticket_id)
63
+ end
64
+ end
65
+
66
+ def self.find_by_id(project_id, ticket_id, id)
67
+ self.find_all(ticket_id).select { |comment| comment[:id] == id }.first
68
+ end
69
+
70
+ def self.find_all(ticket_id)
71
+ comments = CommentUtil.new(ticket_id,TaskMapper::Provider::Trac.api).comments
72
+ comments.compact.collect do |comment|
73
+ TaskMapper::Provider::Trac::Comment.new comment
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,72 @@
1
+ module TaskMapper::Provider
2
+ module Trac
3
+ # Project class for taskmapper-yoursystem
4
+ #
5
+ #
6
+ class Project < TaskMapper::Provider::Base::Project
7
+ # declare needed overloaded methods here
8
+
9
+ attr_reader :created_at, :updated_at
10
+ def initialize(*object)
11
+ if object.first
12
+ object = object.first
13
+ @system_data = {:client => object}
14
+ unless object.is_a? Hash
15
+ hash = {:repository => object.url,
16
+ :owner => object.username,
17
+ :name => object.name,
18
+ :id => object.name}
19
+ else
20
+ hash = object
21
+ end
22
+ super hash
23
+ end
24
+ end
25
+
26
+ # copy from this.copy(that) copies that into this
27
+ def copy(project)
28
+ project.tickets.each do |ticket|
29
+ copy_ticket = self.ticket!(:title => ticket.title, :description => ticket.description)
30
+ ticket.comments.each do |comment|
31
+ copy_ticket.comment!(:body => comment.body)
32
+ sleep 1
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.find(*options)
38
+ mode = options.first
39
+ trac = TaskMapper::Provider::Trac.api
40
+ if mode.is_a? String
41
+ self.new({:url => trac[:url], :username => trac[:username], :name=> "#{trac[:username]}-project"})
42
+ end
43
+ end
44
+
45
+ def id
46
+ 1
47
+ end
48
+
49
+ def ticket(*options)
50
+ unless options.empty?
51
+ options = options.first
52
+ trac = TaskMapper::Provider::Trac.api
53
+ if options.is_a? Hash
54
+ Ticket.find_by_id(trac[:trac].tickets.query(options).first, self[:name])
55
+ end
56
+ else
57
+ TaskMapper::Provider::Trac::Ticket
58
+ end
59
+ end
60
+
61
+ def ticket!(*options)
62
+ options = options.first
63
+ Ticket.create options
64
+ end
65
+
66
+ def tickets(*options)
67
+ Ticket.find(self.name, options)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,126 @@
1
+ module TaskMapper::Provider
2
+ module Trac
3
+ # Ticket class for taskmapper-yoursystem
4
+ #
5
+
6
+ class Ticket < TaskMapper::Provider::Base::Ticket
7
+ # declare needed overloaded methods here
8
+
9
+ def initialize(*object)
10
+ if object.first
11
+ args = object
12
+ object = args.shift
13
+ project_id = args.shift
14
+ unless object.is_a? Hash
15
+ @system_data = {:client => object}
16
+ hash = {:id => object.id,
17
+ :severity => object.severity,
18
+ :milestone => object.milestone,
19
+ :status => object.status,
20
+ :type => object.type,
21
+ :priority => object.priority,
22
+ :version => object.version,
23
+ :reporter => object.reporter,
24
+ :owner => object.owner,
25
+ :cc => object.cc,
26
+ :summary => object.summary,
27
+ :assignee => object.owner,
28
+ :requestor => object.reporter,
29
+ :title => object.summary,
30
+ :project_id => project_id,
31
+ :description => object.description,
32
+ :keywords => object.keywords,
33
+ :created_at => object.created_at,
34
+ :updated_at => object.updated_at}
35
+ else
36
+ hash = object
37
+ end
38
+ super(hash)
39
+ end
40
+ end
41
+
42
+ def created_at
43
+ normalize_datetime(self[:created_at])
44
+ end
45
+
46
+ def updated_at
47
+ normalize_datetime(self[:updated_at])
48
+ end
49
+
50
+ def self.find_by_id(id, project_id)
51
+ trac = TaskMapper::Provider::Trac.api
52
+ retryable(:tries => 10) do
53
+ self.new trac[:trac].tickets.get(id), project_id
54
+ end
55
+ end
56
+
57
+ def self.find(project_id, *options)
58
+ mode = options[0].first
59
+ trac = TaskMapper::Provider::Trac.api
60
+ if options[0].empty?
61
+ self.find_all(project_id, trac[:trac].tickets.list)
62
+ elsif mode.is_a? Array
63
+ self.find_all(project_id, mode)
64
+ elsif mode.is_a? Hash
65
+ self.find_all(project_id, trac[:trac].tickets.query(mode))
66
+ end
67
+ end
68
+
69
+ def self.find_all(project_id, tickets)
70
+ tickets.collect do |ticket_id|
71
+ self.find_by_id(ticket_id, project_id)
72
+ end
73
+ end
74
+
75
+ def self.create(*options)
76
+ mandatory = options.shift
77
+ attributes = {}
78
+ attributes ||= options.shift
79
+ trac = TaskMapper::Provider::Trac.api
80
+ begin
81
+ self.find_by_id trac[:trac].tickets.create(mandatory[:summary], mandatory[:description], attributes)
82
+ rescue
83
+ self
84
+ end
85
+ end
86
+
87
+ def comments(*options)
88
+ Comment.find(self.project_id, self.id, options)
89
+ end
90
+
91
+ def comment(*options)
92
+ if options.empty?
93
+ TaskMapper::Provider::Trac::Comment.new
94
+ elsif options.first.is_a? Fixnum
95
+ Comment.find_by_id(self.project_id, self.id, options.first)
96
+ elsif options.first.is_a? Hash
97
+ Comment.find_by_attributes(self.project_id, self.id, options.first).first
98
+ end
99
+ end
100
+
101
+ def comment!
102
+ warn "Trac doesn't support creation of comments"
103
+ []
104
+ end
105
+
106
+ private
107
+ def normalize_datetime(datetime)
108
+ datetime = datetime.to_time
109
+ end
110
+
111
+ # Extracted this code from facet http://api.mackframework.com/mack-facets/classes/Kernel.html
112
+ def self.retryable(options = {}, &block)
113
+ opts = { :tries => 5, :on => Exception }.merge(options)
114
+
115
+ retry_exception, retries = opts[:on], opts[:tries]
116
+
117
+ begin
118
+ return yield
119
+ rescue retry_exception
120
+ retry if (retries -= 1) > 0
121
+ end
122
+ yield
123
+ end
124
+ end
125
+ end
126
+ end