sinatra-torrent 0.0.3 → 0.0.4
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/Rakefile +0 -1
- data/Readme.md +31 -5
- data/VERSION +1 -1
- data/lib/sinatra/torrent/activerecord.rb +39 -4
- data/lib/sinatra/torrent/hashing.rb +83 -0
- data/lib/sinatra/torrent/helpers.rb +38 -0
- data/lib/sinatra/torrent.rb +29 -31
- data/sinatra-torrent.gemspec +5 -4
- metadata +6 -5
- data/views/torrents_index.haml +0 -5
    
        data/Rakefile
    CHANGED
    
    
    
        data/Readme.md
    CHANGED
    
    | @@ -15,13 +15,9 @@ Usage | |
| 15 15 |  | 
| 16 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…
         | 
| 17 17 |  | 
| 18 | 
            -
            **NB.** Files that take longer than 1s to hash will fail at the moment!
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            The extension is in it's early stages at the moment, so many of the settings aren't adhered to, and there are some issues with the webseeding… however it *does* work.
         | 
| 21 | 
            -
             | 
| 22 18 | 
             
            ### I want options!
         | 
| 23 19 |  | 
| 24 | 
            -
            There needs to be a database of torrents and peers, this is taken care of by a database adapter. Currently I've written (a  | 
| 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:
         | 
| 25 21 |  | 
| 26 22 | 
             
                require 'sinatra'
         | 
| 27 23 | 
             
                require 'sinatra/torrent/activerecord'
         | 
| @@ -31,6 +27,36 @@ There needs to be a database of torrents and peers, this is taken care of by a d | |
| 31 27 | 
             
                }
         | 
| 32 28 | 
             
                require 'sinatra/torrent'
         | 
| 33 29 |  | 
| 30 | 
            +
            Rake
         | 
| 31 | 
            +
            ----
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            If a torrent takes longer than 1 second to generate on-the-fly, it'll be added to a queue for processing in a background task. If you require a special script in your Rakefile you'll be able to process the queue, add to it or pre-hash all the files in your download directory:
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            	require 'rake'
         | 
| 36 | 
            +
            	
         | 
| 37 | 
            +
            	# These need to be the same adaptor and settings as your app, of course!
         | 
| 38 | 
            +
            	require 'sinatra/torrent/activerecord'
         | 
| 39 | 
            +
            	Sinatra::Torrent::Database.settings = {
         | 
| 40 | 
            +
            	  'adapter' => 'sqlite3',
         | 
| 41 | 
            +
            	  'database' => 'torrents.db'
         | 
| 42 | 
            +
            	}
         | 
| 43 | 
            +
            	require 'sinatra/torrent/hashing'
         | 
| 44 | 
            +
            	
         | 
| 45 | 
            +
            	# This line is optional, 'downloads' is the default
         | 
| 46 | 
            +
            	# If you've used `set :download_directory, 'files'` in your sinatra app, you need to do:
         | 
| 47 | 
            +
            	Sinatra::Torrent::DOWNLOAD_DIRECTORY = 'files'
         | 
| 48 | 
            +
            	
         | 
| 49 | 
            +
            	# The rest of your Rakefile
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            * `rake hash:add filename.ext` will add `filename.ext` inside your download directory to the hash queue
         | 
| 52 | 
            +
            * `rake hash:queue` will process all the hash jobs in the queue (you may want to set up a cron job to run this)
         | 
| 53 | 
            +
            * `rake hash:all` will hash all files in the downloads directory right now, so none will be processed on-the-fly when the .torrent file is downloaded
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            To Do
         | 
| 56 | 
            +
            -----
         | 
| 57 | 
            +
             | 
| 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.
         | 
| 59 | 
            +
             | 
| 34 60 | 
             
            Ummmm
         | 
| 35 61 | 
             
            -----
         | 
| 36 62 |  | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.4
         | 
| @@ -32,7 +32,11 @@ module Sinatra | |
| 32 32 | 
             
                        end
         | 
| 33 33 |  | 
| 34 34 | 
             
                        add_index :torrents, :infohash, :unique => true
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    end
         | 
| 35 37 |  | 
| 38 | 
            +
                    unless Peer.table_exists?
         | 
| 39 | 
            +
                      ActiveRecord::Schema.define do
         | 
| 36 40 | 
             
                        create_table :peers do |table|
         | 
| 37 41 | 
             
                          table.string :torrent_infohash, :null => false
         | 
| 38 42 | 
             
                          table.string :peer_id
         | 
| @@ -45,7 +49,19 @@ module Sinatra | |
| 45 49 | 
             
                          table.timestamps
         | 
| 46 50 | 
             
                        end
         | 
| 47 51 |  | 
| 48 | 
            -
                        add_index :peers, [:peer_id,:torrent_infohash] | 
| 52 | 
            +
                        add_index :peers, [:peer_id,:torrent_infohash], :unique => true
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                    
         | 
| 56 | 
            +
                    unless DelayedJob.table_exists?
         | 
| 57 | 
            +
                      ActiveRecord::Schema.define do
         | 
| 58 | 
            +
                        create_table :delayed_jobs do |table|
         | 
| 59 | 
            +
                          table.string :filename, :null => false
         | 
| 60 | 
            +
                          
         | 
| 61 | 
            +
                          table.timestamp :created_at
         | 
| 62 | 
            +
                        end
         | 
| 63 | 
            +
                    
         | 
| 64 | 
            +
                        add_index :delayed_jobs, :filename, :unique => true
         | 
| 49 65 | 
             
                      end
         | 
| 50 66 | 
             
                    end
         | 
| 51 67 | 
             
                  end
         | 
| @@ -129,15 +145,34 @@ module Sinatra | |
| 129 145 |  | 
| 130 146 | 
             
                    peer.save
         | 
| 131 147 | 
             
                  end
         | 
| 148 | 
            +
                  
         | 
| 149 | 
            +
                  
         | 
| 150 | 
            +
                  # Registers a file to be hashed offline
         | 
| 151 | 
            +
                  def add_hashjob(filename)
         | 
| 152 | 
            +
                    DelayedJob.find_or_create_by_filename(filename)
         | 
| 153 | 
            +
                    # return eta in seconds, where possible
         | 
| 154 | 
            +
                    nil
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
                
         | 
| 157 | 
            +
                  # Lists outstanding files to be hashed, by request date hopefully!
         | 
| 158 | 
            +
                  def list_hashjobs
         | 
| 159 | 
            +
                    DelayedJob.find(:all,:order => 'created_at DESC').collect{|dj| dj.filename}
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                
         | 
| 162 | 
            +
                  # Removes a file from the 'to be hashed' list
         | 
| 163 | 
            +
                  def remove_hashjob(filename)
         | 
| 164 | 
            +
                    DelayedJob.find_by_filename(filename).delete rescue false
         | 
| 165 | 
            +
                  end
         | 
| 132 166 |  | 
| 133 167 | 
             
                  private
         | 
| 168 | 
            +
                  
         | 
| 134 169 | 
             
                  class Torrent < ActiveRecord::Base
         | 
| 135 170 | 
             
                    serialize :metadata, Hash
         | 
| 136 171 | 
             
                  end
         | 
| 137 172 |  | 
| 138 | 
            -
                  class Peer < ActiveRecord::Base
         | 
| 139 | 
            -
             | 
| 140 | 
            -
                  end
         | 
| 173 | 
            +
                  class Peer < ActiveRecord::Base; end
         | 
| 174 | 
            +
                  
         | 
| 175 | 
            +
                  class DelayedJob < ActiveRecord::Base; end
         | 
| 141 176 | 
             
                end
         | 
| 142 177 | 
             
              end
         | 
| 143 178 | 
             
            end
         | 
| @@ -0,0 +1,83 @@ | |
| 1 | 
            +
            require 'sinatra/torrent/helpers'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            namespace :hash do
         | 
| 4 | 
            +
              begin
         | 
| 5 | 
            +
                torrent_db = Sinatra::Torrent::Database.new
         | 
| 6 | 
            +
              rescue NameError
         | 
| 7 | 
            +
                raise RuntimeError, "Please require a sinatra-torrent database adapter in your rakefile."
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              task :add do
         | 
| 11 | 
            +
                ARGV[1..-1].each do |rel_location|
         | 
| 12 | 
            +
                  if (File.exists?(File.join(Sinatra::Torrent::DOWNLOADS_DIRECTORY,rel_location)))
         | 
| 13 | 
            +
                    torrent_db.add_hashjob(rel_location)
         | 
| 14 | 
            +
                    $stdout.puts "added to queue: #{rel_location}"
         | 
| 15 | 
            +
                  else
         | 
| 16 | 
            +
                    $stderr.puts "#{rel_location} doesn't exist in the downloads directory"
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              task :all do
         | 
| 22 | 
            +
                completed = 0
         | 
| 23 | 
            +
                failed = 0
         | 
| 24 | 
            +
                
         | 
| 25 | 
            +
                Dir[File.join(Sinatra::Torrent::DOWNLOADS_DIRECTORY,'**')].each do |filename|
         | 
| 26 | 
            +
                  rel_location = filename[Sinatra::Torrent::DOWNLOADS_DIRECTORY.length+1..-1]
         | 
| 27 | 
            +
                  
         | 
| 28 | 
            +
                  begin
         | 
| 29 | 
            +
                    if !torrent_db.torrent_by_path_and_timestamp(rel_location,File.mtime(filename))
         | 
| 30 | 
            +
                      d = Sinatra::Torrent.create(filename)
         | 
| 31 | 
            +
                    
         | 
| 32 | 
            +
                      torrent_db.store_torrent(rel_location,File.mtime(filename),d['metadata'],d['infohash'])
         | 
| 33 | 
            +
                    
         | 
| 34 | 
            +
                      torrent_db.remove_hashjob(rel_location)
         | 
| 35 | 
            +
                      $stdout.puts "Hashed: #{rel_location}"
         | 
| 36 | 
            +
                      
         | 
| 37 | 
            +
                      completed += 1
         | 
| 38 | 
            +
                    else
         | 
| 39 | 
            +
                      $stdout.puts "Already hashed: #{rel_location}"
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  rescue
         | 
| 42 | 
            +
                    $stderr.puts "Not hashed: #{rel_location} (Unknown error)"
         | 
| 43 | 
            +
                    failed += 1
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
                
         | 
| 47 | 
            +
                $stdout.puts "#{completed} hash job#{(completed == 1) ? '' : 's'} completed sucessfully"
         | 
| 48 | 
            +
                $stderr.puts "#{failed} failed!" unless failed == 0
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
              
         | 
| 51 | 
            +
              task :queue do
         | 
| 52 | 
            +
                completed = 0
         | 
| 53 | 
            +
                failed = 0
         | 
| 54 | 
            +
                
         | 
| 55 | 
            +
                torrent_db.list_hashjobs.each do |rel_location|
         | 
| 56 | 
            +
                  filename = File.join(Sinatra::Torrent::DOWNLOADS_DIRECTORY,rel_location)
         | 
| 57 | 
            +
                  begin
         | 
| 58 | 
            +
                    if torrent_db.torrent_by_path_and_timestamp(rel_location,File.mtime(filename))
         | 
| 59 | 
            +
                      torrent_db.remove_hashjob(rel_location)
         | 
| 60 | 
            +
                    else
         | 
| 61 | 
            +
                      d = Sinatra::Torrent.create(filename)
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                      torrent_db.store_torrent(rel_location,File.mtime(filename),d['metadata'],d['infohash'])
         | 
| 64 | 
            +
                    
         | 
| 65 | 
            +
                      completed += 1
         | 
| 66 | 
            +
                      torrent_db.remove_hashjob(rel_location)
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  rescue Errno::ENOENT
         | 
| 69 | 
            +
                    $stderr.puts "#{rel_location} no longer exists to be hashed. Removing job."
         | 
| 70 | 
            +
                    torrent_db.remove_hashjob(rel_location)
         | 
| 71 | 
            +
                    
         | 
| 72 | 
            +
                    failed += 1
         | 
| 73 | 
            +
                  rescue
         | 
| 74 | 
            +
                    $stderr.puts "Uncaught failure reason for #{rel_location}"
         | 
| 75 | 
            +
                    # TODO: trace?
         | 
| 76 | 
            +
                    failed += 1
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
                
         | 
| 80 | 
            +
                $stdout.puts "#{completed} queued hash job#{(completed == 1) ? '' : 's'} completed sucessfully"
         | 
| 81 | 
            +
                $stderr.puts "#{failed} failed!" unless failed == 0
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            require 'time'
         | 
| 2 | 
            +
            require 'digest/sha1'
         | 
| 3 | 
            +
            require 'bencode'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Sinatra
         | 
| 6 | 
            +
              module Torrent
         | 
| 7 | 
            +
                DOWNLOADS_DIRECTORY = 'downloads'
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                def self.create(filename)
         | 
| 10 | 
            +
                  d = {
         | 
| 11 | 
            +
                    'metadata' => {
         | 
| 12 | 
            +
                      'created by' => "sinatra-torrent (#{File.read(File.expand_path(File.join(__FILE__,'..','..','..','..','VERSION'))).strip}) (http://github.com/jphastings/sinatra-torrent)",
         | 
| 13 | 
            +
                      'creation date' => Time.now.to_i,
         | 
| 14 | 
            +
                      'info' => {
         | 
| 15 | 
            +
                        'name' => File.basename(filename),
         | 
| 16 | 
            +
                        'length' => File.size(filename),
         | 
| 17 | 
            +
                        'piece length' => 2**10, # TODO: Choose reasonable piece size
         | 
| 18 | 
            +
                        'pieces' => ''
         | 
| 19 | 
            +
                      }
         | 
| 20 | 
            +
                    }
         | 
| 21 | 
            +
                  }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  begin
         | 
| 24 | 
            +
                    file = open(filename,'r')
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    begin
         | 
| 27 | 
            +
                      d['metadata']['info']['pieces'] += Digest::SHA1.digest(file.read(d['metadata']['info']['piece length']))
         | 
| 28 | 
            +
                    end until file.eof?
         | 
| 29 | 
            +
                  ensure
         | 
| 30 | 
            +
                    file.close
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  d['infohash'] = Digest::SHA1.hexdigest(d['metadata']['info'].bencode)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  return d
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
    
        data/lib/sinatra/torrent.rb
    CHANGED
    
    | @@ -1,8 +1,6 @@ | |
| 1 1 | 
             
            require 'timeout'
         | 
| 2 | 
            -
            require 'time'
         | 
| 3 | 
            -
            require 'digest/sha1'
         | 
| 4 | 
            -
            require 'bencode'
         | 
| 5 2 | 
             
            require 'sinatra/base'
         | 
| 3 | 
            +
            require 'sinatra/torrent/helpers'
         | 
| 6 4 |  | 
| 7 5 | 
             
            # This extension will serve up the contents of the specified folder as web seeded torrents.
         | 
| 8 6 | 
             
            # Both webseed versions are supported (shad0w's and GetRight's) and there is an inbuilt tracker
         | 
| @@ -16,7 +14,7 @@ module Sinatra | |
| 16 14 | 
             
                  # Putting the annouce URL of a tracker in here will use that tracker rather than the inbuilt one
         | 
| 17 15 | 
             
                  app.set :external_tracker, nil
         | 
| 18 16 | 
             
                  # Directory which holds all the files which will be provided as torrents
         | 
| 19 | 
            -
                  app.set :downloads_directory, File.dirname(__FILE__) | 
| 17 | 
            +
                  app.set :downloads_directory, File.join(File.dirname(__FILE__),Sinatra::Torrent::DOWNLOADS_DIRECTORY)
         | 
| 20 18 | 
             
                  # Mount point for the downloads directory
         | 
| 21 19 | 
             
                  app.set :downloads_mount, 'downloads'
         | 
| 22 20 | 
             
                  # Mount point for the torrents directory
         | 
| @@ -41,38 +39,31 @@ module Sinatra | |
| 41 39 | 
             
                    filename = File.join(options.downloads_directory, rel_location)
         | 
| 42 40 | 
             
                    halt(404, "That file doesn't exist! #{filename}") unless File.exists?(filename)
         | 
| 43 41 |  | 
| 44 | 
            -
                    if  | 
| 45 | 
            -
                      
         | 
| 46 | 
            -
                      d = {
         | 
| 47 | 
            -
                        'metadata' => {
         | 
| 48 | 
            -
                          # TODO: Version?
         | 
| 49 | 
            -
                          'created by' => 'sinatra-torrent (0.0.1) (http://github.com/jphastings/sinatra-torrent)',
         | 
| 50 | 
            -
                          'creation date' => Time.now.to_i,
         | 
| 51 | 
            -
                          'info' => {
         | 
| 52 | 
            -
                            'name' => File.basename(rel_location),
         | 
| 53 | 
            -
                            'length' => File.size(filename),
         | 
| 54 | 
            -
                            'piece length' => 2**10, # TODO: Choose reasonable piece size
         | 
| 55 | 
            -
                            'pieces' => ''
         | 
| 56 | 
            -
                          }
         | 
| 57 | 
            -
                        }
         | 
| 58 | 
            -
                      }
         | 
| 42 | 
            +
                    if !(d = options.database_adapter.torrent_by_path_and_timestamp(filename,File.mtime(filename)))
         | 
| 59 43 |  | 
| 60 44 | 
             
                      begin
         | 
| 61 | 
            -
                        file = open(filename,'r')
         | 
| 62 | 
            -
                        
         | 
| 63 45 | 
             
                        Timeout::timeout(1) do
         | 
| 64 | 
            -
                           | 
| 65 | 
            -
                            d['metadata']['info']['pieces'] += Digest::SHA1.digest(file.read(d['metadata']['info']['piece length']))
         | 
| 66 | 
            -
                          end until file.eof?
         | 
| 46 | 
            +
                          d = Sinatra::Torrent.create(filename)
         | 
| 67 47 | 
             
                        end
         | 
| 68 48 | 
             
                      rescue Timeout::Error
         | 
| 69 | 
            -
                         | 
| 70 | 
            -
                         | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 49 | 
            +
                        eta = options.database_adapter.add_hashjob(filename)
         | 
| 50 | 
            +
                        
         | 
| 51 | 
            +
                        begin
         | 
| 52 | 
            +
                          wait = case (eta/60).floor
         | 
| 53 | 
            +
                          when 0
         | 
| 54 | 
            +
                            'under a minute'
         | 
| 55 | 
            +
                          when 1
         | 
| 56 | 
            +
                            'about a minute'
         | 
| 57 | 
            +
                          else
         | 
| 58 | 
            +
                            "about #{(eta/60).floor} minutes"
         | 
| 59 | 
            +
                          end
         | 
| 60 | 
            +
                        rescue NoMethodError
         | 
| 61 | 
            +
                          wait = "a short while"
         | 
| 62 | 
            +
                        end
         | 
| 63 | 
            +
                        
         | 
| 64 | 
            +
                        halt(503,"This torrent is taking too long to build, we're running it in the background. Please try again in #{wait}.")
         | 
| 73 65 | 
             
                      end
         | 
| 74 66 |  | 
| 75 | 
            -
                      d['infohash'] = Digest::SHA1.hexdigest(d['metadata']['info'].bencode)
         | 
| 76 67 | 
             
                      options.database_adapter.store_torrent(filename,File.mtime(filename),d['metadata'],d['infohash'])
         | 
| 77 68 | 
             
                    end
         | 
| 78 69 |  | 
| @@ -128,8 +119,15 @@ module Sinatra | |
| 128 119 | 
             
                  end
         | 
| 129 120 |  | 
| 130 121 | 
             
            # INDEX PAGE
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                  # TODO: Have a 'fallback' index view?
         | 
| 131 124 | 
             
                  app.get "/#{app.options.torrents_mount}/" do
         | 
| 132 | 
            -
                     | 
| 125 | 
            +
                    locals = {:torrents => (Dir.glob("#{options.downloads_directory}/**").collect {|f| f[options.downloads_directory.length+1..-1] } rescue [])}
         | 
| 126 | 
            +
                    begin
         | 
| 127 | 
            +
                      haml :torrents_index,:locals => locals
         | 
| 128 | 
            +
                    rescue Errno::ENOENT
         | 
| 129 | 
            +
                      "<ul>"<<locals[:torrents].collect{|t| "<li><a href=\"/#{options.torrents_mount}/#{t}.torrent\">#{t}</a></li>" }.join<<"</ul>"
         | 
| 130 | 
            +
                    end
         | 
| 133 131 | 
             
                  end
         | 
| 134 132 |  | 
| 135 133 | 
             
            # DATA
         | 
| @@ -158,4 +156,4 @@ module Sinatra | |
| 158 156 | 
             
              end
         | 
| 159 157 |  | 
| 160 158 | 
             
              register Torrent
         | 
| 161 | 
            -
            end
         | 
| 159 | 
            +
            end
         | 
    
        data/sinatra-torrent.gemspec
    CHANGED
    
    | @@ -5,11 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |s|
         | 
| 7 7 | 
             
              s.name = %q{sinatra-torrent}
         | 
| 8 | 
            -
              s.version = "0.0. | 
| 8 | 
            +
              s.version = "0.0.4"
         | 
| 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- | 
| 12 | 
            +
              s.date = %q{2011-02-09}
         | 
| 13 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 14 | 
             
              s.email = %q{jphastings@gmail.com}
         | 
| 15 15 | 
             
              s.files = [
         | 
| @@ -18,8 +18,9 @@ Gem::Specification.new do |s| | |
| 18 18 | 
             
                 "VERSION",
         | 
| 19 19 | 
             
                 "lib/sinatra/torrent.rb",
         | 
| 20 20 | 
             
                 "lib/sinatra/torrent/activerecord.rb",
         | 
| 21 | 
            -
                 "sinatra | 
| 22 | 
            -
                 " | 
| 21 | 
            +
                 "lib/sinatra/torrent/hashing.rb",
         | 
| 22 | 
            +
                 "lib/sinatra/torrent/helpers.rb",
         | 
| 23 | 
            +
                 "sinatra-torrent.gemspec"
         | 
| 23 24 | 
             
              ]
         | 
| 24 25 | 
             
              s.homepage = %q{http://github.com/jphastings/sinatra-torrent}
         | 
| 25 26 | 
             
              s.rdoc_options = ["--charset=UTF-8"]
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: sinatra-torrent
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 23
         | 
| 5 5 | 
             
              prerelease: false
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 0
         | 
| 8 8 | 
             
              - 0
         | 
| 9 | 
            -
              -  | 
| 10 | 
            -
              version: 0.0. | 
| 9 | 
            +
              - 4
         | 
| 10 | 
            +
              version: 0.0.4
         | 
| 11 11 | 
             
            platform: ruby
         | 
| 12 12 | 
             
            authors: 
         | 
| 13 13 | 
             
            - JP Hastings-Spital
         | 
| @@ -15,7 +15,7 @@ autorequire: | |
| 15 15 | 
             
            bindir: bin
         | 
| 16 16 | 
             
            cert_chain: []
         | 
| 17 17 |  | 
| 18 | 
            -
            date: 2011-02- | 
| 18 | 
            +
            date: 2011-02-09 00:00:00 +00:00
         | 
| 19 19 | 
             
            default_executable: 
         | 
| 20 20 | 
             
            dependencies: 
         | 
| 21 21 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -48,8 +48,9 @@ files: | |
| 48 48 | 
             
            - VERSION
         | 
| 49 49 | 
             
            - lib/sinatra/torrent.rb
         | 
| 50 50 | 
             
            - lib/sinatra/torrent/activerecord.rb
         | 
| 51 | 
            +
            - lib/sinatra/torrent/hashing.rb
         | 
| 52 | 
            +
            - lib/sinatra/torrent/helpers.rb
         | 
| 51 53 | 
             
            - sinatra-torrent.gemspec
         | 
| 52 | 
            -
            - views/torrents_index.haml
         | 
| 53 54 | 
             
            has_rdoc: true
         | 
| 54 55 | 
             
            homepage: http://github.com/jphastings/sinatra-torrent
         | 
| 55 56 | 
             
            licenses: []
         |