gem_on_demand 1.0.0
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/MIT-LICENSE.txt +20 -0
- data/lib/gem_on_demand/cli.rb +49 -0
- data/lib/gem_on_demand/server.rb +30 -0
- data/lib/gem_on_demand/version.rb +3 -0
- data/lib/gem_on_demand.rb +173 -0
- data.tar.gz.sig +0 -0
- metadata +85 -0
- metadata.gz.sig +3 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 517e2aeefdc0e9f09c3432de6c218d87f6f67587
         | 
| 4 | 
            +
              data.tar.gz: 2d79c118bec199a2af27b74a90096ce852bc0840
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: e8f8848702f5eacf1480cc2468337c4fc1cc9516f1b944a88cbc513fd8dae8558d01f6e7b49fda3eb66b5f99ea26964e81eebf248a5a626498780e5f9cc7d8c3
         | 
| 7 | 
            +
              data.tar.gz: 78b4e5368d71432e328e1c1547dc8d48a2ac1146cea2b95c9d99eebd8fa32126e8bf9940d7d9173c8682dd7d44a6896b50d04f125764654337a153e23d41837f
         | 
    
        checksums.yaml.gz.sig
    ADDED
    
    | Binary file | 
    
        data/MIT-LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            Copyright (C) 2013 Michael Grosser <michael@grosser.it>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            the following conditions:
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            require 'optparse'
         | 
| 2 | 
            +
            require 'gem_on_demand/version'
         | 
| 3 | 
            +
            require 'gem_on_demand/server'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module GemOnDemand
         | 
| 6 | 
            +
              class CLI
         | 
| 7 | 
            +
                class << self
         | 
| 8 | 
            +
                  def run(argv)
         | 
| 9 | 
            +
                    options = parse_options(argv)
         | 
| 10 | 
            +
                    if expire = options[:expire]
         | 
| 11 | 
            +
                      GemOnDemand.expire(*expire.split("/"))
         | 
| 12 | 
            +
                    else
         | 
| 13 | 
            +
                      GemOnDemand::Server.run!(options)
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                    0
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  private
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def parse_options(argv)
         | 
| 21 | 
            +
                    options = {}
         | 
| 22 | 
            +
                    parser = OptionParser.new do |opts|
         | 
| 23 | 
            +
                      opts.banner = <<-BANNER.gsub(/^ {12}/, "")
         | 
| 24 | 
            +
                        Run your own gem server that fetches from github, uses tags as version and builds gems on demand
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                        Usage:
         | 
| 27 | 
            +
                            gem-on-demand --server
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                        Options:
         | 
| 30 | 
            +
                      BANNER
         | 
| 31 | 
            +
                      opts.on("-s", "--server", "Start server") { options[:server] = true }
         | 
| 32 | 
            +
                      opts.on("-e", "--expire NAME", String, "Expire gem cache for {user}/{project}") { |name| options[:expire] = name }
         | 
| 33 | 
            +
                      opts.on("-p", "--port PORT", Integer, "Port for server (default #{GemOnDemand::Server.port})") { |port| options[:port] = port }
         | 
| 34 | 
            +
                      opts.on("-h", "--help", "Show this.") { puts opts; exit }
         | 
| 35 | 
            +
                      opts.on("-v", "--version", "Show Version"){ puts GemOnDemand::VERSION; exit}
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    parser.parse!(argv)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    # force server for now ...
         | 
| 40 | 
            +
                    if !options.delete(:server) && !options[:expire]
         | 
| 41 | 
            +
                      puts parser
         | 
| 42 | 
            +
                      exit 1
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    options
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require 'sinatra/base'
         | 
| 2 | 
            +
            require 'gem_on_demand'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module GemOnDemand
         | 
| 5 | 
            +
              class Server < Sinatra::Base
         | 
| 6 | 
            +
                set :port, 7154
         | 
| 7 | 
            +
                set :lock, true # multi threading is not supported when doing chdir foo
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                get '/:username/api/v1/dependencies' do
         | 
| 10 | 
            +
                  user = params[:username]
         | 
| 11 | 
            +
                  if gems = params[:gems]
         | 
| 12 | 
            +
                    dependencies = GemOnDemand.dependencies(user, gems.split(","))
         | 
| 13 | 
            +
                    if params[:debug]
         | 
| 14 | 
            +
                      dependencies.inspect
         | 
| 15 | 
            +
                    else
         | 
| 16 | 
            +
                      Marshal.dump(dependencies)
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  else
         | 
| 19 | 
            +
                    "" # first request wants no response ...
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                get '/:username/gems/:project-:version.gem' do
         | 
| 24 | 
            +
                  user = params[:username]
         | 
| 25 | 
            +
                  project = params[:project]
         | 
| 26 | 
            +
                  version = params[:version]
         | 
| 27 | 
            +
                  GemOnDemand.build_gem(user, project, version)
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,173 @@ | |
| 1 | 
            +
            require 'tmpdir'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module GemOnDemand
         | 
| 4 | 
            +
              PROJECT_CACHE = File.expand_path("~/.gem-on-demand/cache")
         | 
| 5 | 
            +
              DATA_CACHE = "cache"
         | 
| 6 | 
            +
              CACHE_DURATION = 15 * 60 # for project tags
         | 
| 7 | 
            +
              ProjectNotFound = Class.new(Exception)
         | 
| 8 | 
            +
              VERSION_REX = /^v?\d+\.\d+\.\d+(\.\w+)?$/ # with or without v and pre-release (cannot do others or we get: 'Malformed version number string 1.0.0-rails3' from bundler)
         | 
| 9 | 
            +
              HEAVY_FORKED = ["rails", "mysql", "mysql2"]
         | 
| 10 | 
            +
              MAX_VERSIONS = 50 # some projects just have a million versions ...
         | 
| 11 | 
            +
              DEPENDENCIES = "dependencies"
         | 
| 12 | 
            +
              NOT_FOUND = "not-found"
         | 
| 13 | 
            +
              UPDATED_AT = "updated_at"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              class << self
         | 
| 16 | 
            +
                def build_gem(user, project, version)
         | 
| 17 | 
            +
                  inside_of_project(user, project) do
         | 
| 18 | 
            +
                    cache("gem-#{version}") do
         | 
| 19 | 
            +
                      checkout_version("v#{version}")
         | 
| 20 | 
            +
                      gemspec = "#{project}.gemspec"
         | 
| 21 | 
            +
                      remove_signing(gemspec)
         | 
| 22 | 
            +
                      sh("gem build #{gemspec}")
         | 
| 23 | 
            +
                      File.read("#{project}-#{version}.gem")
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def dependencies(user, gems)
         | 
| 29 | 
            +
                  (gems - HEAVY_FORKED).map do |project|
         | 
| 30 | 
            +
                    project_dependencies(user, project)
         | 
| 31 | 
            +
                  end.flatten
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def expire(user, project)
         | 
| 35 | 
            +
                  remove_directory "#{PROJECT_CACHE}/#{user}/#{project}/#{DATA_CACHE}"
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                private
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def project_dependencies(user, project)
         | 
| 41 | 
            +
                  inside_of_project(user, project) do
         | 
| 42 | 
            +
                    cache DEPENDENCIES do
         | 
| 43 | 
            +
                      versions_for_project.last(MAX_VERSIONS).map do |version|
         | 
| 44 | 
            +
                        next unless dependencies = dependencies_for_version(project, version)
         | 
| 45 | 
            +
                        {
         | 
| 46 | 
            +
                          :name => project,
         | 
| 47 | 
            +
                          :number => version.sub(/^v/, ""),
         | 
| 48 | 
            +
                          :platform => "ruby",
         | 
| 49 | 
            +
                          :dependencies => Marshal.load(dependencies)
         | 
| 50 | 
            +
                        }
         | 
| 51 | 
            +
                      end.compact
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                rescue ProjectNotFound
         | 
| 55 | 
            +
                  []
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def versions_for_project
         | 
| 59 | 
            +
                  sh("git tag").split($/).grep(VERSION_REX)
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def dependencies_for_version(project, version)
         | 
| 63 | 
            +
                  cache "dependencies-#{version}" do
         | 
| 64 | 
            +
                    checkout_version(version)
         | 
| 65 | 
            +
                    sh(%{ruby -e 'print Marshal.dump(eval(File.read("#{project}.gemspec")).runtime_dependencies.map{|d| [d.name, d.requirement.to_s]})'}, :fail => :allow)
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                def cache(file, value = nil, &block)
         | 
| 70 | 
            +
                  ensure_directory(DATA_CACHE)
         | 
| 71 | 
            +
                  file = "#{DATA_CACHE}/#{file}"
         | 
| 72 | 
            +
                  if block
         | 
| 73 | 
            +
                    if File.exist?(file)
         | 
| 74 | 
            +
                      Marshal.load(File.read(file))
         | 
| 75 | 
            +
                    else
         | 
| 76 | 
            +
                      result = yield
         | 
| 77 | 
            +
                      File.write(file, Marshal.dump(result))
         | 
| 78 | 
            +
                      result
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  else
         | 
| 81 | 
            +
                    if value.nil?
         | 
| 82 | 
            +
                      Marshal.load(File.read(file)) if File.exist?(file)
         | 
| 83 | 
            +
                    else
         | 
| 84 | 
            +
                      File.write(file, Marshal.dump(value))
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def expire_key(key)
         | 
| 90 | 
            +
                  key = "#{DATA_CACHE}/#{key}"
         | 
| 91 | 
            +
                  File.unlink(key) if File.exist?(key)
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                def sh(command, options = { })
         | 
| 95 | 
            +
                  puts command
         | 
| 96 | 
            +
                  result = `#{command}`
         | 
| 97 | 
            +
                  if $?.success?
         | 
| 98 | 
            +
                    result
         | 
| 99 | 
            +
                  elsif options[:fail] == :allow
         | 
| 100 | 
            +
                    false
         | 
| 101 | 
            +
                  else
         | 
| 102 | 
            +
                    raise "Command failed: #{result}"
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def inside_of_project(user, project, &block)
         | 
| 107 | 
            +
                  dir = "#{PROJECT_CACHE}/#{user}"
         | 
| 108 | 
            +
                  ensure_directory(dir)
         | 
| 109 | 
            +
                  Dir.chdir(dir) do
         | 
| 110 | 
            +
                    clone_or_refresh_project(user, project)
         | 
| 111 | 
            +
                    Dir.chdir(project, &block)
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                def ensure_directory(dir)
         | 
| 116 | 
            +
                  FileUtils.mkdir_p(dir) unless File.directory?(dir)
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                def clone_or_refresh_project(user, project)
         | 
| 120 | 
            +
                  if File.directory?("#{project}/.git")
         | 
| 121 | 
            +
                    if refresh?(project)
         | 
| 122 | 
            +
                      Dir.chdir(project) do
         | 
| 123 | 
            +
                        sh "git fetch origin"
         | 
| 124 | 
            +
                        expire_key DEPENDENCIES
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                      refreshed!(project)
         | 
| 127 | 
            +
                    end
         | 
| 128 | 
            +
                  elsif not_found?(project)
         | 
| 129 | 
            +
                    raise ProjectNotFound
         | 
| 130 | 
            +
                  else
         | 
| 131 | 
            +
                    remove_directory(project)
         | 
| 132 | 
            +
                    found = sh "git clone git@github.com:#{user}/#{project}.git", :fail => :allow
         | 
| 133 | 
            +
                    if found
         | 
| 134 | 
            +
                      refreshed!(project)
         | 
| 135 | 
            +
                    else
         | 
| 136 | 
            +
                      not_found!(project)
         | 
| 137 | 
            +
                      raise ProjectNotFound
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                def remove_directory(project)
         | 
| 143 | 
            +
                  FileUtils.rm_rf(project) if File.exist?(project)
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                def not_found?(project)
         | 
| 147 | 
            +
                  File.directory?(project) && Dir.chdir(project) { cache(NOT_FOUND) }
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                def not_found!(project)
         | 
| 151 | 
            +
                  ensure_directory(project)
         | 
| 152 | 
            +
                  Dir.chdir(project) { cache(NOT_FOUND, true) }
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                def refreshed!(project)
         | 
| 156 | 
            +
                  Dir.chdir(project) { cache(UPDATED_AT, Time.now.to_i) }
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                def refresh?(project)
         | 
| 160 | 
            +
                  Dir.chdir(project) { cache(UPDATED_AT).to_i } < Time.now.to_i - CACHE_DURATION
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                def checkout_version(version)
         | 
| 164 | 
            +
                  sh("git checkout #{version} --force")
         | 
| 165 | 
            +
                end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                # ERROR:  While executing gem ... (Gem::Security::Exception)
         | 
| 168 | 
            +
                # certificate /CN=michael/DC=grosser/DC=it not valid after 2014-02-03 18:13:11 UTC
         | 
| 169 | 
            +
                def remove_signing(gemspec)
         | 
| 170 | 
            +
                  File.write(gemspec, File.read(gemspec).gsub(/.*\.(signing_key|cert_chain).*/, ""))
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
              end
         | 
| 173 | 
            +
            end
         | 
    
        data.tar.gz.sig
    ADDED
    
    | Binary file | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,85 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: gem_on_demand
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Michael Grosser
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain:
         | 
| 11 | 
            +
            - |
         | 
| 12 | 
            +
              -----BEGIN CERTIFICATE-----
         | 
| 13 | 
            +
              MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
         | 
| 14 | 
            +
              YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
         | 
| 15 | 
            +
              MB4XDTE0MDIwNDIwMjk0MVoXDTE1MDIwNDIwMjk0MVowPzEQMA4GA1UEAwwHbWlj
         | 
| 16 | 
            +
              aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
         | 
| 17 | 
            +
              dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
         | 
| 18 | 
            +
              MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
         | 
| 19 | 
            +
              cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
         | 
| 20 | 
            +
              6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
         | 
| 21 | 
            +
              h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
         | 
| 22 | 
            +
              FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
         | 
| 23 | 
            +
              /88CAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFLIj
         | 
| 24 | 
            +
              Z1x7SnjGGHK+MiVZkFjjS/iMMB0GA1UdEQQWMBSBEm1pY2hhZWxAZ3Jvc3Nlci5p
         | 
| 25 | 
            +
              dDAdBgNVHRIEFjAUgRJtaWNoYWVsQGdyb3NzZXIuaXQwDQYJKoZIhvcNAQEFBQAD
         | 
| 26 | 
            +
              ggEBAExBcUWfGuamYn+IddOA0Ws8jUKwB14RXoZRDrTiTAlMm3Bkg2OKyxS3uJXa
         | 
| 27 | 
            +
              6Z+LwFiZwVYk62yHXqNzEJycQk4SEmY+xDWLj0p7X6qEeU4QZKwR1TwJ5z3PTrZ6
         | 
| 28 | 
            +
              irJgM3q7NIBRvmTzRaAghWcQn+Eyr5YLOfMksjVBMUMnzh5/ZDgq53LphgJbGwvz
         | 
| 29 | 
            +
              ScJAgfNclLHnjk9q1mT1s0e1FPWbiAL3siBIR5HpH8qtSEiivTf2ntciebOqS93f
         | 
| 30 | 
            +
              F5etKHZg0j3eHO31/i2HnswY04lqGImUu6aM5EnijFTB7PPW2KwKKM4+kKDYFdlw
         | 
| 31 | 
            +
              /0WV1Ng2/Y6qsHwmqGg2VlYj2h4=
         | 
| 32 | 
            +
              -----END CERTIFICATE-----
         | 
| 33 | 
            +
            date: 2014-03-01 00:00:00.000000000 Z
         | 
| 34 | 
            +
            dependencies:
         | 
| 35 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 36 | 
            +
              name: sinatra
         | 
| 37 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 38 | 
            +
                requirements:
         | 
| 39 | 
            +
                - - '>='
         | 
| 40 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 41 | 
            +
                    version: '0'
         | 
| 42 | 
            +
              type: :runtime
         | 
| 43 | 
            +
              prerelease: false
         | 
| 44 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 45 | 
            +
                requirements:
         | 
| 46 | 
            +
                - - '>='
         | 
| 47 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 48 | 
            +
                    version: '0'
         | 
| 49 | 
            +
            description: 
         | 
| 50 | 
            +
            email: michael@grosser.it
         | 
| 51 | 
            +
            executables: []
         | 
| 52 | 
            +
            extensions: []
         | 
| 53 | 
            +
            extra_rdoc_files: []
         | 
| 54 | 
            +
            files:
         | 
| 55 | 
            +
            - MIT-LICENSE.txt
         | 
| 56 | 
            +
            - lib/gem_on_demand.rb
         | 
| 57 | 
            +
            - lib/gem_on_demand/cli.rb
         | 
| 58 | 
            +
            - lib/gem_on_demand/server.rb
         | 
| 59 | 
            +
            - lib/gem_on_demand/version.rb
         | 
| 60 | 
            +
            homepage: https://github.com/grosser/gem_on_demand
         | 
| 61 | 
            +
            licenses:
         | 
| 62 | 
            +
            - MIT
         | 
| 63 | 
            +
            metadata: {}
         | 
| 64 | 
            +
            post_install_message: 
         | 
| 65 | 
            +
            rdoc_options: []
         | 
| 66 | 
            +
            require_paths:
         | 
| 67 | 
            +
            - lib
         | 
| 68 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 69 | 
            +
              requirements:
         | 
| 70 | 
            +
              - - '>='
         | 
| 71 | 
            +
                - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                  version: '0'
         | 
| 73 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 74 | 
            +
              requirements:
         | 
| 75 | 
            +
              - - '>='
         | 
| 76 | 
            +
                - !ruby/object:Gem::Version
         | 
| 77 | 
            +
                  version: '0'
         | 
| 78 | 
            +
            requirements: []
         | 
| 79 | 
            +
            rubyforge_project: 
         | 
| 80 | 
            +
            rubygems_version: 2.0.14
         | 
| 81 | 
            +
            signing_key: 
         | 
| 82 | 
            +
            specification_version: 4
         | 
| 83 | 
            +
            summary: Run your own gem server that fetches from github, uses tags as version and
         | 
| 84 | 
            +
              builds gems on demand
         | 
| 85 | 
            +
            test_files: []
         | 
    
        metadata.gz.sig
    ADDED