alloy-microgem 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/LICENSE +21 -0
- data/README.rdoc +55 -0
- data/Rakefile +24 -0
- data/TODO +13 -0
- data/bin/zinflate +17 -0
- data/bin//302/265gem +14 -0
- data/lib/microgem.rb +56 -0
- data/lib/microgem/bare_specification.rb +40 -0
- data/lib/microgem/bin_wrapper_emitter.rb +58 -0
- data/lib/microgem/config.rb +96 -0
- data/lib/microgem/dependency.rb +37 -0
- data/lib/microgem/downloader.rb +48 -0
- data/lib/microgem/installer.rb +147 -0
- data/lib/microgem/options_parser.rb +67 -0
- data/lib/microgem/requirement.rb +36 -0
- data/lib/microgem/source.rb +108 -0
- data/lib/microgem/specification.rb +65 -0
- data/lib/microgem/specification_emitter.rb +75 -0
- data/lib/microgem/unpacker.rb +55 -0
- data/lib/microgem/utils.rb +51 -0
- data/lib/microgem/version.rb +35 -0
- data/lib/microgem/yamlable.rb +32 -0
- data/test/bare_specification_test.rb +43 -0
- data/test/bin_wrapper_emitter_test.rb +57 -0
- data/test/config_test.rb +131 -0
- data/test/dependency_test.rb +41 -0
- data/test/downloader_test.rb +100 -0
- data/test/fixtures/gems.github.com +0 -0
- data/test/fixtures/gems.rubyforge.org +0 -0
- data/test/fixtures/gems/rake-0.8.0/rake.rb +1 -0
- data/test/fixtures/gems/rake-0.8.1/rake.rb +1 -0
- data/test/fixtures/gems/test-spec-0.3.0/test-spec.rb +1 -0
- data/test/fixtures/gems/test-spec-mock-0.3.0/test-spec-mock.rb +1 -0
- data/test/fixtures/rails-2.1.1.gemspec +26 -0
- data/test/fixtures/rails-2.1.1.gemspec.marshal +0 -0
- data/test/fixtures/rake-0.8.1.gem +0 -0
- data/test/fixtures/rake-0.8.1.gemspec +20 -0
- data/test/fixtures/rake-0.8.1.gemspec.marshal +0 -0
- data/test/fixtures/rake-0.8.1.gemspec.rz +2 -0
- data/test/fixtures/specs.4.8.gz +0 -0
- data/test/installer_test.rb +198 -0
- data/test/microgem_test.rb +34 -0
- data/test/options_parser_test.rb +36 -0
- data/test/requirement_test.rb +40 -0
- data/test/source_test.rb +153 -0
- data/test/specification_emitter_test.rb +139 -0
- data/test/specification_test.rb +45 -0
- data/test/test_helper.rb +71 -0
- data/test/unpacker_test.rb +91 -0
- data/test/utils_test.rb +42 -0
- data/test/version_test.rb +27 -0
- data/test/yamlable_test.rb +15 -0
- metadata +114 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) <2009> Eloy Duran <eloy.de.enige@gmail.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
== MicroGem
|
2
|
+
The aim of this project is, at first, to create a re-implementation of the
|
3
|
+
RubyGems +install+ command, which should be easier to get up and running on
|
4
|
+
Ruby implementations such as MacRuby.
|
5
|
+
|
6
|
+
See the TODO file for a list of todo's.
|
7
|
+
|
8
|
+
=== Installation
|
9
|
+
|
10
|
+
$ sudo gem install alloy-microgem -s http://gems.github.com
|
11
|
+
|
12
|
+
=== µgem banner
|
13
|
+
Microgem is an unsophisticated package manager for Ruby.
|
14
|
+
And the first commandline utility to start with a multibyte character; µ
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
µgem [command] [arguments…] [options…]
|
18
|
+
|
19
|
+
Example:
|
20
|
+
µgem install rake
|
21
|
+
µgem install rails --force
|
22
|
+
µgem cache update --debug
|
23
|
+
|
24
|
+
Options:
|
25
|
+
--debug Raises the log level to `debug'
|
26
|
+
--force Forces a command
|
27
|
+
--simple-downloader Use curl to download files instead of Net::HTTP
|
28
|
+
--simple-unpacker Use external tools to unpack archives instead of Zlib
|
29
|
+
--simple Enables --simple-downloader and --simple-unpacker
|
30
|
+
--help Show help information
|
31
|
+
|
32
|
+
=== Development
|
33
|
+
The way it's being developed is in a test and RubyGems data driven manner.
|
34
|
+
We are using the `quick' marshalled specs, so we use those fixtures to run the tests.
|
35
|
+
|
36
|
+
==== Getting started
|
37
|
+
|
38
|
+
Get the source:
|
39
|
+
|
40
|
+
$ git clone git://github.com/alloy/microgem.git
|
41
|
+
|
42
|
+
Install a gem:
|
43
|
+
|
44
|
+
$ ./bin/µgem install rake
|
45
|
+
|
46
|
+
Note that unless you set the PRODUCTION environment variable everything is installed in ./tmp.
|
47
|
+
|
48
|
+
The current default sources are rubyforge and github.
|
49
|
+
|
50
|
+
=== Goals
|
51
|
+
* Install gems.
|
52
|
+
* Small.
|
53
|
+
* Test driven.
|
54
|
+
* Clean room design.
|
55
|
+
* Naive, no more code than necessary should be written. (YAGNI)
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
HOME = File.expand_path('../tmp/gem_home', __FILE__)
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.test_files = FileList['test/*_test.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc "Cleans the temporary development directory"
|
12
|
+
task :clean do
|
13
|
+
rm_rf 'tmp'
|
14
|
+
rm_rf 'pkg'
|
15
|
+
end
|
16
|
+
|
17
|
+
directory 'pkg'
|
18
|
+
|
19
|
+
desc "Builds and installs the gem"
|
20
|
+
task :install => :pkg do
|
21
|
+
# TODO: install gem with µgem, this is why we don't use the rake gem tasks.
|
22
|
+
sh 'gem build microgem.gemspec && mv microgem-*.gem pkg/'
|
23
|
+
sh 'cd pkg && sudo gem install microgem-*.gem'
|
24
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
=== TODO (in order of priority)
|
2
|
+
* Add support for <tt>~/.gemrc</tt>
|
3
|
+
* Add support for configuring multiple gem servers.
|
4
|
+
* Remove any unnecessary “complex” code.
|
5
|
+
* Bring back to _one_ file, or at least less files if it doesn't harm
|
6
|
+
readability.
|
7
|
+
|
8
|
+
==== Laurents wish list
|
9
|
+
* More commands:
|
10
|
+
* +uninstall+
|
11
|
+
* +search+
|
12
|
+
* +update+
|
13
|
+
* +list+
|
data/bin/zinflate
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# TODO: We should probably write a C version of this.
|
4
|
+
|
5
|
+
require File.expand_path('../../lib/microgem/utils', __FILE__)
|
6
|
+
require File.expand_path('../../lib/microgem/unpacker', __FILE__)
|
7
|
+
|
8
|
+
archive, out_file = ARGV[0], ARGV[1]
|
9
|
+
|
10
|
+
if archive && out_file
|
11
|
+
Gem::Micro::Unpacker.inflate_with_zlib(archive, out_file)
|
12
|
+
else
|
13
|
+
puts "This is a simple bin file which is able to inflate the .Z/.rz files returned from a gem server."
|
14
|
+
puts "This bin can be invoked from microgem with a Ruby which does support zlib."
|
15
|
+
puts ''
|
16
|
+
puts "Usage: zinflate /path/to/archive.Z /path/to/uncompressed_file"
|
17
|
+
end
|
data/bin//302/265gem
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if defined?(Gem)
|
4
|
+
# Hack to make sure we don't run with RubyGems loaded.
|
5
|
+
ENV['PRODUCTION'] = 'true'
|
6
|
+
exec "#{File.expand_path(__FILE__)} #{ARGV.join(' ')}"
|
7
|
+
|
8
|
+
else
|
9
|
+
# Run the normal operations.
|
10
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
11
|
+
require 'microgem'
|
12
|
+
|
13
|
+
Gem::Micro.run(ARGV)
|
14
|
+
end
|
data/lib/microgem.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'microgem/yamlable'
|
2
|
+
require 'microgem/utils'
|
3
|
+
|
4
|
+
require 'microgem/bare_specification'
|
5
|
+
require 'microgem/bin_wrapper_emitter'
|
6
|
+
require 'microgem/config'
|
7
|
+
require 'microgem/dependency'
|
8
|
+
require 'microgem/downloader'
|
9
|
+
require 'microgem/installer'
|
10
|
+
require 'microgem/options_parser'
|
11
|
+
require 'microgem/requirement'
|
12
|
+
require 'microgem/source'
|
13
|
+
require 'microgem/specification'
|
14
|
+
require 'microgem/specification_emitter'
|
15
|
+
require 'microgem/unpacker'
|
16
|
+
require 'microgem/version'
|
17
|
+
|
18
|
+
module Gem
|
19
|
+
module Micro
|
20
|
+
class << self
|
21
|
+
include Utils
|
22
|
+
|
23
|
+
# The main +run+ method which is used by the µgem script to perform the
|
24
|
+
# actions specified by the user.
|
25
|
+
def run(arguments)
|
26
|
+
parser = OptionsParser.new
|
27
|
+
parser.parse(arguments)
|
28
|
+
Config.merge!(parser.options)
|
29
|
+
|
30
|
+
case parser.command
|
31
|
+
when 'install'
|
32
|
+
gem_spec = Source.gem_spec(parser.arguments.first, Gem::Version[:version => '0'])
|
33
|
+
gem_spec.install!
|
34
|
+
|
35
|
+
when 'sources'
|
36
|
+
case parser.arguments.first
|
37
|
+
when 'update'
|
38
|
+
Source.update!
|
39
|
+
|
40
|
+
end
|
41
|
+
else
|
42
|
+
puts parser.banner
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns an array of all installed gems their directory names,
|
47
|
+
# optionally limited to gems matching the given +name+.
|
48
|
+
def installed_gem_dirnames(name = nil)
|
49
|
+
directories = Dir.glob(File.join(Config.gems_path, '*')).sort
|
50
|
+
directories = directories.map { |dir| File.basename(dir) }
|
51
|
+
|
52
|
+
name.nil? ? directories : directories.select { |dirname| dirname =~ /^#{name}-[\d\.]+/ }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gem
|
2
|
+
module Micro
|
3
|
+
class BareSpecification
|
4
|
+
include Utils
|
5
|
+
|
6
|
+
def initialize(source, name, version)
|
7
|
+
@source, @name, @version = source, name, version
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns the url from where the gemspec should be downloaded.
|
11
|
+
def gem_spec_url
|
12
|
+
"http://#{@source.host}/quick/Marshal.4.8/#{@name}-#{@version}.gemspec.rz"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the full path to the gemspec file in the temporary work
|
16
|
+
# directory.
|
17
|
+
def gem_spec_work_file
|
18
|
+
File.join(tmpdir, "#{@name}-#{@version}.gemspec")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the full path to the archive containing the gemspec file in the
|
22
|
+
# temporary work directory.
|
23
|
+
def gem_spec_work_archive_file
|
24
|
+
"#{gem_spec_work_file}.rz"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retrieves the gem spec from gem_spec_url and loads the marshalled data.
|
28
|
+
#
|
29
|
+
# The returned Gem::Specification instance knows to which
|
30
|
+
# Gem::Micro::Source it belongs.
|
31
|
+
def gem_spec
|
32
|
+
Downloader.get(gem_spec_url, gem_spec_work_archive_file)
|
33
|
+
Unpacker.inflate(gem_spec_work_archive_file, gem_spec_work_file)
|
34
|
+
gem_spec = Marshal.load(File.read(gem_spec_work_file))
|
35
|
+
gem_spec.source = @source
|
36
|
+
gem_spec
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Micro
|
5
|
+
class BinWrapperEmitter
|
6
|
+
# Initializes a new BinWrapperEmitter with a +gem_name+ and a +bin_name+.
|
7
|
+
def initialize(gem_name, bin_name)
|
8
|
+
@gem_name, @bin_name = gem_name, bin_name
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the full path to where the bin wrapper script should be
|
12
|
+
# created. If Ruby was installed with a prefix or suffix it will be
|
13
|
+
# inflected and added to the name of the executable.
|
14
|
+
#
|
15
|
+
# If the prefix is, for instance, `mac' an executable like +macrake+ will
|
16
|
+
# be installed. With a suffix like `19' the name will be +rake19+.
|
17
|
+
def bin_wrapper_file
|
18
|
+
rbconfig('ruby_install_name').match /^(.*)ruby(.*)$/
|
19
|
+
File.join(Config.bin_dir, "#{$1}#{@bin_name}#{$2}")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Creates the bin wrapper script in bin_wrapper_file.
|
23
|
+
def create_bin_wrapper!
|
24
|
+
Utils.log(:debug, "Creating bin wrapper `#{bin_wrapper_file}'")
|
25
|
+
File.open(bin_wrapper_file, 'w') { |f| f << to_ruby }
|
26
|
+
File.chmod(0755, bin_wrapper_file)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a string representation of the bin wrapper file.
|
30
|
+
def to_ruby
|
31
|
+
%{#!#{ File.join(rbconfig('bindir'), rbconfig('ruby_install_name')) }
|
32
|
+
#
|
33
|
+
# This file was generated by MicroGem (µgem).
|
34
|
+
#
|
35
|
+
# The application '#{@bin_name}' is installed as part of a gem, and
|
36
|
+
# this file is here to facilitate running it.
|
37
|
+
|
38
|
+
require 'rubygems'
|
39
|
+
|
40
|
+
version = "> 0"
|
41
|
+
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
42
|
+
version = $1
|
43
|
+
ARGV.shift
|
44
|
+
end
|
45
|
+
|
46
|
+
gem '#{@gem_name}', version
|
47
|
+
load '#{@bin_name}'
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def rbconfig(key)
|
54
|
+
::Config::CONFIG[key]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Micro
|
5
|
+
class Config
|
6
|
+
class << self
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
# Returns the full path to the Gem home directory.
|
10
|
+
def gem_home
|
11
|
+
@gem_home ||= ensure_dir(if ENV['PRODUCTION']
|
12
|
+
sitelibdir = ::Config::CONFIG['sitelibdir']
|
13
|
+
version = ::Config::CONFIG['ruby_version']
|
14
|
+
File.expand_path("../../Gems/#{version}", sitelibdir)
|
15
|
+
else
|
16
|
+
File.expand_path("../../../tmp/gem_home", __FILE__)
|
17
|
+
end)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the full path to the bin directory.
|
21
|
+
def bin_dir
|
22
|
+
@bin_dir ||= if ENV['PRODUCTION']
|
23
|
+
if macruby?
|
24
|
+
'/usr/local/bin'
|
25
|
+
elsif osx_default_ruby?
|
26
|
+
'/usr/bin'
|
27
|
+
else
|
28
|
+
::Config::CONFIG['bindir']
|
29
|
+
end
|
30
|
+
else
|
31
|
+
ensure_dir(File.expand_path("../../../tmp/bin", __FILE__))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the full path to the directory where the installed gems are.
|
36
|
+
def gems_path
|
37
|
+
@gems_path ||= ensure_dir(File.join(gem_home, 'gems'))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the full path to the directory where the installed gem specs
|
41
|
+
# are.
|
42
|
+
def specifications_path
|
43
|
+
@specifications_path ||= ensure_dir(File.join(gem_home, 'specifications'))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the full path to the directory where the gems are cached.
|
47
|
+
def cache_path
|
48
|
+
@cache_path ||= ensure_dir(File.join(gem_home, 'cache'))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns an array of source hosts from which to fetch gems.
|
52
|
+
def sources
|
53
|
+
%w{ gems.rubyforge.org gems.github.com }
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_writer :log_level, :force, :simple_downloader, :simple_unpacker
|
57
|
+
|
58
|
+
# Returns the current log level, which is +:info+ or +:debug+.
|
59
|
+
def log_level
|
60
|
+
@log_level ||= :info
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns whether or not actions should be forced.
|
64
|
+
def force?
|
65
|
+
@force ||= false
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns whether or not to use +curl+ instead of Net::HTTP.
|
69
|
+
def simple_downloader?
|
70
|
+
@simple_downloader ||= false
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns whether or not to use the external +xinflate+ instead of
|
74
|
+
# Zlib::Inflate.inflate.
|
75
|
+
def simple_unpacker?
|
76
|
+
@simple_unpacker ||= false
|
77
|
+
end
|
78
|
+
|
79
|
+
# Merges the values from the +options+ hash.
|
80
|
+
def merge!(options)
|
81
|
+
options.each { |k,v| send("#{k}=", v) }
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def osx_default_ruby?
|
87
|
+
defined? RUBY_FRAMEWORK_VERSION
|
88
|
+
end
|
89
|
+
|
90
|
+
def macruby?
|
91
|
+
defined? MACRUBY_VERSION
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Gem
|
2
|
+
module Micro
|
3
|
+
class GemSpecMissingError < StandardError; end
|
4
|
+
end
|
5
|
+
|
6
|
+
class Dependency < Micro::YAMLable
|
7
|
+
attr_reader :name, :version, :version_requirements
|
8
|
+
|
9
|
+
# Returns whether or not any of the installed gems matches the requirements.
|
10
|
+
#
|
11
|
+
# For now we just compare against the last one which should be the highest.
|
12
|
+
def meets_requirements?
|
13
|
+
if dirname = Micro.installed_gem_dirnames(name).last
|
14
|
+
Gem::Version.from_gem_dirname(dirname) >= @version_requirements.version
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the Gem::Specification instance for this dependency. If the
|
19
|
+
# required version is `0' then the latest version is used.
|
20
|
+
def gem_spec
|
21
|
+
if @gem_spec.nil?
|
22
|
+
unless @gem_spec = Micro::Source.gem_spec(@name, @version_requirements.version)
|
23
|
+
raise Micro::GemSpecMissingError, "Unable to locate Gem::Specification for Gem::Dependency `#{self}'"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@gem_spec
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a ‘pretty’ string representation of the Dependency instance:
|
31
|
+
#
|
32
|
+
# dependency.to_s # => "rake >= 0.8.1"
|
33
|
+
def to_s
|
34
|
+
"#{name} #{@version_requirements}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|