gem-mirror 0.0.1
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 +5 -0
- data/.yardopts +11 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/MANIFEST +33 -0
- data/README.md +80 -0
- data/Rakefile +12 -0
- data/bin/gem-mirror +5 -0
- data/doc/.gitkeep +0 -0
- data/doc/Contributing.md +125 -0
- data/doc/DCO.md +25 -0
- data/doc/css/.gitkeep +0 -0
- data/doc/css/common.css +68 -0
- data/gem-mirror.gemspec +26 -0
- data/lib/gem-mirror.rb +31 -0
- data/lib/gem-mirror/cli.rb +65 -0
- data/lib/gem-mirror/cli/checksum.rb +41 -0
- data/lib/gem-mirror/cli/index.rb +31 -0
- data/lib/gem-mirror/cli/init.rb +21 -0
- data/lib/gem-mirror/cli/update.rb +23 -0
- data/lib/gem-mirror/configuration.rb +132 -0
- data/lib/gem-mirror/gem.rb +53 -0
- data/lib/gem-mirror/gems_fetcher.rb +194 -0
- data/lib/gem-mirror/mirror_directory.rb +59 -0
- data/lib/gem-mirror/mirror_file.rb +63 -0
- data/lib/gem-mirror/source.rb +106 -0
- data/lib/gem-mirror/version.rb +3 -0
- data/lib/gem-mirror/versions_fetcher.rb +30 -0
- data/lib/gem-mirror/versions_file.rb +64 -0
- data/task/manifest.rake +8 -0
- data/template/config.rb +25 -0
- data/template/public/checksums/.gitkeep +0 -0
- data/template/public/gems/.gitkeep +0 -0
- metadata +174 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
module GemMirror
|
2
|
+
##
|
3
|
+
# The MirrorDirectory is used for dealing with files and directories that are
|
4
|
+
# mirrored from an external source.
|
5
|
+
#
|
6
|
+
# @!attribute [r] path
|
7
|
+
# @return [String]
|
8
|
+
#
|
9
|
+
class MirrorDirectory
|
10
|
+
attr_reader :path
|
11
|
+
|
12
|
+
##
|
13
|
+
# @param [String] path
|
14
|
+
#
|
15
|
+
def initialize(path)
|
16
|
+
@path = path
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Creates a new directory with the given name.
|
21
|
+
#
|
22
|
+
# @param [String] name
|
23
|
+
# @return [GemMirror::MirrorDirectory]
|
24
|
+
#
|
25
|
+
def add_directory(name)
|
26
|
+
full_path = File.join(path, name)
|
27
|
+
|
28
|
+
Dir.mkdir(full_path) unless File.directory?(full_path)
|
29
|
+
|
30
|
+
return self.class.new(full_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Creates a new file with the given name and content.
|
35
|
+
#
|
36
|
+
# @param [String] name
|
37
|
+
# @param [String] content
|
38
|
+
# @return [Gem::MirrorFile]
|
39
|
+
#
|
40
|
+
def add_file(name, content)
|
41
|
+
full_path = File.join(path, name)
|
42
|
+
file = MirrorFile.new(full_path)
|
43
|
+
|
44
|
+
file.write(content)
|
45
|
+
|
46
|
+
return file
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Checks if a given file exists in the current directory.
|
51
|
+
#
|
52
|
+
# @param [String] name
|
53
|
+
# @return [TrueClass|FalseClass]
|
54
|
+
#
|
55
|
+
def file_exists?(name)
|
56
|
+
return File.file?(File.join(path, name))
|
57
|
+
end
|
58
|
+
end # MirrorDirectory
|
59
|
+
end # GemMirror
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module GemMirror
|
2
|
+
##
|
3
|
+
# Similar to {GemMirror::MirrorDirectory} the MirrorFile class is used to
|
4
|
+
# make it easier to read and write data in a directory that mirrors data from
|
5
|
+
# an external source.
|
6
|
+
#
|
7
|
+
# @!attribute [r] path
|
8
|
+
# @return [String]
|
9
|
+
#
|
10
|
+
class MirrorFile
|
11
|
+
attr_reader :path
|
12
|
+
|
13
|
+
##
|
14
|
+
# @param [String] path
|
15
|
+
#
|
16
|
+
def initialize(path)
|
17
|
+
@path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Writes the specified content to the current file. Existing files are
|
22
|
+
# overwritten.
|
23
|
+
#
|
24
|
+
# @param [String] content
|
25
|
+
#
|
26
|
+
def write(content)
|
27
|
+
handle = File.open(path, 'w')
|
28
|
+
|
29
|
+
handle.write(content)
|
30
|
+
handle.close
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Reads the content of the current file.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
#
|
38
|
+
def read
|
39
|
+
handle = File.open(path, 'r')
|
40
|
+
content = handle.read
|
41
|
+
|
42
|
+
handle.close
|
43
|
+
|
44
|
+
return content
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Reads the contents of a Gzip encoded file.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
#
|
52
|
+
def read_gzip
|
53
|
+
content = nil
|
54
|
+
|
55
|
+
Zlib::GzipReader.open(path) do |gz|
|
56
|
+
content = gz.read
|
57
|
+
gz.close
|
58
|
+
end
|
59
|
+
|
60
|
+
return content
|
61
|
+
end
|
62
|
+
end # MirrorFile
|
63
|
+
end # GemMirror
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module GemMirror
|
2
|
+
##
|
3
|
+
# The Source class is used for storing information about an external source
|
4
|
+
# such as the name and the Gems to mirror.
|
5
|
+
#
|
6
|
+
# @!attribute [r] name
|
7
|
+
# @return [String]
|
8
|
+
# @!attribute [r] host
|
9
|
+
# @return [String]
|
10
|
+
# @!attribute [r] gems
|
11
|
+
# @return [Array]
|
12
|
+
#
|
13
|
+
class Source
|
14
|
+
attr_reader :name, :host, :gems
|
15
|
+
|
16
|
+
##
|
17
|
+
# @param [String] name
|
18
|
+
# @param [String] host
|
19
|
+
# @param [Array] gems
|
20
|
+
#
|
21
|
+
def initialize(name, host, gems = [])
|
22
|
+
@name = name.downcase.gsub(/\s+/, '_')
|
23
|
+
@host = host.chomp('/')
|
24
|
+
@gems = gems
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Returns a new Source instance based on the current one.
|
29
|
+
#
|
30
|
+
# @param [Array] new_gems The gems to set, overwrites the current ones.
|
31
|
+
# @return [Source]
|
32
|
+
#
|
33
|
+
def updated(new_gems)
|
34
|
+
return self.class.new(name, host, new_gems)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Fetches a list of all the available Gems and their versions.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
#
|
42
|
+
def fetch_versions
|
43
|
+
return http_get(host + '/' + Configuration.versions_file).body
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Fetches the Gem specification of a Gem.
|
48
|
+
#
|
49
|
+
# @param [String] name
|
50
|
+
# @param [String] version
|
51
|
+
# @return [String]
|
52
|
+
#
|
53
|
+
def fetch_specification(name, version)
|
54
|
+
url = host + "/quick/#{Configuration.marshal_identifier}" +
|
55
|
+
"/#{name}-#{version}.gemspec.rz"
|
56
|
+
|
57
|
+
return http_get(url).body
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Fetches the `.gem` file of a given Gem and version.
|
62
|
+
#
|
63
|
+
# @param [String] name
|
64
|
+
# @param [String] version
|
65
|
+
# @return [String]
|
66
|
+
#
|
67
|
+
def fetch_gem(name, version)
|
68
|
+
return http_get(host + "/gems/#{name}-#{version}.gem").body
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Adds a new Gem to the source.
|
73
|
+
#
|
74
|
+
# @param [String] name
|
75
|
+
# @param [String] requirement
|
76
|
+
#
|
77
|
+
def gem(name, requirement = nil)
|
78
|
+
gems << Gem.new(name, ::Gem::Requirement.new(requirement))
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
##
|
84
|
+
# Requests the given HTTP resource.
|
85
|
+
#
|
86
|
+
# @param [String] url
|
87
|
+
# @return [HTTP::Message]
|
88
|
+
#
|
89
|
+
def http_get(url)
|
90
|
+
response = client.get(url, :follow_redirect => true)
|
91
|
+
|
92
|
+
unless HTTP::Status.successful?(response.status)
|
93
|
+
raise HTTPClient::BadResponseError, response.reason
|
94
|
+
end
|
95
|
+
|
96
|
+
return response
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# @return [HTTPClient]
|
101
|
+
#
|
102
|
+
def client
|
103
|
+
return @client ||= HTTPClient.new
|
104
|
+
end
|
105
|
+
end # Source
|
106
|
+
end # GemMirror
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module GemMirror
|
2
|
+
##
|
3
|
+
# The VersionsFetcher class is used for retrieving the file that contains all
|
4
|
+
# registered Gems and their versions.
|
5
|
+
#
|
6
|
+
# @!attribute [r] source
|
7
|
+
# @return [Source]
|
8
|
+
#
|
9
|
+
class VersionsFetcher
|
10
|
+
attr_reader :source
|
11
|
+
|
12
|
+
##
|
13
|
+
# @param [Source] source
|
14
|
+
#
|
15
|
+
def initialize(source)
|
16
|
+
@source = source
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# @return [GemMirror::VersionsFile]
|
21
|
+
#
|
22
|
+
def fetch
|
23
|
+
GemMirror.configuration.logger.info(
|
24
|
+
"Updating #{source.name} (#{source.host})"
|
25
|
+
)
|
26
|
+
|
27
|
+
return VersionsFile.load(source.fetch_versions)
|
28
|
+
end
|
29
|
+
end # VersionsFetcher
|
30
|
+
end # GemMirror
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module GemMirror
|
2
|
+
##
|
3
|
+
# The VersionsFile class acts as a small Ruby wrapper around the RubyGems
|
4
|
+
# file that contains all Gems and their associated versions.
|
5
|
+
#
|
6
|
+
# @!attribute [r] versions
|
7
|
+
# @return [Array]
|
8
|
+
# @!attribute [r] versions_hash
|
9
|
+
# @return [Hash]
|
10
|
+
#
|
11
|
+
class VersionsFile
|
12
|
+
attr_reader :versions, :versions_hash
|
13
|
+
|
14
|
+
##
|
15
|
+
# Reads the versions file from the specified String.
|
16
|
+
#
|
17
|
+
# @param [String] content
|
18
|
+
# @return [GemMirror::VersionsFile]
|
19
|
+
#
|
20
|
+
def self.load(content)
|
21
|
+
buffer = StringIO.new(content)
|
22
|
+
reader = Zlib::GzipReader.new(buffer)
|
23
|
+
instance = new(Marshal.load(reader.read))
|
24
|
+
|
25
|
+
reader.close
|
26
|
+
|
27
|
+
return instance
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# @param [Array] versions
|
32
|
+
#
|
33
|
+
def initialize(versions)
|
34
|
+
@versions = versions
|
35
|
+
@versions_hash = create_versions_hash
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Creates a Hash based on the Array containing all versions. This Hash is
|
40
|
+
# used to more easily (and faster) iterate over all the gems/versions.
|
41
|
+
#
|
42
|
+
# @return [Hash]
|
43
|
+
#
|
44
|
+
def create_versions_hash
|
45
|
+
hash = Hash.new { |h, k| h[k] = [] }
|
46
|
+
|
47
|
+
versions.each do |version|
|
48
|
+
hash[version[0]] << version
|
49
|
+
end
|
50
|
+
|
51
|
+
return hash
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Returns an Array containing all the available versions for a Gem.
|
56
|
+
#
|
57
|
+
# @param [String] gem
|
58
|
+
# @return [Array]
|
59
|
+
#
|
60
|
+
def versions_for(gem)
|
61
|
+
return versions_hash[gem].map { |version| version[1] }
|
62
|
+
end
|
63
|
+
end # VersionsFile
|
64
|
+
end # GemMirror
|
data/task/manifest.rake
ADDED
data/template/config.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# This is the main configuration file for your RubyGems mirror. Here you can
|
2
|
+
# change settings such as the location to store Gem files in and what sources
|
3
|
+
# and Gems you'd like to mirror.
|
4
|
+
GemMirror.configuration.configure do
|
5
|
+
# The directory to store indexing information as well as the Gem files in.
|
6
|
+
destination File.expand_path('../public', __FILE__)
|
7
|
+
|
8
|
+
# Directory to use for storing SHA512 checksums of each Gem.
|
9
|
+
checksums File.expand_path('../public/checksums', __FILE__)
|
10
|
+
|
11
|
+
# When set to `true` development dependencies of Gems will also be mirrored.
|
12
|
+
development false
|
13
|
+
|
14
|
+
# If you're mirroring a lot of Gems you'll probably want to switch the
|
15
|
+
# logging level to Logger::ERROR or Logger::INFO to reduce the amount of
|
16
|
+
# noise.
|
17
|
+
logger.level = Logger::DEBUG
|
18
|
+
|
19
|
+
# A source is a remote location that you want to mirror. The first parameter
|
20
|
+
# of this method is the human readable name, the second one the URL. The
|
21
|
+
# supplied block is used to determine what Gems (and versions) to mirror.
|
22
|
+
source 'rubygems', 'http://rubygems.org' do
|
23
|
+
gem 'rack', '>= 1.0.0'
|
24
|
+
end
|
25
|
+
end
|
File without changes
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem-mirror
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yorick Peterse
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: slop
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httpclient
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: builder
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: yard
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: redcarpet
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rake
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Gem for easily creating your own RubyGems mirror.
|
111
|
+
email: yorickpeterse@gmail.com
|
112
|
+
executables:
|
113
|
+
- gem-mirror
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- .yardopts
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE
|
121
|
+
- MANIFEST
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/gem-mirror
|
125
|
+
- doc/.gitkeep
|
126
|
+
- doc/Contributing.md
|
127
|
+
- doc/DCO.md
|
128
|
+
- doc/css/.gitkeep
|
129
|
+
- doc/css/common.css
|
130
|
+
- gem-mirror.gemspec
|
131
|
+
- lib/gem-mirror.rb
|
132
|
+
- lib/gem-mirror/cli.rb
|
133
|
+
- lib/gem-mirror/cli/checksum.rb
|
134
|
+
- lib/gem-mirror/cli/index.rb
|
135
|
+
- lib/gem-mirror/cli/init.rb
|
136
|
+
- lib/gem-mirror/cli/update.rb
|
137
|
+
- lib/gem-mirror/configuration.rb
|
138
|
+
- lib/gem-mirror/gem.rb
|
139
|
+
- lib/gem-mirror/gems_fetcher.rb
|
140
|
+
- lib/gem-mirror/mirror_directory.rb
|
141
|
+
- lib/gem-mirror/mirror_file.rb
|
142
|
+
- lib/gem-mirror/source.rb
|
143
|
+
- lib/gem-mirror/version.rb
|
144
|
+
- lib/gem-mirror/versions_fetcher.rb
|
145
|
+
- lib/gem-mirror/versions_file.rb
|
146
|
+
- task/manifest.rake
|
147
|
+
- template/config.rb
|
148
|
+
- template/public/checksums/.gitkeep
|
149
|
+
- template/public/gems/.gitkeep
|
150
|
+
homepage: https://github.com/yorickpeterse/gem-mirror
|
151
|
+
licenses: []
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
none: false
|
158
|
+
requirements:
|
159
|
+
- - ! '>='
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 1.9.2
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 1.8.25
|
171
|
+
signing_key:
|
172
|
+
specification_version: 3
|
173
|
+
summary: Gem for easily creating your own RubyGems mirror.
|
174
|
+
test_files: []
|