trac4r 1.1.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/LICENCE +42 -0
- data/README.rdoc +16 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/bin/trac +289 -0
- data/lib/trac4r/error.rb +14 -6
- data/lib/trac4r/query.rb +1 -5
- data/lib/trac4r/ticket.rb +8 -1
- data/lib/trac4r/tickets.rb +27 -5
- data/lib/trac4r/wiki.rb +5 -0
- data/lib/trac4r.rb +9 -3
- metadata +40 -13
data/LICENCE
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
Copyright (c) 2008 Niklas E. Cathor <niklas@brueckenschlaeger.de>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
copy of this software and associated documentation files (the "Software"),
|
5
|
+
to deal in the Software without restriction, including without limitation
|
6
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
8
|
+
Software is furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
Copyright (c) 2008 Niklas E. Cathor <niklas@brueckenschlaeger.de>
|
25
|
+
|
26
|
+
Hiermit wird unentgeltlich, jeder Person, die eine Kopie der Software und
|
27
|
+
der zugeh�rigen Dokumentationen (die "Software") erh�lt, die Erlaubnis
|
28
|
+
erteilt, uneingeschr�nkt zu benutzen, inklusive und ohne au�nahme, dem
|
29
|
+
Recht, sie zu verwenden, kopieren, �ndern, fusionieren, verlegen, verbreiten,
|
30
|
+
unterlizenzieren und/oder zu verkaufen, und Personen, die diese Software
|
31
|
+
erhalten, diese Rechte zu geben, unter den folgenden Bedingungen:
|
32
|
+
|
33
|
+
Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in alle
|
34
|
+
Kopien oder Teilkopien der Software beizulegen.
|
35
|
+
|
36
|
+
DIE SOFTWARE WIRD OHNE JEDE AUSDR�CKLICHE ODER IMPLIZIERTE GARANTIE BEREITGE-
|
37
|
+
STELLT, EINSCHIESSLICH DER GARANTIE ZUR BENUTZUNG F�R DEN VORGESEHENEN ODER
|
38
|
+
EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF
|
39
|
+
BESCHR�NKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER F�R
|
40
|
+
JEGLICHEN SCHADEN ODER SONSTIGE ANSPRUCH HAFTBAR ZU MACHEN, OB INFOLGE DER
|
41
|
+
ERF�LLUNG VON EINEM VERTRAG, EINEM DELIKT ODER ANDERS IM ZUSAMMENHANG MIT
|
42
|
+
DER BENUTZUNG ODER SONSTIGE VERWENDUNG DER SOFTWARE ENTSTANDEN.
|
data/README.rdoc
CHANGED
@@ -2,6 +2,7 @@ trac4r: Ruby wrapper for the Trac XML-RPC API
|
|
2
2
|
=============================================
|
3
3
|
|
4
4
|
Author:: Niklas Cathor
|
5
|
+
Author:: David Copeland
|
5
6
|
License:: See LICENSE in source distribution
|
6
7
|
|
7
8
|
For more information on the Trac XML-RPC see the {plugin's page on trac-hacks.com}[http://trac-hacks.org/wiki/XmlRpcPlugin#UsingfromRuby]
|
@@ -29,6 +30,21 @@ This wraps the Trac XML-RPC plugin.
|
|
29
30
|
trac.tickets.list # get all tickets
|
30
31
|
trac.tickets.get 2334 # Get ticket #2334
|
31
32
|
|
33
|
+
=== Tickets
|
34
|
+
|
35
|
+
Trac's backbone is tickets. The Tickets class contains many useful methods, but can also run arbitrary queries against Trac using
|
36
|
+
a more Rubyesque syntax:
|
37
|
+
|
38
|
+
# Gets all tickets in the "Web" component with a status of either "assigned"
|
39
|
+
# "accepted", or "new"
|
40
|
+
available_web_tickets = trac.tickets.query(:component => 'Web', :status => [:assigned,:accepted,:new])
|
41
|
+
|
42
|
+
# Ticktes that are not closed
|
43
|
+
unclosed_tickets = trac.tickets.query(:status => "!closed")
|
44
|
+
|
45
|
+
# This is a bit wierd, the "!" in the first element means "none of these values"
|
46
|
+
not_closed_nor_testing = trac.tickets.query(:status => ["!closed","test"])
|
47
|
+
|
32
48
|
== More Info
|
33
49
|
|
34
50
|
* {RDoc}[http://davetron5000.github.com/trac4r]
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'hanna/rdoctask'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
$: << '../grancher/lib'
|
7
|
+
begin
|
8
|
+
require 'grancher/task'
|
9
|
+
Grancher::Task.new do |g|
|
10
|
+
g.branch = 'gh-pages'
|
11
|
+
g.push_to = 'origin'
|
12
|
+
g.directory 'html'
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
#puts "you may install the optional gem 'grancher'"
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'jeweler'
|
20
|
+
Jeweler::Tasks.new do |s|
|
21
|
+
s.name = "trac4r"
|
22
|
+
s.executables = "trac"
|
23
|
+
s.summary = 'Ruby Client Library for Trac'
|
24
|
+
s.email = "davidcopeland@naildrivin5.com"
|
25
|
+
s.description = 'Basic ruby client library and command line interface for accessing Trac instances via its XML RPC API'
|
26
|
+
s.authors = ['Niklas Cathro','David Copeland']
|
27
|
+
s.add_dependency('rainbow', '>= 1.0.4')
|
28
|
+
s.add_dependency('gli', '>= 1.1.0')
|
29
|
+
s.has_rdoc = true
|
30
|
+
s.extra_rdoc_files = ['README.rdoc']
|
31
|
+
s.rdoc_options << '--title' << 'trac4r Trac Ruby Client' << '--main' << 'README.rdoc' << '-ri'
|
32
|
+
s.require_paths << 'lib'
|
33
|
+
end
|
34
|
+
Jeweler::GemcutterTasks.new
|
35
|
+
rescue LoadError
|
36
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::RDocTask.new do |rd|
|
40
|
+
rd.main = "README.rdoc"
|
41
|
+
rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
|
42
|
+
rd.title = 'Ruby interface to Trac'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
task :publish_rdoc => [:rdoc,:publish]
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.1
|
data/bin/trac
ADDED
@@ -0,0 +1,289 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
|
3
|
+
require 'rubygems'
|
4
|
+
require 'gli'
|
5
|
+
require 'trac4r'
|
6
|
+
require 'rainbow'
|
7
|
+
require 'cgi'
|
8
|
+
|
9
|
+
include GLI
|
10
|
+
|
11
|
+
OPENER_DEFAULT = RUBY_PLATFORM =~ /darwin/ ? 'open' : nil
|
12
|
+
begin
|
13
|
+
# TODO: Figure out a better way to do this
|
14
|
+
cols = `stty -a | grep "columns;" | head -1`.split(/;/)
|
15
|
+
COLUMNS_DEFAULT = cols[2].gsub(' columns','')
|
16
|
+
rescue
|
17
|
+
COLUMNS_DEFAULT = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
config_file '.trac4r'
|
21
|
+
|
22
|
+
desc 'Command to use to open URLs'
|
23
|
+
default_value OPENER_DEFAULT
|
24
|
+
flag [:o,:open]
|
25
|
+
|
26
|
+
desc 'URL to trac'
|
27
|
+
flag [:url]
|
28
|
+
|
29
|
+
desc 'Your username'
|
30
|
+
flag [:u,:user]
|
31
|
+
|
32
|
+
desc 'Your password'
|
33
|
+
flag [:p,:password]
|
34
|
+
|
35
|
+
desc 'Do not format output'
|
36
|
+
long_desc 'By default, the output is formatted fo readability in the terminal. By disabling this, the output is more "machine readable" and parsable by other scripts'
|
37
|
+
switch [:noformat]
|
38
|
+
|
39
|
+
desc 'number of columns for formatting'
|
40
|
+
default_value COLUMNS_DEFAULT
|
41
|
+
flag [:cols]
|
42
|
+
|
43
|
+
desc 'Open the ticket or wiki page'
|
44
|
+
arg_name 'the id of the ticket or name of wiki page'
|
45
|
+
command :open do |c|
|
46
|
+
c.action do |global_options,options,args|
|
47
|
+
raise "You must supply a ticket ID or WikiName" if args.empty?
|
48
|
+
id = args[0]
|
49
|
+
if id =~ /^\d+$/
|
50
|
+
system "#{global_options[:o]} #{$url}/ticket/#{id}"
|
51
|
+
else
|
52
|
+
system "#{global_options[:o]} #{$url}/wiki/#{args.map{ |x| x[0..0].upcase + x[1..-1]}.join('')}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc 'Go to the new ticket web interface'
|
58
|
+
long_desc 'Navigates your browser to the web interface, initialized with the values you provide, but does not actually create the ticket'
|
59
|
+
arg_name 'summary for the ticket'
|
60
|
+
command [:newticket] do |c|
|
61
|
+
c.desc 'component'
|
62
|
+
c.flag [:c,:component]
|
63
|
+
|
64
|
+
c.desc 'type'
|
65
|
+
c.flag [:t,:type]
|
66
|
+
|
67
|
+
c.desc 'priority'
|
68
|
+
c.flag [:p,:priority]
|
69
|
+
|
70
|
+
c.action do |global_options,options,args|
|
71
|
+
query_params = {}
|
72
|
+
query_params['priority'] = options[:p] if options[:p]
|
73
|
+
query_params['component'] = options[:c] if options[:c]
|
74
|
+
query_params['type'] = options[:t] if options[:t]
|
75
|
+
query_params['summary'] = args.join(' ')
|
76
|
+
query_string = ''
|
77
|
+
query_params.each do |key,value|
|
78
|
+
query_string += key
|
79
|
+
query_string += '='
|
80
|
+
query_string += CGI.escape(value)
|
81
|
+
query_string += '&'
|
82
|
+
end
|
83
|
+
|
84
|
+
url = $url.gsub(/\/xmlrpc/,'') + '/newticket?' + query_string
|
85
|
+
system "#{global_options[:o]} \"#{url}\""
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
FORMATTING = {
|
90
|
+
'id' => { :color => :green, :size => 6 },
|
91
|
+
'status' => { :color => :cyan, :size => 9 },
|
92
|
+
'owner' => { :size => 17 },
|
93
|
+
'component' => { :size => 10, :color => :magenta },
|
94
|
+
'milestone' => { :size => 28, :color => :cyan },
|
95
|
+
}
|
96
|
+
desc 'Lists tickets'
|
97
|
+
arg_name 'ticket ids (blank for all)'
|
98
|
+
command [:tickets,:ls] do |c|
|
99
|
+
c.desc 'Show tickets accepted'
|
100
|
+
c.switch [:a,:accepted]
|
101
|
+
|
102
|
+
c.desc 'Component'
|
103
|
+
c.flag [:c,:component]
|
104
|
+
|
105
|
+
c.desc 'Show full description'
|
106
|
+
c.switch [:l,:description]
|
107
|
+
|
108
|
+
c.desc 'Arbitrary query (flags are included, too)'
|
109
|
+
c.flag [:q,:query]
|
110
|
+
|
111
|
+
c.desc 'Owner ("ME" for the -u user)'
|
112
|
+
c.flag [:o,:owner]
|
113
|
+
|
114
|
+
c.desc 'Columns to show'
|
115
|
+
c.long_desc 'comma-delimited list of the column names from the tickets to show in the output'
|
116
|
+
c.flag [:columns]
|
117
|
+
|
118
|
+
c.action do |global_options,options,args|
|
119
|
+
opts = {}
|
120
|
+
|
121
|
+
if options[:q]
|
122
|
+
raise "bad query" if options[:q] =~ /\}/
|
123
|
+
opts = instance_eval('{' + options[:q] + '}')
|
124
|
+
else
|
125
|
+
opts[:owner] = options[:o]
|
126
|
+
opts[:owner] = global_options[:u] if options[:o] == "ME"
|
127
|
+
if options[:a]
|
128
|
+
opts[:status] = :accepted
|
129
|
+
else
|
130
|
+
opts[:status] = ["!closed","testing"]
|
131
|
+
end
|
132
|
+
opts[:component] = options[:c] if options[:c]
|
133
|
+
end
|
134
|
+
ids = args
|
135
|
+
ids = $trac.tickets.query(opts) if ids.empty?
|
136
|
+
tickets = ids.map{ |id| $trac.tickets.get(id) }
|
137
|
+
tickets.sort{ |a,b| a.summary.downcase <=> b.summary.downcase }.each do |ticket|
|
138
|
+
if global_options[:noformat]
|
139
|
+
puts [ticket.id,ticket.status,ticket.owner,ticket.summary].join("\t")
|
140
|
+
else
|
141
|
+
columns = options[:columns]
|
142
|
+
columns = 'id,status,owner,summary' if !columns
|
143
|
+
columns = columns.split(/,/)
|
144
|
+
printf_string = ""
|
145
|
+
padding = 0
|
146
|
+
args = []
|
147
|
+
columns.each do |col|
|
148
|
+
if col != 'summary'
|
149
|
+
size = FORMATTING[col] && FORMATTING[col][:size]
|
150
|
+
size = 10 if !size
|
151
|
+
padding += size == "" ? 3 : (size.to_i + 3)
|
152
|
+
size += 9 if size && FORMATTING[col] && FORMATTING[col][:color]
|
153
|
+
printf_string += "%#{size}s - "
|
154
|
+
if FORMATTING[col] && FORMATTING[col][:color]
|
155
|
+
args << ticket.send(col.to_sym).to_s.color(FORMATTING[col][:color])
|
156
|
+
else
|
157
|
+
args << ticket.send(col.to_sym).to_s
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
printf_string.gsub!(/ - $/,'')
|
162
|
+
if columns.include? 'summary'
|
163
|
+
args << wrap(ticket.summary,padding+1,global_options[:cols])
|
164
|
+
printf_string += " - %s"
|
165
|
+
end
|
166
|
+
printf("#{printf_string}\n",*args)
|
167
|
+
end
|
168
|
+
if (options[:l])
|
169
|
+
description = ticket.description
|
170
|
+
if !global_options[:noformat]
|
171
|
+
description = bold(description)
|
172
|
+
description = italic(description)
|
173
|
+
description = code(description)
|
174
|
+
end
|
175
|
+
puts
|
176
|
+
puts "#{description}"
|
177
|
+
puts "----"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Not sure about this
|
184
|
+
def wrap(string,indent,cols)
|
185
|
+
cols_left = cols.to_i - indent
|
186
|
+
raise "Your terminal is too small for formatting" if (cols_left < 5)
|
187
|
+
return_me = ""
|
188
|
+
line = ""
|
189
|
+
prev_word = ""
|
190
|
+
string.split(/\s/).each do |word|
|
191
|
+
if line.length <= cols_left
|
192
|
+
line += " #{word}" if line != ""
|
193
|
+
line += "#{word}" if line == ""
|
194
|
+
prev_word = word
|
195
|
+
else
|
196
|
+
line.gsub!(/#{prev_word}$/,'')
|
197
|
+
return_me += line.underline + "\n"
|
198
|
+
indent.times { return_me += " " }
|
199
|
+
line = prev_word
|
200
|
+
end
|
201
|
+
end
|
202
|
+
if (line.length > cols_left)
|
203
|
+
line.gsub!(/#{prev_word}$/,'')
|
204
|
+
return_me += line.underline + "\n"
|
205
|
+
indent.times { return_me += " " }
|
206
|
+
line = prev_word
|
207
|
+
end
|
208
|
+
return_me += line.underline
|
209
|
+
return_me.gsub(/^\s/,'')
|
210
|
+
end
|
211
|
+
|
212
|
+
def bold(string)
|
213
|
+
desc = string.split("'''")
|
214
|
+
description = ""
|
215
|
+
bold = false
|
216
|
+
desc.each do |part|
|
217
|
+
description << part.bright.foreground(:cyan) if bold
|
218
|
+
description << part.reset if !bold
|
219
|
+
bold = !bold
|
220
|
+
end
|
221
|
+
description
|
222
|
+
end
|
223
|
+
|
224
|
+
def italic(string)
|
225
|
+
desc = string.split("''")
|
226
|
+
description = ""
|
227
|
+
bold = false
|
228
|
+
desc.each do |part|
|
229
|
+
description << part.italic.foreground(:magenta) if bold
|
230
|
+
description << part.reset if !bold
|
231
|
+
bold = !bold
|
232
|
+
end
|
233
|
+
description
|
234
|
+
end
|
235
|
+
|
236
|
+
def code(string)
|
237
|
+
desc = string.split("`")
|
238
|
+
description = ""
|
239
|
+
bold = false
|
240
|
+
desc.each do |part|
|
241
|
+
description << part.bright.foreground(:green) if bold
|
242
|
+
description << part.reset if !bold
|
243
|
+
bold = !bold
|
244
|
+
end
|
245
|
+
in_code = false
|
246
|
+
coded = ''
|
247
|
+
description.split(/\n/).each do |line|
|
248
|
+
ignore = false
|
249
|
+
if line =~ /^\{\{\{\s*$/
|
250
|
+
in_code = true
|
251
|
+
ignore = true
|
252
|
+
elsif line =~ /^\}\}\}/
|
253
|
+
in_code = false
|
254
|
+
ignore = true
|
255
|
+
end
|
256
|
+
if !ignore
|
257
|
+
if in_code
|
258
|
+
coded += line.bright.foreground(:green)
|
259
|
+
else
|
260
|
+
coded += line
|
261
|
+
end
|
262
|
+
end
|
263
|
+
coded += "\n"
|
264
|
+
end
|
265
|
+
coded
|
266
|
+
end
|
267
|
+
|
268
|
+
pre do |global,command,options,args|
|
269
|
+
if command.nil? || command.name == :help
|
270
|
+
# not creating a trac instance
|
271
|
+
else
|
272
|
+
$url = global[:url]
|
273
|
+
raise "You must specify a URL" if $url.nil?
|
274
|
+
$trac = Trac.new($url,global[:u],global[:p])
|
275
|
+
end
|
276
|
+
true
|
277
|
+
end
|
278
|
+
|
279
|
+
post do |global,command,options,args|
|
280
|
+
# Post logic here
|
281
|
+
end
|
282
|
+
|
283
|
+
on_error do |exception|
|
284
|
+
# Error logic here
|
285
|
+
# return false to skip default error handling
|
286
|
+
true
|
287
|
+
end
|
288
|
+
|
289
|
+
GLI.run(ARGV)
|
data/lib/trac4r/error.rb
CHANGED
@@ -8,22 +8,28 @@ module Trac
|
|
8
8
|
# [+path+] the path to the Trac API
|
9
9
|
# [+method+] the XML RPC method being called
|
10
10
|
# [+args+] the args (as an array) that were sent with the call
|
11
|
-
|
12
|
-
|
13
|
-
if http_error =~
|
14
|
-
http_error.
|
11
|
+
# [+exception+] the exception that was caught
|
12
|
+
def initialize(http_error,host,port,path,method,args,exception)
|
13
|
+
if (http_error =~ /HTTP-Error: /)
|
14
|
+
http_error = http_error.sub 'HTTP-Error: ',''
|
15
|
+
if http_error =~ /\n/
|
16
|
+
http_error.split(/\n/).each do |line|
|
15
17
|
if line =~ /^\d\d\d/
|
16
18
|
http_error = line
|
17
19
|
break
|
18
20
|
end
|
21
|
+
end
|
19
22
|
end
|
23
|
+
@http_status,@http_message = http_error.split(/\s+/,2)
|
24
|
+
else
|
25
|
+
@http_message = http_error
|
20
26
|
end
|
21
|
-
@http_status,@http_message = http_error.split(/\s+/,2)
|
22
27
|
@host = host
|
23
28
|
@port = port
|
24
29
|
@path = path
|
25
30
|
@method = method
|
26
31
|
@args = args
|
32
|
+
@exception = exception
|
27
33
|
end
|
28
34
|
|
29
35
|
# Gives a more useful message for common problems
|
@@ -32,8 +38,10 @@ module Trac
|
|
32
38
|
"Couldn't find Trac API at #{url}, check your configuration"
|
33
39
|
elsif @http_status == '401'
|
34
40
|
"Your username/password didn't authenticate, check your configuration"
|
41
|
+
elsif @http_status
|
42
|
+
"#{@http_message} (#{@http_status}) when trying URL #{url} and method #{@method}(#{@args.join('.')})"
|
35
43
|
else
|
36
|
-
"#{@http_message}
|
44
|
+
"#{@http_message} when trying URL #{url} and method #{@method}(#{@args.join('.')})"
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
data/lib/trac4r/query.rb
CHANGED
@@ -50,11 +50,7 @@ module Trac
|
|
50
50
|
begin
|
51
51
|
return @connection.call(command,*args)
|
52
52
|
rescue => e
|
53
|
-
|
54
|
-
raise TracException.new(e.message,@host,@port,@path,command,args)
|
55
|
-
else
|
56
|
-
raise
|
57
|
-
end
|
53
|
+
raise TracException.new(e.message,@host,@port,@path,command,args,e)
|
58
54
|
end
|
59
55
|
end
|
60
56
|
end
|
data/lib/trac4r/ticket.rb
CHANGED
@@ -36,10 +36,17 @@ module Trac
|
|
36
36
|
# we return its value. e.g. if our tickets have a custom field
|
37
37
|
# called +work_units+, then +some_ticket.work_units+ will
|
38
38
|
# retrieve that value. This currently only allows retrieval and
|
39
|
-
# not updating the value.
|
39
|
+
# not updating the value. Also note that you can retrieve a custom
|
40
|
+
# field using "!" and this will silently return nil if the instance
|
41
|
+
# variable didn't exist. This is useful if some tickets just don't
|
42
|
+
# have the custom field, but you don't wish to check for it
|
40
43
|
def method_missing(sym,*args)
|
44
|
+
method = sym.to_s
|
45
|
+
method = method[0..-2] if method =~ /!$/
|
41
46
|
if args.size == 0 && instance_variables.include?("@" + sym.to_s)
|
42
47
|
instance_eval("@" + sym.to_s)
|
48
|
+
elsif method != sym.to_s
|
49
|
+
nil
|
43
50
|
else
|
44
51
|
super.method_missing(sym,args)
|
45
52
|
end
|
data/lib/trac4r/tickets.rb
CHANGED
@@ -34,15 +34,25 @@ module Trac
|
|
34
34
|
# list :include_closed => false
|
35
35
|
# to only get open tickets.
|
36
36
|
def list options={ }
|
37
|
-
include_closed =
|
38
|
-
|
39
|
-
tickets
|
37
|
+
include_closed = true
|
38
|
+
include_closed = options[:include_closed] if !options[:include_closed].nil?
|
39
|
+
tickets = query(:status => "!closed")
|
40
|
+
tickets += query(:status => "closed") if include_closed
|
40
41
|
return tickets
|
41
42
|
end
|
42
|
-
|
43
|
+
|
44
|
+
# Run an arbitrary ticket query
|
45
|
+
# [+args+] a hash of options, each should use a symbol or string
|
46
|
+
# as the key and a symbol/string or array of symbols/strings as the value. If the
|
47
|
+
# value starts with a +!+, it will be treated as a not equal.
|
48
|
+
# Multiple values mean "or", as in any value may match
|
49
|
+
def query(args)
|
50
|
+
@trac.query("ticket.query",args_to_trac_args(args))
|
51
|
+
end
|
52
|
+
|
43
53
|
# like `list', but only gets closed tickets
|
44
54
|
def list_closed
|
45
|
-
|
55
|
+
query(:status => "closed")
|
46
56
|
end
|
47
57
|
|
48
58
|
# returns all tickets (not just the ids) in a hash
|
@@ -155,5 +165,17 @@ module Trac
|
|
155
165
|
end
|
156
166
|
return @settings
|
157
167
|
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def args_to_trac_args(args)
|
172
|
+
trac_args = []
|
173
|
+
args.each do |key,value|
|
174
|
+
value = [value].flatten.map{ |x| x.to_s }.join('|')
|
175
|
+
trac_args << key.to_s + (value =~ /^!/ ? "!=#{value[1..-1]}" : "=#{value}")
|
176
|
+
end
|
177
|
+
trac_args.join('&')
|
178
|
+
end
|
179
|
+
|
158
180
|
end
|
159
181
|
end
|
data/lib/trac4r/wiki.rb
CHANGED
@@ -44,6 +44,11 @@ module Trac
|
|
44
44
|
@trac.query('wiki.getPageHTML',name)
|
45
45
|
end
|
46
46
|
|
47
|
+
# returns a whole page in HTML
|
48
|
+
def get_info name
|
49
|
+
@trac.query('wiki.getPageInfo',name)
|
50
|
+
end
|
51
|
+
|
47
52
|
# returns a whole page in raw format
|
48
53
|
def get_raw name
|
49
54
|
@trac.query('wiki.getPage',name)
|
data/lib/trac4r.rb
CHANGED
@@ -64,13 +64,19 @@ module Trac
|
|
64
64
|
def initialize url,user,pass
|
65
65
|
@user = user
|
66
66
|
@pass = pass
|
67
|
-
|
68
|
-
|
67
|
+
@url = url
|
68
|
+
@url.gsub!(/\/$/,'')
|
69
|
+
if @url.split('/').last != 'xmlrpc'
|
70
|
+
@url = url+'/xmlrpc'
|
69
71
|
end
|
70
|
-
|
72
|
+
@connection = Query.new(@url,@user,@pass)
|
71
73
|
@wiki = Wiki.new(@connection)
|
72
74
|
@tickets = Tickets.new(@connection)
|
73
75
|
end
|
76
|
+
|
77
|
+
def query(command,*args)
|
78
|
+
@connection.query(command,*args)
|
79
|
+
end
|
74
80
|
|
75
81
|
def api_version
|
76
82
|
@connection.query("system.getAPIVersion")
|
metadata
CHANGED
@@ -1,40 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trac4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Niklas Cathro
|
8
|
+
- David Copeland
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
date: 2010-01-03 00:00:00 -05:00
|
14
|
+
default_executable: trac
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rainbow
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.0.4
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: gli
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.1.0
|
35
|
+
version:
|
36
|
+
description: Basic ruby client library and command line interface for accessing Trac instances via its XML RPC API
|
37
|
+
email: davidcopeland@naildrivin5.com
|
38
|
+
executables:
|
39
|
+
- trac
|
20
40
|
extensions: []
|
21
41
|
|
22
42
|
extra_rdoc_files:
|
23
43
|
- README.rdoc
|
24
44
|
files:
|
45
|
+
- .gitignore
|
46
|
+
- LICENCE
|
47
|
+
- README.rdoc
|
48
|
+
- Rakefile
|
49
|
+
- VERSION
|
50
|
+
- bin/trac
|
51
|
+
- lib/trac4r.rb
|
25
52
|
- lib/trac4r/error.rb
|
26
53
|
- lib/trac4r/query.rb
|
27
54
|
- lib/trac4r/ticket.rb
|
28
55
|
- lib/trac4r/tickets.rb
|
29
56
|
- lib/trac4r/wiki.rb
|
30
|
-
- lib/trac4r.rb
|
31
|
-
- README.rdoc
|
32
57
|
has_rdoc: true
|
33
|
-
homepage:
|
58
|
+
homepage:
|
34
59
|
licenses: []
|
35
60
|
|
36
61
|
post_install_message:
|
37
62
|
rdoc_options:
|
63
|
+
- --charset=UTF-8
|
38
64
|
- --title
|
39
65
|
- trac4r Trac Ruby Client
|
40
66
|
- --main
|
@@ -43,6 +69,7 @@ rdoc_options:
|
|
43
69
|
require_paths:
|
44
70
|
- lib
|
45
71
|
- lib
|
72
|
+
- lib
|
46
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
47
74
|
requirements:
|
48
75
|
- - ">="
|
@@ -57,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
84
|
version:
|
58
85
|
requirements: []
|
59
86
|
|
60
|
-
rubyforge_project:
|
87
|
+
rubyforge_project:
|
61
88
|
rubygems_version: 1.3.5
|
62
89
|
signing_key:
|
63
90
|
specification_version: 3
|