github-downloads 0.1.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.
- data/Gemfile +11 -0
 - data/Gemfile.lock +55 -0
 - data/README.md +25 -0
 - data/Rakefile +102 -0
 - data/bin/github-downloads +5 -0
 - data/lib/github.rb +2 -0
 - data/lib/github/client.rb +142 -0
 - data/lib/github/downloads.rb +66 -0
 - data/lib/github/downloads_controller.rb +109 -0
 - data/lib/github/s3_uploader.rb +24 -0
 - data/spec/fixtures/textfile.txt +0 -0
 - data/spec/github_client_spec.rb +211 -0
 - data/spec/github_download_spec.rb +87 -0
 - data/spec/spec_helper.rb +26 -0
 - metadata +229 -0
 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            PATH
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: .
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                github-downloads (0.1.0)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  highline (~> 1.6.2)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  hirb (~> 0.4.5)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  json (~> 1.5.3)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  mime-types (~> 1.16.0)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rest-client (~> 1.6.3)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  simpleconsole (~> 0.1.1)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 13 
     | 
    
         
            +
              remote: http://rubygems.org/
         
     | 
| 
      
 14 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 15 
     | 
    
         
            +
                awesome_print (0.3.1)
         
     | 
| 
      
 16 
     | 
    
         
            +
                diff-lcs (1.1.2)
         
     | 
| 
      
 17 
     | 
    
         
            +
                highline (1.6.2)
         
     | 
| 
      
 18 
     | 
    
         
            +
                hirb (0.4.5)
         
     | 
| 
      
 19 
     | 
    
         
            +
                json (1.5.3)
         
     | 
| 
      
 20 
     | 
    
         
            +
                mime-types (1.16)
         
     | 
| 
      
 21 
     | 
    
         
            +
                mimic (0.4.1)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  json
         
     | 
| 
      
 23 
     | 
    
         
            +
                  plist
         
     | 
| 
      
 24 
     | 
    
         
            +
                  rack
         
     | 
| 
      
 25 
     | 
    
         
            +
                  sinatra
         
     | 
| 
      
 26 
     | 
    
         
            +
                mocha (0.9.10)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  rake
         
     | 
| 
      
 28 
     | 
    
         
            +
                plist (3.1.0)
         
     | 
| 
      
 29 
     | 
    
         
            +
                rack (1.2.1)
         
     | 
| 
      
 30 
     | 
    
         
            +
                rake (0.9.2)
         
     | 
| 
      
 31 
     | 
    
         
            +
                rest-client (1.6.3)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  mime-types (>= 1.16)
         
     | 
| 
      
 33 
     | 
    
         
            +
                rspec (2.5.0)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  rspec-core (~> 2.5.0)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  rspec-expectations (~> 2.5.0)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  rspec-mocks (~> 2.5.0)
         
     | 
| 
      
 37 
     | 
    
         
            +
                rspec-core (2.5.2)
         
     | 
| 
      
 38 
     | 
    
         
            +
                rspec-expectations (2.5.0)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  diff-lcs (~> 1.1.2)
         
     | 
| 
      
 40 
     | 
    
         
            +
                rspec-mocks (2.5.0)
         
     | 
| 
      
 41 
     | 
    
         
            +
                simpleconsole (0.1.1)
         
     | 
| 
      
 42 
     | 
    
         
            +
                sinatra (1.1.2)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  rack (~> 1.1)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  tilt (~> 1.2)
         
     | 
| 
      
 45 
     | 
    
         
            +
                tilt (1.2.2)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 48 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 51 
     | 
    
         
            +
              awesome_print
         
     | 
| 
      
 52 
     | 
    
         
            +
              github-downloads!
         
     | 
| 
      
 53 
     | 
    
         
            +
              mimic
         
     | 
| 
      
 54 
     | 
    
         
            +
              mocha
         
     | 
| 
      
 55 
     | 
    
         
            +
              rspec
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # github-downloads - a gem for managing your downloads, on Github
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This is a simple gem that does exactly what it says on the tin: manages your Github project downloads.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                $ gem install github-downloads
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            It can be used to list the downloads for your project:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                $ github-downloads list -u lukeredpath -r simpleconfig
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
            It can also be used to create a new download:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                $ github-downloads create -u lukeredpath -r simpleconfig -f ~/myproject/somefile.zip -d "This is an important file"
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
            ### Github::Client, a generic Github API client
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            The gem is built on top of [version 3 of the Github API](http://developer.github.com/v3/); included in the source is a class, Github::Client, a simple wrapper around the Github API that uses RestClient and simplifies communication with the Github API. 
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            It provides a simple interface to the Github REST API. It handles errors appropriately and returns parsed response data as well as additional metadata such as API rate limits. 
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            It doesn't aim to be a full-blown Github API library (completely with a local domain model) but a very thin utility ckass that can be used to write other simple scripts and gems, like this one. Feel free to use this in your own project if you are working with the Github API.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ### License
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            This code is provided under the terms of the MIT license.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,102 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rdoc/task'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            desc "Run all examples"
         
     | 
| 
      
 7 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:specs)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            task :default => :specs
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            require "rubygems"
         
     | 
| 
      
 12 
     | 
    
         
            +
            require "rubygems/package_task"
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            GEM_VERSION = "0.1.0"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            # This builds the actual gem. For details of what all these options
         
     | 
| 
      
 17 
     | 
    
         
            +
            # mean, and other ones you can add, check the documentation here:
         
     | 
| 
      
 18 
     | 
    
         
            +
            #
         
     | 
| 
      
 19 
     | 
    
         
            +
            #   http://rubygems.org/read/chapter/20
         
     | 
| 
      
 20 
     | 
    
         
            +
            #
         
     | 
| 
      
 21 
     | 
    
         
            +
            spec = Gem::Specification.new do |s|
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # Change these as appropriate
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.name              = "github-downloads"
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.version           = GEM_VERSION
         
     | 
| 
      
 26 
     | 
    
         
            +
              s.summary           = "Manages downloads for your Github projects"
         
     | 
| 
      
 27 
     | 
    
         
            +
              s.author            = "Luke Redpath"
         
     | 
| 
      
 28 
     | 
    
         
            +
              s.email             = "luke@lukeredpath.co.uk"
         
     | 
| 
      
 29 
     | 
    
         
            +
              s.homepage          = "http://lukeredpath.co.uk"
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              s.has_rdoc          = false
         
     | 
| 
      
 32 
     | 
    
         
            +
              # s.extra_rdoc_files  = %w(README)
         
     | 
| 
      
 33 
     | 
    
         
            +
              # s.rdoc_options      = %w(--main README)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              # Add any extra files to include in the gem
         
     | 
| 
      
 36 
     | 
    
         
            +
              s.files             = %w(Gemfile Gemfile.lock Rakefile README.md) + Dir.glob("{bin,spec,lib}/**/*")
         
     | 
| 
      
 37 
     | 
    
         
            +
              s.executables       = FileList["bin/**"].map { |f| File.basename(f) }
         
     | 
| 
      
 38 
     | 
    
         
            +
              s.require_paths     = ["lib"]
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              # If you want to depend on other gems, add them here, along with any
         
     | 
| 
      
 41 
     | 
    
         
            +
              # relevant versions
         
     | 
| 
      
 42 
     | 
    
         
            +
              gem "rest-client"
         
     | 
| 
      
 43 
     | 
    
         
            +
              gem "json"
         
     | 
| 
      
 44 
     | 
    
         
            +
              gem "simpleconsole"
         
     | 
| 
      
 45 
     | 
    
         
            +
              gem "hirb"
         
     | 
| 
      
 46 
     | 
    
         
            +
              gem "mime-types"
         
     | 
| 
      
 47 
     | 
    
         
            +
              gem "highline"
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
              s.add_dependency("rest-client", "~> 1.6.3")
         
     | 
| 
      
 50 
     | 
    
         
            +
              s.add_dependency("json", "~> 1.5.3")
         
     | 
| 
      
 51 
     | 
    
         
            +
              s.add_dependency("simpleconsole", "~> 0.1.1")
         
     | 
| 
      
 52 
     | 
    
         
            +
              s.add_dependency("hirb", "~> 0.4.5")
         
     | 
| 
      
 53 
     | 
    
         
            +
              s.add_dependency("mime-types", "~> 1.16.0")
         
     | 
| 
      
 54 
     | 
    
         
            +
              s.add_dependency("highline", "~> 1.6.2")
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              # If your tests use any gems, include them here
         
     | 
| 
      
 57 
     | 
    
         
            +
              s.add_development_dependency("rspec")
         
     | 
| 
      
 58 
     | 
    
         
            +
              s.add_development_dependency("mocha")
         
     | 
| 
      
 59 
     | 
    
         
            +
              s.add_development_dependency("mimic")
         
     | 
| 
      
 60 
     | 
    
         
            +
              s.add_development_dependency("awesome_print")
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            # This task actually builds the gem. We also regenerate a static
         
     | 
| 
      
 64 
     | 
    
         
            +
            # .gemspec file, which is useful if something (i.e. GitHub) will
         
     | 
| 
      
 65 
     | 
    
         
            +
            # be automatically building a gem for this project. If you're not
         
     | 
| 
      
 66 
     | 
    
         
            +
            # using GitHub, edit as appropriate.
         
     | 
| 
      
 67 
     | 
    
         
            +
            #
         
     | 
| 
      
 68 
     | 
    
         
            +
            # To publish your gem online, install the 'gemcutter' gem; Read more 
         
     | 
| 
      
 69 
     | 
    
         
            +
            # about that here: http://gemcutter.org/pages/gem_docs
         
     | 
| 
      
 70 
     | 
    
         
            +
            Gem::PackageTask.new(spec) do |pkg|
         
     | 
| 
      
 71 
     | 
    
         
            +
              pkg.gem_spec = spec
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            desc "Build the gemspec file #{spec.name}.gemspec"
         
     | 
| 
      
 75 
     | 
    
         
            +
            task :gemspec do
         
     | 
| 
      
 76 
     | 
    
         
            +
              file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
         
     | 
| 
      
 77 
     | 
    
         
            +
              File.open(file, "w") {|f| f << spec.to_ruby }
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            # If you don't want to generate the .gemspec file, just remove this line. Reasons
         
     | 
| 
      
 81 
     | 
    
         
            +
            # why you might want to generate a gemspec:
         
     | 
| 
      
 82 
     | 
    
         
            +
            #  - using bundler with a git source
         
     | 
| 
      
 83 
     | 
    
         
            +
            #  - building the gem without rake (i.e. gem build blah.gemspec)
         
     | 
| 
      
 84 
     | 
    
         
            +
            #  - maybe others?
         
     | 
| 
      
 85 
     | 
    
         
            +
            task :package => :gemspec
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            # Generate documentation
         
     | 
| 
      
 88 
     | 
    
         
            +
            RDoc::Task.new do |rd|
         
     | 
| 
      
 89 
     | 
    
         
            +
              rd.main = "README"
         
     | 
| 
      
 90 
     | 
    
         
            +
              rd.rdoc_files.include("README", "lib/**/*.rb")
         
     | 
| 
      
 91 
     | 
    
         
            +
              rd.rdoc_dir = "rdoc"
         
     | 
| 
      
 92 
     | 
    
         
            +
            end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            desc 'Clear out RDoc and generated packages'
         
     | 
| 
      
 95 
     | 
    
         
            +
            task :clean => [:clobber_rdoc, :clobber_package] do
         
     | 
| 
      
 96 
     | 
    
         
            +
              rm "#{spec.name}.gemspec"
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            desc 'Publish gem'
         
     | 
| 
      
 100 
     | 
    
         
            +
            task :publish => :gem do
         
     | 
| 
      
 101 
     | 
    
         
            +
              system "gem push pkg/#{spec.file_name}"
         
     | 
| 
      
 102 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/github.rb
    ADDED
    
    
| 
         @@ -0,0 +1,142 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'restclient'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'ostruct'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Github
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 7 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def connect(base_url, user = nil, pass = nil)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    new RestClient::Resource.new(base_url, user, pass)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                  
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def proxy=(proxy_host)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    RestClient.proxy = proxy_host
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                
         
     | 
| 
      
 17 
     | 
    
         
            +
                def initialize(resource)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @resource = resource
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
                
         
     | 
| 
      
 21 
     | 
    
         
            +
                def get(path)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  request :get, path
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
                
         
     | 
| 
      
 25 
     | 
    
         
            +
                def post(path, data)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  request :post, path, data
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                def put(path, data)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  request :put, path, data
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
                
         
     | 
| 
      
 33 
     | 
    
         
            +
                def delete(path)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  request :delete, path
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
                
         
     | 
| 
      
 37 
     | 
    
         
            +
                def head(path)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  request :head, path
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                private
         
     | 
| 
      
 42 
     | 
    
         
            +
                
         
     | 
| 
      
 43 
     | 
    
         
            +
                def request(method, path, data = nil)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  if data
         
     | 
| 
      
 45 
     | 
    
         
            +
                    Response.new(@resource[path].send(method, data.to_json))
         
     | 
| 
      
 46 
     | 
    
         
            +
                  else
         
     | 
| 
      
 47 
     | 
    
         
            +
                    Response.new(@resource[path].send(method))
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                rescue RestClient::Exception => e
         
     | 
| 
      
 50 
     | 
    
         
            +
                  if Response.can_handle?(e.response)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    Response.new(e.response)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  else
         
     | 
| 
      
 53 
     | 
    
         
            +
                    raise e
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
                
         
     | 
| 
      
 57 
     | 
    
         
            +
                class Response
         
     | 
| 
      
 58 
     | 
    
         
            +
                  SUCCESS_CODES = [200, 201]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  FAILURE_CODES = [400, 401, 422]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  
         
     | 
| 
      
 61 
     | 
    
         
            +
                  def initialize(response)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @response = response
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  
         
     | 
| 
      
 65 
     | 
    
         
            +
                  def self.can_handle?(response)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    (SUCCESS_CODES + FAILURE_CODES).include?(response.code)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  
         
     | 
| 
      
 69 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 70 
     | 
    
         
            +
                    "#{@response.description.strip} | Rate limit: #{rate_limit_remaining} / #{rate_limit_remaining}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  
         
     | 
| 
      
 73 
     | 
    
         
            +
                  def success?
         
     | 
| 
      
 74 
     | 
    
         
            +
                    when_statuses_are *SUCCESS_CODES
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  
         
     | 
| 
      
 77 
     | 
    
         
            +
                  def error?
         
     | 
| 
      
 78 
     | 
    
         
            +
                    when_statuses_are *FAILURE_CODES
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def error_message
         
     | 
| 
      
 82 
     | 
    
         
            +
                    parsed_response["message"]
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  
         
     | 
| 
      
 85 
     | 
    
         
            +
                  def errors
         
     | 
| 
      
 86 
     | 
    
         
            +
                    parsed_response["errors"].map { |hash| EntityError.new(hash) }
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  
         
     | 
| 
      
 89 
     | 
    
         
            +
                  def rate_limit
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @response.headers[:x_ratelimit_limit].to_i
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  
         
     | 
| 
      
 93 
     | 
    
         
            +
                  def rate_limit_remaining
         
     | 
| 
      
 94 
     | 
    
         
            +
                    @response.headers[:x_ratelimit_remaining].to_i
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  
         
     | 
| 
      
 97 
     | 
    
         
            +
                  def location
         
     | 
| 
      
 98 
     | 
    
         
            +
                    @response.headers[:location]
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  
         
     | 
| 
      
 101 
     | 
    
         
            +
                  def data
         
     | 
| 
      
 102 
     | 
    
         
            +
                    parsed_response
         
     | 
| 
      
 103 
     | 
    
         
            +
                  end
         
     | 
| 
      
 104 
     | 
    
         
            +
                  
         
     | 
| 
      
 105 
     | 
    
         
            +
                  private
         
     | 
| 
      
 106 
     | 
    
         
            +
                  
         
     | 
| 
      
 107 
     | 
    
         
            +
                  def parsed_response
         
     | 
| 
      
 108 
     | 
    
         
            +
                    @parsed_response ||= JSON.parse(@response)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  
         
     | 
| 
      
 111 
     | 
    
         
            +
                  def when_statuses_are(*codes)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    codes.include?(@response.code)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
                
         
     | 
| 
      
 116 
     | 
    
         
            +
                class EntityError < OpenStruct
         
     | 
| 
      
 117 
     | 
    
         
            +
                  MISSING        = "missing"
         
     | 
| 
      
 118 
     | 
    
         
            +
                  MISSING_FIELD  = "missing_field"
         
     | 
| 
      
 119 
     | 
    
         
            +
                  INVALID        = "invalid"
         
     | 
| 
      
 120 
     | 
    
         
            +
                  ALREADY_EXISTS = "already_exists"
         
     | 
| 
      
 121 
     | 
    
         
            +
                  
         
     | 
| 
      
 122 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 123 
     | 
    
         
            +
                    "<Github::Client::EntityError: #{description}>"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  
         
     | 
| 
      
 126 
     | 
    
         
            +
                  def description
         
     | 
| 
      
 127 
     | 
    
         
            +
                    case self.code
         
     | 
| 
      
 128 
     | 
    
         
            +
                      when MISSING
         
     | 
| 
      
 129 
     | 
    
         
            +
                        "#{self.resource} is missing"
         
     | 
| 
      
 130 
     | 
    
         
            +
                      when MISSING_FIELD
         
     | 
| 
      
 131 
     | 
    
         
            +
                        "#{self.resource}##{self.field} is missing"
         
     | 
| 
      
 132 
     | 
    
         
            +
                      when INVALID
         
     | 
| 
      
 133 
     | 
    
         
            +
                        "#{self.resource}##{self.field} is invalid (refer to documentation)"
         
     | 
| 
      
 134 
     | 
    
         
            +
                      when ALREADY_EXISTS
         
     | 
| 
      
 135 
     | 
    
         
            +
                        "#{self.resource}##{self.field} value is already taken (must be unique)"
         
     | 
| 
      
 136 
     | 
    
         
            +
                      else
         
     | 
| 
      
 137 
     | 
    
         
            +
                        "#{self.resource}##{self.field} error: #{self.code}"
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
              end
         
     | 
| 
      
 142 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ostruct'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mime/types'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'github/client'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Github
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Downloads
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :uploader
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                GITHUB_BASE_URL = "https://api.github.com"
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(client, user, repos)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @client = client
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @user = user
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @repos = repos
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                
         
     | 
| 
      
 17 
     | 
    
         
            +
                def self.connect(user, password, repos)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  client = Client.connect(GITHUB_BASE_URL, user, password)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  new(client, user, repos)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                class UnexpectedResponse < StandardError
         
     | 
| 
      
 23 
     | 
    
         
            +
                  attr_reader :response
         
     | 
| 
      
 24 
     | 
    
         
            +
                  
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def initialize(response)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @response = response
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
                
         
     | 
| 
      
 30 
     | 
    
         
            +
                def list
         
     | 
| 
      
 31 
     | 
    
         
            +
                  response = @client.get(downloads_resource_path)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  
         
     | 
| 
      
 33 
     | 
    
         
            +
                  if response.success?
         
     | 
| 
      
 34 
     | 
    
         
            +
                    from_response_data(response.data)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  else
         
     | 
| 
      
 36 
     | 
    
         
            +
                    raise UnexpectedResponse, response
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
                
         
     | 
| 
      
 40 
     | 
    
         
            +
                def create(file_path, description = "")
         
     | 
| 
      
 41 
     | 
    
         
            +
                  response = @client.post(downloads_resource_path, {
         
     | 
| 
      
 42 
     | 
    
         
            +
                    :name         => File.basename(file_path),
         
     | 
| 
      
 43 
     | 
    
         
            +
                    :description  => description,
         
     | 
| 
      
 44 
     | 
    
         
            +
                    :content_type => MIME::Types.type_for(file_path)[0] || MIME::Types["application/octet-stream"][0],
         
     | 
| 
      
 45 
     | 
    
         
            +
                    :size         => File.size?(file_path)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  })
         
     | 
| 
      
 47 
     | 
    
         
            +
                  
         
     | 
| 
      
 48 
     | 
    
         
            +
                  if response.success?
         
     | 
| 
      
 49 
     | 
    
         
            +
                    uploader.upload(File.expand_path(file_path), response.data)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
                
         
     | 
| 
      
 53 
     | 
    
         
            +
                private
         
     | 
| 
      
 54 
     | 
    
         
            +
                
         
     | 
| 
      
 55 
     | 
    
         
            +
                def downloads_resource_path
         
     | 
| 
      
 56 
     | 
    
         
            +
                  "/repos/#{@user}/#{@repos}/downloads"
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
                
         
     | 
| 
      
 59 
     | 
    
         
            +
                def from_response_data(data)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  data.map { |hash| Download.new(hash) }
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                class Download < OpenStruct
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'simpleconsole'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'hirb'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'highline/import'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'osx_keychain'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'github/downloads'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'github/s3_uploader'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module Github
         
     | 
| 
      
 10 
     | 
    
         
            +
              class DownloadsController < SimpleConsole::Controller
         
     | 
| 
      
 11 
     | 
    
         
            +
                include Hirb::Console
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
                params :string => { 
         
     | 
| 
      
 14 
     | 
    
         
            +
                  :u => :user, 
         
     | 
| 
      
 15 
     | 
    
         
            +
                  :f => :file, 
         
     | 
| 
      
 16 
     | 
    
         
            +
                  :n => :name, 
         
     | 
| 
      
 17 
     | 
    
         
            +
                  :r => :repos,
         
     | 
| 
      
 18 
     | 
    
         
            +
                  :d => :description,
         
     | 
| 
      
 19 
     | 
    
         
            +
                  :p => :proxy
         
     | 
| 
      
 20 
     | 
    
         
            +
                }, 
         
     | 
| 
      
 21 
     | 
    
         
            +
                :bool => {
         
     | 
| 
      
 22 
     | 
    
         
            +
                  :o => :overwrite
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
                    
         
     | 
| 
      
 25 
     | 
    
         
            +
                before_filter :set_proxy
         
     | 
| 
      
 26 
     | 
    
         
            +
                
         
     | 
| 
      
 27 
     | 
    
         
            +
                def default
         
     | 
| 
      
 28 
     | 
    
         
            +
                  puts "Valid actions: list, upload, delete"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                def list
         
     | 
| 
      
 33 
     | 
    
         
            +
                  if (downloads = github.list)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    table downloads, {:fields => [:name, :description, :download_count]}
         
     | 
| 
      
 35 
     | 
    
         
            +
                  else
         
     | 
| 
      
 36 
     | 
    
         
            +
                    puts "Couldn't fetch downloads!"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                rescue Github::Downloads::UnexpectedResponse => e
         
     | 
| 
      
 39 
     | 
    
         
            +
                  fail! "Unexpected response (#{e.response})."
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
                
         
     | 
| 
      
 42 
     | 
    
         
            +
                def create
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if params[:file].nil?
         
     | 
| 
      
 44 
     | 
    
         
            +
                    fail! "* A file must be specified (-f or --file)"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  if (url_for_upload = github(:authenticated).create(params[:file], params[:description]))
         
     | 
| 
      
 48 
     | 
    
         
            +
                    puts "Upload successful! (#{url_for_upload})"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  else
         
     | 
| 
      
 50 
     | 
    
         
            +
                    fail! "Upload failed!"
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                rescue Github::Downloads::UnexpectedResponse => e
         
     | 
| 
      
 53 
     | 
    
         
            +
                  fail! "Unexpected response (#{e.response})."
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
                
         
     | 
| 
      
 56 
     | 
    
         
            +
                private
         
     | 
| 
      
 57 
     | 
    
         
            +
                
         
     | 
| 
      
 58 
     | 
    
         
            +
                def fail!(message, status = 1)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  puts(message)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  exit(status)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                def fetch_downloads(repo)
         
     | 
| 
      
 64 
     | 
    
         
            +
                   Hpricot(open("https://github.com/#{repo}/downloads"))
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
                
         
     | 
| 
      
 67 
     | 
    
         
            +
                def set_proxy
         
     | 
| 
      
 68 
     | 
    
         
            +
                  Github::Client.proxy = params[:proxy]
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
                
         
     | 
| 
      
 71 
     | 
    
         
            +
                def github(authentication_required = false)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  if params[:repos].nil? || params[:user].nil?
         
     | 
| 
      
 73 
     | 
    
         
            +
                    fail! "* Please specify a user (-u or --user) and repository (-r or --repos)"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  
         
     | 
| 
      
 76 
     | 
    
         
            +
                  if authentication_required
         
     | 
| 
      
 77 
     | 
    
         
            +
                    password = lookup_or_prompt_for_password(params[:user])
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @github ||= Github::Downloads.connect(params[:user], password, params[:repos]).tap do |gh|
         
     | 
| 
      
 81 
     | 
    
         
            +
                    gh.uploader = Github::S3Uploader.new
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
                
         
     | 
| 
      
 85 
     | 
    
         
            +
                def lookup_or_prompt_for_password(user)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  fetch_password_from_keychain(user) || prompt_for_password(user)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
                
         
     | 
| 
      
 89 
     | 
    
         
            +
                def prompt_for_password(user)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  ask("Enter Github password:") {|q| q.echo = false }.tap do |password|
         
     | 
| 
      
 91 
     | 
    
         
            +
                    store_password_in_keychain(user, password)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
                
         
     | 
| 
      
 95 
     | 
    
         
            +
                def mac?
         
     | 
| 
      
 96 
     | 
    
         
            +
                  RUBY_PLATFORM.match(/darwin/)
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
                
         
     | 
| 
      
 99 
     | 
    
         
            +
                KEYCHAIN_SERVICE = "github-uploads"
         
     | 
| 
      
 100 
     | 
    
         
            +
                
         
     | 
| 
      
 101 
     | 
    
         
            +
                def fetch_password_from_keychain(user)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  OSXKeychain.new[KEYCHAIN_SERVICE, user] if mac?
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
                
         
     | 
| 
      
 105 
     | 
    
         
            +
                def store_password_in_keychain(user, password)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  OSXKeychain.new[KEYCHAIN_SERVICE, user] = password if mac?
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'restclient'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Github
         
     | 
| 
      
 4 
     | 
    
         
            +
              class S3Uploader 
         
     | 
| 
      
 5 
     | 
    
         
            +
                def upload(path, metadata)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  response = RestClient.post(metadata["s3_url"], [
         
     | 
| 
      
 7 
     | 
    
         
            +
                    ["key", "#{metadata["prefix"]}#{metadata["name"]}"],
         
     | 
| 
      
 8 
     | 
    
         
            +
                    ["acl", metadata["acl"]],
         
     | 
| 
      
 9 
     | 
    
         
            +
                    ["success_action_status", 201],
         
     | 
| 
      
 10 
     | 
    
         
            +
                    ["Filename", metadata["name"]],
         
     | 
| 
      
 11 
     | 
    
         
            +
                    ["AWSAccessKeyId", metadata["accesskeyid"]],
         
     | 
| 
      
 12 
     | 
    
         
            +
                    ["Policy", metadata["policy"]],
         
     | 
| 
      
 13 
     | 
    
         
            +
                    ["Signature", metadata["signature"]],
         
     | 
| 
      
 14 
     | 
    
         
            +
                    ["Content-Type", metadata["mime_type"]],
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ["file", File.open(path)]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  ])
         
     | 
| 
      
 17 
     | 
    
         
            +
                  if response.code == 201
         
     | 
| 
      
 18 
     | 
    
         
            +
                    metadata["url"]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  else 
         
     | 
| 
      
 20 
     | 
    
         
            +
                    false
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,211 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'github/client'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class FakeResource # fake RestClient::Resource
         
     | 
| 
      
 5 
     | 
    
         
            +
              attr_reader :path
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
              def initialize(path = "/")
         
     | 
| 
      
 8 
     | 
    
         
            +
                @path = Mocha::Mockery.instance.new_state_machine("location").starts_as(path)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              def [](path)
         
     | 
| 
      
 12 
     | 
    
         
            +
                tap { @path.become(path) }
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            describe "Github::Client" do
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 19 
     | 
    
         
            +
                @resource = FakeResource.new
         
     | 
| 
      
 20 
     | 
    
         
            +
                @client = Github::Client.new(@resource)
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              
         
     | 
| 
      
 23 
     | 
    
         
            +
              describe "#get" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                it "performs a GET request to /some/path on the resource" do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @resource.expects(:get).when @resource.path.is("/some/path")
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @client.get("/some/path")
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                it "returns a Github::Client::Response" do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @resource.stubs(:get)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @client.get("/some/path").should be_instance_of(Github::Client::Response)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
              
         
     | 
| 
      
 35 
     | 
    
         
            +
              describe "#post" do
         
     | 
| 
      
 36 
     | 
    
         
            +
                it "performs a POST request with the supplied data in JSON format to /some/path on the resource" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @resource.expects(:post).with({"foo" => "bar"}.to_json).when @resource.path.is("/some/path")
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @client.post("/some/path", {"foo" => "bar"})
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                it "returns a Github::Client::Response" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @resource.stubs(:post)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @client.post("/some/path", nil).should be_instance_of(Github::Client::Response)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
              
         
     | 
| 
      
 47 
     | 
    
         
            +
              describe "#put" do
         
     | 
| 
      
 48 
     | 
    
         
            +
                it "performs a PUT request with the supplied data in JSON format to /some/path on the resource" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @resource.expects(:put).with({"foo" => "bar"}.to_json).when @resource.path.is("/some/path")
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @client.put("/some/path", {"foo" => "bar"})
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
                
         
     | 
| 
      
 53 
     | 
    
         
            +
                it "returns a Github::Client::Response" do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @resource.stubs(:put)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @client.put("/some/path", nil).should be_instance_of(Github::Client::Response)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
              
         
     | 
| 
      
 59 
     | 
    
         
            +
              describe "#delete" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                it "performs a DELETE request to /some/path on the resource" do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @resource.expects(:delete).when @resource.path.is("/some/path")
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @client.delete("/some/path")
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                
         
     | 
| 
      
 65 
     | 
    
         
            +
                it "returns a Github::Client::Response" do
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @resource.stubs(:delete)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  @client.delete("/some/path").should be_instance_of(Github::Client::Response)
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
              
         
     | 
| 
      
 71 
     | 
    
         
            +
              describe "#head" do
         
     | 
| 
      
 72 
     | 
    
         
            +
                it "performs a HEAD request to /some/path on the resource" do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @resource.expects(:head).when @resource.path.is("/some/path")
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @client.head("/some/path")
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
                it "returns a Github::Client::Response" do
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @resource.stubs(:head)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  @client.head("/some/path").should be_instance_of(Github::Client::Response)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            describe "Github::Client::Response" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                
         
     | 
| 
      
 87 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 88 
     | 
    
         
            +
                @client = Github::Client.connect("http://localhost:#{mimic_port}")
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
              
         
     | 
| 
      
 91 
     | 
    
         
            +
              def response
         
     | 
| 
      
 92 
     | 
    
         
            +
                @client.get("/some/path")
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
              
         
     | 
| 
      
 95 
     | 
    
         
            +
              def post_response(data = "")
         
     | 
| 
      
 96 
     | 
    
         
            +
                @client.post("/some/path", data)
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
              
         
     | 
| 
      
 99 
     | 
    
         
            +
              context "for a standard non-paginated 200 response" do
         
     | 
| 
      
 100 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 101 
     | 
    
         
            +
                  Mimic.mimic.get("/some/path").returning({"result" => "ok"}.to_json, 200, {"X-RateLimit-Limit" => "5000", "X-RateLimit-Remaining" => "4966"})
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
                
         
     | 
| 
      
 104 
     | 
    
         
            +
                it "indicates success" do
         
     | 
| 
      
 105 
     | 
    
         
            +
                  response.should be_success
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
                
         
     | 
| 
      
 108 
     | 
    
         
            +
                it "stores the current rate limit" do
         
     | 
| 
      
 109 
     | 
    
         
            +
                  response.rate_limit.should == 5000
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
                
         
     | 
| 
      
 112 
     | 
    
         
            +
                it "stores the number of rate-limited requests remaining" do
         
     | 
| 
      
 113 
     | 
    
         
            +
                  response.rate_limit_remaining.should == 4966
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
                
         
     | 
| 
      
 116 
     | 
    
         
            +
                it "returns the parsed JSON response" do
         
     | 
| 
      
 117 
     | 
    
         
            +
                  response.data.should == {"result" => "ok"}
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
              
         
     | 
| 
      
 121 
     | 
    
         
            +
              context "for 201 created responses" do
         
     | 
| 
      
 122 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 123 
     | 
    
         
            +
                  Mimic.mimic.post("/some/path").returning("", 201, {"Location" => "http://example.com/resource"})
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
                
         
     | 
| 
      
 126 
     | 
    
         
            +
                it "indicates success" do
         
     | 
| 
      
 127 
     | 
    
         
            +
                  post_response.should be_success
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
                
         
     | 
| 
      
 130 
     | 
    
         
            +
                it "returns the location of the created resource" do
         
     | 
| 
      
 131 
     | 
    
         
            +
                  post_response.location.should == "http://example.com/resource"
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
              end
         
     | 
| 
      
 134 
     | 
    
         
            +
              
         
     | 
| 
      
 135 
     | 
    
         
            +
              context "for a bad request" do
         
     | 
| 
      
 136 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 137 
     | 
    
         
            +
                  Mimic.mimic.get("/some/path").returning({"message" => "There was an error"}.to_json, 400, {})
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
                
         
     | 
| 
      
 140 
     | 
    
         
            +
                it "indicates an error" do
         
     | 
| 
      
 141 
     | 
    
         
            +
                  response.should be_error
         
     | 
| 
      
 142 
     | 
    
         
            +
                  response.should_not be_success
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
                
         
     | 
| 
      
 145 
     | 
    
         
            +
                it "returns the error message" do
         
     | 
| 
      
 146 
     | 
    
         
            +
                  response.error_message.should == "There was an error"
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
              end
         
     | 
| 
      
 149 
     | 
    
         
            +
              
         
     | 
| 
      
 150 
     | 
    
         
            +
              context "for requests with invalid data" do
         
     | 
| 
      
 151 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 152 
     | 
    
         
            +
                  Mimic.mimic.get("/some/path").returning(
         
     | 
| 
      
 153 
     | 
    
         
            +
                    {"message" => "Validation failed", 
         
     | 
| 
      
 154 
     | 
    
         
            +
                      "errors" => [
         
     | 
| 
      
 155 
     | 
    
         
            +
                        {"resource" => "Issue", "field" => "title", "code" => "missing_field"}
         
     | 
| 
      
 156 
     | 
    
         
            +
                      ]}.to_json, 422, {})
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
                
         
     | 
| 
      
 159 
     | 
    
         
            +
                it "indicates an error" do
         
     | 
| 
      
 160 
     | 
    
         
            +
                  response.should be_error
         
     | 
| 
      
 161 
     | 
    
         
            +
                  response.should_not be_success
         
     | 
| 
      
 162 
     | 
    
         
            +
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
                
         
     | 
| 
      
 164 
     | 
    
         
            +
                it "returns the error message" do
         
     | 
| 
      
 165 
     | 
    
         
            +
                  response.error_message.should == "Validation failed"
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
                
         
     | 
| 
      
 168 
     | 
    
         
            +
                it "returns the errors" do
         
     | 
| 
      
 169 
     | 
    
         
            +
                  response.should have(1).errors
         
     | 
| 
      
 170 
     | 
    
         
            +
                  response.errors[0].resource.should == "Issue"
         
     | 
| 
      
 171 
     | 
    
         
            +
                  response.errors[0].field.should == "title"
         
     | 
| 
      
 172 
     | 
    
         
            +
                  response.errors[0].code.should == Github::Client::EntityError::MISSING_FIELD
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
              end
         
     | 
| 
      
 175 
     | 
    
         
            +
              
         
     | 
| 
      
 176 
     | 
    
         
            +
              context "for a server error" do
         
     | 
| 
      
 177 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 178 
     | 
    
         
            +
                  Mimic.mimic.get("/some/path").returning("", 500)
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
                
         
     | 
| 
      
 181 
     | 
    
         
            +
                it "raises an exception" do
         
     | 
| 
      
 182 
     | 
    
         
            +
                  proc{ @client.get("/some/path") }.should raise_error
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end  
         
     | 
| 
      
 185 
     | 
    
         
            +
            end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
            describe "Github::Client authentication" do
         
     | 
| 
      
 188 
     | 
    
         
            +
                
         
     | 
| 
      
 189 
     | 
    
         
            +
              context "with basic auth" do
         
     | 
| 
      
 190 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 191 
     | 
    
         
            +
                  Mimic.mimic do
         
     | 
| 
      
 192 
     | 
    
         
            +
                    use Rack::Auth::Basic do |user, pass|
         
     | 
| 
      
 193 
     | 
    
         
            +
                      user == "joebloggs" and pass == "letmein"
         
     | 
| 
      
 194 
     | 
    
         
            +
                    end
         
     | 
| 
      
 195 
     | 
    
         
            +
              
         
     | 
| 
      
 196 
     | 
    
         
            +
                    get("/some/path") { [200, {}, ""] }
         
     | 
| 
      
 197 
     | 
    
         
            +
                  end
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
                
         
     | 
| 
      
 200 
     | 
    
         
            +
                it "should succeed when authenticated correctly" do
         
     | 
| 
      
 201 
     | 
    
         
            +
                  @client = Github::Client.connect("http://localhost:#{mimic_port}", "joebloggs", "letmein")
         
     | 
| 
      
 202 
     | 
    
         
            +
                  @client.get("/some/path").should be_success
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
      
 204 
     | 
    
         
            +
                
         
     | 
| 
      
 205 
     | 
    
         
            +
                it "should fail when not authenticated correctly" do
         
     | 
| 
      
 206 
     | 
    
         
            +
                  @client = Github::Client.connect("http://localhost:#{mimic_port}", "joebloggs", "wrongpass")
         
     | 
| 
      
 207 
     | 
    
         
            +
                  @client.get("/some/path").should be_error
         
     | 
| 
      
 208 
     | 
    
         
            +
                end
         
     | 
| 
      
 209 
     | 
    
         
            +
              end
         
     | 
| 
      
 210 
     | 
    
         
            +
              
         
     | 
| 
      
 211 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,87 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'github/downloads'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe "Github::Downloads" do
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 7 
     | 
    
         
            +
                @client = mock("client")
         
     | 
| 
      
 8 
     | 
    
         
            +
                @downloads = Github::Downloads.new(@client, "username", "somerepo")
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              describe "#list" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                it "returns an empty array when there is no downloads" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @client.stubs(:get).with("/repos/username/somerepo/downloads").returns successful_response_with([])
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @downloads.list.should be_empty
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                
         
     | 
| 
      
 17 
     | 
    
         
            +
                it "returns an array of downloads parsed from the response when there are downloads" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @client.stubs(:get).with("/repos/username/somerepo/downloads").returns successful_response_with([
         
     | 
| 
      
 19 
     | 
    
         
            +
                    {
         
     | 
| 
      
 20 
     | 
    
         
            +
                      "url" => "https://api.github.com/repos/octocat/Hello-World/downloads/1",
         
     | 
| 
      
 21 
     | 
    
         
            +
                      "html_url" => "https://github.com/repos/octocat/Hello-World/downloads/filename",
         
     | 
| 
      
 22 
     | 
    
         
            +
                      "id" => 1,
         
     | 
| 
      
 23 
     | 
    
         
            +
                      "name" => "file.zip",
         
     | 
| 
      
 24 
     | 
    
         
            +
                      "description" => "The latest release",
         
     | 
| 
      
 25 
     | 
    
         
            +
                      "size" => 1024,
         
     | 
| 
      
 26 
     | 
    
         
            +
                      "download_count" => 40
         
     | 
| 
      
 27 
     | 
    
         
            +
                    }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  ])
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @downloads.list.size.should == 1
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @downloads.list.first.description.should == "The latest release"
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
                
         
     | 
| 
      
 33 
     | 
    
         
            +
                it "raises if the response is not successful" do
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @client.stubs(:get).with("/repos/username/somerepo/downloads").returns unsuccessful_response
         
     | 
| 
      
 35 
     | 
    
         
            +
                  proc { @downloads.list }.should raise_error(Github::Downloads::UnexpectedResponse)
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
              
         
     | 
| 
      
 39 
     | 
    
         
            +
              describe "#upload" do
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @uploader = mock("uploader")
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @downloads.uploader = @uploader
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                it "posts the file metadata to the server" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @client.expects(:post).with("/repos/username/somerepo/downloads", {
         
     | 
| 
      
 48 
     | 
    
         
            +
                    :name         => "textfile.txt",
         
     | 
| 
      
 49 
     | 
    
         
            +
                    :description  => "an example file",
         
     | 
| 
      
 50 
     | 
    
         
            +
                    :content_type => "text/plain",
         
     | 
| 
      
 51 
     | 
    
         
            +
                    :size         => File.size?("fixtures/textfile.txt")
         
     | 
| 
      
 52 
     | 
    
         
            +
                  }).returns(unsuccessful_response)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @downloads.create("fixtures/textfile.txt", "an example file")
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
                
         
     | 
| 
      
 57 
     | 
    
         
            +
                it "passes the upload response data to the uploader if successful" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @client.stubs(:post).returns successful_response_with("upload data")
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @uploader.expects(:upload).with(File.expand_path("fixtures/textfile.txt"), "upload data")
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @downloads.create("fixtures/textfile.txt", "an example file")
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                it "returns the URL returned by the uploader if successful" do
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @client.stubs(:post).returns successful_response_with("upload data")
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @uploader.stubs(:upload).returns("http://www.example.com/download")
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @downloads.create("fixtures/textfile.txt", "an example file").should == "http://www.example.com/download"
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
                
         
     | 
| 
      
 69 
     | 
    
         
            +
                it "returns false without uploading anything when upload post fails" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @client.stubs(:post).returns unsuccessful_response
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @uploader.expects(:upload).never
         
     | 
| 
      
 72 
     | 
    
         
            +
                  @downloads.create("fixtures/textfile.txt", "an example file").should be_false
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
                
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
              
         
     | 
| 
      
 77 
     | 
    
         
            +
              private
         
     | 
| 
      
 78 
     | 
    
         
            +
              
         
     | 
| 
      
 79 
     | 
    
         
            +
              def unsuccessful_response
         
     | 
| 
      
 80 
     | 
    
         
            +
                stub("response", :success? => false)
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
              def successful_response_with(data)
         
     | 
| 
      
 84 
     | 
    
         
            +
                stub("response", :success? => true, :data => data)
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
              
         
     | 
| 
      
 87 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "rubygems"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rspec'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'mocha'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'mimic'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'ap'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            $:.unshift(File.join(File.dirname(__FILE__), *%w[.. lib]))
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Rspec.configure do |config|
         
     | 
| 
      
 11 
     | 
    
         
            +
              config.color_enabled = true
         
     | 
| 
      
 12 
     | 
    
         
            +
              config.mock_with :mocha
         
     | 
| 
      
 13 
     | 
    
         
            +
              config.before(:each) do
         
     | 
| 
      
 14 
     | 
    
         
            +
                Mimic.cleanup!
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            USE_CHARLES_PROXY = false
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            def mimic_port
         
     | 
| 
      
 21 
     | 
    
         
            +
              if USE_CHARLES_PROXY
         
     | 
| 
      
 22 
     | 
    
         
            +
                11989
         
     | 
| 
      
 23 
     | 
    
         
            +
              else
         
     | 
| 
      
 24 
     | 
    
         
            +
                Mimic::MIMIC_DEFAULT_PORT
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,229 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: github-downloads
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              hash: 27
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
              segments: 
         
     | 
| 
      
 7 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 8 
     | 
    
         
            +
              - 1
         
     | 
| 
      
 9 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 10 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 12 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 13 
     | 
    
         
            +
            - Luke Redpath
         
     | 
| 
      
 14 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 16 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            date: 2011-06-27 00:00:00 Z
         
     | 
| 
      
 19 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 20 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 21 
     | 
    
         
            +
              name: rest-client
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 23 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 24 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 25 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 26 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    hash: 9
         
     | 
| 
      
 28 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 30 
     | 
    
         
            +
                    - 6
         
     | 
| 
      
 31 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: 1.6.3
         
     | 
| 
      
 33 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              requirement: *id001
         
     | 
| 
      
 36 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 37 
     | 
    
         
            +
              name: json
         
     | 
| 
      
 38 
     | 
    
         
            +
              version_requirements: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 39 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 40 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 41 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 42 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 43 
     | 
    
         
            +
                    hash: 5
         
     | 
| 
      
 44 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 45 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 46 
     | 
    
         
            +
                    - 5
         
     | 
| 
      
 47 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 48 
     | 
    
         
            +
                    version: 1.5.3
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 51 
     | 
    
         
            +
              requirement: *id002
         
     | 
| 
      
 52 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 53 
     | 
    
         
            +
              name: simpleconsole
         
     | 
| 
      
 54 
     | 
    
         
            +
              version_requirements: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 55 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 56 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 57 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 58 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 59 
     | 
    
         
            +
                    hash: 25
         
     | 
| 
      
 60 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 61 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 62 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 64 
     | 
    
         
            +
                    version: 0.1.1
         
     | 
| 
      
 65 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 66 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 67 
     | 
    
         
            +
              requirement: *id003
         
     | 
| 
      
 68 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 69 
     | 
    
         
            +
              name: hirb
         
     | 
| 
      
 70 
     | 
    
         
            +
              version_requirements: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 71 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 75 
     | 
    
         
            +
                    hash: 5
         
     | 
| 
      
 76 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 77 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 78 
     | 
    
         
            +
                    - 4
         
     | 
| 
      
 79 
     | 
    
         
            +
                    - 5
         
     | 
| 
      
 80 
     | 
    
         
            +
                    version: 0.4.5
         
     | 
| 
      
 81 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 82 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 83 
     | 
    
         
            +
              requirement: *id004
         
     | 
| 
      
 84 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 85 
     | 
    
         
            +
              name: mime-types
         
     | 
| 
      
 86 
     | 
    
         
            +
              version_requirements: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 87 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 88 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 89 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 90 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 91 
     | 
    
         
            +
                    hash: 87
         
     | 
| 
      
 92 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 93 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 94 
     | 
    
         
            +
                    - 16
         
     | 
| 
      
 95 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: 1.16.0
         
     | 
| 
      
 97 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 98 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirement: *id005
         
     | 
| 
      
 100 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 101 
     | 
    
         
            +
              name: highline
         
     | 
| 
      
 102 
     | 
    
         
            +
              version_requirements: &id006 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 103 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 104 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 105 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 106 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 107 
     | 
    
         
            +
                    hash: 11
         
     | 
| 
      
 108 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 109 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 110 
     | 
    
         
            +
                    - 6
         
     | 
| 
      
 111 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 112 
     | 
    
         
            +
                    version: 1.6.2
         
     | 
| 
      
 113 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 114 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 115 
     | 
    
         
            +
              requirement: *id006
         
     | 
| 
      
 116 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 117 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 118 
     | 
    
         
            +
              version_requirements: &id007 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 119 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 120 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 121 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 122 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 123 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 124 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 125 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 126 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 127 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 128 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 129 
     | 
    
         
            +
              requirement: *id007
         
     | 
| 
      
 130 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 131 
     | 
    
         
            +
              name: mocha
         
     | 
| 
      
 132 
     | 
    
         
            +
              version_requirements: &id008 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 133 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 134 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 135 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 136 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 137 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 138 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 139 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 140 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 141 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 142 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 143 
     | 
    
         
            +
              requirement: *id008
         
     | 
| 
      
 144 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 145 
     | 
    
         
            +
              name: mimic
         
     | 
| 
      
 146 
     | 
    
         
            +
              version_requirements: &id009 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 147 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 148 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 149 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 150 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 151 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 152 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 153 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 154 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 155 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 156 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 157 
     | 
    
         
            +
              requirement: *id009
         
     | 
| 
      
 158 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 159 
     | 
    
         
            +
              name: awesome_print
         
     | 
| 
      
 160 
     | 
    
         
            +
              version_requirements: &id010 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 161 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 162 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 163 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 164 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 165 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 166 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 167 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 168 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 169 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 170 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 171 
     | 
    
         
            +
              requirement: *id010
         
     | 
| 
      
 172 
     | 
    
         
            +
            description: 
         
     | 
| 
      
 173 
     | 
    
         
            +
            email: luke@lukeredpath.co.uk
         
     | 
| 
      
 174 
     | 
    
         
            +
            executables: 
         
     | 
| 
      
 175 
     | 
    
         
            +
            - github-downloads
         
     | 
| 
      
 176 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 181 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 182 
     | 
    
         
            +
            - Gemfile.lock
         
     | 
| 
      
 183 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 184 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 185 
     | 
    
         
            +
            - bin/github-downloads
         
     | 
| 
      
 186 
     | 
    
         
            +
            - spec/fixtures/textfile.txt
         
     | 
| 
      
 187 
     | 
    
         
            +
            - spec/github_client_spec.rb
         
     | 
| 
      
 188 
     | 
    
         
            +
            - spec/github_download_spec.rb
         
     | 
| 
      
 189 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 190 
     | 
    
         
            +
            - lib/github/client.rb
         
     | 
| 
      
 191 
     | 
    
         
            +
            - lib/github/downloads.rb
         
     | 
| 
      
 192 
     | 
    
         
            +
            - lib/github/downloads_controller.rb
         
     | 
| 
      
 193 
     | 
    
         
            +
            - lib/github/s3_uploader.rb
         
     | 
| 
      
 194 
     | 
    
         
            +
            - lib/github.rb
         
     | 
| 
      
 195 
     | 
    
         
            +
            homepage: http://lukeredpath.co.uk
         
     | 
| 
      
 196 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 199 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 202 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 203 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 204 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 205 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 206 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 207 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 208 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 209 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 210 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 211 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 212 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 213 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 214 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 215 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 216 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 217 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 218 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 219 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 220 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 221 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 224 
     | 
    
         
            +
            rubygems_version: 1.8.5
         
     | 
| 
      
 225 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 226 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 227 
     | 
    
         
            +
            summary: Manages downloads for your Github projects
         
     | 
| 
      
 228 
     | 
    
         
            +
            test_files: []
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     |