gemirro 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of gemirro might be problematic. Click here for more details.
- checksums.yaml +15 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +24 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/MANIFEST +46 -0
- data/README.md +60 -0
- data/Rakefile +10 -0
- data/bin/gemirro +6 -0
- data/gemirro.gemspec +31 -0
- data/lib/gemirro.rb +37 -0
- data/lib/gemirro/cli.rb +63 -0
- data/lib/gemirro/cli/index.rb +24 -0
- data/lib/gemirro/cli/init.rb +17 -0
- data/lib/gemirro/cli/server.rb +19 -0
- data/lib/gemirro/cli/update.rb +18 -0
- data/lib/gemirro/configuration.rb +137 -0
- data/lib/gemirro/gem.rb +70 -0
- data/lib/gemirro/gems_fetcher.rb +126 -0
- data/lib/gemirro/http.rb +37 -0
- data/lib/gemirro/indexer.rb +56 -0
- data/lib/gemirro/mirror_directory.rb +59 -0
- data/lib/gemirro/mirror_file.rb +48 -0
- data/lib/gemirro/server.rb +164 -0
- data/lib/gemirro/source.rb +58 -0
- data/lib/gemirro/version.rb +5 -0
- data/lib/gemirro/versions_fetcher.rb +31 -0
- data/lib/gemirro/versions_file.rb +65 -0
- data/spec/gemirro/cli_spec.rb +51 -0
- data/spec/gemirro/configuration_spec.rb +88 -0
- data/spec/gemirro/gem_spec.rb +37 -0
- data/spec/gemirro/gems_fetcher_spec.rb +104 -0
- data/spec/gemirro/http_spec.rb +36 -0
- data/spec/gemirro/indexer_spec.rb +55 -0
- data/spec/gemirro/mirror_directory_spec.rb +37 -0
- data/spec/gemirro/mirror_file_spec.rb +23 -0
- data/spec/gemirro/server_spec.rb +96 -0
- data/spec/gemirro/source_spec.rb +44 -0
- data/spec/gemirro/versions_fetcher_spec.rb +25 -0
- data/spec/gemirro/versions_file_spec.rb +52 -0
- data/spec/spec_helper.rb +17 -0
- data/task/manifest.rake +9 -0
- data/task/rspec.rake +6 -0
- data/task/rubocop.rake +5 -0
- data/template/config.rb +25 -0
- data/template/public/gems/.gitkeep +0 -0
- metadata +230 -0
data/MANIFEST
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
.gitignore
|
2
|
+
.rubocop.yml
|
3
|
+
.travis.yml
|
4
|
+
Gemfile
|
5
|
+
LICENSE
|
6
|
+
MANIFEST
|
7
|
+
README.md
|
8
|
+
Rakefile
|
9
|
+
bin/gemirro
|
10
|
+
gemirro.gemspec
|
11
|
+
lib/gemirro.rb
|
12
|
+
lib/gemirro/cli.rb
|
13
|
+
lib/gemirro/cli/index.rb
|
14
|
+
lib/gemirro/cli/init.rb
|
15
|
+
lib/gemirro/cli/server.rb
|
16
|
+
lib/gemirro/cli/update.rb
|
17
|
+
lib/gemirro/configuration.rb
|
18
|
+
lib/gemirro/gem.rb
|
19
|
+
lib/gemirro/gems_fetcher.rb
|
20
|
+
lib/gemirro/http.rb
|
21
|
+
lib/gemirro/indexer.rb
|
22
|
+
lib/gemirro/mirror_directory.rb
|
23
|
+
lib/gemirro/mirror_file.rb
|
24
|
+
lib/gemirro/server.rb
|
25
|
+
lib/gemirro/source.rb
|
26
|
+
lib/gemirro/version.rb
|
27
|
+
lib/gemirro/versions_fetcher.rb
|
28
|
+
lib/gemirro/versions_file.rb
|
29
|
+
spec/gemirro/cli_spec.rb
|
30
|
+
spec/gemirro/configuration_spec.rb
|
31
|
+
spec/gemirro/gem_spec.rb
|
32
|
+
spec/gemirro/gems_fetcher_spec.rb
|
33
|
+
spec/gemirro/http_spec.rb
|
34
|
+
spec/gemirro/indexer_spec.rb
|
35
|
+
spec/gemirro/mirror_directory_spec.rb
|
36
|
+
spec/gemirro/mirror_file_spec.rb
|
37
|
+
spec/gemirro/server_spec.rb
|
38
|
+
spec/gemirro/source_spec.rb
|
39
|
+
spec/gemirro/versions_fetcher_spec.rb
|
40
|
+
spec/gemirro/versions_file_spec.rb
|
41
|
+
spec/spec_helper.rb
|
42
|
+
task/manifest.rake
|
43
|
+
task/rspec.rake
|
44
|
+
task/rubocop.rake
|
45
|
+
template/config.rb
|
46
|
+
template/public/gems/.gitkeep
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Gemirro | [![Build Status](https://travis-ci.org/PierreRambaud/gemirro.svg)](https://travis-ci.org/PierreRambaud/gemirro)
|
2
|
+
|
3
|
+
Gemirro is a Ruby application that makes it easy way to create your own RubyGems mirror without having to push or write all gem you wanted in a configuration file.
|
4
|
+
It does mirroring only, it has no authentication and you can't upload Gems to it.
|
5
|
+
More you only need to launch the server and gems will automaticly be downloaded when requests come.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
* Ruby 1.9.2 or newer
|
10
|
+
* Enough space to store Gems
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Assuming RubyGems isn't down you can install the Gem as following:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
$ gem install gemirro
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
The process of setting up a mirror is fairly easy and can be done in few seconds.
|
23
|
+
|
24
|
+
The first step is to set up a new, empty mirror directory.
|
25
|
+
This is done by running the `gemirro init` command.
|
26
|
+
|
27
|
+
```bash
|
28
|
+
$ gemirro init /srv/http/mirror.com/
|
29
|
+
```
|
30
|
+
|
31
|
+
Once created you can edit the main configuration file called `config.rb`.
|
32
|
+
This configuration file specifies what source to mirror, destination directory, server host and port, etc.
|
33
|
+
|
34
|
+
Once configured and if you add gem in the `define_source`, you can pull them by running the following command:
|
35
|
+
|
36
|
+
```bash
|
37
|
+
$ gemirro update
|
38
|
+
```
|
39
|
+
|
40
|
+
Once all the Gems have been downloaded you'll need to generate an index of all the installed files. This can be done as following:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
$ gemirro index
|
44
|
+
```
|
45
|
+
|
46
|
+
|
47
|
+
Last, launch the `TCPServer`, and all requests will check if gems are detected, and download them if necessary and generate index immediately.
|
48
|
+
|
49
|
+
```bash
|
50
|
+
$ gemirro server
|
51
|
+
```
|
52
|
+
|
53
|
+
If you want to use a custom configuration file not located in the current directory, use the `-c` or `--config` option.
|
54
|
+
|
55
|
+
|
56
|
+
##Apache configuration
|
57
|
+
TODO
|
58
|
+
|
59
|
+
##Nginx configuration
|
60
|
+
TODO
|
data/Rakefile
ADDED
data/bin/gemirro
ADDED
data/gemirro.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/gemirro/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'gemirro'
|
6
|
+
s.version = Gemirro::VERSION
|
7
|
+
s.date = '2014-08-19'
|
8
|
+
s.authors = ['Pierre Rambaud']
|
9
|
+
s.email = 'pierre.rambaud86@gmail.com'
|
10
|
+
s.license = 'GPL-3.0'
|
11
|
+
s.summary = 'Gem for easily creating your own RubyGems mirror.'
|
12
|
+
s.homepage = 'https://github.com/PierreRambaud/gemirro'
|
13
|
+
s.description = 'Create your own gem mirro with a simple TCPServer.'
|
14
|
+
s.executables = ['gemirro']
|
15
|
+
|
16
|
+
s.files = File.read(File.expand_path('../MANIFEST', __FILE__)).split("\n")
|
17
|
+
|
18
|
+
s.required_ruby_version = '~> 1.9.2'
|
19
|
+
|
20
|
+
s.add_dependency 'slop', '~>3.6'
|
21
|
+
s.add_dependency 'httpclient', '~>2.4'
|
22
|
+
s.add_dependency 'confstruct', '~>0.2'
|
23
|
+
s.add_dependency 'builder', '~>3.2'
|
24
|
+
|
25
|
+
s.add_development_dependency 'mime-types', '~>2.3'
|
26
|
+
s.add_development_dependency 'rake', '~>10.0'
|
27
|
+
s.add_development_dependency 'rspec', '~>3.0'
|
28
|
+
s.add_development_dependency 'simplecov', '~>0.9'
|
29
|
+
s.add_development_dependency 'rubocop', '~>0.25'
|
30
|
+
s.add_development_dependency 'fakefs', '~>0.5'
|
31
|
+
end
|
data/lib/gemirro.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/user_interaction'
|
4
|
+
require 'rubygems/indexer'
|
5
|
+
require 'slop'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'digest/sha2'
|
8
|
+
require 'confstruct'
|
9
|
+
require 'zlib'
|
10
|
+
require 'httpclient'
|
11
|
+
require 'logger'
|
12
|
+
require 'stringio'
|
13
|
+
require 'socket'
|
14
|
+
require 'mime/types'
|
15
|
+
|
16
|
+
unless $LOAD_PATH.include?(File.expand_path('../', __FILE__))
|
17
|
+
$LOAD_PATH.unshift(File.expand_path('../', __FILE__))
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'gemirro/version'
|
21
|
+
require 'gemirro/configuration'
|
22
|
+
require 'gemirro/gem'
|
23
|
+
require 'gemirro/http'
|
24
|
+
require 'gemirro/indexer'
|
25
|
+
require 'gemirro/server'
|
26
|
+
require 'gemirro/source'
|
27
|
+
require 'gemirro/mirror_directory'
|
28
|
+
require 'gemirro/mirror_file'
|
29
|
+
require 'gemirro/versions_file'
|
30
|
+
require 'gemirro/versions_fetcher'
|
31
|
+
require 'gemirro/gems_fetcher'
|
32
|
+
|
33
|
+
require 'gemirro/cli'
|
34
|
+
require 'gemirro/cli/init'
|
35
|
+
require 'gemirro/cli/update'
|
36
|
+
require 'gemirro/cli/index'
|
37
|
+
require 'gemirro/cli/server'
|
data/lib/gemirro/cli.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Gemirro
|
3
|
+
# CLI mode
|
4
|
+
module CLI
|
5
|
+
##
|
6
|
+
# Hash containing the default Slop options.
|
7
|
+
#
|
8
|
+
# @return [Hash]
|
9
|
+
#
|
10
|
+
SLOP_OPTIONS = {
|
11
|
+
strict: true,
|
12
|
+
help: true,
|
13
|
+
banner: 'Usage: gemirro [COMMAND] [OPTIONS]'
|
14
|
+
}
|
15
|
+
|
16
|
+
##
|
17
|
+
# @return [Slop]
|
18
|
+
#
|
19
|
+
def self.options
|
20
|
+
@options ||= default_options
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Loads the specified configuration file or displays an error if it doesn't
|
25
|
+
# exist.
|
26
|
+
#
|
27
|
+
# @param [String] config_file
|
28
|
+
# @return [Gemirro::Configuration]
|
29
|
+
#
|
30
|
+
def self.load_configuration(config_file)
|
31
|
+
config_file ||= Configuration.default_configuration_file
|
32
|
+
config_file = File.expand_path(config_file, Dir.pwd)
|
33
|
+
|
34
|
+
unless File.file?(config_file)
|
35
|
+
abort "The configuration file #{config_file} does not exist"
|
36
|
+
end
|
37
|
+
|
38
|
+
require(config_file)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @return [Slop]
|
43
|
+
#
|
44
|
+
def self.default_options
|
45
|
+
Slop.new(SLOP_OPTIONS.dup) do
|
46
|
+
separator "\nOptions:\n"
|
47
|
+
|
48
|
+
on :v, :version, 'Shows the current version' do
|
49
|
+
puts CLI.version_information
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Returns a String containing some platform/version related information.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
#
|
59
|
+
def self.version_information
|
60
|
+
"gemirro v#{VERSION} on #{RUBY_DESCRIPTION}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
Gemirro::CLI.options.command 'index' do
|
3
|
+
banner 'Usage: gemirro index [OPTIONS]'
|
4
|
+
description 'Retrieve specs list from source.'
|
5
|
+
separator "\nOptions:\n"
|
6
|
+
|
7
|
+
on :c=, :config=, 'Path to the configuration file'
|
8
|
+
|
9
|
+
run do |opts, _args|
|
10
|
+
Gemirro::CLI.load_configuration(opts[:c])
|
11
|
+
config = Gemirro.configuration
|
12
|
+
|
13
|
+
unless File.directory?(config.destination)
|
14
|
+
config.logger.error("The directory #{config.destination} does not exist")
|
15
|
+
abort
|
16
|
+
end
|
17
|
+
|
18
|
+
indexer = Gemirro::Indexer.new(config.destination)
|
19
|
+
indexer.ui = Gem::SilentUI.new
|
20
|
+
|
21
|
+
config.logger.info('Generating indexes')
|
22
|
+
indexer.generate_index
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
Gemirro::CLI.options.command 'init' do
|
3
|
+
banner 'Usage: gemirro init [DIRECTORY] [OPTIONS]'
|
4
|
+
description 'Sets up a new mirror'
|
5
|
+
separator "\nOptions:\n"
|
6
|
+
|
7
|
+
run do |_opts, args|
|
8
|
+
directory = File.expand_path(args[0] || Dir.pwd)
|
9
|
+
template = Gemirro::Configuration.template_directory
|
10
|
+
|
11
|
+
Dir.mkdir(directory) unless File.directory?(directory)
|
12
|
+
|
13
|
+
FileUtils.cp_r(File.join(template, '.'), directory)
|
14
|
+
|
15
|
+
puts "Initialized empty mirror in #{directory}"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
Gemirro::CLI.options.command 'server' do
|
3
|
+
banner 'Usage: gemirro server [OPTIONS]'
|
4
|
+
description 'Run web server'
|
5
|
+
separator "\nOptions:\n"
|
6
|
+
|
7
|
+
on :c=, :config=, 'Path to the configuration file'
|
8
|
+
|
9
|
+
run do |opts, _args|
|
10
|
+
Gemirro::CLI.load_configuration(opts[:c])
|
11
|
+
config = Gemirro.configuration
|
12
|
+
unless File.directory?(config.destination)
|
13
|
+
config.logger.error("The directory #{config.destination} does not exist")
|
14
|
+
abort
|
15
|
+
end
|
16
|
+
|
17
|
+
Gemirro::Server.new.run
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
Gemirro::CLI.options.command 'update' do
|
3
|
+
banner 'Usage: gemirro update [OPTIONS]'
|
4
|
+
description 'Updates the list of Gems'
|
5
|
+
separator "\nOptions:\n"
|
6
|
+
|
7
|
+
on :c=, :config=, 'Path to the configuration file'
|
8
|
+
|
9
|
+
run do |opts, _args|
|
10
|
+
Gemirro::CLI.load_configuration(opts[:c])
|
11
|
+
|
12
|
+
source = Gemirro.configuration.source
|
13
|
+
versions = Gemirro::VersionsFetcher.new(source).fetch
|
14
|
+
gems = Gemirro::GemsFetcher.new(source, versions)
|
15
|
+
|
16
|
+
gems.fetch
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Configuration
|
3
|
+
module Gemirro
|
4
|
+
##
|
5
|
+
# @return [Gemirro::Configuration]
|
6
|
+
#
|
7
|
+
def self.configuration
|
8
|
+
@configuration ||= Configuration.new
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Configuration class used for storing data about a mirror such as the
|
13
|
+
# destination directory, source, ignored Gems, etc.
|
14
|
+
#
|
15
|
+
class Configuration < Confstruct::Configuration
|
16
|
+
attr_reader :logger, :mirror_directory
|
17
|
+
attr_accessor :source, :ignored_gems
|
18
|
+
|
19
|
+
##
|
20
|
+
# Returns the logger
|
21
|
+
#
|
22
|
+
# @return [Logger]
|
23
|
+
#
|
24
|
+
def logger
|
25
|
+
@logger ||= Logger.new(STDOUT)
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Returns the template path to init directory
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
#
|
33
|
+
def self.template_directory
|
34
|
+
File.expand_path('../../../template', __FILE__)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Returns default configuration file path
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
#
|
42
|
+
def self.default_configuration_file
|
43
|
+
File.expand_path('config.rb', Dir.pwd)
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Returns the name of the directory that contains the quick
|
48
|
+
# specification files.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
#
|
52
|
+
def self.marshal_identifier
|
53
|
+
"Marshal.#{marshal_version}"
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Returns the name of the file that contains an index of all the versions.
|
58
|
+
#
|
59
|
+
# @return [String]
|
60
|
+
#
|
61
|
+
def self.versions_file
|
62
|
+
"specs.#{marshal_version}.gz"
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns a String containing the Marshal version.
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
#
|
70
|
+
def self.marshal_version
|
71
|
+
"#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Return mirror directory
|
76
|
+
#
|
77
|
+
# @return [Gemirro::MirrorDirectory]
|
78
|
+
#
|
79
|
+
def mirror_directory
|
80
|
+
@mirror_directory ||= MirrorDirectory.new(gems_directory)
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Returns gems directory
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
#
|
88
|
+
def gems_directory
|
89
|
+
File.join(destination, 'gems')
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Returns a Hash containing various Gems to ignore and their versions.
|
94
|
+
#
|
95
|
+
# @return [Hash]
|
96
|
+
#
|
97
|
+
def ignored_gems
|
98
|
+
@ignored_gems ||= Hash.new { |hash, key| hash[key] = [] }
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Adds a Gem to the list of Gems to ignore.
|
103
|
+
#
|
104
|
+
# @param [String] name
|
105
|
+
# @param [String] version
|
106
|
+
#
|
107
|
+
def ignore_gem(name, version)
|
108
|
+
ignored_gems[name] ||= []
|
109
|
+
ignored_gems[name] << version
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Checks if a Gem should be ignored.
|
114
|
+
#
|
115
|
+
# @param [String] name
|
116
|
+
# @param [String] version
|
117
|
+
# @return [TrueClass|FalseClass]
|
118
|
+
#
|
119
|
+
def ignore_gem?(name, version)
|
120
|
+
ignored_gems[name].include?(version)
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Define the source to mirror.
|
125
|
+
#
|
126
|
+
# @param [String] name
|
127
|
+
# @param [String] url
|
128
|
+
# @param [Proc] block
|
129
|
+
#
|
130
|
+
def define_source(name, url, &block)
|
131
|
+
source = Source.new(name, url)
|
132
|
+
source.instance_eval(&block)
|
133
|
+
|
134
|
+
@source = source
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|