sinatra-torrent 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rake'
2
+ require 'rspec/core/rake_task'
2
3
 
3
4
  begin
4
5
  require 'jeweler'
@@ -11,32 +12,22 @@ begin
11
12
  gem.authors = ["JP Hastings-Spital"]
12
13
 
13
14
  gem.add_dependency('sinatra','>=1.1.2') # Required for send_file modifications
15
+ gem.add_dependency('bencode')
14
16
  end
15
17
  Jeweler::GemcutterTasks.new
16
18
  rescue LoadError
17
19
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
20
  end
19
21
 
20
- require 'rake/testtask'
21
- Rake::TestTask.new(:test) do |test|
22
- test.libs << 'lib' << 'test'
23
- test.pattern = 'test/**/test_*.rb'
24
- test.verbose = true
25
- end
22
+ task :default => :test
23
+ task :test => :spec
26
24
 
27
- begin
28
- require 'rcov/rcovtask'
29
- Rcov::RcovTask.new do |test|
30
- test.libs << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
- rescue LoadError
35
- task :rcov do
36
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
25
+ if !defined?(RSpec)
26
+ puts "spec targets require RSpec"
27
+ else
28
+ desc "Run all examples"
29
+ RSpec::Core::RakeTask.new(:spec) do |t|
30
+ t.pattern = 'spec/**/*_spec.rb'
31
+ t.rspec_opts = ['-cfs']
37
32
  end
38
- end
39
-
40
- task :test => :check_dependencies
41
-
42
- task :default => :test
33
+ end
data/Readme.md CHANGED
@@ -13,20 +13,24 @@ Usage
13
13
 
14
14
  "Woah, that's pretty simple!" I hear you say. Why yes, I think it is.
15
15
 
16
- All files you put in the `downloads` directory at the root of your sinatra app will be downloadable at `/downloads/your_file.ext` and it's torrent will be dynamically generated (and cached) at `/torrents/your_file.ext.torrent`. You will have trouble with larger files as it currently hashes as part of the request first time round. I'm planning on pushing this out to workers at some point. Not yet sure how I'm going to do that…
16
+ All files you put in the `downloads` directory at the root of your sinatra app will be downloadable at `/downloads/your_file.ext` and it's torrent will be dynamically generated (and cached) at `/torrents/your_file.ext.torrent`. If a torrent file takes over 1 second to be generated, it'll be put in a queue for creation in a background job. You can run these background jobs using the Rake helper (see below).
17
+
18
+ If you have set the `:torrent_timeout` sinatra setting to a `Proc`, it will be run (synchronously!) after the delayed job has been queued and before the user is sent the error message. eg. `set :torrent_timeout, Proc.new { start_process_forked_running_rake_hash_queue }`
17
19
 
18
20
  ### I want options!
19
21
 
20
- There needs to be a database of torrents and peers, this is taken care of by a database adapter. Currently I've written (a really basic) one for active record, so many databases are supported as is, but you can write your own for others (eg. mongo). I'm still finding my way around the Sinatra extensions api, so this is how you specify your own ActiveRecord settings:
22
+ There needs to be a database of torrents, peers and background hashing jobs, this is taken care of by a database adapter. Currently I've written (a really basic) one for active record, so many databases are supported as is, but you can write your own for others (eg. mongo). I'm still finding my way around the Sinatra extensions api, so this is how you specify your own ActiveRecord settings:
21
23
 
22
24
  require 'sinatra'
23
25
  require 'sinatra/torrent/activerecord'
24
- SinatraTorrentDatabase.settings = {
26
+ Sinatra::Torrent::Database.settings = {
25
27
  'adapater' => 'sqlite3',
26
28
  'database' => 'torrents.db'
27
29
  }
28
30
  require 'sinatra/torrent'
29
31
 
32
+ The active record adapter is loaded by default if no others are specified and an SQLite database will be maintained in memory unless settings (like those above) are specified. This means that, unless you set options like this, when your app shuts down your hashes will be lost!
33
+
30
34
  Rake
31
35
  ----
32
36
 
@@ -55,7 +59,7 @@ If a torrent takes longer than 1 second to generate on-the-fly, it'll be added t
55
59
  To Do
56
60
  -----
57
61
 
58
- * Execute a user-writen block of code when an on-the-fly torrent creation times out. This will allow people to trigger the background rake task immediately, rather than waiting on cron.
62
+ * Get the BitTornado webseed style to work.
59
63
 
60
64
  Ummmm
61
65
  -----
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
@@ -8,17 +8,25 @@ require 'sinatra/torrent/helpers'
8
8
 
9
9
  module Sinatra
10
10
  module Torrent
11
-
12
- # Options etc
11
+ # Sets the settings for the app
12
+ def self.settings=(settings = {})
13
+ @@settings = {
14
+ # Directory which holds all the files which will be provided as torrents
15
+ :downloads_directory => File.join(File.dirname(__FILE__),Sinatra::Torrent.downloads_directory),
16
+ # Mount point for the downloads directory
17
+ :downloads_mount => 'downloads',
18
+ # Mount point for the torrents directory
19
+ :torrents_mount => 'torrents'
20
+ }
21
+ settings.each { |key,value| @@settings[key] = value unless @@settings[value].nil? }
22
+ end
23
+
24
+ # settings etc
13
25
  def self.registered(app)
26
+ # Set default settings
27
+ begin @@settings rescue self.settings=({}) end
14
28
  # Putting the annouce URL of a tracker in here will use that tracker rather than the inbuilt one
15
29
  app.set :external_tracker, nil
16
- # Directory which holds all the files which will be provided as torrents
17
- app.set :downloads_directory, File.join(File.dirname(__FILE__),Sinatra::Torrent.downloads_directory)
18
- # Mount point for the downloads directory
19
- app.set :downloads_mount, 'downloads'
20
- # Mount point for the torrents directory
21
- app.set :torrents_mount, 'torrents'
22
30
  # Load up a database adapter if one isn't already loaded
23
31
  require 'sinatra/torrent/activerecord' unless (Sinatra::Torrent.const_defined?('Database') rescue false)
24
32
  # Stores the instance of the database used to store tracker info.
@@ -28,25 +36,26 @@ module Sinatra
28
36
  # Do we wish to track external torrents too? (untested)
29
37
  app.set :allow_external_torrents, false
30
38
  # The frequency with which we ask trackers to announce themselves. Once every x seconds
31
- app.set :announce_frequency, 30
39
+ app.set :announce_frequency, 900
40
+ # Method to call when torrent creation timesout
41
+ app.set :torrent_timeout, nil
32
42
 
33
43
  # TORRENTS
34
44
 
35
45
  app.mime_type :torrent, 'application/x-bittorrent'
36
46
 
37
47
  # Serves up the torrents with appropriate announce URL
38
- app.get Regexp.new("^/#{app.options.torrents_mount}/(.+)\.torrent$") do |rel_location|
39
- filename = File.join(options.downloads_directory, rel_location)
48
+ app.get Regexp.new("^/#{@@settings[:torrents_mount]}/(.+)\.torrent$") do |rel_location|
49
+ filename = File.join(@@settings[:downloads_directory], rel_location)
40
50
  halt(404, "That file doesn't exist! #{filename}") unless File.exists?(filename)
41
51
 
42
- if !(d = options.database_adapter.torrent_by_path_and_timestamp(rel_location,File.mtime(filename)))
43
- p d
52
+ if !(d = settings.database_adapter.torrent_by_path_and_timestamp(rel_location,File.mtime(filename)))
44
53
  begin
45
54
  Timeout::timeout(1) do
46
55
  d = Sinatra::Torrent.create(filename)
47
56
  end
48
57
  rescue Timeout::Error
49
- eta = options.database_adapter.add_hashjob(rel_location)
58
+ eta = settings.database_adapter.add_hashjob(rel_location)
50
59
 
51
60
  begin
52
61
  wait = case (eta/60).floor
@@ -61,18 +70,21 @@ module Sinatra
61
70
  wait = "a short while"
62
71
  end
63
72
 
73
+ settings.torrent_timeout.call if settings.torrent_timeout.is_a?(Proc)
74
+
64
75
  halt(503,"This torrent is taking too long to build, we're running it in the background. Please try again in #{wait}.")
65
76
  end
66
77
 
67
- options.database_adapter.store_torrent(rel_location,File.mtime(filename),d['metadata'],d['infohash'])
78
+ settings.database_adapter.store_torrent(rel_location,File.mtime(filename),d['metadata'],d['infohash'])
68
79
  end
69
80
 
70
- # These are options which could change between database retrievals
81
+ # These are settings which could change between database retrievals
71
82
  d['metadata'].merge!({
72
- 'httpseeds' => [File.join('http://'+env['HTTP_HOST'],URI.encode(options.torrents_mount),'webseed')],
73
- 'url-list' => [File.join('http://'+env['HTTP_HOST'],URI.encode(options.downloads_mount),URI.encode(rel_location)+'?'+d['infohash'])],
74
- 'announce' => options.external_tracker || File.join('http://'+env['HTTP_HOST'],URI.encode(options.torrents_mount),'announce'),
75
- 'comment' => options.torrent_comment,
83
+ # Webseeds not currently supported
84
+ # 'httpseeds' => [File.join('http://'+env['HTTP_HOST'],URI.encode(settings.torrents_mount),'webseed')],
85
+ 'url-list' => [File.join('http://'+env['HTTP_HOST'],URI.encode(@@settings[:downloads_mount]),URI.encode(rel_location)+'?'+d['infohash'])],
86
+ 'announce' => settings.external_tracker || File.join('http://'+env['HTTP_HOST'],URI.encode(@@settings[:torrents_mount]),'announce'),
87
+ 'comment' => settings.torrent_comment,
76
88
  })
77
89
 
78
90
  content_type :torrent, :charset => 'utf-8'
@@ -82,13 +94,13 @@ module Sinatra
82
94
  # TRACKER
83
95
 
84
96
  # Tracker announce mount point
85
- app.get "/#{app.options.torrents_mount}/announce" do
97
+ app.get "/#{@@settings[:torrents_mount]}/announce" do
86
98
  # Convert to a hex info_hash if required TODO: Is it required?
87
99
  params['info_hash'] = Digest.hexencode(params['info_hash'] || '')
88
100
  halt(400,"A valid info-hash was not given") if params['info_hash'].match(/^[0-9a-f]{40}$/).nil?
89
- info = options.database_adapter.torrent_info(params['info_hash'])
101
+ info = settings.database_adapter.torrent_info(params['info_hash'])
90
102
 
91
- if (!options.allow_external_torrents and !options.database_adapter.torrent_by_infohash(params['info_hash']))
103
+ if (!settings.allow_external_torrents and !settings.database_adapter.torrent_by_infohash(params['info_hash']))
92
104
  return {
93
105
  'failure reason' => 'This tracker does not track that torrent'
94
106
  }.bencode
@@ -102,54 +114,68 @@ module Sinatra
102
114
  params['peer_id'] = params['peer_id'].force_encoding("ISO-8859-1")
103
115
 
104
116
  # Registers this peer's announcement
105
- options.database_adapter.announce(params)
117
+ settings.database_adapter.announce(params)
106
118
 
107
119
  {
108
- 'interval' => options.announce_frequency,
120
+ 'interval' => settings.announce_frequency,
109
121
  #'tracker id' => 'bleugh', # TODO: Keep this?
110
122
  'complete' => info['complete'],
111
123
  'incomplete' => info['incomplete'],
112
- 'peers' => options.database_adapter.peers_by_infohash(params['info_hash'],[params['peer_id']],(params['numwant'] || 50).to_i),
124
+ 'peers' => settings.database_adapter.peers_by_infohash(params['info_hash'],[params['peer_id']],(params['numwant'] || 50).to_i),
113
125
  }.bencode
114
126
  end
115
127
 
116
128
  # TODO: Scrape
117
129
  app.get '/torrents/scrape' do
118
- # TODO: Make it work!
130
+ {
131
+ 'files' => Hash[*request.env['QUERY_STRING'].scan(/info_hash=([0-9a-f]{20})/).collect do |infohash|
132
+ torrent = settings.database_adapter.torrent_by_infohash(infohash[0])
133
+ next if !torrent
134
+ stats = settings.database_adapter.torrent_info(infohash[0])
135
+ [
136
+ torrent['infohash'],
137
+ {
138
+ 'complete' => stats['complete'],
139
+ 'downloaded' => 0,
140
+ 'incomplete' => stats['incomplete'],
141
+ 'name' => File.basename(torrent['path'])
142
+ }
143
+ ]
144
+ end.compact.flatten]
145
+ }.bencode
119
146
  end
120
147
 
121
148
  # INDEX PAGE
122
149
 
123
- # TODO: Have a 'fallback' index view?
124
- app.get "/#{app.options.torrents_mount}/" do
125
- locals = {:torrents => (Dir.glob("#{options.downloads_directory}/**").collect {|f| f[options.downloads_directory.length+1..-1] } rescue [])}
150
+ app.get "/#{@@settings[:torrents_mount]}/" do
151
+ locals = {:torrents => (Dir.glob("#{@@settings[:downloads_directory]}/**").collect {|f| {:file => f[@@settings[:downloads_directory].length+1..-1],:hashed? => settings.database_adapter.torrent_by_path_and_timestamp(f[@@settings[:downloads_directory].length+1..-1],File.mtime(f)) != false} } rescue [])}
126
152
  begin
127
153
  haml :torrents_index,:locals => locals
128
154
  rescue Errno::ENOENT
129
- "<ul>"<<locals[:torrents].collect{|t| "<li><a href=\"/#{options.torrents_mount}/#{t}.torrent\">#{t}</a></li>" }.join<<"</ul>"
155
+ "<ul>"<<locals[:torrents].collect{|t| "<li><a href=\"/#{@@settings[:torrents_mount]}/#{t[:file]}.torrent\" class=\"#{(t[:hashed?] ? 'ready' : 'unhashed')}\">#{t[:file]}</a></li>" }.join<<"</ul>"
130
156
  end
131
157
  end
132
158
 
133
159
  # DATA
134
160
 
161
+ =begin : Not currently supported
135
162
  # BitTornado WebSeeding manager
136
- app.get "/#{app.options.torrents_mount}/webseed" do
163
+ # http://bittornado.com/docs/webseed-spec.txt
164
+ app.get "/#{settings.torrents_mount}/webseed" do
137
165
  # Which file is the client looking for?
138
- halt(404, "Torrent not tracked") unless (options.database_adapter.torrent_by_infohash(params[:infohash]))
166
+ halt(404, "Torrent not tracked") unless (d = settings.database_adapter.torrent_by_infohash(params[:infohash]))
139
167
 
140
- # http://bittornado.com/docs/webseed-spec.txt
141
168
 
142
- # TODO: intelligent wait period
143
- halt(503,"15") if false # ask clients to wait 15 seconds before requesting again
144
169
  end
170
+ =end
145
171
 
146
172
  # Provides the files for web download. Any query parameters are treated as a checksum for the file (via the torrent infohash)
147
- app.get "/#{app.options.downloads_mount}/:filename" do
148
- filename = File.join(options.downloads_directory,File.expand_path('/'+params[:filename]))
173
+ app.get "/#{@@settings[:downloads_mount]}/:filename" do
174
+ filename = File.join(@@settings[:downloads_directory],File.expand_path('/'+params[:filename]))
149
175
  halt(404) unless File.exists?(filename)
150
176
 
151
177
  # If there are query params then we assume it's specifying a specific version of the file by info_hash
152
- halt(409,"The file is no longer the same as the one specified in your torrent") if !env['QUERY_STRING'].empty? and (options.database_adapter.torrent_by_path_and_timestamp(filename,File.mtime(filename))['infohash'] rescue nil) != env['QUERY_STRING']
178
+ halt(409,"The file is no longer the same as the one specified in your torrent") if !env['QUERY_STRING'].empty? and (settings.database_adapter.torrent_by_path_and_timestamp(filename,File.mtime(filename))['infohash'] rescue nil) != env['QUERY_STRING']
153
179
  send_file(filename)
154
180
  end
155
181
  end
@@ -1,6 +1,8 @@
1
1
  # The active record adapter works with SQLite3 in memory by default
2
2
  require 'active_record'
3
3
 
4
+ ActiveRecord::Base.logger = nil
5
+
4
6
  module Sinatra
5
7
  module Torrent
6
8
  # This is the wrapper class used by sinatra-torrent to communicate with
@@ -21,7 +23,7 @@ module Sinatra
21
23
  # Makes sure the table is present & ready, log in using the settings
22
24
  def initialize
23
25
  @db = ActiveRecord::Base.establish_connection(@@settings)
24
-
26
+
25
27
  unless Torrent.table_exists?
26
28
  ActiveRecord::Schema.define do
27
29
  create_table :torrents do |table|
@@ -1,44 +1,47 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{sinatra-torrent}
8
- s.version = "0.0.5"
7
+ s.name = "sinatra-torrent"
8
+ s.version = "0.0.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["JP Hastings-Spital"]
12
- s.date = %q{2011-02-10}
13
- s.description = %q{An extension to Sinatra which will allow you to run a webseeded torrent tracker of files in the folder you specify.}
14
- s.email = %q{jphastings@gmail.com}
12
+ s.date = "2012-07-01"
13
+ s.description = "An extension to Sinatra which will allow you to run a webseeded torrent tracker of files in the folder you specify."
14
+ s.email = "jphastings@gmail.com"
15
15
  s.files = [
16
16
  "Rakefile",
17
- "Readme.md",
18
- "VERSION",
19
- "lib/sinatra/torrent.rb",
20
- "lib/sinatra/torrent/activerecord.rb",
21
- "lib/sinatra/torrent/hashing.rb",
22
- "lib/sinatra/torrent/helpers.rb",
23
- "sinatra-torrent.gemspec"
17
+ "Readme.md",
18
+ "VERSION",
19
+ "lib/sinatra/torrent.rb",
20
+ "lib/sinatra/torrent/activerecord.rb",
21
+ "lib/sinatra/torrent/hashing.rb",
22
+ "lib/sinatra/torrent/helpers.rb",
23
+ "sinatra-torrent.gemspec",
24
+ "spec/spec_helper.rb",
25
+ "spec/torrent_spec.rb"
24
26
  ]
25
- s.homepage = %q{http://github.com/jphastings/sinatra-torrent}
26
- s.rdoc_options = ["--charset=UTF-8"]
27
+ s.homepage = "http://github.com/jphastings/sinatra-torrent"
27
28
  s.require_paths = ["lib"]
28
- s.rubygems_version = %q{1.3.7}
29
- s.summary = %q{A sinatra extension to run webseeded torrent tracker}
29
+ s.rubygems_version = "1.8.24"
30
+ s.summary = "A sinatra extension to run webseeded torrent tracker"
30
31
 
31
32
  if s.respond_to? :specification_version then
32
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
33
33
  s.specification_version = 3
34
34
 
35
35
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
36
36
  s.add_runtime_dependency(%q<sinatra>, [">= 1.1.2"])
37
+ s.add_runtime_dependency(%q<bencode>, [">= 0"])
37
38
  else
38
39
  s.add_dependency(%q<sinatra>, [">= 1.1.2"])
40
+ s.add_dependency(%q<bencode>, [">= 0"])
39
41
  end
40
42
  else
41
43
  s.add_dependency(%q<sinatra>, [">= 1.1.2"])
44
+ s.add_dependency(%q<bencode>, [">= 0"])
42
45
  end
43
46
  end
44
47
 
@@ -0,0 +1,9 @@
1
+ require 'sinatra'
2
+ require 'rack/test'
3
+
4
+ module RSpecMixin
5
+ include Rack::Test::Methods
6
+ def app() Sinatra::Application end
7
+ end
8
+
9
+ RSpec.configure { |c| c.include RSpecMixin }
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+ require File.join(File.dirname(__FILE__),'..','lib','sinatra','torrent')
3
+
4
+ describe 'The Torrent extension' do
5
+ it 'should load correctly in sinatra'
6
+
7
+ describe 'the scrape url' do
8
+ it 'should provide scrape information' do
9
+
10
+ end
11
+
12
+ it 'should provide scrape information for multiple infohashes' do
13
+
14
+ end
15
+ end
16
+
17
+ it 'should have more test cases'
18
+ end
metadata CHANGED
@@ -1,48 +1,55 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sinatra-torrent
3
- version: !ruby/object:Gem::Version
4
- hash: 21
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 5
10
- version: 0.0.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - JP Hastings-Spital
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-02-10 00:00:00 +00:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-07-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: sinatra
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.2
22
+ type: :runtime
23
23
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 23
30
- segments:
31
- - 1
32
- - 1
33
- - 2
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
34
29
  version: 1.1.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: bencode
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
35
38
  type: :runtime
36
- version_requirements: *id001
37
- description: An extension to Sinatra which will allow you to run a webseeded torrent tracker of files in the folder you specify.
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: An extension to Sinatra which will allow you to run a webseeded torrent
47
+ tracker of files in the folder you specify.
38
48
  email: jphastings@gmail.com
39
49
  executables: []
40
-
41
50
  extensions: []
42
-
43
51
  extra_rdoc_files: []
44
-
45
- files:
52
+ files:
46
53
  - Rakefile
47
54
  - Readme.md
48
55
  - VERSION
@@ -51,39 +58,30 @@ files:
51
58
  - lib/sinatra/torrent/hashing.rb
52
59
  - lib/sinatra/torrent/helpers.rb
53
60
  - sinatra-torrent.gemspec
54
- has_rdoc: true
61
+ - spec/spec_helper.rb
62
+ - spec/torrent_spec.rb
55
63
  homepage: http://github.com/jphastings/sinatra-torrent
56
64
  licenses: []
57
-
58
65
  post_install_message:
59
- rdoc_options:
60
- - --charset=UTF-8
61
- require_paths:
66
+ rdoc_options: []
67
+ require_paths:
62
68
  - lib
63
- required_ruby_version: !ruby/object:Gem::Requirement
69
+ required_ruby_version: !ruby/object:Gem::Requirement
64
70
  none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- hash: 3
69
- segments:
70
- - 0
71
- version: "0"
72
- required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
76
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- hash: 3
78
- segments:
79
- - 0
80
- version: "0"
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
81
  requirements: []
82
-
83
82
  rubyforge_project:
84
- rubygems_version: 1.3.7
83
+ rubygems_version: 1.8.24
85
84
  signing_key:
86
85
  specification_version: 3
87
86
  summary: A sinatra extension to run webseeded torrent tracker
88
87
  test_files: []
89
-