gemi 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.mkd +151 -0
- data/Rakefile +18 -2
- data/VERSION +1 -1
- data/bin/gemi +3 -89
- data/features/basic_commands.feature +40 -0
- data/features/command_specific_options.feature +25 -0
- data/features/config_file.feature +27 -0
- data/features/gems_yaml.feature +52 -0
- data/features/multiple_rubys.feature +21 -0
- data/features/step_definitions/gemi_steps.rb +45 -0
- data/features/support/env.rb +24 -0
- data/gemi.gemspec +42 -8
- data/gemirc.yml +6 -13
- data/lib/gemi.rb +14 -0
- data/lib/gemi/commands.rb +40 -0
- data/lib/gemi/conf.rb +53 -0
- data/lib/gemi/gem.rb +38 -0
- data/lib/gemi/options.rb +69 -0
- data/lib/gemi/ruby.rb +5 -0
- data/lib/gemi/runner.rb +89 -0
- metadata +44 -9
- data/README +0 -35
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
features/tmp/
|
data/README.mkd
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
gemi
|
2
|
+
====
|
3
|
+
|
4
|
+
Gemi is a simple tool for installing gems for multiple rubys.
|
5
|
+
It also can install specific versions of the gems listed in a YAML file.
|
6
|
+
|
7
|
+
without gemi, you need to type 'install' for all your rubys:
|
8
|
+
|
9
|
+
$ gem install foo bar baz quux
|
10
|
+
$ gem-1.9 install foo bar baz quux
|
11
|
+
|
12
|
+
with gemi, it's just:
|
13
|
+
|
14
|
+
$ gemi foo bar baz quux
|
15
|
+
|
16
|
+
or even:
|
17
|
+
|
18
|
+
$ gemi gems.yml
|
19
|
+
|
20
|
+
Install
|
21
|
+
-------
|
22
|
+
|
23
|
+
$ gem install gemi
|
24
|
+
|
25
|
+
Setup
|
26
|
+
-----
|
27
|
+
|
28
|
+
First, execute gemi without any options:
|
29
|
+
|
30
|
+
$ gemi
|
31
|
+
|
32
|
+
then ~/.gemirc is created. Edit it for your environment.
|
33
|
+
|
34
|
+
Example:
|
35
|
+
|
36
|
+
rubys:
|
37
|
+
- name: 'MRI 1.8'
|
38
|
+
command: 'gem'
|
39
|
+
install_options: '--no-format-executable --user-install'
|
40
|
+
- name: 'MRI 1.9'
|
41
|
+
command: 'gem-1.9'
|
42
|
+
install_options: '--format-executable --user-install'
|
43
|
+
|
44
|
+
Usage
|
45
|
+
-----
|
46
|
+
|
47
|
+
First of all,
|
48
|
+
|
49
|
+
$ gemi foo
|
50
|
+
|
51
|
+
will install the gem 'foo' for all your rubys.
|
52
|
+
|
53
|
+
gemi can also uninstall, update, or cleanup the gems.
|
54
|
+
|
55
|
+
### Install gems
|
56
|
+
|
57
|
+
Just give the names of the gems to gemi.
|
58
|
+
|
59
|
+
$ gemi foo bar (= gem install foo bar)
|
60
|
+
|
61
|
+
You can also install gems defined in a YAML file:
|
62
|
+
|
63
|
+
$ gemi gems.yml
|
64
|
+
|
65
|
+
Example of gems.yml:
|
66
|
+
|
67
|
+
gems:
|
68
|
+
- name: 'ruby-openid'
|
69
|
+
version: '2.1.4'
|
70
|
+
|
71
|
+
- name: 'nokogiri'
|
72
|
+
version: '1.4.0'
|
73
|
+
install_options: --with-foo
|
74
|
+
|
75
|
+
### Uninstall gems
|
76
|
+
|
77
|
+
Specify '-d' for "gem uninstall".
|
78
|
+
|
79
|
+
$ gemi -d foo bar (= gem uninstall foo bar)
|
80
|
+
|
81
|
+
### Update gems
|
82
|
+
|
83
|
+
Specify '-u' for "gem upgrade".
|
84
|
+
|
85
|
+
$ gemi -u foo bar (= gem upgrade foo bar)
|
86
|
+
|
87
|
+
### Cleanup old gems
|
88
|
+
|
89
|
+
Specify '-c' for "gem cleanup".
|
90
|
+
|
91
|
+
$ gemi -c foo bar (= gem cleanup foo bar)
|
92
|
+
|
93
|
+
### Other gem commands
|
94
|
+
|
95
|
+
With '--', you can run any gem commands for rubys:
|
96
|
+
|
97
|
+
$ gemi -- list --local (= gem list --local)
|
98
|
+
|
99
|
+
The arguments after '--' are passed to each gem command.
|
100
|
+
(Note that 'gemi list' is expanded to 'gem install list'!)
|
101
|
+
|
102
|
+
Configuration
|
103
|
+
-------------
|
104
|
+
|
105
|
+
### .gemirc
|
106
|
+
|
107
|
+
~/.gemirc contains the information about each gem commands.
|
108
|
+
|
109
|
+
Example:
|
110
|
+
|
111
|
+
rubys:
|
112
|
+
- name: Ruby 1.8
|
113
|
+
command: gem
|
114
|
+
- name: Ruby 1.9
|
115
|
+
command: gem-1.9
|
116
|
+
install_options: --foo
|
117
|
+
uninstall_options: --bar
|
118
|
+
update_options: --baz
|
119
|
+
clean_options: --quux
|
120
|
+
|
121
|
+
{install,uninstall,update,clean}_options will be appended to the
|
122
|
+
arguments. In this case, the command:
|
123
|
+
|
124
|
+
$ gemi a b c
|
125
|
+
|
126
|
+
resuls in running these two gem commands.
|
127
|
+
|
128
|
+
$ gem install a b c --foo
|
129
|
+
$ gem-1.9 install a b c --foo
|
130
|
+
|
131
|
+
### Alternative .gemirc
|
132
|
+
|
133
|
+
You can specify an alternative gemirc with '-r' (or '--rc').
|
134
|
+
|
135
|
+
Example: use myconf.yml instead of ~/.gemirc
|
136
|
+
|
137
|
+
$ gemi -r myconf.yml foo bar
|
138
|
+
|
139
|
+
Repository
|
140
|
+
----------
|
141
|
+
|
142
|
+
http://github.com/yhara/gemi
|
143
|
+
|
144
|
+
Authors
|
145
|
+
-------
|
146
|
+
|
147
|
+
yhara (Yutaka HARA) yutaka.hara.gmail.com
|
148
|
+
http://route477.net/
|
149
|
+
|
150
|
+
Kazuyoshi Tlacaelel
|
151
|
+
http://github.com/ktlacaelel
|
data/Rakefile
CHANGED
@@ -8,9 +8,25 @@ end
|
|
8
8
|
|
9
9
|
Jeweler::Tasks.new do |gemspec|
|
10
10
|
gemspec.name = "#{PROJECT_NAME}"
|
11
|
-
gemspec.summary = "
|
11
|
+
gemspec.summary = "gem command for multiple rubys"
|
12
12
|
gemspec.email = "yutaka.hara/at/gmail.com"
|
13
13
|
gemspec.homepage = "http://github.com/yhara/#{PROJECT_NAME}"
|
14
|
-
gemspec.description =
|
14
|
+
gemspec.description = <<-EOD
|
15
|
+
gemi runs 'gem install' for each your rubys.
|
16
|
+
Example:
|
17
|
+
without gemi:
|
18
|
+
$ gem install foo bar
|
19
|
+
$ gem-1.9 install foo bar
|
20
|
+
with gemi:
|
21
|
+
$ gemi foo bar
|
22
|
+
EOD
|
15
23
|
gemspec.authors = ["Yutaka HARA"]
|
24
|
+
gemspec.add_development_dependency('cucumber', '>= 0.4.2')
|
25
|
+
gemspec.add_development_dependency('kagemusha')
|
26
|
+
gemspec.post_install_message = <<-EOD
|
27
|
+
Thank you for installing gemi!
|
28
|
+
The format of ~/.gemirc is changed in gemi 0.1.0.
|
29
|
+
If you have been using gemi 0.0.x,
|
30
|
+
please modify it (see gemirc.yml)
|
31
|
+
EOD
|
16
32
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bin/gemi
CHANGED
@@ -1,91 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require '
|
4
|
-
require 'yaml'
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__))
|
3
|
+
require 'gemi'
|
5
4
|
|
6
|
-
|
7
|
-
GEMIRC = File.expand_path("~/.gemirc")
|
8
|
-
|
9
|
-
def initialize(arg)
|
10
|
-
@arg = arg
|
11
|
-
@rubys = []
|
12
|
-
end
|
13
|
-
|
14
|
-
def run
|
15
|
-
if gemirc_exists?
|
16
|
-
Gemi.usage! if @arg.empty?
|
17
|
-
|
18
|
-
@rubys = load_gemirc
|
19
|
-
install_gems
|
20
|
-
else
|
21
|
-
setup
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def gemirc_exists?
|
28
|
-
File.exist?(GEMIRC)
|
29
|
-
end
|
30
|
-
|
31
|
-
def load_gemirc
|
32
|
-
YAML.load_file(GEMIRC)
|
33
|
-
end
|
34
|
-
|
35
|
-
def install_gems
|
36
|
-
@rubys.each do |ruby|
|
37
|
-
puts "------- installing for #{ruby[:name]} ..."
|
38
|
-
cmd = "#{gem_home(ruby)} #{ruby[:command]} install #{@arg} #{ruby[:options]}"
|
39
|
-
puts cmd
|
40
|
-
system cmd
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def gem_home(ruby)
|
45
|
-
if ruby[:gem_home]
|
46
|
-
# Note: single quote(') is needed to run the command in shell
|
47
|
-
# see the reference of Kernel#system
|
48
|
-
"GEM_HOME='#{File.expand_path ruby[:gem_home]}'"
|
49
|
-
else
|
50
|
-
""
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def setup
|
55
|
-
create_gemirc
|
56
|
-
puts "Created #{GEMIRC}"
|
57
|
-
puts "please edit it before using gemi."
|
58
|
-
end
|
59
|
-
|
60
|
-
def create_gemirc
|
61
|
-
template_path = File.expand_path("../gemirc.yml", File.dirname(__FILE__))
|
62
|
-
FileUtils.cp(template_path, GEMIRC)
|
63
|
-
end
|
64
|
-
|
65
|
-
# command line options
|
66
|
-
|
67
|
-
@opt = OptionParser.new{|o|
|
68
|
-
o.banner = "Usage: #$0 [gemi-options] foo bar [gem-options]\n" +
|
69
|
-
"Gemi Options:"
|
70
|
-
o.on("-h", "--help", "show this message"){
|
71
|
-
Gemi.usage!
|
72
|
-
}
|
73
|
-
}
|
74
|
-
|
75
|
-
def self.parse_argv
|
76
|
-
gemi_opts = []
|
77
|
-
while ARGV[0] =~ /\A-/
|
78
|
-
gemi_opts.push ARGV.shift
|
79
|
-
end
|
80
|
-
@opt.parse!(gemi_opts)
|
81
|
-
|
82
|
-
return ARGV.join(" ")
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.usage!
|
86
|
-
puts @opt.to_s
|
87
|
-
exit
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
Gemi.new(Gemi.parse_argv).run
|
5
|
+
Gemi::Runner.new(ARGV).run
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: Basic commands
|
2
|
+
Background:
|
3
|
+
Given I have the config file with:
|
4
|
+
"""
|
5
|
+
rubys:
|
6
|
+
- name: MRI 1.8
|
7
|
+
command: 'gem'
|
8
|
+
"""
|
9
|
+
|
10
|
+
Scenario Outline: Simple cases
|
11
|
+
When I run gemi with '<args>'
|
12
|
+
Then it should execute '<gem_command>'
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
| args | gem_command |
|
16
|
+
| foo bar | gem install foo bar |
|
17
|
+
| -u foo bar | gem uninstall foo bar |
|
18
|
+
| --uninstall foo bar | gem uninstall foo bar |
|
19
|
+
| -n foo bar | gem update foo bar |
|
20
|
+
| --update foo bar | gem update foo bar |
|
21
|
+
| -c foo bar | gem clean foo bar |
|
22
|
+
| --clean foo bar | gem clean foo bar |
|
23
|
+
|
24
|
+
Scenario Outline: With options for gem command
|
25
|
+
When I run gemi with '<args>'
|
26
|
+
Then it should execute '<gem_command>'
|
27
|
+
|
28
|
+
Examples:
|
29
|
+
| args | gem_command |
|
30
|
+
| foo bar -n ~/bin | gem install foo bar -n ~/bin |
|
31
|
+
| -u foo --user-install | gem uninstall foo --user-install |
|
32
|
+
|
33
|
+
Scenario Outline: With verbatim args
|
34
|
+
When I run gemi with '<args>'
|
35
|
+
Then it should execute '<gem_command>'
|
36
|
+
|
37
|
+
Examples:
|
38
|
+
| args | gem_command |
|
39
|
+
| -- stale | gem stale |
|
40
|
+
| -- list -l | gem list -l |
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Command specific options
|
2
|
+
Background:
|
3
|
+
Given I have the config file with:
|
4
|
+
"""
|
5
|
+
rubys:
|
6
|
+
- name: MRI 1.8
|
7
|
+
command: 'gem'
|
8
|
+
install_options: --foo
|
9
|
+
uninstall_options: --bar
|
10
|
+
update_options: --baz
|
11
|
+
clean_options: --quux
|
12
|
+
"""
|
13
|
+
# Note: these options are just example.
|
14
|
+
# The real gem command does not have such options!
|
15
|
+
|
16
|
+
Scenario Outline:
|
17
|
+
When I run gemi with '<args>'
|
18
|
+
Then it should execute '<gem_command>'
|
19
|
+
|
20
|
+
Examples:
|
21
|
+
| args | gem_command |
|
22
|
+
| a b | gem install a b --foo |
|
23
|
+
| -u a b | gem uninstall a b --bar |
|
24
|
+
| -n a b | gem update a b --baz |
|
25
|
+
| -c a b | gem clean a b --quux |
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: Config file
|
2
|
+
|
3
|
+
Scenario: Load from default path
|
4
|
+
# Note: this is tested in basic_commands.feature
|
5
|
+
|
6
|
+
Scenario: Create config if none
|
7
|
+
|
8
|
+
Scenario Outline: Specifying alternative config file path
|
9
|
+
Given a yaml file named "myconf.yml" with:
|
10
|
+
"""
|
11
|
+
rubys:
|
12
|
+
- name: myruby
|
13
|
+
command: mygem
|
14
|
+
install_options: --myoption
|
15
|
+
"""
|
16
|
+
When I run gemi with '<args>'
|
17
|
+
Then it should execute '<gem_command>'
|
18
|
+
|
19
|
+
Examples:
|
20
|
+
| args | gem_command |
|
21
|
+
| -r myconf.yml foo bar | mygem install foo bar --myoption |
|
22
|
+
| --rc myconf.yml -u foo bar | mygem uninstall foo bar |
|
23
|
+
| --rc myconf.yml -- stale | mygem stale |
|
24
|
+
|
25
|
+
Scenario: Use default settings if yaml is given
|
26
|
+
# Note: this is tested in gems_yaml.feature
|
27
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
Feature: With gems.yaml
|
2
|
+
|
3
|
+
Scenario Outline: Yaml containing names only
|
4
|
+
Given a yaml file named "names.yml" with:
|
5
|
+
"""
|
6
|
+
gems:
|
7
|
+
- name: foo
|
8
|
+
- name: bar
|
9
|
+
"""
|
10
|
+
When I run gemi with '<args>'
|
11
|
+
Then it should execute '<gem_command>'
|
12
|
+
|
13
|
+
Examples:
|
14
|
+
| args | gem_command |
|
15
|
+
| names.yml | gem install foo bar |
|
16
|
+
| -u names.yml | gem uninstall foo bar |
|
17
|
+
| -n names.yml | *ERROR* |
|
18
|
+
| -c names.yml | *ERROR* |
|
19
|
+
|
20
|
+
Scenario Outline: Yaml containing versions
|
21
|
+
Given a yaml file named "names_and_versions.yml" with:
|
22
|
+
"""
|
23
|
+
gems:
|
24
|
+
- name: foo
|
25
|
+
version: 0.1
|
26
|
+
- name: bar
|
27
|
+
version: 0.2
|
28
|
+
"""
|
29
|
+
When I run gemi with '<args>'
|
30
|
+
Then it should execute '<gem_command>'
|
31
|
+
|
32
|
+
Examples:
|
33
|
+
| args | gem_command |
|
34
|
+
| names_and_versions.yml | gem install foo -v 0.1 ; gem install bar -v 0.2 |
|
35
|
+
| -u names_and_versions.yml | gem uninstall foo -v 0.1 ; gem uninstall bar -v 0.2 |
|
36
|
+
|
37
|
+
Scenario Outline: Yaml containing options
|
38
|
+
Given a yaml file named "names_and_options.yml" with:
|
39
|
+
"""
|
40
|
+
gems:
|
41
|
+
- name: foo
|
42
|
+
install_options: --with-foo
|
43
|
+
- name: bar
|
44
|
+
version: 0.2
|
45
|
+
"""
|
46
|
+
When I run gemi with '<args>'
|
47
|
+
Then it should execute '<gem_command>'
|
48
|
+
|
49
|
+
Examples:
|
50
|
+
| args | gem_command |
|
51
|
+
| names_and_options.yml | gem install foo --with-foo ; gem install bar -v 0.2 |
|
52
|
+
| -u names_and_options.yml | gem uninstall foo ; gem uninstall bar -v 0.2 |
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Multiple Rubys
|
2
|
+
Background:
|
3
|
+
Given I have the config file with:
|
4
|
+
"""
|
5
|
+
rubys:
|
6
|
+
- name: MRI 1.8
|
7
|
+
command: 'gem'
|
8
|
+
- name: MRI 1.9
|
9
|
+
command: 'gem-1.9'
|
10
|
+
"""
|
11
|
+
|
12
|
+
Scenario Outline:
|
13
|
+
When I run gemi with '<args>'
|
14
|
+
Then it should execute the commands '<gem_commands>'
|
15
|
+
|
16
|
+
Examples:
|
17
|
+
| args | gem_commands |
|
18
|
+
| a b | gem install a b , gem-1.9 install a b |
|
19
|
+
| -u a b | gem uninstall a b , gem-1.9 uninstall a b |
|
20
|
+
| -n a b | gem update a b , gem-1.9 update a b |
|
21
|
+
| -c a b | gem clean a b , gem-1.9 clean a b |
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'kagemusha'
|
2
|
+
|
3
|
+
Given /^I have the config file with:$/ do |string|
|
4
|
+
File.open(GemiWorld::GEMIRC_TMP, "wb"){|f|
|
5
|
+
f.write string
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^a yaml file named "([^\"]*)" with:$/ do |filename, content|
|
10
|
+
File.open(File.join(GemiWorld::TMP_DIR, filename), "wb"){|f|
|
11
|
+
f.write content
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
When /^I run gemi with '(.*)'$/ do |args_str|
|
16
|
+
argv = args_str.split.map{|arg|
|
17
|
+
if arg =~ Gemi::REXP_YAML
|
18
|
+
File.join(GemiWorld::TMP_DIR, arg)
|
19
|
+
else
|
20
|
+
arg
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
cmds = []
|
25
|
+
Kagemusha.new(Gemi::Runner).def(:execute){|cmd|
|
26
|
+
cmds << cmd
|
27
|
+
}.swap {
|
28
|
+
begin
|
29
|
+
Gemi::Runner.new(argv).main
|
30
|
+
rescue Gemi::Error
|
31
|
+
cmds << "*ERROR*"
|
32
|
+
end
|
33
|
+
}
|
34
|
+
@cmds = cmds
|
35
|
+
end
|
36
|
+
|
37
|
+
Then /^it should execute the commands '(.*)'$/ do |cmds|
|
38
|
+
@cmds.should == cmds.split(/\s*,\s*/)
|
39
|
+
end
|
40
|
+
|
41
|
+
Then /^it should execute '(.*)'$/ do |cmd|
|
42
|
+
@cmds.first.rstrip.should == cmd
|
43
|
+
end
|
44
|
+
|
45
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", File.dirname(__FILE__))
|
2
|
+
require 'gemi'
|
3
|
+
|
4
|
+
class GemiWorld
|
5
|
+
# Path to make Temporary files
|
6
|
+
TMP_DIR = File.expand_path("../tmp/", File.dirname(__FILE__))
|
7
|
+
|
8
|
+
# Path of config file to use temporarily
|
9
|
+
GEMIRC_TMP = File.join(TMP_DIR, "gemirc")
|
10
|
+
|
11
|
+
# Replace the content of the constant (hack!)
|
12
|
+
Gemi::GEMIRC.replace GEMIRC_TMP
|
13
|
+
end
|
14
|
+
|
15
|
+
Before do
|
16
|
+
File.unlink GemiWorld::GEMIRC_TMP if File.exist? GemiWorld::GEMIRC_TMP
|
17
|
+
end
|
18
|
+
|
19
|
+
World do
|
20
|
+
GemiWorld.new
|
21
|
+
end
|
22
|
+
|
23
|
+
After do
|
24
|
+
end
|
data/gemi.gemspec
CHANGED
@@ -5,40 +5,74 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{gemi}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Yutaka HARA"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-01-13}
|
13
13
|
s.default_executable = %q{gemi}
|
14
|
-
s.description = %q{
|
14
|
+
s.description = %q{ gemi runs 'gem install' for each your rubys.
|
15
|
+
Example:
|
16
|
+
without gemi:
|
17
|
+
$ gem install foo bar
|
18
|
+
$ gem-1.9 install foo bar
|
19
|
+
with gemi:
|
20
|
+
$ gemi foo bar
|
21
|
+
}
|
15
22
|
s.email = %q{yutaka.hara/at/gmail.com}
|
16
23
|
s.executables = ["gemi"]
|
17
24
|
s.extra_rdoc_files = [
|
18
|
-
"README"
|
25
|
+
"README.mkd"
|
19
26
|
]
|
20
27
|
s.files = [
|
21
|
-
"
|
22
|
-
"
|
28
|
+
".gitignore",
|
29
|
+
"History.txt",
|
30
|
+
"README.mkd",
|
23
31
|
"Rakefile",
|
24
32
|
"VERSION",
|
25
33
|
"bin/gemi",
|
34
|
+
"features/basic_commands.feature",
|
35
|
+
"features/command_specific_options.feature",
|
36
|
+
"features/config_file.feature",
|
37
|
+
"features/gems_yaml.feature",
|
38
|
+
"features/multiple_rubys.feature",
|
39
|
+
"features/step_definitions/gemi_steps.rb",
|
40
|
+
"features/support/env.rb",
|
41
|
+
"features/tmp/.gitignore",
|
26
42
|
"gemi.gemspec",
|
27
|
-
"gemirc.yml"
|
43
|
+
"gemirc.yml",
|
44
|
+
"lib/gemi.rb",
|
45
|
+
"lib/gemi/commands.rb",
|
46
|
+
"lib/gemi/conf.rb",
|
47
|
+
"lib/gemi/gem.rb",
|
48
|
+
"lib/gemi/options.rb",
|
49
|
+
"lib/gemi/ruby.rb",
|
50
|
+
"lib/gemi/runner.rb"
|
28
51
|
]
|
29
52
|
s.homepage = %q{http://github.com/yhara/gemi}
|
53
|
+
s.post_install_message = %q{ Thank you for installing gemi!
|
54
|
+
The format of ~/.gemirc is changed in gemi 0.1.0.
|
55
|
+
If you have been using gemi 0.0.x,
|
56
|
+
please modify it (see gemirc.yml)
|
57
|
+
}
|
30
58
|
s.rdoc_options = ["--charset=UTF-8"]
|
31
59
|
s.require_paths = ["lib"]
|
32
60
|
s.rubygems_version = %q{1.3.5}
|
33
|
-
s.summary = %q{
|
61
|
+
s.summary = %q{gem command for multiple rubys}
|
34
62
|
|
35
63
|
if s.respond_to? :specification_version then
|
36
64
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
37
65
|
s.specification_version = 3
|
38
66
|
|
39
67
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
68
|
+
s.add_development_dependency(%q<cucumber>, [">= 0.4.2"])
|
69
|
+
s.add_development_dependency(%q<kagemusha>, [">= 0"])
|
40
70
|
else
|
71
|
+
s.add_dependency(%q<cucumber>, [">= 0.4.2"])
|
72
|
+
s.add_dependency(%q<kagemusha>, [">= 0"])
|
41
73
|
end
|
42
74
|
else
|
75
|
+
s.add_dependency(%q<cucumber>, [">= 0.4.2"])
|
76
|
+
s.add_dependency(%q<kagemusha>, [">= 0"])
|
43
77
|
end
|
44
78
|
end
|
data/gemirc.yml
CHANGED
@@ -1,14 +1,7 @@
|
|
1
|
-
|
2
|
-
:
|
3
|
-
|
4
|
-
# :gem_home: ~/.gem1.8
|
5
|
-
|
6
|
-
- :name: 'MRI 1.9'
|
7
|
-
:command: 'gem-1.9'
|
8
|
-
:options: '--format-executable' # install bin/foobar as foobar-1.9
|
9
|
-
# :gem_home: ~/.gem1.9
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
rubys:
|
2
|
+
- name: 'MRI 1.8' # used just for showing messages
|
3
|
+
command: 'sudo gem' # gem command to install
|
14
4
|
|
5
|
+
- name: 'MRI 1.9'
|
6
|
+
command: 'gem-1.9'
|
7
|
+
install_options: '--format-executable' # install bin/foo as foo-1.9
|
data/lib/gemi.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Gemi
|
2
|
+
GEMIRC = File.expand_path("~/.gemirc")
|
3
|
+
REXP_YAML = /.ya?ml\z/i
|
4
|
+
|
5
|
+
class Error < StandardError; end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'gemi/commands.rb'
|
9
|
+
require 'gemi/conf.rb'
|
10
|
+
require 'gemi/gem.rb'
|
11
|
+
require 'gemi/options.rb'
|
12
|
+
require 'gemi/ruby.rb'
|
13
|
+
require 'gemi/runner.rb'
|
14
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gemi
|
2
|
+
class Command
|
3
|
+
|
4
|
+
def initialize(type, gem_names, yamls)
|
5
|
+
@type = type
|
6
|
+
|
7
|
+
@gems = [
|
8
|
+
gem_names.map{|s| Gem.new(s)},
|
9
|
+
yamls.map{|path| Gem.from_yaml(YAML.load_file(path))}
|
10
|
+
].flatten
|
11
|
+
end
|
12
|
+
|
13
|
+
def build(ruby)
|
14
|
+
if @gems.any?{|gem| gem.version or gem.options[@type]}
|
15
|
+
@gems.map{|gem|
|
16
|
+
build_command(gem.to_command(@type), ruby)
|
17
|
+
}.join(" ; ")
|
18
|
+
else
|
19
|
+
gem_names = @gems.map(&:name).join(" ")
|
20
|
+
build_command(gem_names, ruby)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_command(gem_opts, ruby)
|
27
|
+
return [
|
28
|
+
# gem, gem-1.8, gem-1.9, etc.
|
29
|
+
ruby.gem_command,
|
30
|
+
# install, update, etc.
|
31
|
+
@type.to_s,
|
32
|
+
# gem names and a version, if any
|
33
|
+
gem_opts,
|
34
|
+
# user options specific to installing, uninstalling, etc.
|
35
|
+
(ruby.options[@type] || ""),
|
36
|
+
].reject(&:empty?).join(" ")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/lib/gemi/conf.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Gemi
|
4
|
+
class Conf
|
5
|
+
|
6
|
+
class GemircError < StandardError
|
7
|
+
def initialize(attr)
|
8
|
+
super("you must give '#{attr}' in your gemirc")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create
|
13
|
+
unless File.exist?(GEMIRC)
|
14
|
+
here = File.dirname(__FILE__)
|
15
|
+
template_path = File.expand_path("../../gemirc.yml", here)
|
16
|
+
FileUtils.cp(template_path, GEMIRC)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(yaml_path)
|
21
|
+
if yaml_path
|
22
|
+
yaml = YAML.load_file(yaml_path)
|
23
|
+
@rubys = parse_rubys(yaml["rubys"])
|
24
|
+
else
|
25
|
+
@rubys = [Ruby::Default]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
attr_reader :rubys
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def parse_rubys(rubys)
|
33
|
+
rubys.map{|ruby|
|
34
|
+
name = ruby["name"]
|
35
|
+
raise GemircError.new("name") unless name
|
36
|
+
|
37
|
+
command = ruby["command"]
|
38
|
+
raise GemircError.new("command") unless command
|
39
|
+
|
40
|
+
gem_home = ruby["gem_home"]
|
41
|
+
|
42
|
+
options = {
|
43
|
+
:install => ruby["install_options"],
|
44
|
+
:uninstall => ruby["uninstall_options"],
|
45
|
+
:update => ruby["update_options"],
|
46
|
+
:clean => ruby["clean_options"],
|
47
|
+
}
|
48
|
+
|
49
|
+
Ruby.new(name, command, gem_home, options)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/gemi/gem.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gemi
|
2
|
+
class Gem
|
3
|
+
|
4
|
+
class OptionNotSupported < Gemi::Error; end
|
5
|
+
|
6
|
+
# Returns an array of Gem
|
7
|
+
def self.from_yaml(yaml)
|
8
|
+
return [] unless yaml["gems"]
|
9
|
+
|
10
|
+
yaml["gems"].map{|spec|
|
11
|
+
options = {
|
12
|
+
:install => spec["install_options"],
|
13
|
+
:uninstall => spec["uninstall_options"],
|
14
|
+
}
|
15
|
+
%w(update_options clean_options).each do |key|
|
16
|
+
if spec[key]
|
17
|
+
raise OptionNotSupported, "you cannot specify #{key} in YAML file"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
new(spec["name"], spec["version"], options)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(name, version=nil, options={})
|
25
|
+
@name, @version, @options = name, version, options
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :name, :version, :options
|
29
|
+
|
30
|
+
def to_command(type)
|
31
|
+
s = @name
|
32
|
+
s << " -v #{@version}" if @version
|
33
|
+
s << " #{@options[type]}" if @options[type]
|
34
|
+
s
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/gemi/options.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Gemi
|
2
|
+
class Options
|
3
|
+
|
4
|
+
class YamlGivenError < Gemi::Error; end
|
5
|
+
|
6
|
+
def self.parse(argv)
|
7
|
+
new(argv)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(argv)
|
11
|
+
@confpath, @type, @gem_names, @yamls = parse(argv)
|
12
|
+
end
|
13
|
+
attr_reader :confpath, :type, :gem_names, :yamls
|
14
|
+
|
15
|
+
def empty?
|
16
|
+
@yamls.empty? and @gem_names.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
TYPES = {
|
20
|
+
"-u" => :uninstall,
|
21
|
+
"--uninstall" => :uninstall,
|
22
|
+
"-n" => :update,
|
23
|
+
"--update" => :update,
|
24
|
+
"-c" => :clean,
|
25
|
+
"--clean" => :clean,
|
26
|
+
}
|
27
|
+
|
28
|
+
def parse(argv)
|
29
|
+
confpath = GEMIRC
|
30
|
+
|
31
|
+
if %w(-r --rc).include?(argv.first)
|
32
|
+
confpath = argv[1]
|
33
|
+
if not File.exist?(confpath)
|
34
|
+
raise ConfNotFound, "config file not found in #{confpath}"
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
argv.shift
|
38
|
+
argv.shift
|
39
|
+
end
|
40
|
+
|
41
|
+
case
|
42
|
+
when TYPES.key?(argv.first)
|
43
|
+
type = TYPES[argv.first]
|
44
|
+
args = argv[1..-1]
|
45
|
+
|
46
|
+
when argv.first == "--"
|
47
|
+
type = nil
|
48
|
+
args = argv[1..-1]
|
49
|
+
|
50
|
+
else # gem names only
|
51
|
+
type = :install
|
52
|
+
args = argv
|
53
|
+
end
|
54
|
+
|
55
|
+
case type
|
56
|
+
when nil # verbatim(--)
|
57
|
+
yamls = []
|
58
|
+
gem_names = args
|
59
|
+
else
|
60
|
+
yamls, gem_names = args.partition{|s| s =~ REXP_YAML}
|
61
|
+
if [:update, :clean].include?(type) and not yamls.empty?
|
62
|
+
raise YamlGivenError, "You cannot give yaml files with #{argv.first}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
return confpath, type, gem_names, yamls
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/gemi/ruby.rb
ADDED
data/lib/gemi/runner.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Gemi
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
class ConfNotFound < Gemi::Error; end
|
5
|
+
|
6
|
+
def initialize(argv)
|
7
|
+
@argv = argv.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
begin
|
12
|
+
main
|
13
|
+
rescue => e
|
14
|
+
$stderr.puts "Error: #{e.message}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def main
|
19
|
+
@opt = Options.parse(@argv)
|
20
|
+
|
21
|
+
if @opt.empty?
|
22
|
+
usage
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
conf = load_conf
|
27
|
+
execute_commands(conf)
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_conf
|
31
|
+
conf_exist = File.exist?(@opt.confpath)
|
32
|
+
yaml_given = !@opt.yamls.empty?
|
33
|
+
|
34
|
+
if conf_exist
|
35
|
+
Conf.new(@opt.confpath)
|
36
|
+
else
|
37
|
+
if yaml_given
|
38
|
+
Conf.new(nil)
|
39
|
+
elsif @opt.confpath == GEMIRC
|
40
|
+
create_conf
|
41
|
+
return
|
42
|
+
else
|
43
|
+
raise ConfNotFound, "config file not found in #{@opt.confpath}"
|
44
|
+
return
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute_commands(conf)
|
50
|
+
conf.rubys.each do |ruby|
|
51
|
+
puts "------- installing for #{ruby[:name]} ..."
|
52
|
+
cmd = Command.new(@opt.type, @opt.gem_names, @opt.yamls).build(ruby)
|
53
|
+
execute(cmd)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def execute(cmd)
|
58
|
+
puts cmd
|
59
|
+
system cmd
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def usage
|
65
|
+
$stderr.puts [
|
66
|
+
"Usage: gemi -unc GEM1 GEM2 YAML1.yml",
|
67
|
+
"Options:",
|
68
|
+
" -u, --uninstall : gem uninstall",
|
69
|
+
" -n, --update : gem update",
|
70
|
+
" -c, --clean : gem clean",
|
71
|
+
" -- : pass the arguments to gem commands",
|
72
|
+
" -r PATH : specify the path of gemirc",
|
73
|
+
].join("\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_conf
|
77
|
+
$stderr.puts "Error: config file not found in #{GEMIRC}"
|
78
|
+
$stderr.print "May I create a new one? [Y/n]"
|
79
|
+
ans = gets.chomp
|
80
|
+
$stderr.puts
|
81
|
+
|
82
|
+
if ["Y", "YES", ""].include?(ans.upcase)
|
83
|
+
Conf.create
|
84
|
+
$stderr.puts "Done. Please edit #{GEMIRC} for your environment."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yutaka HARA
|
@@ -9,31 +9,66 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-13 00:00:00 +09:00
|
13
13
|
default_executable: gemi
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: cucumber
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.4.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: kagemusha
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: " gemi runs 'gem install' for each your rubys.\n Example:\n without gemi:\n $ gem install foo bar\n $ gem-1.9 install foo bar\n with gemi:\n $ gemi foo bar\n"
|
17
36
|
email: yutaka.hara/at/gmail.com
|
18
37
|
executables:
|
19
38
|
- gemi
|
20
39
|
extensions: []
|
21
40
|
|
22
41
|
extra_rdoc_files:
|
23
|
-
- README
|
42
|
+
- README.mkd
|
24
43
|
files:
|
44
|
+
- .gitignore
|
25
45
|
- History.txt
|
26
|
-
- README
|
46
|
+
- README.mkd
|
27
47
|
- Rakefile
|
28
48
|
- VERSION
|
29
49
|
- bin/gemi
|
50
|
+
- features/basic_commands.feature
|
51
|
+
- features/command_specific_options.feature
|
52
|
+
- features/config_file.feature
|
53
|
+
- features/gems_yaml.feature
|
54
|
+
- features/multiple_rubys.feature
|
55
|
+
- features/step_definitions/gemi_steps.rb
|
56
|
+
- features/support/env.rb
|
57
|
+
- features/tmp/.gitignore
|
30
58
|
- gemi.gemspec
|
31
59
|
- gemirc.yml
|
60
|
+
- lib/gemi.rb
|
61
|
+
- lib/gemi/commands.rb
|
62
|
+
- lib/gemi/conf.rb
|
63
|
+
- lib/gemi/gem.rb
|
64
|
+
- lib/gemi/options.rb
|
65
|
+
- lib/gemi/ruby.rb
|
66
|
+
- lib/gemi/runner.rb
|
32
67
|
has_rdoc: true
|
33
68
|
homepage: http://github.com/yhara/gemi
|
34
69
|
licenses: []
|
35
70
|
|
36
|
-
post_install_message:
|
71
|
+
post_install_message: " Thank you for installing gemi!\n The format of ~/.gemirc is changed in gemi 0.1.0.\n If you have been using gemi 0.0.x,\n please modify it (see gemirc.yml)\n"
|
37
72
|
rdoc_options:
|
38
73
|
- --charset=UTF-8
|
39
74
|
require_paths:
|
@@ -56,6 +91,6 @@ rubyforge_project:
|
|
56
91
|
rubygems_version: 1.3.5
|
57
92
|
signing_key:
|
58
93
|
specification_version: 3
|
59
|
-
summary:
|
94
|
+
summary: gem command for multiple rubys
|
60
95
|
test_files: []
|
61
96
|
|
data/README
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
= gemi
|
2
|
-
|
3
|
-
gemi is a simple tool for installing gems for multiple rubys.
|
4
|
-
|
5
|
-
== Install
|
6
|
-
|
7
|
-
1. gem install gemcutter
|
8
|
-
|
9
|
-
2. gem tumble
|
10
|
-
|
11
|
-
3. gem install gemi
|
12
|
-
|
13
|
-
or:
|
14
|
-
|
15
|
-
gem install gemi --source=http://gemcutter.org
|
16
|
-
|
17
|
-
== Setup
|
18
|
-
|
19
|
-
$ gemi
|
20
|
-
|
21
|
-
then edit ~/.gemirc
|
22
|
-
|
23
|
-
== Usage
|
24
|
-
|
25
|
-
$ gemi foobar
|
26
|
-
|
27
|
-
installs the gem 'foobar' for your rubys.
|
28
|
-
|
29
|
-
== Contact
|
30
|
-
|
31
|
-
http://github.com/yhara/gemi
|
32
|
-
|
33
|
-
yhara (Yutaka HARA)
|
34
|
-
yutaka.hara.gmail.com
|
35
|
-
http://route477.net/
|