rewritten 0.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.
Files changed (46) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.rdoc +93 -0
  4. data/Rakefile +28 -0
  5. data/bin/rewritten-web.rb +25 -0
  6. data/config.ru +4 -0
  7. data/lib/rack/dummy.rb +22 -0
  8. data/lib/rack/html.rb +44 -0
  9. data/lib/rack/record.rb +30 -0
  10. data/lib/rack/url.rb +47 -0
  11. data/lib/rewritten/config.ru +4 -0
  12. data/lib/rewritten/helpers.rb +58 -0
  13. data/lib/rewritten/server/public/favicon.ico +0 -0
  14. data/lib/rewritten/server/public/idle.png +0 -0
  15. data/lib/rewritten/server/public/jquery-1.3.2.min.js +19 -0
  16. data/lib/rewritten/server/public/jquery.relatize_date.js +95 -0
  17. data/lib/rewritten/server/public/poll.png +0 -0
  18. data/lib/rewritten/server/public/ranger.js +73 -0
  19. data/lib/rewritten/server/public/reset.css +48 -0
  20. data/lib/rewritten/server/public/style.css +85 -0
  21. data/lib/rewritten/server/public/working.png +0 -0
  22. data/lib/rewritten/server/test_helper.rb +19 -0
  23. data/lib/rewritten/server/views/clear_hits.erb +10 -0
  24. data/lib/rewritten/server/views/delete.erb +16 -0
  25. data/lib/rewritten/server/views/error.erb +1 -0
  26. data/lib/rewritten/server/views/failed.erb +64 -0
  27. data/lib/rewritten/server/views/hits.erb +30 -0
  28. data/lib/rewritten/server/views/key_sets.erb +19 -0
  29. data/lib/rewritten/server/views/key_string.erb +11 -0
  30. data/lib/rewritten/server/views/layout.erb +44 -0
  31. data/lib/rewritten/server/views/mappings.erb +61 -0
  32. data/lib/rewritten/server/views/new.erb +16 -0
  33. data/lib/rewritten/server/views/next_more.erb +11 -0
  34. data/lib/rewritten/server/views/overview.erb +8 -0
  35. data/lib/rewritten/server/views/queues.erb +49 -0
  36. data/lib/rewritten/server/views/stats.erb +62 -0
  37. data/lib/rewritten/server/views/to.erb +22 -0
  38. data/lib/rewritten/server/views/workers.erb +109 -0
  39. data/lib/rewritten/server/views/working.erb +72 -0
  40. data/lib/rewritten/server.rb +209 -0
  41. data/lib/rewritten/version.rb +3 -0
  42. data/lib/rewritten.rb +403 -0
  43. data/lib/test.ru +17 -0
  44. data/rewritten.gemspec +40 -0
  45. data/test/test_rewritten.rb +6 -0
  46. metadata +174 -0
data/lib/rewritten.rb ADDED
@@ -0,0 +1,403 @@
1
+ require 'redis/namespace'
2
+ require 'rewritten/version'
3
+ require 'rewritten/helpers'
4
+ require 'rack/dummy'
5
+ require 'rack/url'
6
+ require 'rack/record'
7
+ require 'rack/html'
8
+
9
+ module Rewritten
10
+ include Helpers
11
+ extend self
12
+
13
+ # Accepts:
14
+ # 1. A 'hostname:port' String
15
+ # 2. A 'hostname:port:db' String (to select the Redis db)
16
+ # 3. A 'hostname:port/namespace' String (to set the Redis namespace)
17
+ # 4. A Redis URL String 'redis://host:port'
18
+ # 5. An instance of `Redis`, `Redis::Client`, `Redis::DistRedis`,
19
+ # or `Redis::Namespace`.
20
+ def redis=(server)
21
+ case server
22
+ when String
23
+ if server =~ /redis\:\/\//
24
+ redis = Redis.connect(:url => server, :thread_safe => true)
25
+ else
26
+ server, namespace = server.split('/', 2)
27
+ host, port, db = server.split(':')
28
+ redis = Redis.new(:host => host, :port => port,
29
+ :thread_safe => true, :db => db)
30
+ end
31
+ namespace ||= :rewritten
32
+
33
+ @redis = Redis::Namespace.new(namespace, :redis => redis)
34
+ when Redis::Namespace
35
+ @redis = server
36
+ else
37
+ @redis = Redis::Namespace.new(:rewritten, :redis => server)
38
+ end
39
+ end
40
+
41
+ # Returns the current Redis connection. If none has been created, will
42
+ # create a new one.
43
+ def redis
44
+ return @redis if @redis
45
+ self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
46
+ self.redis
47
+ end
48
+
49
+ def redis_id
50
+ # support 1.x versions of redis-rb
51
+ if redis.respond_to?(:server)
52
+ redis.server
53
+ elsif redis.respond_to?(:nodes) # distributed
54
+ redis.nodes.map { |n| n.id }.join(', ')
55
+ else
56
+ redis.client.id
57
+ end
58
+ end
59
+
60
+ # The `before_first_fork` hook will be run in the **parent** process
61
+ # only once, before forking to run the first job. Be careful- any
62
+ # changes you make will be permanent for the lifespan of the
63
+ # worker.
64
+ #
65
+ # Call with a block to set the hook.
66
+ # Call with no arguments to return the hook.
67
+ def before_first_fork(&block)
68
+ block ? (@before_first_fork = block) : @before_first_fork
69
+ end
70
+
71
+ # Set a proc that will be called in the parent process before the
72
+ # worker forks for the first time.
73
+ def before_first_fork=(before_first_fork)
74
+ @before_first_fork = before_first_fork
75
+ end
76
+
77
+ # The `before_fork` hook will be run in the **parent** process
78
+ # before every job, so be careful- any changes you make will be
79
+ # permanent for the lifespan of the worker.
80
+ #
81
+ # Call with a block to set the hook.
82
+ # Call with no arguments to return the hook.
83
+ def before_fork(&block)
84
+ block ? (@before_fork = block) : @before_fork
85
+ end
86
+
87
+ # Set the before_fork proc.
88
+ def before_fork=(before_fork)
89
+ @before_fork = before_fork
90
+ end
91
+
92
+ # The `after_fork` hook will be run in the child process and is passed
93
+ # the current job. Any changes you make, therefore, will only live as
94
+ # long as the job currently being processed.
95
+ #
96
+ # Call with a block to set the hook.
97
+ # Call with no arguments to return the hook.
98
+ def after_fork(&block)
99
+ block ? (@after_fork = block) : @after_fork
100
+ end
101
+
102
+ # Set the after_fork proc.
103
+ def after_fork=(after_fork)
104
+ @after_fork = after_fork
105
+ end
106
+
107
+ def to_s
108
+ "Rewritten Client connected to #{redis_id}"
109
+ end
110
+
111
+ # If 'inline' is true Resque will call #perform method inline
112
+ # without queuing it into Redis and without any Resque callbacks.
113
+ # The 'inline' is false Resque jobs will be put in queue regularly.
114
+ def inline?
115
+ @inline
116
+ end
117
+ alias_method :inline, :inline?
118
+
119
+ def inline=(inline)
120
+ @inline = inline
121
+ end
122
+
123
+ #
124
+ # translations
125
+ #
126
+
127
+ def add_translation(from, to)
128
+ redis.set("from:#{from}", to)
129
+ redis.lpush(:froms, from)
130
+ redis.lpush(:tos, to)
131
+ redis.rpush("to:#{to}", from)
132
+ end
133
+
134
+ def num_translations(to)
135
+ Rewritten.size("to:#{to}")
136
+ end
137
+
138
+ def remove_translation(from, to)
139
+ Rewritten.redis.del("from:#{from}")
140
+ Rewritten.redis.lrem("froms", 0, from)
141
+ Rewritten.redis.lrem("to:#{to}", 0, from)
142
+ Rewritten.redis.lrem("tos", 0, to) if num_translations(to) == 0
143
+ end
144
+
145
+ def get_current_translation(path)
146
+ translation = Rewritten.list_range("to:#{path}", -1, 1)
147
+ return translation if translation
148
+ return path
149
+ end
150
+
151
+
152
+
153
+ def add_hit(path, code, content_type)
154
+ h = {:path => path, :code => code, :content_type => content_type}
155
+ Rewritten.redis.sadd("hits", encode(h) )
156
+ end
157
+
158
+ def all_hits
159
+ Rewritten.redis.smembers("hits").map{|e| decode(e)}
160
+ end
161
+
162
+ def include?(path)
163
+ Rewritten.redis.get("from:#{path}")
164
+ end
165
+
166
+ #
167
+ # queue manipulation
168
+ #
169
+
170
+ # Pushes a job onto a queue. Queue name should be a string and the
171
+ # item should be any JSON-able Ruby object.
172
+ #
173
+ # Resque works generally expect the `item` to be a hash with the following
174
+ # keys:
175
+ #
176
+ # class - The String name of the job to run.
177
+ # args - An Array of arguments to pass the job. Usually passed
178
+ # via `class.to_class.perform(*args)`.
179
+ #
180
+ # Example
181
+ #
182
+ # Resque.push('archive', :class => 'Archive', :args => [ 35, 'tar' ])
183
+ #
184
+ # Returns nothing
185
+ def push(queue, item)
186
+ watch_queue(queue)
187
+ redis.rpush "queue:#{queue}", encode(item)
188
+ end
189
+
190
+ # Pops a job off a queue. Queue name should be a string.
191
+ #
192
+ # Returns a Ruby object.
193
+ def pop(queue)
194
+ decode redis.lpop("queue:#{queue}")
195
+ end
196
+
197
+ # Returns an integer representing the size of translations for a target.
198
+ # Target name should be a string.
199
+ def size(target)
200
+ #redis.llen("target:#{target}").to_i
201
+ redis.llen(target).to_i
202
+ end
203
+
204
+ # Returns an array of items currently queued. Queue name should be
205
+ # a string.
206
+ #
207
+ # start and count should be integer and can be used for pagination.
208
+ # start is the item to begin, count is how many items to return.
209
+ #
210
+ # To get the 3rd page of a 30 item, paginatied list one would use:
211
+ # Resque.peek('my_list', 59, 30)
212
+ def peek(queue, start = 0, count = 1)
213
+ list_range("queue:#{queue}", start, count)
214
+ end
215
+
216
+ # Does the dirty work of fetching a range of items from a Redis list
217
+ # and converting them into Ruby objects.
218
+ def list_range(key, start = 0, count = 1)
219
+ if count == 1
220
+ #decode redis.lindex(key, start)
221
+ redis.lindex(key, start)
222
+ else
223
+ Array(redis.lrange(key, start, start+count-1)).map do |item|
224
+ #decode item
225
+ item
226
+ end
227
+ end
228
+ end
229
+
230
+ # Returns an array of all known Resque queues as strings.
231
+ def queues
232
+ Array(redis.smembers(:queues))
233
+ end
234
+
235
+ # Returns an array of all known URL targets.
236
+ def targets
237
+ Array(redis.smembers(:targets))
238
+ end
239
+
240
+ # Returns an array of all known source URLs (that are to translated)
241
+ def froms
242
+ Array(redis.smembers(:froms))
243
+ end
244
+
245
+
246
+
247
+ # Given a queue name, completely deletes the queue.
248
+ def remove_queue(queue)
249
+ redis.srem(:queues, queue.to_s)
250
+ redis.del("queue:#{queue}")
251
+ end
252
+
253
+ # Used internally to keep track of which queues we've created.
254
+ # Don't call this directly.
255
+ def watch_queue(queue)
256
+ redis.sadd(:queues, queue.to_s)
257
+ end
258
+
259
+
260
+ #
261
+ # job shortcuts
262
+ #
263
+
264
+ # This method can be used to conveniently add a job to a queue.
265
+ # It assumes the class you're passing it is a real Ruby class (not
266
+ # a string or reference) which either:
267
+ #
268
+ # a) has a @queue ivar set
269
+ # b) responds to `queue`
270
+ #
271
+ # If either of those conditions are met, it will use the value obtained
272
+ # from performing one of the above operations to determine the queue.
273
+ #
274
+ # If no queue can be inferred this method will raise a `Resque::NoQueueError`
275
+ #
276
+ # This method is considered part of the `stable` API.
277
+ def enqueue(klass, *args)
278
+ Job.create(queue_from_class(klass), klass, *args)
279
+
280
+ Plugin.after_enqueue_hooks(klass).each do |hook|
281
+ klass.send(hook, *args)
282
+ end
283
+ end
284
+
285
+ # This method can be used to conveniently remove a job from a queue.
286
+ # It assumes the class you're passing it is a real Ruby class (not
287
+ # a string or reference) which either:
288
+ #
289
+ # a) has a @queue ivar set
290
+ # b) responds to `queue`
291
+ #
292
+ # If either of those conditions are met, it will use the value obtained
293
+ # from performing one of the above operations to determine the queue.
294
+ #
295
+ # If no queue can be inferred this method will raise a `Resque::NoQueueError`
296
+ #
297
+ # If no args are given, this method will dequeue *all* jobs matching
298
+ # the provided class. See `Resque::Job.destroy` for more
299
+ # information.
300
+ #
301
+ # Returns the number of jobs destroyed.
302
+ #
303
+ # Example:
304
+ #
305
+ # # Removes all jobs of class `UpdateNetworkGraph`
306
+ # Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph)
307
+ #
308
+ # # Removes all jobs of class `UpdateNetworkGraph` with matching args.
309
+ # Resque.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
310
+ #
311
+ # This method is considered part of the `stable` API.
312
+ def dequeue(klass, *args)
313
+ Job.destroy(queue_from_class(klass), klass, *args)
314
+ end
315
+
316
+ # Given a class, try to extrapolate an appropriate queue based on a
317
+ # class instance variable or `queue` method.
318
+ def queue_from_class(klass)
319
+ klass.instance_variable_get(:@queue) ||
320
+ (klass.respond_to?(:queue) and klass.queue)
321
+ end
322
+
323
+ # This method will return a `Resque::Job` object or a non-true value
324
+ # depending on whether a job can be obtained. You should pass it the
325
+ # precise name of a queue: case matters.
326
+ #
327
+ # This method is considered part of the `stable` API.
328
+ def reserve(queue)
329
+ Job.reserve(queue)
330
+ end
331
+
332
+ # Validates if the given klass could be a valid Resque job
333
+ #
334
+ # If no queue can be inferred this method will raise a `Resque::NoQueueError`
335
+ #
336
+ # If given klass is nil this method will raise a `Resque::NoClassError`
337
+ def validate(klass, queue = nil)
338
+ queue ||= queue_from_class(klass)
339
+
340
+ if !queue
341
+ raise NoQueueError.new("Jobs must be placed onto a queue.")
342
+ end
343
+
344
+ if klass.to_s.empty?
345
+ raise NoClassError.new("Jobs must be given a class.")
346
+ end
347
+ end
348
+
349
+
350
+ #
351
+ # worker shortcuts
352
+ #
353
+
354
+ # A shortcut to Worker.all
355
+ def workers
356
+ Worker.all
357
+ end
358
+
359
+ # A shortcut to Worker.working
360
+ def working
361
+ Worker.working
362
+ end
363
+
364
+ # A shortcut to unregister_worker
365
+ # useful for command line tool
366
+ def remove_worker(worker_id)
367
+ worker = Resque::Worker.find(worker_id)
368
+ worker.unregister_worker
369
+ end
370
+
371
+ #
372
+ # stats
373
+ #
374
+
375
+ # Returns a hash, similar to redis-rb's #info, of interesting stats.
376
+ def info
377
+ return {
378
+ :pending => queues.inject(0) { |m,k| m + size(k) },
379
+ #:processed => Stat[:processed],
380
+ #:queues => queues.size,
381
+ #:workers => workers.size.to_i,
382
+ #:working => working.size,
383
+ #:failed => Stat[:failed],
384
+ :servers => [redis_id],
385
+ :environment => ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
386
+ }
387
+ end
388
+
389
+ # Returns an array of all known Resque keys in Redis. Redis' KEYS operation
390
+ # is O(N) for the keyspace, so be careful - this can be slow for big databases.
391
+ def keys
392
+ redis.keys("*").map do |key|
393
+ key.sub("#{redis.namespace}:", '')
394
+ end
395
+ end
396
+
397
+ def per_page
398
+ 20
399
+ end
400
+
401
+
402
+ end
403
+
data/lib/test.ru ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+ require 'rewritten'
4
+ require 'rewritten/server'
5
+
6
+ map "/" do
7
+ use Rack::Rewritten::Record
8
+ use Rack::Rewritten::Url
9
+ use Rack::Rewritten::Html
10
+ run Rack::Dummy.new
11
+ end
12
+
13
+ map "/rewritten" do
14
+ run Rewritten::Server
15
+ end
16
+
17
+
data/rewritten.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rewritten/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rewritten"
7
+ s.version = Rewritten::VERSION
8
+ s.authors = ["Kai Rubarth"]
9
+ s.email = ["kai@doxter.de"]
10
+ s.homepage = ""
11
+ s.summary = %q{Rack app that rewrites URLs -- nicely and uncomplicated}
12
+
13
+ s.rubyforge_project = "rewritten"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency "redis-namespace", "~> 1.0.2"
21
+ s.add_dependency "vegas", "~> 0.1.2"
22
+ s.add_dependency "sinatra", ">= 0.9.2"
23
+ s.add_dependency "multi_json", "~> 1.0"
24
+
25
+ s.description = <<description
26
+ Rewritten is a simple Redis-backed Ruby library that facilitates creating and refactoring
27
+ arbitrary urls in your Rack applications.
28
+
29
+ Rewritten is inspired by the awesome Resque and Rack::Rewrite gems. It is
30
+ compromised of four parts:
31
+
32
+ * A Ruby library for creating and modifying URLs for resources
33
+ * A Rack app that takes care of redirecting old URLS in a SEO friendly matter
34
+ * A Rack app that rewrites links to their nice counterpart
35
+ * A Sinatra app for managing URLs
36
+ description
37
+
38
+ end
39
+
40
+
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+ require "../lib/rack/dummy"
4
+
5
+ run Rack::Dummy.new
6
+
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rewritten
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Kai Rubarth
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-26 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: redis-namespace
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 19
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 2
34
+ version: 1.0.2
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: vegas
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 31
46
+ segments:
47
+ - 0
48
+ - 1
49
+ - 2
50
+ version: 0.1.2
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: sinatra
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 63
62
+ segments:
63
+ - 0
64
+ - 9
65
+ - 2
66
+ version: 0.9.2
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: multi_json
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 15
78
+ segments:
79
+ - 1
80
+ - 0
81
+ version: "1.0"
82
+ type: :runtime
83
+ version_requirements: *id004
84
+ description: " Rewritten is a simple Redis-backed Ruby library that facilitates creating and refactoring \n arbitrary urls in your Rack applications.\n\n Rewritten is inspired by the awesome Resque and Rack::Rewrite gems. It is\n compromised of four parts:\n\n * A Ruby library for creating and modifying URLs for resources \n * A Rack app that takes care of redirecting old URLS in a SEO friendly matter\n * A Rack app that rewrites links to their nice counterpart \n * A Sinatra app for managing URLs \n"
85
+ email:
86
+ - kai@doxter.de
87
+ executables:
88
+ - rewritten-web.rb
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - .gitignore
95
+ - Gemfile
96
+ - README.rdoc
97
+ - Rakefile
98
+ - bin/rewritten-web.rb
99
+ - config.ru
100
+ - lib/rack/dummy.rb
101
+ - lib/rack/html.rb
102
+ - lib/rack/record.rb
103
+ - lib/rack/url.rb
104
+ - lib/rewritten.rb
105
+ - lib/rewritten/config.ru
106
+ - lib/rewritten/helpers.rb
107
+ - lib/rewritten/server.rb
108
+ - lib/rewritten/server/public/favicon.ico
109
+ - lib/rewritten/server/public/idle.png
110
+ - lib/rewritten/server/public/jquery-1.3.2.min.js
111
+ - lib/rewritten/server/public/jquery.relatize_date.js
112
+ - lib/rewritten/server/public/poll.png
113
+ - lib/rewritten/server/public/ranger.js
114
+ - lib/rewritten/server/public/reset.css
115
+ - lib/rewritten/server/public/style.css
116
+ - lib/rewritten/server/public/working.png
117
+ - lib/rewritten/server/test_helper.rb
118
+ - lib/rewritten/server/views/clear_hits.erb
119
+ - lib/rewritten/server/views/delete.erb
120
+ - lib/rewritten/server/views/error.erb
121
+ - lib/rewritten/server/views/failed.erb
122
+ - lib/rewritten/server/views/hits.erb
123
+ - lib/rewritten/server/views/key_sets.erb
124
+ - lib/rewritten/server/views/key_string.erb
125
+ - lib/rewritten/server/views/layout.erb
126
+ - lib/rewritten/server/views/mappings.erb
127
+ - lib/rewritten/server/views/new.erb
128
+ - lib/rewritten/server/views/next_more.erb
129
+ - lib/rewritten/server/views/overview.erb
130
+ - lib/rewritten/server/views/queues.erb
131
+ - lib/rewritten/server/views/stats.erb
132
+ - lib/rewritten/server/views/to.erb
133
+ - lib/rewritten/server/views/workers.erb
134
+ - lib/rewritten/server/views/working.erb
135
+ - lib/rewritten/version.rb
136
+ - lib/test.ru
137
+ - rewritten.gemspec
138
+ - test/test_rewritten.rb
139
+ has_rdoc: true
140
+ homepage: ""
141
+ licenses: []
142
+
143
+ post_install_message:
144
+ rdoc_options: []
145
+
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ hash: 3
154
+ segments:
155
+ - 0
156
+ version: "0"
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ hash: 3
163
+ segments:
164
+ - 0
165
+ version: "0"
166
+ requirements: []
167
+
168
+ rubyforge_project: rewritten
169
+ rubygems_version: 1.6.2
170
+ signing_key:
171
+ specification_version: 3
172
+ summary: Rack app that rewrites URLs -- nicely and uncomplicated
173
+ test_files: []
174
+