taskmapper-fogbugz 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
@@ -0,0 +1,44 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ #.DS_Store
31
+ #
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+ #
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+ #
41
+ # For vim:
42
+ #*.swp
43
+ *.un~
44
+ *.un~
@@ -0,0 +1 @@
1
+ ticketmaster-fogbugz
@@ -0,0 +1 @@
1
+ 1.9.2-p290
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@ticketmaster-fogbugz --create
@@ -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 "http://rubygems.org"
2
+
3
+ gem 'taskmapper', '~> 0.8'
4
+ gem 'rake', '~> 0.9'
5
+ gem 'ruby-fogbugz', '~> 0.1'
6
+
7
+ group :development do
8
+ gem 'rspec', '~> 2.0'
9
+ gem 'fakeweb', '~> 1.3'
10
+ gem 'vcr', '~> 1.11'
11
+ gem "simplecov", "~> 0.5.0", :platform => :ruby_19
12
+ gem "rcov", "~> 1.0.0", :platform => :ruby_18
13
+ end
@@ -0,0 +1,55 @@
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
+ crack (0.3.1)
15
+ diff-lcs (1.1.3)
16
+ fakeweb (1.3.0)
17
+ hashie (1.2.0)
18
+ i18n (0.6.0)
19
+ multi_json (1.0.4)
20
+ rake (0.9.2.2)
21
+ rcov (1.0.0)
22
+ rspec (2.0.1)
23
+ rspec-core (~> 2.0.1)
24
+ rspec-expectations (~> 2.0.1)
25
+ rspec-mocks (~> 2.0.1)
26
+ rspec-core (2.0.1)
27
+ rspec-expectations (2.0.1)
28
+ diff-lcs (>= 1.1.2)
29
+ rspec-mocks (2.0.1)
30
+ rspec-core (~> 2.0.1)
31
+ rspec-expectations (~> 2.0.1)
32
+ ruby-fogbugz (0.1.1)
33
+ crack
34
+ simplecov (0.5.4)
35
+ multi_json (~> 1.0.3)
36
+ simplecov-html (~> 0.5.3)
37
+ simplecov-html (0.5.3)
38
+ taskmapper (0.8.0)
39
+ activeresource (~> 3.0)
40
+ activesupport (~> 3.0)
41
+ hashie (~> 1.2)
42
+ vcr (1.11.3)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ fakeweb (~> 1.3)
49
+ rake (~> 0.9)
50
+ rcov (~> 1.0.0)
51
+ rspec (~> 2.0)
52
+ ruby-fogbugz (~> 0.1)
53
+ simplecov (~> 0.5.0)
54
+ taskmapper (~> 0.8)
55
+ vcr (~> 1.11)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Rafael George
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
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ = taskmapper-fogbugz
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to taskmapper-fogbugz
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Rafael George. See LICENSE.txt for
18
+ further details.
19
+
@@ -0,0 +1,26 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubygems'
3
+ require 'rake'
4
+
5
+ require 'rspec/core'
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = FileList['spec/**/*_spec.rb']
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
12
+ spec.pattern = 'spec/**/*_spec.rb'
13
+ spec.rcov = true
14
+ end
15
+
16
+ task :default => :spec
17
+
18
+ require 'rake/rdoctask'
19
+ Rake::RDocTask.new do |rdoc|
20
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
21
+
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = "taskmapper-kanbanpad#{version}"
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
@@ -0,0 +1,14 @@
1
+ module TaskMapper::Provider
2
+ module Fogbugz
3
+ # The comment class for taskmapper-fogbugz
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
+ #API = Fogbugz::Comment # The class to access the api's comments
10
+ # declare needed overloaded methods here
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ module TaskMapper::Provider
2
+ # This is the Fogbugz Provider for taskmapper
3
+ module Fogbugz
4
+ include TaskMapper::Provider::Base
5
+ class << self
6
+ attr_accessor :api
7
+ end
8
+
9
+ #TICKET_API = Fogbugz::Ticket # The class to access the api's tickets
10
+ #PROJECT_API = Fogbugz::Project # The class to access the api's projects
11
+
12
+ # This is for cases when you want to instantiate using TaskMapper::Provider::Fogbugz.new(auth)
13
+ def self.new(auth = {})
14
+ TaskMapper.new(:fogbugz, auth)
15
+ end
16
+
17
+ # Providers must define an authorize method. This is used to initialize and set authentication
18
+ # parameters to access the API
19
+ def authorize(auth = {})
20
+ @authentication ||= TaskMapper::Authenticator.new(auth)
21
+ auth = @authentication
22
+
23
+ unless auth.email? && auth.password? && auth.uri?
24
+ raise TaskMapper::Exception.new 'Please provide email, password and uri'
25
+ end
26
+
27
+ begin
28
+ @fogbugz = ::Fogbugz::Interface.new(:email => auth.email,
29
+ :uri => auth.uri, :password => auth.password)
30
+ TaskMapper::Provider::Fogbugz.api = @fogbugz
31
+ @fogbugz.authenticate
32
+ rescue Exception => ex
33
+ warn "There was a problem authenticaticating #{ex.message}"
34
+ end
35
+ end
36
+ # declare needed overloaded methods here
37
+
38
+ def projects(*options)
39
+ Project.find(options)
40
+ end
41
+
42
+ def project(*options)
43
+ id = options.empty? ? 0 : options.first.to_i
44
+ Project.find_by_id(id)
45
+ end
46
+
47
+ def valid?
48
+ begin
49
+ @fogbugz.command(:search, :q => 'case')
50
+ true
51
+ rescue
52
+ false
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+
@@ -0,0 +1,93 @@
1
+ module TaskMapper::Provider
2
+ module Fogbugz
3
+ # Project class for taskmapper-fogbugz
4
+ #
5
+ #
6
+ class Project < TaskMapper::Provider::Base::Project
7
+ #API = Fogbugz::Project # The class to access the api's projects
8
+ # declare needed overloaded methods here
9
+
10
+ def initialize(*object)
11
+ if object.first
12
+ object = object.first
13
+ unless object.is_a? Hash
14
+ @system_data = {:client => object}
15
+ hash = {:id => object['ixProject'].to_i,
16
+ :name => object['sProject'],
17
+ :description => object['sProject'],
18
+ :created_at => nil,
19
+ :updated_at => nil}
20
+ else
21
+ hash = object
22
+ end
23
+ super(hash)
24
+ end
25
+ end
26
+
27
+ def id
28
+ ixProject.to_i
29
+ end
30
+
31
+ def name
32
+ sProject
33
+ end
34
+
35
+ def description
36
+ sProject
37
+ end
38
+
39
+ # copy from this.copy(that) copies that into this
40
+ def copy(project)
41
+ project.tickets.each do |ticket|
42
+ copy_ticket = self.ticket!(:title => ticket.title, :description => ticket.description)
43
+ ticket.comments.each do |comment|
44
+ copy_ticket.comment!(:body => comment.body)
45
+ sleep 1
46
+ end
47
+ end
48
+ end
49
+
50
+ def tickets(*options)
51
+ Ticket.find(self.id, options)
52
+ end
53
+
54
+ def ticket(*options)
55
+ if options.first.is_a? Fixnum
56
+ Ticket.find_by_id(self.id, options.first)
57
+ else
58
+ raise "You can only search for a single ticket based on id"
59
+ end
60
+ end
61
+
62
+ def ticket!(attributes_hash)
63
+ provider_parent(self.class)::Ticket.create(attributes_hash.merge :project_id => id)
64
+ end
65
+
66
+ def self.find(*options)
67
+ if options[0].first.is_a? Array
68
+ options[0].first.collect { |project_id| self.find_by_id(project_id) }
69
+ elsif options[0].first.is_a? Hash
70
+ self.find_by_attributes(options[0].first)
71
+ else
72
+ self.find_all
73
+ end
74
+ end
75
+
76
+ def self.find_by_attributes(attributes = {})
77
+ search_by_attribute(self.find_all, attributes)
78
+ end
79
+
80
+ def self.find_by_id(id)
81
+ self.find_all.select { |project| project.id == id }.first
82
+ end
83
+
84
+ def self.find_all
85
+ projects = []
86
+ TaskMapper::Provider::Fogbugz.api.command(:listProjects).each do |project|
87
+ projects << project[1]['project'].map { |xpro| self.new xpro }
88
+ end
89
+ projects.flatten
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,159 @@
1
+ module TaskMapper::Provider
2
+ module Fogbugz
3
+ # Ticket class for taskmapper-fogbugz
4
+ #
5
+
6
+ class Ticket < TaskMapper::Provider::Base::Ticket
7
+ #API = Fogbugz::Ticket # The class to access the api's tickets
8
+ # declare needed overloaded methods here
9
+
10
+ def initialize(*object)
11
+ if object.first
12
+ object = object.first
13
+ unless object.is_a? Hash
14
+ @system_data = {:client => object}
15
+ hash = {:id => object['ixBug'],
16
+ :title => object['sTitle'],
17
+ :description => object['sLatestTextSummary'],
18
+ :status => object['sStatus'],
19
+ :project_id => object['ixProject'],
20
+ :resolution => nil,
21
+ :requestor => nil,
22
+ :priority => object['sPriority'],
23
+ :assignee => object['sPersonAssignedTo'],
24
+ :created_at => nil,
25
+ :updated_at => object['dtLastUpdated']}
26
+ else
27
+ hash = object
28
+ end
29
+ super(hash)
30
+ end
31
+ end
32
+
33
+ def id
34
+ self['ixBug'].to_i
35
+ end
36
+
37
+ def title
38
+ self['sTitle']
39
+ end
40
+
41
+ def title=(val)
42
+ self['sTitle'] = val
43
+ end
44
+
45
+ def description
46
+ self['LatestTextSummary']
47
+ end
48
+
49
+ def project_id
50
+ self['ixProject'].to_i
51
+ end
52
+
53
+ def resolution
54
+ nil
55
+ end
56
+
57
+ def status
58
+ self['sStatus']
59
+ end
60
+
61
+ def requestor
62
+ nil
63
+ end
64
+
65
+ def priority
66
+ self['sPriority']
67
+ end
68
+
69
+ def assignee
70
+ self['sPersonAssignedTo']
71
+ end
72
+
73
+ def created_at
74
+ nil
75
+ end
76
+
77
+ def project_id
78
+ self["ixProject"]
79
+ end
80
+
81
+ def updated_at
82
+ Time.parse(self['dtLastUpdated'])
83
+ end
84
+
85
+ def comments(*options)
86
+ []
87
+ warn "Fogbugz API doesn't support comments"
88
+ end
89
+
90
+ def comment(*options)
91
+ nil
92
+ warn "Fogbugz API doesn't support comments"
93
+ end
94
+
95
+ def self.create(attributes_hash)
96
+ warn "Fogbugz Case doesn't not handle description'" if attributes_hash.has_key? :description
97
+
98
+ options = translate attributes_hash,
99
+ :title => :sTitle,
100
+ :priority => :ixPriority,
101
+ :assignee => :ixPersonAssignedTo,
102
+ :project_id => :ixProject
103
+
104
+ new_case = TaskMapper::Provider::Fogbugz.api.command(:new, options)
105
+
106
+ self.new options.merge :ixBug => new_case["case"]["ixBug"]
107
+ end
108
+
109
+ def save
110
+ !update_case.has_key?("error")
111
+ end
112
+
113
+ def self.find(project_id, options)
114
+ if options.first.is_a? Array
115
+ self.find_all(project_id).select do |ticket|
116
+ options.first.any? { |id| ticket.id == id }
117
+ end
118
+ elsif options.first.is_a? Hash
119
+ self.find_by_attributes(project_id, options.first)
120
+ else
121
+ self.find_all(project_id)
122
+ end
123
+ end
124
+
125
+ def self.find_by_id(project_id, id)
126
+ self.find_all(project_id).select { |ticket| ticket.id == id }.first
127
+ end
128
+
129
+ def self.find_by_attributes(project_id, attributes = {})
130
+ search_by_attribute(self.find_all(project_id), attributes)
131
+ end
132
+
133
+ def self.find_all(project_id)
134
+ tickets = []
135
+ TaskMapper::Provider::Fogbugz.api.command(:search, :q => "project:=#{project_id}", :cols =>"dtLastUpdated,ixBug,sStatus,sTitle,sLatestTextSummary,ixProject,sProject,sPersonAssignedTo,sPriority").each do |ticket|
136
+ tickets << ticket[1]["case"]
137
+ end
138
+ tickets.flatten.map { |xticket| self.new xticket }
139
+ end
140
+
141
+ private
142
+ def update_case
143
+ TaskMapper::Provider::Fogbugz.api.command :edit, to_case_hash
144
+ end
145
+
146
+ def self.translate(hash, mapping)
147
+ Hash[hash.map { |k, v| [mapping[k] ||= k, v]}]
148
+ end
149
+
150
+ #just title until now
151
+ def to_case_hash
152
+ {
153
+ :ixBug => id,
154
+ :sTitle => title
155
+ }
156
+ end
157
+ end
158
+ end
159
+ end