rtrac 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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