rubygems-mirror 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.autotest ADDED
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = 'minitest/unit' if at.respond_to? :testlib=
7
+ end
data/.gemtest ADDED
File without changes
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2011-10-01
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,12 @@
1
+ .autotest
2
+ CHANGELOG.rdoc
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/rubygems/mirror.rb
7
+ lib/rubygems/mirror/command.rb
8
+ lib/rubygems/mirror/fetcher.rb
9
+ lib/rubygems/mirror/pool.rb
10
+ lib/rubygems/mirror/test_setup.rb
11
+ lib/rubygems_plugin.rb
12
+ test/test_gem_mirror.rb
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ = rubygems-mirror
2
+
3
+ http://github.com/rubygems/rubygems-mirror
4
+
5
+ == DESCRIPTION:
6
+
7
+ This is an update to the old `gem mirror` command. It uses net/http/persistent
8
+ and threads to grab the mirror set a little faster than the original.
9
+ Eventually it will replace `gem mirror` completely. Right now the API is not
10
+ completely stable (it will change several times before release), however, I
11
+ will maintain stability in master.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ * Fast mirroring
16
+ * Limited tests - just functional
17
+
18
+ == REQUIREMENTS:
19
+
20
+ * rubygems
21
+ * net/http/persistent
22
+
23
+ == USAGE
24
+
25
+ * In a file at ~/.gem/.mirrorrc add a config that looks like the following:
26
+
27
+ ---
28
+ - from: http://rubygems.org
29
+ to: /data/rubygems
30
+
31
+ * Either install the gem, then run `gem mirror`, or
32
+ * Clone then run `rake mirror:update`
33
+
34
+ == INSTALL:
35
+
36
+ * gem install rubygems-mirror
37
+
38
+ == RESOURCES
39
+
40
+ * {Website}[http://rubygems.org/]
41
+ * {Documentation}[http://rubygems.rubyforge.org/rubygems-mirror/README_rdoc.html]
42
+ * {Wiki}[http://wiki.github.com/rubygems/rubygems-mirror/]
43
+ * {Source Code}[http://github.com/rubygems/rubygems-mirror/]
44
+ * {Issues}[http://github.com/rubygems/rubygems-mirror/issues]
45
+ * {Rubyforge}[http://rubyforge.org/projects/rubygems]
46
+
47
+ == LICENSE:
48
+
49
+ (The MIT License)
50
+
51
+ Copyright (c) 2010 James Tucker, The RubyGems Team
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ 'Software'), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
60
+
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'hoe'
4
+ Hoe.plugin :doofus, :git, :gemcutter
5
+
6
+ Hoe.spec 'rubygems-mirror' do
7
+ developer('James Tucker', 'raggi@rubyforge.org')
8
+
9
+ extra_dev_deps << %w[hoe-doofus >=1.0.0]
10
+ extra_dev_deps << %w[hoe-git >=1.3.0]
11
+ extra_dev_deps << %w[hoe-gemcutter >=1.0.0]
12
+ extra_dev_deps << %w[builder >=2.1.2]
13
+ extra_deps << %w[net-http-persistent >=2.1]
14
+
15
+ self.extra_rdoc_files = FileList["**/*.rdoc"]
16
+ self.history_file = "CHANGELOG.rdoc"
17
+ self.readme_file = "README.rdoc"
18
+ self.rubyforge_name = 'rubygems'
19
+ self.testlib = :minitest
20
+ end
21
+
22
+ namespace :mirror do
23
+ desc "Run the Gem::Mirror::Command"
24
+ task :update do
25
+ $:.unshift 'lib'
26
+ require 'rubygems/mirror/command'
27
+
28
+ mirror = Gem::Commands::MirrorCommand.new
29
+ mirror.execute
30
+ end
31
+ end
32
+
33
+ namespace :test do
34
+ task :integration do
35
+ sh Gem.ruby, '-Ilib', '-rubygems', '-S', 'gem', 'mirror'
36
+ end
37
+ end
@@ -0,0 +1,88 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+
4
+ class Gem::Mirror
5
+ autoload :Fetcher, 'rubygems/mirror/fetcher'
6
+ autoload :Pool, 'rubygems/mirror/pool'
7
+
8
+ VERSION = '1.0.0'
9
+
10
+ SPECS_FILE = "specs.#{Gem.marshal_version}"
11
+ SPECS_FILE_Z = "specs.#{Gem.marshal_version}.gz"
12
+
13
+ DEFAULT_URI = 'http://production.cf.rubygems.org/'
14
+ DEFAULT_TO = File.join(Gem.user_home, '.gem', 'mirror')
15
+
16
+ RUBY = 'ruby'
17
+
18
+ def initialize(from = DEFAULT_URI, to = DEFAULT_TO, parallelism = 10)
19
+ @from, @to = from, to
20
+ @fetcher = Fetcher.new
21
+ @pool = Pool.new(parallelism)
22
+ end
23
+
24
+ def from(*args)
25
+ File.join(@from, *args)
26
+ end
27
+
28
+ def to(*args)
29
+ File.join(@to, *args)
30
+ end
31
+
32
+ def update_specs
33
+ specz = to(SPECS_FILE_Z)
34
+ @fetcher.fetch(from(SPECS_FILE_Z), specz)
35
+ open(to(SPECS_FILE), 'wb') { |f| f << Gem.gunzip(File.read(specz)) }
36
+ end
37
+
38
+ def gems
39
+ update_specs unless File.exists?(to(SPECS_FILE))
40
+
41
+ gems = Marshal.load(File.read(to(SPECS_FILE)))
42
+ gems.map! do |name, ver, plat|
43
+ # If the platform is ruby, it is not in the gem name
44
+ "#{name}-#{ver}#{"-#{plat}" unless plat == RUBY}.gem"
45
+ end
46
+ gems
47
+ end
48
+
49
+ def existing_gems
50
+ Dir[to('gems', '*.gem')].entries.map { |f| File.basename(f) }
51
+ end
52
+
53
+ def gems_to_fetch
54
+ gems - existing_gems
55
+ end
56
+
57
+ def gems_to_delete
58
+ existing_gems - gems
59
+ end
60
+
61
+ def update_gems
62
+ gems_to_fetch.each do |g|
63
+ @pool.job do
64
+ @fetcher.fetch(from('gems', g), to('gems', g))
65
+ yield
66
+ end
67
+ end
68
+
69
+ @pool.run_til_done
70
+ end
71
+
72
+ def delete_gems
73
+ gems_to_delete.each do |g|
74
+ @pool.job do
75
+ File.delete(to('gems', g))
76
+ yield
77
+ end
78
+ end
79
+
80
+ @pool.run_til_done
81
+ end
82
+
83
+ def update
84
+ update_specs
85
+ update_gems
86
+ cleanup_gems
87
+ end
88
+ end
@@ -0,0 +1,71 @@
1
+ require 'rubygems/mirror'
2
+ require 'rubygems/command'
3
+ require 'yaml'
4
+
5
+ class Gem::Commands::MirrorCommand < Gem::Command
6
+ SUPPORTS_INFO_SIGNAL = Signal.list['INFO']
7
+
8
+ def initialize
9
+ super 'mirror', 'Mirror a gem repository'
10
+ end
11
+
12
+ def description # :nodoc:
13
+ <<-EOF
14
+ The mirror command uses the ~/.gemmirrorrc config file to mirror remote gem
15
+ repositories to a local path. The config file is a YAML document that looks
16
+ like this:
17
+
18
+ ---
19
+ - from: http://gems.example.com # source repository URI
20
+ to: /path/to/mirror # destination directory
21
+
22
+ Multiple sources and destinations may be specified.
23
+ EOF
24
+ end
25
+
26
+ def execute
27
+ config_file = File.join Gem.user_home, '.gem', '.mirrorrc'
28
+
29
+ raise "Config file #{config_file} not found" unless File.exist? config_file
30
+
31
+ mirrors = YAML.load_file config_file
32
+
33
+ raise "Invalid config file #{config_file}" unless mirrors.respond_to? :each
34
+
35
+ mirrors.each do |mir|
36
+ raise "mirror missing 'from' field" unless mir.has_key? 'from'
37
+ raise "mirror missing 'to' field" unless mir.has_key? 'to'
38
+
39
+ get_from = mir['from']
40
+ save_to = File.expand_path mir['to']
41
+
42
+ raise "Directory not found: #{save_to}" unless File.exist? save_to
43
+ raise "Not a directory: #{save_to}" unless File.directory? save_to
44
+
45
+ mirror = Gem::Mirror.new(get_from, save_to)
46
+
47
+ say "Fetching: #{mirror.from(Gem::Mirror::SPECS_FILE_Z)}"
48
+ mirror.update_specs
49
+
50
+ say "Total gems: #{mirror.gems.size}"
51
+
52
+ num_to_fetch = mirror.gems_to_fetch.size
53
+
54
+ progress = ui.progress_reporter num_to_fetch,
55
+ "Fetching #{num_to_fetch} gems"
56
+
57
+ trap(:INFO) { puts "Fetched: #{progress.count}/#{num_to_fetch}" } if SUPPORTS_INFO_SIGNAL
58
+
59
+ mirror.update_gems { progress.updated true }
60
+
61
+ num_to_delete = mirror.gems_to_delete.size
62
+
63
+ progress = ui.progress_reporter num_to_delete,
64
+ "Deleting #{num_to_delete} gems"
65
+
66
+ trap(:INFO) { puts "Fetched: #{progress.count}/#{num_to_delete}" } if SUPPORTS_INFO_SIGNAL
67
+
68
+ mirror.delete_gems { progress.updated true }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,56 @@
1
+ require 'net/http/persistent'
2
+ require 'time'
3
+
4
+ class Gem::Mirror::Fetcher
5
+ # TODO beef
6
+ class Error < StandardError; end
7
+
8
+ def initialize
9
+ @http = Net::HTTP::Persistent.new(self.class.name, :ENV)
10
+ end
11
+
12
+ # Fetch a source path under the base uri, and put it in the same or given
13
+ # destination path under the base path.
14
+ def fetch(uri, path)
15
+ modified_time = File.exists?(path) && File.stat(path).mtime.rfc822
16
+
17
+ req = Net::HTTP::Get.new URI.parse(uri).path
18
+ req.add_field 'If-Modified-Since', modified_time if modified_time
19
+
20
+ @http.request URI(uri), req do |resp|
21
+ return handle_response(resp, path)
22
+ end
23
+ end
24
+
25
+ # Handle an http response, follow redirects, etc. returns true if a file was
26
+ # downloaded, false if a 304. Raise Error on unknown responses.
27
+ def handle_response(resp, path)
28
+ case resp.code.to_i
29
+ when 304
30
+ when 302
31
+ fetch resp['location'], path
32
+ when 200
33
+ write_file(resp, path)
34
+ when 403, 404
35
+ warn "#{resp.code} on #{File.basename(path)}"
36
+ else
37
+ raise Error, "unexpected response #{resp.inspect}"
38
+ end
39
+ # TODO rescue http errors and reraise cleanly
40
+ end
41
+
42
+ # Efficiently writes an http response object to a particular path. If there
43
+ # is an error, it will remove the target file.
44
+ def write_file(resp, path)
45
+ FileUtils.mkdir_p File.dirname(path)
46
+ File.open(path, 'wb') do |output|
47
+ resp.read_body { |chunk| output << chunk }
48
+ end
49
+ true
50
+ ensure
51
+ # cleanup incomplete files, rescue perm errors etc, they're being
52
+ # raised already.
53
+ File.delete(path) rescue nil if $!
54
+ end
55
+
56
+ end
@@ -0,0 +1,22 @@
1
+ require 'thread'
2
+
3
+ class Gem::Mirror::Pool
4
+ def initialize(size)
5
+ @size = size
6
+ @queue = Queue.new
7
+ end
8
+
9
+ def job(&blk)
10
+ @queue << blk
11
+ end
12
+
13
+ def run_til_done
14
+ threads = Array.new(@size) do
15
+ Thread.new { @queue.pop.call while true }
16
+ end
17
+ until @queue.empty? && @queue.num_waiting == @size
18
+ threads.each { |t| t.join(0.1) }
19
+ end
20
+ threads.each { |t| t.kill }
21
+ end
22
+ end
@@ -0,0 +1,166 @@
1
+ require 'tempfile'
2
+ require 'fileutils'
3
+ require 'stringio'
4
+ require 'webrick'
5
+
6
+ require "rubygems/user_interaction"
7
+ require "rubygems/indexer"
8
+
9
+ # All files must be proactively loaded, otherwhise when the Gem index is
10
+ # replaced, requires will fail!
11
+ require "rubygems/mirror"
12
+ require "rubygems/mirror/fetcher"
13
+ require "rubygems/mirror/pool"
14
+
15
+ class Gem::Mirror
16
+
17
+ # Provide assistance for authors of code that utilises Gem::Mirror. The
18
+ # module defines several setup and teardown methods that can be used to
19
+ # provide a new gem source on disk.
20
+ module TestSetup
21
+ # An instance of TestSetup::UI, a mock UI for RubyGems.
22
+ attr_reader :ui
23
+
24
+ # The path in which setup_gem_source will place a RubyGems source index
25
+ attr_reader :source_path
26
+
27
+ # A list of gem names in the source_path
28
+ attr_reader :source_gems
29
+
30
+ # A temporary directory where mirrors might put their data
31
+ attr_reader :mirror_path
32
+
33
+ # An rcfile pointing at the source and mirror paths
34
+ attr_reader :mirrorrc
35
+
36
+ # Path to the mock, temporary mirrorrc
37
+ attr_reader :mirrorrc_path
38
+
39
+ class UI < Gem::StreamUI
40
+
41
+ # All input and output from the Gem UI when using TestSetup will pass
42
+ # through StringIO objects placed here. For more information, see the
43
+ # arguments to Gem::StreamUI.
44
+ attr_reader :ui_ios
45
+
46
+ def initialize
47
+ super(*(@ui_ios = Array.new(3) { StringIO.new }))
48
+ end
49
+ end
50
+
51
+ # Setup a new mock UI using TestSetup::UI
52
+ def setup_ui
53
+ @old_ui = Gem::DefaultUserInteraction.ui
54
+ @ui = Gem::DefaultUserInteraction.ui = UI.new
55
+ end
56
+
57
+ # Restore RubyGems default UI
58
+ def teardown_ui
59
+ Gem::DefaultUserInteraction.ui = @old_ui if @old_ui
60
+ end
61
+
62
+ # Setup a new gem source directory containing a few gems suitable for
63
+ # testing mirrors, and place the path to that in source_path.
64
+ def setup_gem_source
65
+ @source_path = Dir.mktmpdir("test_gem_source_path_#{$$}")
66
+
67
+ Dir.mkdir gemdir = File.join(@source_path, 'gems')
68
+
69
+ @source_working = working = Dir.mktmpdir("test_gem_source_#{$$}")
70
+
71
+ Dir.mkdir File.join(working, 'lib')
72
+
73
+ gemspecs = %w[a b c].map do |name|
74
+ FileUtils.touch File.join(working, 'lib', "#{name}.rb")
75
+ Gem::Specification.new do |s|
76
+ s.platform = Gem::Platform::RUBY
77
+ s.name = name
78
+ s.version = 1.0
79
+ s.author = 'rubygems'
80
+ s.email = 'example@example.com'
81
+ s.homepage = 'http://example.com'
82
+ s.has_rdoc = false
83
+ s.description = 'desc'
84
+ s.summary = "summ"
85
+ s.require_paths = %w[lib]
86
+ s.files = %W[lib/#{name}.rb]
87
+ s.rubyforge_project = 'rubygems'
88
+ end
89
+ end
90
+
91
+ gemspecs.each do |spec|
92
+ path = File.join(working, "#{spec.name}.gemspec")
93
+ open(path, 'w') do |io|
94
+ io.write(spec.to_ruby)
95
+ end
96
+ Dir.chdir(working) do
97
+ gem_file = Gem::Builder.new(spec).build
98
+ FileUtils.mv(gem_file, File.join(@source_path, 'gems', gem_file))
99
+ end
100
+ end
101
+
102
+ @source_gems = Dir[File.join(gemdir, '*.gem')].map {|p|File.basename(p)}
103
+
104
+ Gem::Indexer.new(@source_path).generate_index
105
+ end
106
+
107
+ # Cleanup temporary directories that are created by setup_gem_source.
108
+ def teardown_gem_source
109
+ [@source_path, @source_working].each do |path|
110
+ FileUtils.rm_rf path
111
+ end
112
+ end
113
+
114
+ # Setup a new mirrorrc for Gem::Mirror based on a setup from
115
+ # setup_gem_source.
116
+ def setup_mirrorrc
117
+ @mirror_path = Dir.mktmpdir("test_gem_mirror_path_#{$$}")
118
+ @mirrorrc = Tempfile.new('testgemmirrorrc')
119
+ opts = {
120
+ 'mirrors' => {
121
+ 'from' => "http://127.0.0.1:8808/", 'to' => @mirror_path
122
+ }
123
+ }
124
+ @mirrorrc.write YAML.dump(opts)
125
+ @mirrorrc_path = @mirrorrc.path
126
+ end
127
+
128
+ # Cleanup tempfiles created by setup_mirrorrc.
129
+ def teardown_mirrorrc
130
+ FileUtils.rm_rf @mirrorrc_path if @mirrorrc_path
131
+ FileUtils.rm_rf @mirror_path if @mirror_path
132
+ end
133
+
134
+ # Starts a server using Rack that will host the gem source
135
+ def setup_server
136
+ opts = { :Port => 8808, :DocumentRoot => @source_path }
137
+ unless $DEBUG
138
+ require 'logger'
139
+ opts[:Logger] = Logger.new('/dev/null')
140
+ opts[:AccessLog] = Logger.new('/dev/null')
141
+ end
142
+ @server = WEBrick::HTTPServer.new opts
143
+ @server_thread = Thread.new { @server.start }
144
+ @server_thread.join(0.1) # pickup early errors and give it time to start
145
+ end
146
+
147
+ # Shutdown the local server hosting the source_path
148
+ def teardown_server
149
+ @server && @server.shutdown
150
+ @server_thread && @server_thread.join
151
+ end
152
+
153
+ def with_server
154
+ setup_ui
155
+ setup_gem_source
156
+ setup_mirrorrc
157
+ setup_server
158
+ yield
159
+ ensure
160
+ teardown_gem_source
161
+ teardown_server
162
+ teardown_mirrorrc
163
+ teardown_ui
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems/command_manager'
2
+ require 'rubygems/mirror/command'
3
+
4
+ Gem::CommandManager.instance.register_command :mirror
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2011-10-01
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
@@ -0,0 +1,70 @@
1
+ = rubygems-mirror
2
+
3
+ http://github.com/rubygems/rubygems-mirror
4
+
5
+ == DESCRIPTION:
6
+
7
+ This is an update to the old `gem mirror` command. It uses net/http/persistent
8
+ and threads to grab the mirror set a little faster than the original.
9
+ Eventually it will replace `gem mirror` completely. Right now the API is not
10
+ completely stable (it will change several times before release), however, I
11
+ will maintain stability in master.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ * Fast mirroring
16
+ * Limited tests - just functional
17
+
18
+ == REQUIREMENTS:
19
+
20
+ * rubygems
21
+ * net/http/persistent
22
+
23
+ == USAGE
24
+
25
+ * In a file at ~/.gem/.mirrorrc add a config that looks like the following:
26
+
27
+ ---
28
+ - from: http://rubygems.org
29
+ to: /data/rubygems
30
+
31
+ * Either install the gem, then run `gem mirror`, or
32
+ * Clone then run `rake mirror:update`
33
+
34
+ == INSTALL:
35
+
36
+ * gem install rubygems-mirror
37
+
38
+ == RESOURCES
39
+
40
+ * {Website}[http://rubygems.org/]
41
+ * {Documentation}[http://rubygems.rubyforge.org/rubygems-mirror/README_rdoc.html]
42
+ * {Wiki}[http://wiki.github.com/rubygems/rubygems-mirror/]
43
+ * {Source Code}[http://github.com/rubygems/rubygems-mirror/]
44
+ * {Issues}[http://github.com/rubygems/rubygems-mirror/issues]
45
+ * {Rubyforge}[http://rubyforge.org/projects/rubygems]
46
+
47
+ == LICENSE:
48
+
49
+ (The MIT License)
50
+
51
+ Copyright (c) 2010 James Tucker, The RubyGems Team
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ 'Software'), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
60
+
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ require "rubygems_plugin"
2
+ require "rubygems/mirror"
3
+ require "rubygems/mirror/test_setup"
4
+
5
+ require 'minitest/autorun' # damn you autotest.
6
+
7
+ class TestGemMirror < MiniTest::Unit::TestCase
8
+ include Gem::Mirror::TestSetup
9
+
10
+ # Used to make sure we don't raise on construction, works against defaults
11
+ def opts
12
+ ['http://localhost:8808/', mirror_path, 1]
13
+ end
14
+
15
+ def test_update_specs
16
+ with_server do
17
+ mirror = Gem::Mirror.new(*opts)
18
+ mirror.update_specs
19
+ assert File.exists?(mirror_path + "/#{Gem::Mirror::SPECS_FILE_Z}")
20
+ assert File.exists?(mirror_path + "/#{Gem::Mirror::SPECS_FILE_Z}")
21
+ end
22
+ end
23
+
24
+ def test_update_gems
25
+ with_server do
26
+ mirror = Gem::Mirror.new(*opts)
27
+
28
+ updates = 0
29
+ mirror.update_gems { updates += 1 }
30
+
31
+ source_gems, mirror_gems = [source_path, mirror_path].map do |path|
32
+ Dir[path + '/gems/*'].map { |f| File.basename(f) }
33
+ end
34
+
35
+ assert_equal source_gems, mirror_gems
36
+ assert_equal 3, updates
37
+ end
38
+ end
39
+
40
+ def test_delete_gems
41
+ with_server do
42
+ mirror = Gem::Mirror.new(*opts)
43
+ FileUtils.mkdir_p mirror.to('gems')
44
+ FileUtils.touch mirror.to('gems', 'd-1.0.gem')
45
+
46
+ updates = 0
47
+ mirror.delete_gems { updates += 1 }
48
+
49
+ gems = Dir[mirror_path + '/gems/*.gem'].map { |f| File.basename f }
50
+ assert_equal [], gems
51
+ assert_equal 1, updates
52
+ end
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubygems-mirror
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - James Tucker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-02 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: net-http-persistent
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 1
29
+ segments:
30
+ - 2
31
+ - 1
32
+ version: "2.1"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe-doofus
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
48
+ version: 1.0.0
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: hoe-git
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 27
60
+ segments:
61
+ - 1
62
+ - 3
63
+ - 0
64
+ version: 1.3.0
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: hoe-gemcutter
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 23
76
+ segments:
77
+ - 1
78
+ - 0
79
+ - 0
80
+ version: 1.0.0
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: builder
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 15
92
+ segments:
93
+ - 2
94
+ - 1
95
+ - 2
96
+ version: 2.1.2
97
+ type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: hoe
101
+ prerelease: false
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ~>
106
+ - !ruby/object:Gem::Version
107
+ hash: 27
108
+ segments:
109
+ - 2
110
+ - 12
111
+ version: "2.12"
112
+ type: :development
113
+ version_requirements: *id006
114
+ description: |-
115
+ This is an update to the old `gem mirror` command. It uses net/http/persistent
116
+ and threads to grab the mirror set a little faster than the original.
117
+ Eventually it will replace `gem mirror` completely. Right now the API is not
118
+ completely stable (it will change several times before release), however, I
119
+ will maintain stability in master.
120
+ email:
121
+ - raggi@rubyforge.org
122
+ executables: []
123
+
124
+ extensions: []
125
+
126
+ extra_rdoc_files:
127
+ - Manifest.txt
128
+ - CHANGELOG.rdoc
129
+ - pkg/rubygems-mirror-1.0.0/CHANGELOG.rdoc
130
+ - pkg/rubygems-mirror-1.0.0/README.rdoc
131
+ - README.rdoc
132
+ files:
133
+ - .autotest
134
+ - CHANGELOG.rdoc
135
+ - Manifest.txt
136
+ - README.rdoc
137
+ - Rakefile
138
+ - lib/rubygems/mirror.rb
139
+ - lib/rubygems/mirror/command.rb
140
+ - lib/rubygems/mirror/fetcher.rb
141
+ - lib/rubygems/mirror/pool.rb
142
+ - lib/rubygems/mirror/test_setup.rb
143
+ - lib/rubygems_plugin.rb
144
+ - test/test_gem_mirror.rb
145
+ - pkg/rubygems-mirror-1.0.0/CHANGELOG.rdoc
146
+ - pkg/rubygems-mirror-1.0.0/README.rdoc
147
+ - .gemtest
148
+ homepage: http://github.com/rubygems/rubygems-mirror
149
+ licenses: []
150
+
151
+ metadata: {}
152
+
153
+ post_install_message:
154
+ rdoc_options:
155
+ - --main
156
+ - README.rdoc
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ none: false
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ hash: 3
165
+ segments:
166
+ - 0
167
+ version: "0"
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ hash: 3
174
+ segments:
175
+ - 0
176
+ version: "0"
177
+ requirements: []
178
+
179
+ rubyforge_project: rubygems
180
+ rubygems_version: 1.8.10
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: This is an update to the old `gem mirror` command
184
+ test_files:
185
+ - test/test_gem_mirror.rb