Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Implement unyank for local and remote repositories. #26

Merged
merged 1 commit into from

3 participants

@latentflip

Implemented unyank support, you might want to double check how we've done this. Furthermore we've assumed that we don't care if a gem has not previously been yanked when we try to unyank, as it won't overwrite anything anyway.

Getting the tests passing in this PR depends on PR #25 being merged (unless you have those missing gemspec files on your machine already).

Fixes: #9

@copiousfreetime copiousfreetime merged commit dcf69fb into from
@latentflip latentflip deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 7, 2013
  1. @urfolomeus @latentflip

    Implement unyank for local and remote repositories.

    urfolomeus authored latentflip committed
    Fixes: #9
This page is out of date. Refresh to see the latest.
View
50 lib/stickler/client/unyank.rb
@@ -0,0 +1,50 @@
+module Stickler
+ class Client
+ class Unyank < Stickler::Client
+ def self.banner
+<<-_
+Restore a yanked gem to the gemserver's index.
+
+Usage: stickler unyank [options] --gem-version x.y.z gem
+
+ Options:
+_
+ end
+
+ def parser
+ unless @parser then
+ @parser = super
+ @parser.opt( :gem_version, "The version of the gem to unyank (required)", :type => :string, :required => true )
+ @parser.opt( :platform, "The platform of the gem to unyank", :type => :string, :default => ::Gem::Platform::RUBY )
+ end
+ return @parser
+ end
+
+ def parse( argv )
+ gem_name = nil
+ opts = super( argv ) do |p|
+ raise Trollop::CommandlineError, "At least one gem is required to unyank" if p.leftovers.empty?
+ gem_name = p.leftovers.shift
+ end
+ opts[:gem_name] = gem_name
+ return opts
+ end
+
+ def run
+ opts = parse( self.argv )
+ repo = remote_repo_for( opts )
+ spec = Stickler::SpecLite.new( opts[:gem_name], opts[:gem_version], opts[:platform] )
+
+ $stdout.write "Unyanking gem #{spec.full_name} from #{repo.uri} : "
+ $stdout.flush
+ if spec = repo.unyank( spec ) then
+ $stdout.puts "OK"
+ else
+ $stdout.puts "FAILURE"
+ end
+ rescue Stickler::Repository::Error => e
+ $stdout.puts "ERROR: #{e.message}"
+ end
+ end
+ end
+end
View
13 lib/stickler/middleware/gemcutter.rb
@@ -41,6 +41,19 @@ def initialize( app = nil, options = {} )
end
end
+ # gemcutter unyank
+ post '/api/v1/gems/unyank' do
+ begin
+ spec = Stickler::SpecLite.new( params[:spec_name], params[:version] )
+ @repo.unyank( spec )
+ logger.info( "Unyanked #{spec.full_name}" )
+ return spec.to_s
+ rescue Stickler::Repository::Error => e
+ logger.error( "Error unyanking #{spec.full_name} to repo : #{e}" )
+ error( 500, "Error unyanking gem to repo: #{e}" )
+ end
+ end
+
# gemcutter yank
delete '/api/v1/gems/yank' do
spec = Stickler::SpecLite.new( params[:gem_name], params[:version] )
View
12 lib/stickler/repository/local.rb
@@ -162,6 +162,15 @@ def yank( spec )
return uri_for_gem( spec )
end
+ #
+ # See Api#unyank
+ #
+ def unyank( spec )
+ return nil if specification_file_exist?( spec )
+ return nil unless gem_file_exist?( spec )
+ install_specification( spec )
+ end
+
#
# :call-seq:
@@ -194,7 +203,8 @@ def add( io )
# See Api#push
#
def push( path )
- spec = specification_from_gem_file( path )
+ # is this line needed? Never used.
+ # spec = specification_from_gem_file( path )
result = nil
File.open( path ) do |io|
result = add( io )
View
27 lib/stickler/repository/remote.rb
@@ -96,6 +96,19 @@ def yank( spec )
end
#
+ # See Api#unyank
+ #
+ def unyank( spec )
+ return nil unless remote_gem_file_exist?( spec )
+ query = { :spec_name => spec.name, :version => spec.version.to_s }
+ resp = resource_request( unyank_resource, :query => query )
+ true
+ rescue Excon::Errors::Error => e
+ # raise Stickler::Repository::Error, "Failure unyanking: #{e.inspect}"
+ []
+ end
+
+ #
# See Api#delete
#
def delete( spec )
@@ -179,6 +192,10 @@ def yank_uri
Addressable::URI.join( uri, "api/v1/gems/yank" )
end
+ def unyank_uri
+ Addressable::URI.join( uri, "api/v1/gems/unyank" )
+ end
+
def yank_resource
unless @yank_resource then
params = { :method => :delete,
@@ -188,6 +205,16 @@ def yank_resource
end
return @yank_resource
end
+
+ def unyank_resource
+ unless @unyank_resource then
+ params = { :method => :post,
+ :headers => { 'Content-Type' => 'application/x-www-form-urlencoded' },
+ :expects => [200] }
+ @unyank_resource = Excon.new( unyank_uri.to_s, params )
+ end
+ return @unyank_resource
+ end
def gem_resource( spec )
Excon.new( full_uri_to_gem( spec ), :method => :get, :expects => [200] )
View
32 spec/repository/api_behavior.rb
@@ -104,6 +104,38 @@
end
+ describe "#unyank" do
+ before( :each ) do
+ @repo.search_for( @foo_spec ).should be_empty
+ @repo.push( @foo_gem_local_path )
+ end
+
+ it "returns nil if the gem to unyank does not exist" do
+ non_existing_gem = @missing_spec
+ @repo.unyank( non_existing_gem ).should be_nil
+ end
+
+ #Do we even care about this?
+ xit "returns nil if the gem to unyank has not been yanked" do
+ @repo.unyank( @foo_spec ).should be_nil
+ end
+
+ context " when file has been yanked" do
+ before :each do
+ @repo.yank( @foo_spec )
+ end
+
+ it "return true if the gem is successfully unyanked" do
+ @repo.unyank( @foo_spec ).should be_true
+ end
+
+ it "finds the gem in a search" do
+ @repo.unyank( @foo_spec )
+ @repo.search_for( @foo_spec ).should_not be_empty
+ end
+ end
+ end
+
describe "#search_for" do
it "returns specs for items that are found" do
@repo.push( @foo_gem_local_path )
Something went wrong with that request. Please try again.