stickler 2.0.2 → 2.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/.gitignore +1 -0
- data/HISTORY.asciidoc +17 -8
- data/LICENSE +13 -54
- data/README.asciidoc +29 -5
- data/Rakefile +11 -10
- data/TODO.asciidoc +6 -0
- data/bin/stickler +5 -2
- data/examples/fetch-a-gem +6 -0
- data/examples/gemcutter_repo.ru +1 -1
- data/lib/stickler.rb +1 -1
- data/lib/stickler/client.rb +1 -0
- data/lib/stickler/client/list.rb +30 -0
- data/lib/stickler/client/mirror.rb +5 -5
- data/lib/stickler/client/push.rb +1 -1
- data/lib/stickler/middleware/gemcutter.rb +2 -2
- data/lib/stickler/middleware/helpers.rb +37 -42
- data/lib/stickler/middleware/index.rb +51 -19
- data/lib/stickler/repository/index.rb +46 -9
- data/lib/stickler/repository/local.rb +75 -20
- data/lib/stickler/repository/null.rb +0 -2
- data/lib/stickler/repository/remote.rb +81 -64
- data/lib/stickler/repository/rubygems_authenticator.rb +3 -8
- data/lib/stickler/server.rb +1 -1
- data/lib/stickler/spec_lite.rb +13 -10
- data/lib/stickler/version.rb +2 -2
- data/man/stickler.asciidoc +3 -1
- data/spec/data/gems/foo-2.0.0a.gem +0 -0
- data/spec/index_spec_helpers.rb +71 -0
- data/spec/middleware/local_spec.rb +58 -10
- data/spec/middleware/not_found_spec.rb +1 -0
- data/spec/repository/index_spec.rb +15 -0
- data/spec/repository/local_spec.rb +20 -5
- data/spec/repository/remote_spec.rb +2 -3
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +8 -6
- data/spec/spec_lite_spec.rb +19 -6
- data/tasks/man.rake +1 -1
- metadata +74 -40
- data/spec/middleware/common_gem_server_helpers.rb +0 -69
- data/spec/middleware/index_spec.rb +0 -26
- data/spec/middleware/legacy_gem_server_behavior.rb +0 -31
- data/spec/middleware/modern_gem_server_behavior.rb +0 -22
@@ -7,27 +7,33 @@ require 'stickler/logable'
|
|
7
7
|
require 'stickler/paths'
|
8
8
|
|
9
9
|
module Stickler::Middleware
|
10
|
-
# Index is a Rack middleware that passes all requests through except for
|
11
|
-
#
|
10
|
+
# Index is a Rack middleware that passes all requests through except for the
|
11
|
+
# following urls:
|
12
12
|
#
|
13
13
|
# <b>/specs.#{Gem.marhsal_version}.gz</b>:: The [ name, version, platform ] index
|
14
14
|
# of <b>all<b> the gems in the
|
15
15
|
# entire repository
|
16
16
|
#
|
17
|
-
# <b>/latest_specs.#{Gem.marshal_version}.gz</b>:: The [ name, version,
|
17
|
+
# <b>/latest_specs.#{Gem.marshal_version}.gz</b>:: The [ name, version, platform ] index
|
18
18
|
# of the <b>most recent</b> version of each
|
19
19
|
# gem in the repository.
|
20
20
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
21
|
+
# <b>/prerelease_specs.#{Gem.marshal-version}.gz</b>:: The [ name, version, platform ] index
|
22
|
+
# of the <b>prerelease</b> versions of the
|
23
|
+
# prerelease gems in the repository
|
24
|
+
#
|
25
|
+
# <b>/quick/Marshal.#{Gem.marshal_version}/*.gemspec.rz</b>:: The gemspec of each gem
|
26
|
+
#
|
27
|
+
# <b>/gems/*.gem</b>:: The actual .gem file to serve
|
28
|
+
#
|
29
|
+
# For the <b>specs</b> urls, it responds with the summation of all the specs
|
30
|
+
# that are in all the repositories served by stickler
|
24
31
|
#
|
25
32
|
# == Options
|
26
33
|
#
|
27
34
|
# This class is also the base class for all the other GemServer type
|
28
35
|
# middlewares, so there is an optional behavior to NOT respond to the index
|
29
|
-
# url requests
|
30
|
-
# env['stickler.specs'] instead of serving the values out of there.
|
36
|
+
# url requests.
|
31
37
|
#
|
32
38
|
# <b>:serve_indexes</b>:: +true+ or +false+ it defaults to +true+. This
|
33
39
|
# option is used when Index is used in a stack
|
@@ -72,7 +78,6 @@ module Stickler::Middleware
|
|
72
78
|
end
|
73
79
|
|
74
80
|
get '/' do
|
75
|
-
append_specs
|
76
81
|
if @serve_indexes then
|
77
82
|
erb :index
|
78
83
|
else
|
@@ -83,24 +88,29 @@ module Stickler::Middleware
|
|
83
88
|
#
|
84
89
|
# Respond to the requests for the <b>all gems</b> index
|
85
90
|
#
|
86
|
-
get %r{\A/specs.#{Gem.marshal_version}(\.gz)?\Z} do |
|
87
|
-
|
88
|
-
serve_indexes( with_compression )
|
91
|
+
get %r{\A/specs.#{Gem.marshal_version}(\.gz)?\Z} do |compression|
|
92
|
+
serve_indexes( released_specs, compression )
|
89
93
|
end
|
90
94
|
|
91
95
|
#
|
92
96
|
# Respond to the requests for the <b>latest gems</b> index
|
93
97
|
#
|
94
|
-
get %r{\A/latest_specs.#{Gem.marshal_version}(\.gz)?\Z} do |
|
95
|
-
|
96
|
-
|
98
|
+
get %r{\A/latest_specs.#{Gem.marshal_version}(\.gz)?\Z} do |compression|
|
99
|
+
serve_indexes( latest_specs, compression)
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Respond to the request for the <b>pre release gems</b> index
|
104
|
+
#
|
105
|
+
get %r{\A/prerelease_specs.#{Gem.marshal_version}(\.gz)?\Z} do |compression|
|
106
|
+
serve_indexes( prerelease_specs, compression )
|
97
107
|
end
|
98
108
|
|
99
109
|
#
|
100
110
|
# Serve the indexes up as the response if @serve_indexes is true. Otherwise
|
101
111
|
# return false
|
102
112
|
#
|
103
|
-
def serve_indexes( with_compression = :none )
|
113
|
+
def serve_indexes( specs, with_compression = :none )
|
104
114
|
if @serve_indexes then
|
105
115
|
self.compression = to_compression_flag( with_compression )
|
106
116
|
return marshalled_specs( specs )
|
@@ -128,8 +138,10 @@ module Stickler::Middleware
|
|
128
138
|
# Serve up a gemspec. This is really only used by the child classes.
|
129
139
|
# an Index instance will never have any gemspecs to return
|
130
140
|
#
|
131
|
-
|
132
|
-
|
141
|
+
# To support pre-releases the a-z has been added to the version
|
142
|
+
#
|
143
|
+
get %r{\A/quick/Marshal.#{Gem.marshal_version}/(.*?)-([0-9.]+[0-9a-z.]*)(-.*?)?\.gemspec\.rz\Z} do
|
144
|
+
name, version, platform = *params[:captures]
|
133
145
|
spec = Stickler::SpecLite.new( name, version, platform )
|
134
146
|
full_path = @repo.full_path_to_specification( spec )
|
135
147
|
if full_path and File.exist?( full_path ) then
|
@@ -145,7 +157,27 @@ module Stickler::Middleware
|
|
145
157
|
# everywhere
|
146
158
|
#
|
147
159
|
def marshalled_specs( spec_a )
|
148
|
-
|
160
|
+
a = spec_a.collect { |s| s.to_rubygems_a }
|
161
|
+
marshal( optimize_specs( a ) )
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# Optimize the specs marshalling by using identical objects as much as possible. this
|
166
|
+
# is take directly from RubyGems source code. See rubygems/indexer.rb
|
167
|
+
# #compact_specs
|
168
|
+
#
|
169
|
+
def optimize_specs( specs )
|
170
|
+
names = {}
|
171
|
+
versions = {}
|
172
|
+
platforms = {}
|
173
|
+
|
174
|
+
specs.collect do |(name, version, platform)|
|
175
|
+
names[name] = name unless names.include?( name )
|
176
|
+
versions[version] = version unless versions.include?( version )
|
177
|
+
platforms[platform] = platform unless platforms.include?( platform )
|
178
|
+
|
179
|
+
[ names[name], versions[version], platforms[platform] ]
|
180
|
+
end
|
149
181
|
end
|
150
182
|
|
151
183
|
def marshal( data )
|
@@ -18,11 +18,18 @@ module Stickler::Repository
|
|
18
18
|
# The directory the specs live
|
19
19
|
attr_reader :spec_dir
|
20
20
|
|
21
|
-
#
|
21
|
+
# The last time the repository directory was modified
|
22
|
+
attr_reader :last_modified_time
|
23
|
+
|
24
|
+
# The number of entries in the spec directory
|
25
|
+
attr_reader :last_entry_count
|
22
26
|
|
23
27
|
def initialize( spec_dir )
|
24
|
-
@specs
|
25
|
-
@spec_dir
|
28
|
+
@specs = []
|
29
|
+
@spec_dir = spec_dir
|
30
|
+
@last_modified_time = nil
|
31
|
+
@last_entry_count = nil
|
32
|
+
@spec_glob = File.join( @spec_dir, "*.gemspec" )
|
26
33
|
load_specs
|
27
34
|
end
|
28
35
|
|
@@ -31,9 +38,14 @@ module Stickler::Repository
|
|
31
38
|
return @specs
|
32
39
|
end
|
33
40
|
|
41
|
+
#
|
42
|
+
# return all the latest specs in the repository, do not include pre-release
|
43
|
+
# gems
|
44
|
+
#
|
34
45
|
def latest_specs
|
35
46
|
latest = {}
|
36
47
|
specs.each do |s|
|
48
|
+
next if s.prerelease?
|
37
49
|
if old_spec = latest[s.name] then
|
38
50
|
if old_spec.version < s.version then
|
39
51
|
latest[s.name] = s
|
@@ -45,25 +57,49 @@ module Stickler::Repository
|
|
45
57
|
latest.values
|
46
58
|
end
|
47
59
|
|
60
|
+
#
|
61
|
+
# return just the list of pre-release specs
|
62
|
+
#
|
63
|
+
def prerelease_specs
|
64
|
+
specs.select { |s| s.prerelease? }
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# return just the list of release specs
|
69
|
+
#
|
70
|
+
def released_specs
|
71
|
+
specs.select { |s| not s.prerelease? }
|
72
|
+
end
|
73
|
+
|
48
74
|
def load_specs
|
49
75
|
load_specs_in_dir( self.spec_dir )
|
50
76
|
end
|
51
77
|
|
52
78
|
def reload_necessary?
|
53
|
-
return true
|
54
|
-
|
55
|
-
|
56
|
-
|
79
|
+
return true unless @last_modified_time
|
80
|
+
return true unless @last_entry_count
|
81
|
+
return true if (self.current_modified_time > @last_modified_time )
|
82
|
+
return true if (self.current_entry_count != @last_entry_count )
|
83
|
+
return false
|
57
84
|
end
|
58
85
|
|
59
|
-
def
|
86
|
+
def current_modified_time
|
60
87
|
File.stat( self.spec_dir ).mtime
|
61
88
|
end
|
62
89
|
|
90
|
+
def current_entry_count
|
91
|
+
Dir.glob( @spec_glob ).size
|
92
|
+
end
|
93
|
+
|
63
94
|
def spec_dir=( d )
|
64
95
|
raise Error, "#{d} is not a directory" unless File.directory?( d )
|
65
96
|
@spec_dir = d
|
66
|
-
|
97
|
+
update_reload_conditions
|
98
|
+
end
|
99
|
+
|
100
|
+
def update_reload_conditions
|
101
|
+
@last_modified_time = self.current_modified_time
|
102
|
+
@last_entry_count = self.current_entry_count
|
67
103
|
end
|
68
104
|
|
69
105
|
def load_specs_in_dir( spec_dir )
|
@@ -75,6 +111,7 @@ module Stickler::Repository
|
|
75
111
|
next unless entry =~ /\.gemspec\Z/
|
76
112
|
add_spec_from_file( File.join( spec_dir, entry ) )
|
77
113
|
end
|
114
|
+
update_reload_conditions
|
78
115
|
end
|
79
116
|
|
80
117
|
def add_spec_from_file( path )
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'stickler/spec_lite'
|
2
|
+
require 'stickler/logable'
|
2
3
|
require 'stickler/repository'
|
3
4
|
require 'stickler/repository/api'
|
4
5
|
require 'stickler/repository/index'
|
5
6
|
require 'addressable/uri'
|
6
7
|
require 'tempfile'
|
8
|
+
require 'forwardable'
|
7
9
|
|
8
10
|
module Stickler::Repository
|
9
11
|
#
|
@@ -18,6 +20,10 @@ module Stickler::Repository
|
|
18
20
|
#
|
19
21
|
class Local
|
20
22
|
class Error < ::Stickler::Repository::Error; end
|
23
|
+
include Stickler::Logable
|
24
|
+
|
25
|
+
# The name to give to this repository
|
26
|
+
attr_reader :name
|
21
27
|
|
22
28
|
# the root directory of the repository
|
23
29
|
attr_reader :root_dir
|
@@ -34,13 +40,73 @@ module Stickler::Repository
|
|
34
40
|
# the index of the repository
|
35
41
|
attr_reader :index
|
36
42
|
|
37
|
-
|
43
|
+
# mutex for synchronizing local instance allocations
|
44
|
+
@mutex = Mutex.new
|
45
|
+
|
46
|
+
# The list of repos keyd by root_dir
|
47
|
+
@repos = Hash.new
|
48
|
+
|
49
|
+
#
|
50
|
+
# Return the list of all the Local repositories
|
51
|
+
#
|
52
|
+
def self.repos
|
53
|
+
return @repos
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Purge the list of local repos that are known. This is mainly used in
|
58
|
+
# testing.
|
59
|
+
#
|
60
|
+
def self.purge
|
61
|
+
@mutex.synchronize { @repos.clear }
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# :call-seq:
|
66
|
+
# Local.new( '/tmp/repo' )
|
67
|
+
# Local.new( '/tmp/repo', "Temporary Repo" )
|
68
|
+
#
|
69
|
+
# Create a new Local repository. Local repository instances
|
70
|
+
# are shared if the +root_dir+ is the same. That is
|
71
|
+
#
|
72
|
+
# repo1 = Local.new( '/foo/bar' )
|
73
|
+
# repo2 = Local.new( '/foo/bar' )
|
74
|
+
#
|
75
|
+
# repo1 and repo2 will be references to the sname object
|
76
|
+
#
|
77
|
+
# If a new is called for an already existing repo, and the +name+
|
78
|
+
# of the repo is not nil, and different than the existing repo
|
79
|
+
# an exception is raised.
|
80
|
+
#
|
81
|
+
def self.new( root_dir, name = nil )
|
82
|
+
repo = nil
|
83
|
+
@mutex.synchronize do
|
84
|
+
local_key = File.expand_path( root_dir ) + File::SEPARATOR
|
85
|
+
repo = @repos[local_key]
|
86
|
+
if repo.nil? then
|
87
|
+
repo = super( local_key, name )
|
88
|
+
@repos[local_key] = repo
|
89
|
+
else
|
90
|
+
if name and (repo.name != name) then
|
91
|
+
raise Error, "A repository already exists for #{root_dir} with name has the name #{repo.name} which conflicts with the given name #{name}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
repo
|
96
|
+
end
|
97
|
+
|
98
|
+
def initialize( root_dir, name = nil )
|
38
99
|
@root_dir = File.expand_path( root_dir ) + File::SEPARATOR
|
100
|
+
@name = name || @root_dir
|
39
101
|
@gems_dir = File.join( @root_dir, 'gems/' )
|
40
102
|
@specifications_dir = File.join( @root_dir, 'specifications/' )
|
41
103
|
@temp_dir = File.join( @root_dir, "tmp/" )
|
42
|
-
|
104
|
+
|
105
|
+
# setup the dirs before doing the index because the @specifications_dir
|
106
|
+
# may not exist yet.
|
43
107
|
setup_dirs
|
108
|
+
|
109
|
+
@index = ::Stickler::Repository::Index.new( @specifications_dir )
|
44
110
|
end
|
45
111
|
|
46
112
|
#
|
@@ -66,25 +132,14 @@ module Stickler::Repository
|
|
66
132
|
end
|
67
133
|
|
68
134
|
#
|
69
|
-
#
|
135
|
+
# Forward some calls directly to the index
|
70
136
|
#
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
#
|
78
|
-
def latest_specs
|
79
|
-
@index.latest_specs
|
80
|
-
end
|
81
|
-
|
82
|
-
#
|
83
|
-
# The last time this index was modified
|
84
|
-
#
|
85
|
-
def last_modified_time
|
86
|
-
@index.last_modified_time
|
87
|
-
end
|
137
|
+
extend Forwardable
|
138
|
+
def_delegators :@index, :specs,
|
139
|
+
:released_specs,
|
140
|
+
:latest_specs,
|
141
|
+
:prerelease_specs,
|
142
|
+
:last_modified_time
|
88
143
|
|
89
144
|
#
|
90
145
|
# See Api#search_for
|
@@ -1,5 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'excon'
|
2
2
|
require 'stickler/repository'
|
3
|
+
require 'stickler/version'
|
3
4
|
require 'stickler/repository/api'
|
4
5
|
require 'stickler/repository/rubygems_authenticator'
|
5
6
|
require 'stringio'
|
@@ -11,19 +12,13 @@ module ::Stickler::Repository
|
|
11
12
|
# cutter api (push/yank/unyank). The legacy gem server api is not utilized.
|
12
13
|
#
|
13
14
|
class Remote
|
14
|
-
# the http client
|
15
|
-
attr_reader :http
|
16
15
|
|
17
|
-
|
18
|
-
options[:authenticator] ||= Stickler::Repository::RubygemsAuthenticator.new
|
19
|
-
options[:cache_manager] ||= Resourceful::InMemoryCacheManager.new
|
20
|
-
if options.delete(:debug) then
|
21
|
-
options[:logger] ||= Resourceful::StdOutLogger.new
|
22
|
-
end
|
16
|
+
attr_reader :authenticator
|
23
17
|
|
24
|
-
|
25
|
-
@
|
26
|
-
@
|
18
|
+
def initialize( repo_uri, options = {} )
|
19
|
+
@authenticator = options[:authenticator] || Stickler::Repository::RubygemsAuthenticator.new
|
20
|
+
@uri = Addressable::URI.parse( ensure_http( ensure_trailing_slash( repo_uri ) ) )
|
21
|
+
@specs_list = nil
|
27
22
|
end
|
28
23
|
|
29
24
|
#
|
@@ -80,13 +75,11 @@ module ::Stickler::Repository
|
|
80
75
|
def push( path )
|
81
76
|
spec = speclite_from_gem_file( path )
|
82
77
|
raise Stickler::Repository::Error, "gem #{spec.full_name} already exists in remote repository" if remote_gem_file_exist?( spec )
|
83
|
-
|
84
|
-
resp = push_resource.post( IO.read( path ) )
|
85
|
-
rescue Resourceful::UnsuccessfulHttpRequestError => e
|
86
|
-
msg = "Failure pushing #{path} to remote repository : response code => #{e.http_response.code}, response message => '#{e.http_response.body}'"
|
87
|
-
raise Stickler::Repository::Error, msg
|
88
|
-
end
|
78
|
+
resp = resource_request( push_resource, :body => IO.read( path ) )
|
89
79
|
return spec
|
80
|
+
rescue Excon::Errors::Error => e
|
81
|
+
msg = "Failure pushing #{path} to remote repository : response code => #{e.response.status}, response message => '#{e.response.body}'"
|
82
|
+
raise Stickler::Repository::Error, msg
|
90
83
|
end
|
91
84
|
|
92
85
|
#
|
@@ -94,15 +87,11 @@ module ::Stickler::Repository
|
|
94
87
|
#
|
95
88
|
def yank( spec )
|
96
89
|
return nil unless remote_gem_file_exist?( spec )
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
return full_uri_to_gem( spec )
|
103
|
-
rescue Resourceful::UnsuccessfulHttpRequestError => e
|
104
|
-
raise Stickler::Repository::Error, "Failure yanking: #{e.inspect}"
|
105
|
-
end
|
90
|
+
query = { :gem_name => spec.name, :version => spec.version.to_s }
|
91
|
+
resp = resource_request( yank_resource, :query => query )
|
92
|
+
return full_uri_to_gem( spec )
|
93
|
+
rescue Excon::Errors::Error => e
|
94
|
+
raise Stickler::Repository::Error, "Failure yanking: #{e.inspect}"
|
106
95
|
end
|
107
96
|
|
108
97
|
#
|
@@ -110,12 +99,10 @@ module ::Stickler::Repository
|
|
110
99
|
#
|
111
100
|
def delete( spec )
|
112
101
|
return false unless remote_gem_file_exist?( spec )
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
return false
|
118
|
-
end
|
102
|
+
resource_request( gem_resource( spec ), :method => :delete )
|
103
|
+
return true
|
104
|
+
rescue Excon::Errors::Error => e
|
105
|
+
return false
|
119
106
|
end
|
120
107
|
|
121
108
|
#
|
@@ -123,22 +110,21 @@ module ::Stickler::Repository
|
|
123
110
|
#
|
124
111
|
def open( spec, &block )
|
125
112
|
return nil unless remote_gem_file_exist?( spec )
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
io.close
|
134
|
-
end
|
135
|
-
else
|
136
|
-
return io
|
113
|
+
data = download_resource( gem_resource( spec ) )
|
114
|
+
io = StringIO.new( data , "rb" )
|
115
|
+
if block_given? then
|
116
|
+
begin
|
117
|
+
yield io
|
118
|
+
ensure
|
119
|
+
io.close
|
137
120
|
end
|
138
|
-
|
139
|
-
return
|
121
|
+
else
|
122
|
+
return io
|
140
123
|
end
|
141
124
|
nil
|
125
|
+
rescue Excon::Errors::Error => e
|
126
|
+
$stderr.puts e.inspect
|
127
|
+
return nil
|
142
128
|
end
|
143
129
|
|
144
130
|
private
|
@@ -162,7 +148,7 @@ module ::Stickler::Repository
|
|
162
148
|
end
|
163
149
|
|
164
150
|
def specs_list_resource
|
165
|
-
@specs_list_resource ||=
|
151
|
+
@specs_list_resource ||= Excon.new( specs_list_uri.to_s, :method => :get, :expects => [200] )
|
166
152
|
end
|
167
153
|
|
168
154
|
def push_uri
|
@@ -170,7 +156,11 @@ module ::Stickler::Repository
|
|
170
156
|
end
|
171
157
|
|
172
158
|
def push_resource
|
173
|
-
@push_resource
|
159
|
+
unless @push_resource then
|
160
|
+
params = { :method => :post, :headers => { 'Content-Type' => 'application/octet-stream' }, :expects => [ 201, 200 ] }
|
161
|
+
@push_resource = Excon.new( push_uri.to_s, params )
|
162
|
+
end
|
163
|
+
return @push_resource
|
174
164
|
end
|
175
165
|
|
176
166
|
def yank_uri
|
@@ -178,11 +168,17 @@ module ::Stickler::Repository
|
|
178
168
|
end
|
179
169
|
|
180
170
|
def yank_resource
|
181
|
-
@yank_resource
|
171
|
+
unless @yank_resource then
|
172
|
+
params = { :method => :delete,
|
173
|
+
:headers => { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
174
|
+
:expects => [200] }
|
175
|
+
@yank_resource = Excon.new( yank_uri.to_s, params )
|
176
|
+
end
|
177
|
+
return @yank_resource
|
182
178
|
end
|
183
179
|
|
184
180
|
def gem_resource( spec )
|
185
|
-
|
181
|
+
Excon.new( full_uri_to_gem( spec ), :method => :get, :expects => [200] )
|
186
182
|
end
|
187
183
|
|
188
184
|
def download_specs_list
|
@@ -198,15 +194,14 @@ module ::Stickler::Repository
|
|
198
194
|
end
|
199
195
|
|
200
196
|
def download_uri( uri )
|
201
|
-
download_resource(
|
197
|
+
download_resource( Excon.new( uri ) )
|
202
198
|
end
|
203
199
|
|
204
200
|
def download_resource( resource )
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
201
|
+
resource_request( resource, :method => :get, :expects => [200] ).body
|
202
|
+
rescue Excon::Errors::Error => e
|
203
|
+
puts e.inspect
|
204
|
+
return false
|
210
205
|
end
|
211
206
|
|
212
207
|
def remote_gem_file_exist?( spec )
|
@@ -215,14 +210,10 @@ module ::Stickler::Repository
|
|
215
210
|
end
|
216
211
|
|
217
212
|
def remote_uri_exist?( uri )
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
return rc
|
223
|
-
rescue Resourceful::UnsuccessfulHttpRequestError => e
|
224
|
-
return false
|
225
|
-
end
|
213
|
+
rc = resource_request( Excon.new( uri.to_s ), :method => :head, :expects => [200] )
|
214
|
+
return true
|
215
|
+
rescue Excon::Errors::Error => e
|
216
|
+
return false
|
226
217
|
end
|
227
218
|
|
228
219
|
def speclite_from_gem_file( path )
|
@@ -237,5 +228,31 @@ module ::Stickler::Repository
|
|
237
228
|
def speclite_from_specification( spec )
|
238
229
|
Stickler::SpecLite.new( spec.name, spec.version.to_s, spec.platform )
|
239
230
|
end
|
231
|
+
|
232
|
+
def resource_request( resource, params = {} )
|
233
|
+
trys = 0
|
234
|
+
begin
|
235
|
+
resource.connection[:headers]['User-Agent'] = "Stickler Client v#{Stickler::VERSION}"
|
236
|
+
resource.connection[:headers].delete('Authorization')
|
237
|
+
if authenticator.handles?( resource.connection[:scheme], resource.connection[:host] ) then
|
238
|
+
resource.connection[:headers]['Authorization'] = authenticator.credentials
|
239
|
+
end
|
240
|
+
trys += 1
|
241
|
+
#puts "Making request #{resource.connection.inspect} with extra params #{params.inspect}"
|
242
|
+
resource.request( params )
|
243
|
+
rescue Excon::Errors::MovedPermanently, Excon::Errors::Found,
|
244
|
+
Excon::Errors::SeeOther, Excon::Errors::TemporaryRedirect => redirect
|
245
|
+
# follow a redirect, it is only allowable to follow redirects from a GET or
|
246
|
+
# HEAD request. Only follow a few times though.
|
247
|
+
raise redirect unless [ :get, :head ].include?( redirect.request[:method] )
|
248
|
+
raise redirect if trys > 5
|
249
|
+
#puts "Redirecting to #{redirect.response.headers['Location']}"
|
250
|
+
resource = Excon::Connection.new( redirect.response.headers['Location'],
|
251
|
+
{ :headers => resource.connection[:headers],
|
252
|
+
:query => resource.connection[:headers],
|
253
|
+
:method => resource.connection[:method] } )
|
254
|
+
retry
|
255
|
+
end
|
256
|
+
end
|
240
257
|
end
|
241
258
|
end
|