rtrac 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2007-11-25
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,14 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/rtrac
6
+ lib/rtrac.rb
7
+ lib/rtrac/util.rb
8
+ lib/rtrac/base.rb
9
+ lib/rtrac/ticket.rb
10
+ test/test_helper.rb
11
+ test/test_rtrac.rb
12
+ test/test_base.rb
13
+ test/test_ticket.rb
14
+ test/test_rtrac.rb
data/README.txt ADDED
@@ -0,0 +1,54 @@
1
+ rtrac
2
+ by Josh Stephenson
3
+ http://rtrac.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Trac API wrappers
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Ticket access for Trac
12
+
13
+ == SYNOPSIS:
14
+
15
+ Rtrac::Base.get_by_milestone(milestone).each do |id|
16
+ # grab the ticket's data
17
+ tick = Rtrac::Ticket.new(id)
18
+ iteration_hash[:total] += tick.severity.to_i
19
+ iteration_hash[:tickets] << {:id => id, :points => tick.severity.to_i, :status => tick.status, :updated_at =>Time.parse(tick.updated_at.to_s)}
20
+ end
21
+
22
+ == REQUIREMENTS:
23
+
24
+ active_support
25
+ hoe
26
+
27
+ == INSTALL:
28
+
29
+ sudo gem install rtrac
30
+
31
+ == LICENSE:
32
+
33
+ (The MIT License)
34
+
35
+ Copyright (c) 2007 Josh Stephenson
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining
38
+ a copy of this software and associated documentation files (the
39
+ 'Software'), to deal in the Software without restriction, including
40
+ without limitation the rights to use, copy, modify, merge, publish,
41
+ distribute, sublicense, and/or sell copies of the Software, and to
42
+ permit persons to whom the Software is furnished to do so, subject to
43
+ the following conditions:
44
+
45
+ The above copyright notice and this permission notice shall be
46
+ included in all copies or substantial portions of the Software.
47
+
48
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
49
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
52
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
53
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
54
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require './lib/rtrac.rb'
4
+
5
+ Hoe.new('rtrac', Rtrac::Config.version) do |p|
6
+ p.rubyforge_name = 'rtrac'
7
+ p.author = 'Josh Stephenson'
8
+ p.email = 'josh@elctech.com'
9
+ p.summary = 'Trac wrapper with command line tool'
10
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
11
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
12
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
13
+ end
14
+
15
+ # vim: syntax=Ruby
data/bin/rtrac ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'rtrac'
5
+ require 'rtrac/util'
6
+
7
+ Rtrac::Util.run!
data/lib/rtrac.rb ADDED
@@ -0,0 +1,15 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ module Rtrac
3
+ class Config
4
+ def self.version
5
+ '1.0.1'
6
+ end
7
+ end
8
+ end
9
+ require 'rubygems'
10
+ require 'yaml'
11
+ require 'active_support'
12
+ require 'xmlrpc/client'
13
+ require 'rtrac/base'
14
+ require 'rtrac/ticket'
15
+ require 'rtrac/util'
data/lib/rtrac/base.rb ADDED
@@ -0,0 +1,190 @@
1
+ module Rtrac
2
+ class Base
3
+
4
+ cattr_accessor :connection, :config
5
+
6
+ class << self
7
+ # handles the sending of queries to Trac with exception handling
8
+ def send_query(*args)
9
+ begin
10
+ connection.call(*args)
11
+ rescue
12
+ # print a standard error
13
+ logger.error "Error connecting to Trac API"
14
+ if logger.level > Logger::INFO
15
+ logger.error $@
16
+ end
17
+ exit
18
+ end
19
+ end
20
+
21
+ def connection
22
+ @connection ||= self.open_connection
23
+ end
24
+
25
+ # list all methods supported by the trac api
26
+ def list_methods
27
+ send_query('system.listMethods')
28
+ end
29
+
30
+ def custom(*args)
31
+ send_query(*args)
32
+ end
33
+
34
+ def get_by_milestone(milestone)
35
+ send_query('ticket.query', "milestone=#{milestone.strip}")
36
+ end
37
+
38
+ # returns method help
39
+ def method_help(method)
40
+ send_query('system.methodHelp', method)
41
+ end
42
+
43
+ # Returns an array of ticket ids
44
+ # Valid order types include:
45
+ def get_tickets(count, order = :priority)
46
+ extract_account_info
47
+ order = :priority unless columns.include?(order)
48
+ send_query('ticket.query', "order=#{order.to_s}")[0,count].collect{ |id| id }
49
+ end
50
+
51
+ #:stopdoc:
52
+ def open_connection
53
+ if (options = extract_account_info)
54
+ @username, @password, @url = options
55
+ uri = URI.parse @url
56
+ #puts "Connecting to \"#{@url}\" using username \"#{@username}\" and password \"#{@password}\""
57
+ @connection = XMLRPC::Client.new3(:host => uri.host, :path => "#{uri.path}/login/xmlrpc", :user => @username, :password => @password, :use_ssl => true)
58
+ end
59
+ end
60
+
61
+ def extract_account_info
62
+ username = password = url = columns = nil
63
+ configuration_options.each do |key, value|
64
+ if key.to_sym == :username
65
+ username = value.to_s
66
+ elsif key.to_sym == :password
67
+ password = value.to_s
68
+ elsif key.to_sym == :url
69
+ url = value.to_s
70
+ elsif key.to_sym == :columns
71
+ @columns = value.to_a
72
+ end
73
+ end
74
+ if invalid_config?(username, password, url, @columns)
75
+ logger.error "Invalid configuration options. Please edit your #{config_path} file accordingly."
76
+ return false
77
+ end
78
+ [username, password, url, @columns]
79
+ end
80
+
81
+ def configuration_options
82
+ return @configuration_options unless @configuration_options.nil?
83
+ if self.config.nil?
84
+ @configuration_options = find_or_create_config
85
+ else
86
+ if File.exist?(config)
87
+ @configuration_options = YAML::load(open(config))
88
+ end
89
+ end
90
+ @configuration_options
91
+ end
92
+
93
+ def invalid_config?(username, password, url, columns)
94
+ username.empty? || password.empty? || columns.empty? || ![url =~ /^http(s|):\/\/.+/i].any?
95
+ end
96
+
97
+ def columns
98
+ extract_account_info
99
+ @columns ||= required_columns + optional_columns
100
+ end
101
+
102
+ def required_columns
103
+ extract_account_info
104
+ @configuration_options["columns"]["required"]
105
+ end
106
+
107
+ def optional_columns
108
+ extract_account_info
109
+ @configuration_options["columns"]["optional"]
110
+ end
111
+
112
+ def find_or_create_config
113
+ begin
114
+ config = YAML::load(open(config_path))
115
+ rescue
116
+ create_new_config
117
+ end
118
+ config
119
+ end
120
+
121
+ def home_dir
122
+ ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
123
+ end
124
+
125
+ def config_path
126
+ if RAILS_ROOT
127
+ File.join(RAILS_ROOT, 'config', Rtrac::Configuration.options[:config_filename])
128
+ else
129
+ File.join(home_dir, ".#{Rtrac::Configuration.options[:config_filename]}") # hide it if it goes in home
130
+ end
131
+ end
132
+
133
+ def create_new_config
134
+ file = File.open(config_path, "w+")
135
+ file.write(Rtrac::Configuration.options[:default_config_file])
136
+ file.flush
137
+ file.close
138
+ logger.info "No config file found in #{home_dir}
139
+ A new one has been created. Please edit it before continuing
140
+ #{config_path}
141
+ "
142
+ exit
143
+ end
144
+
145
+ def logger
146
+ if @logger.nil?
147
+ @logger = Logger.new(STDERR)
148
+ @logger.level = Logger::INFO
149
+ end
150
+ @logger
151
+ end
152
+ #:start_doc:
153
+ end
154
+ end
155
+ class Configuration
156
+ class << self
157
+ def options
158
+ {:default_config_file => default_config_file, :config_filename => 'rtrac.yml'}
159
+ end
160
+
161
+ def default_config_file
162
+ default_config_file=<<CONFIG
163
+ username:
164
+ password:
165
+ url:
166
+ columns:
167
+ required:
168
+ - :summary
169
+ - :description
170
+ optional:
171
+ - :type
172
+ - :time
173
+ - :changetime
174
+ - :component
175
+ - :severity
176
+ - :priority
177
+ - :owner
178
+ - :reporter
179
+ - :cc
180
+ - :version
181
+ - :milestone
182
+ - :status
183
+ - :resolution
184
+ - :keywords
185
+ CONFIG
186
+ default_config_file
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,96 @@
1
+ module Rtrac
2
+ class TicketError < StandardError; end
3
+ class Ticket < Rtrac::Base
4
+
5
+ attr_accessor :trac_id
6
+
7
+ def initialize(trac_id, logger = nil)
8
+ @logger = logger
9
+ @trac_id = trac_id
10
+ end
11
+
12
+ def created_at
13
+ Time.at(ticket_attributes[1].to_i)
14
+ end
15
+
16
+ def updated_at
17
+ Time.at(+ticket_attributes[2].to_i)
18
+ end
19
+
20
+ def attributes
21
+ extended_attributes = ticket_attributes[3].symbolize_keys!
22
+ {:id => ticket_attributes[0], :created_at => ticket_attributes[1], :updated_at => ticket_attributes[2]}.merge(extended_attributes)
23
+ end
24
+
25
+ def attributes=(attributes)
26
+ @ticket_attributes = attributes
27
+ end
28
+
29
+ # ticket description
30
+ def description
31
+ method_missing(:description)
32
+ end
33
+ alias_method :body, :description
34
+
35
+ # ticket summary
36
+ def summary
37
+ method_missing(:summary)
38
+ end
39
+ alias_method :title, :summary
40
+
41
+ # update a ticket with a comment and attributes
42
+ def update(comment, attributes = {})
43
+ sendable_attributes = attributes
44
+ sendable_attributes.delete(:created_at) && sendable_attributes.delete(:updated_at)
45
+ self.class.send_query('ticket.update', @trac_id, comment, sendable_attributes)
46
+ end
47
+
48
+ # create a new ticket
49
+ def self.create(title, description, attributes = {})
50
+ send_query('ticket.create', title, description, attributes)
51
+ end
52
+
53
+ # delete a ticket forever
54
+ def self.destroy(trac_id)
55
+ send_query('ticket.delete', trac_id)
56
+ end
57
+
58
+ def to_s
59
+ "#{summary}"
60
+ end
61
+
62
+ protected
63
+
64
+ def method_missing(method)
65
+ if attributes.has_key?(method)
66
+ attributes[method]
67
+ else
68
+ logger.debug "No attribute found for #{method}"
69
+ end
70
+ end
71
+
72
+ # returns a hash of ticket attributes
73
+ def get
74
+ self.class.send_query('ticket.get', @trac_id)
75
+ end
76
+
77
+ def ticket_attributes
78
+ @ticket_attributes ||= get
79
+ end
80
+
81
+ def logger
82
+ @logger ||= Logger.new(STDERR)
83
+ end
84
+ end
85
+ end
86
+ class Hash
87
+ def symbolize_keys!
88
+ keys.each do |key|
89
+ unless key.is_a?(Symbol) || (new_key = key.to_sym).nil?
90
+ self[new_key] = self[key]
91
+ delete(key)
92
+ end
93
+ end
94
+ self
95
+ end
96
+ end
data/lib/rtrac/util.rb ADDED
@@ -0,0 +1,165 @@
1
+ module Rtrac
2
+ class Util < Rtrac::Base
3
+ VALID_COMMANDS = [:list, :show, :update, :delete, :create]
4
+
5
+ class << self
6
+ def run!
7
+ if ARGV.include?('--debug')
8
+ @logger = Logger.new(STDERR)
9
+ @logger.level = Logger::DEBUG
10
+ ARGV.delete('--debug')
11
+ end
12
+ command = ARGV.shift
13
+ if command.nil?
14
+ usage
15
+ else
16
+ case command.to_sym
17
+ when :list
18
+ list(ARGV.shift, ARGV.shift)
19
+ when :show
20
+ show(ARGV.shift)
21
+ when :update
22
+ update(ARGV.shift)
23
+ when :delete
24
+ delete(ARGV.shift)
25
+ when :close
26
+ close(ARGV.shift)
27
+ when :create
28
+ create
29
+ else
30
+ usage
31
+ end
32
+ end
33
+ end
34
+
35
+ def list(count, order = 'priority')
36
+ Rtrac::Base.get_tickets(count.to_i, order).each do |id|
37
+ tick = Rtrac::Ticket.new(id)
38
+ keys = tick.attributes.keys.reject{|k| k == :id || k == :type }
39
+
40
+ keys.each do |key|
41
+ puts "#{key.to_s[0,16].rjust(16, ' ')}: #{tick.send(key).to_s[0,60].rjust(60, ' ')}"
42
+ end
43
+ puts ""
44
+ end
45
+ end
46
+
47
+ def show(id)
48
+ usage if id.nil?
49
+ tick = get_ticket(id)
50
+ display(tick)
51
+ end
52
+
53
+ def delete(id)
54
+ if(Rtrac::Ticket.destroy(id)).to_i.zero?
55
+ puts 'Deleted'
56
+ else
57
+ puts 'Error deleting ticket.'
58
+ end
59
+ end
60
+
61
+ def create
62
+ required_attributes = {}
63
+ optional_attributes = {}
64
+ read_required_attributes(required_attributes)
65
+ read_optional_attributes(optional_attributes)
66
+ required_attributes = required_attributes.values
67
+ puts Rtrac::Ticket.create(required_attributes.shift, required_attributes.shift, optional_attributes)
68
+ end
69
+
70
+ def update(id)
71
+ tick = get_ticket(id)
72
+ all_attributes = tick.attributes
73
+ read_optional_attributes(all_attributes, true)
74
+ comment = read_value(:comment)
75
+ resp = tick.update(comment, all_attributes)
76
+ # tick.attributes = all_attributes
77
+ # display(tick)
78
+ end
79
+
80
+ def read_required_attributes(attribute_hash)
81
+ self.required_columns.each do |attr|
82
+ while attribute_hash[attr].nil?
83
+ puts "#{attr.to_s.capitalize}: "
84
+ value = STDIN.readline
85
+ attribute_hash[attr] = value
86
+ end
87
+ end
88
+ end
89
+
90
+ def read_optional_attributes(attribute_hash, conflate = false)
91
+ cols = conflate ? self.required_columns + self.optional_columns : self.optional_columns
92
+ display_menu(attribute_hash, cols)
93
+ until (num = STDIN.readline.strip).empty?
94
+ num = num.to_i
95
+ attribute = cols[num-1]
96
+ attribute_hash[cols[num-1]] = read_value(attribute)
97
+ display_menu(attribute_hash, cols)
98
+ end
99
+ end
100
+
101
+ def read_value(attribute)
102
+ puts "#{attribute.to_s.capitalize}: "
103
+ STDIN.readline.strip
104
+ end
105
+
106
+ def display_menu(attribute_hash, cols)
107
+ puts "Enter the number of an attribute to fill in or <Enter> to submit"
108
+ cols.each_with_index do |attr, idx|
109
+ puts "#{idx+1}. #{attr.to_s.capitalize} => #{attribute_hash[attr]}"
110
+ end
111
+ puts ""
112
+ end
113
+
114
+ def close(id, comment = nil)
115
+ raise NotImplementedError
116
+ end
117
+
118
+ def get_ticket(id)
119
+ @tick ||= Rtrac::Ticket.new(id, @logger)
120
+ end
121
+
122
+ def display(tick)
123
+ if tick.is_a?(Rtrac::Ticket)
124
+ display_ticket(tick)
125
+ else
126
+ display_ticket_from_hash(tick)
127
+ end
128
+ end
129
+
130
+ def display_ticket(tick)
131
+ # reject #id and #type or ruby will choke!
132
+ keys = tick.attributes.keys.reject{|k| k == :id || k == :type }
133
+
134
+ keys.each do |key|
135
+ # we'll send the method to the ticket so dates are parsed
136
+ puts "#{key.to_s[0,16].rjust(16, ' ')}: #{tick.send(key).to_s[0,60].rjust(60, ' ')}"
137
+ end
138
+ end
139
+
140
+ def display_ticket_from_hash(attributes)
141
+ # reject #id and #type or ruby will choke!
142
+ keys = attributes.keys.reject{|k| k == :id || k == :type }
143
+
144
+ keys.each do |key|
145
+ # we'll send the method to the ticket so dates are parsed
146
+ puts "#{key.to_s[0,16].rjust(16, ' ')}: #{tick.attributes[key].to_s[0,60].rjust(60, ' ')}"
147
+ end
148
+ end
149
+
150
+ def usage
151
+ usage=<<USAGE
152
+ rtrac COMMAND [OPTIONS]
153
+ COMMANDS:
154
+ list [COUNT] [PRIORITY]
155
+ show ID
156
+ create
157
+ update ID
158
+ delete ID
159
+ USAGE
160
+ puts usage
161
+ exit
162
+ end
163
+ end
164
+ end
165
+ end
data/test/test_base.rb ADDED
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RtracBaseTest < Test::Unit::TestCase
4
+ # def test_send_query_should_open_connection
5
+ # XMLRPC::Client.expects(:new3).returns(stub())
6
+ # Rtrac::Base.expects(:open_connection).returns(stub(:call => ''))
7
+ # Rtrac::Base.send_query('foo')
8
+ # end
9
+ #
10
+ # def test_open_connection_should_hit_xmlrpc
11
+ # Rtrac::Base.send_query('foo')
12
+ # end
13
+
14
+ def test_connection
15
+ Rtrac::Base.expects(:open_connection)
16
+ Rtrac::Base.connection
17
+ end
18
+
19
+ def test_list_methods
20
+ Rtrac::Base.expects(:send_query)
21
+ Rtrac::Base.list_methods
22
+ end
23
+
24
+ def test_get_tickets
25
+ Rtrac::Base.expects(:send_query)
26
+ Rtrac::Base.list_methods
27
+ end
28
+
29
+ def test_open_connection
30
+ XMLRPC::Client.expects(:new3)
31
+ URI.expects(:parse).returns(stub(:host => 'foo.com', :path => 'foo'))
32
+ Rtrac::Base.send(:open_connection)
33
+ end
34
+
35
+ def test_extract_account_info
36
+ Rtrac::Base.expects(:configuration_options).returns({:username => 'foo', :password => '123', :url => 'http://wush.net/trac/foo'})
37
+ Rtrac::Base.expects(:invalid_config?).returns(false)
38
+ Rtrac::Base.send(:extract_account_info)
39
+ end
40
+
41
+ def test_valid_config
42
+ assert_equal false, Rtrac::Base.send(:invalid_config?, 'foo', 'bar', 'http://wush.net/trac/foo', ['foo'])
43
+ end
44
+
45
+ def test_invalid_config
46
+ assert Rtrac::Base.send(:invalid_config?, 'foo', 'bar', 'ttp://wush.net/trac/foo', ['foo'])
47
+ end
48
+
49
+ end
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'mocha'
4
+ require File.dirname(__FILE__) + '/../lib/rtrac'
File without changes
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class TestTicket < Test::Unit::TestCase
4
+ def test_attributes
5
+ tick = Rtrac::Ticket.new(1)
6
+ tick.stubs(:ticket_attributes).returns(['1', 1195317367, 1195317367, {'summary' => 'test summary', 'description' => 'test description'}])
7
+ assert_equal tick.attributes, {:id => '1', :created_at => 1195317367, :updated_at => 1195317367, :summary => 'test summary', :description => 'test description'}
8
+ end
9
+
10
+ def test_setting_attributes
11
+ tick = Rtrac::Ticket.new(1)
12
+ tick.attributes = {:foo => 'foo'}
13
+ assert_equal tick.instance_variable_get(:@ticket_attributes), {:foo => 'foo'}
14
+ end
15
+
16
+ def test_update_should_remove_updated_at_and_created_at
17
+ tick = Rtrac::Ticket.new(1, {:summary => 'foo', :created_at => 'foo', :updated_at => 'foo'})
18
+ Rtrac::Ticket.expects(:send_query).with('ticket.update', 1, 'Testing Comment', {:summary => 'foo'}).returns(true)
19
+ tick.update('Testing Comment', {:summary => 'foo', :created_at => 'foo', :updated_at => 'foo'})
20
+ end
21
+
22
+ def test_create
23
+ Rtrac::Ticket.expects(:send_query).with('ticket.create', 'Test Title', 'Test Description', {:foo => 'foo'})
24
+ Rtrac::Ticket.create('Test Title', 'Test Description', {:foo => 'foo'})
25
+ end
26
+
27
+ def test_destroy
28
+ Rtrac::Ticket.expects(:send_query).with('ticket.delete', 1)
29
+ Rtrac::Ticket.destroy(1)
30
+ end
31
+
32
+ def test_get
33
+ tick = Rtrac::Ticket.new(1)
34
+ Rtrac::Ticket.expects(:send_query).with('ticket.get', 1)
35
+ tick.send(:get)
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rtrac
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Stephenson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-08 23:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.0
23
+ version:
24
+ description: "== FEATURES/PROBLEMS: Ticket access for Trac == SYNOPSIS: Rtrac::Base.get_by_milestone(milestone).each do |id| # grab the ticket's data tick = Rtrac::Ticket.new(id) iteration_hash[:total] += tick.severity.to_i iteration_hash[:tickets] << {:id => id, :points => tick.severity.to_i, :status => tick.status, :updated_at =>Time.parse(tick.updated_at.to_s)} end == REQUIREMENTS: active_support hoe"
25
+ email: josh@elctech.com
26
+ executables:
27
+ - rtrac
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - bin/rtrac
40
+ - lib/rtrac.rb
41
+ - lib/rtrac/util.rb
42
+ - lib/rtrac/base.rb
43
+ - lib/rtrac/ticket.rb
44
+ - test/test_helper.rb
45
+ - test/test_rtrac.rb
46
+ - test/test_base.rb
47
+ - test/test_ticket.rb
48
+ has_rdoc: true
49
+ homepage: " by Josh Stephenson"
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README.txt
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: rtrac
71
+ rubygems_version: 1.0.1
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Trac wrapper with command line tool
75
+ test_files:
76
+ - test/test_base.rb
77
+ - test/test_helper.rb
78
+ - test/test_rtrac.rb
79
+ - test/test_ticket.rb