pik 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +36 -0
- data/Manifest.txt +42 -0
- data/README.rdoc +174 -0
- data/Rakefile +37 -0
- data/bin/pik +33 -0
- data/lib/pik.rb +30 -0
- data/lib/pik/batch_file.rb +70 -0
- data/lib/pik/checkup.rb +11 -0
- data/lib/pik/commands.rb +35 -0
- data/lib/pik/commands/add_command.rb +65 -0
- data/lib/pik/commands/batch_file_editor.rb +62 -0
- data/lib/pik/commands/checkup_command.rb +67 -0
- data/lib/pik/commands/command.rb +166 -0
- data/lib/pik/commands/config_command.rb +28 -0
- data/lib/pik/commands/config_file_editor.rb +12 -0
- data/lib/pik/commands/default_command.rb +22 -0
- data/lib/pik/commands/gemsync_command.rb +69 -0
- data/lib/pik/commands/help_command.rb +44 -0
- data/lib/pik/commands/implode_command.rb +16 -0
- data/lib/pik/commands/list_command.rb +34 -0
- data/lib/pik/commands/remove_command.rb +29 -0
- data/lib/pik/commands/run_command.rb +37 -0
- data/lib/pik/commands/switch_command.rb +49 -0
- data/lib/pik/config_file.rb +21 -0
- data/lib/pik/core_ext/pathname.rb +15 -0
- data/lib/pik/options.rb +56 -0
- data/lib/pik/runner.rb +16 -0
- data/lib/pik/search_path.rb +51 -0
- data/lib/pik/windows_env.rb +64 -0
- data/spec/add_command_spec.rb +15 -0
- data/spec/batch_file_spec.rb +31 -0
- data/spec/command_spec.rb +34 -0
- data/spec/commands_spec.rb +44 -0
- data/spec/default_command_spec.rb +6 -0
- data/spec/gemsync_command_spec.rb +15 -0
- data/spec/help_command_spec.rb +30 -0
- data/spec/list_command_spec.rb +33 -0
- data/spec/remove_command_spec.rb +25 -0
- data/spec/run_command_spec.rb +36 -0
- data/spec/search_path_spec.rb +121 -0
- data/spec/spec.opts +3 -0
- data/spec/switch_command_spec.rb +44 -0
- metadata +143 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
module Pik
|
2
|
+
|
3
|
+
class Add < Command
|
4
|
+
|
5
|
+
it 'Adds another ruby location to pik.'
|
6
|
+
include ConfigFileEditor
|
7
|
+
|
8
|
+
attr_reader :interactive
|
9
|
+
|
10
|
+
def execute(path=nil)
|
11
|
+
return add_interactive if interactive
|
12
|
+
path = @args.first || ::Config::CONFIG['bindir']
|
13
|
+
add(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(path)
|
17
|
+
path = Pathname.new(path)
|
18
|
+
path = path.dirname if path.file?
|
19
|
+
if ruby_exists_at?(path)
|
20
|
+
if config[get_version(path)]
|
21
|
+
puts "This version has already been added."
|
22
|
+
else
|
23
|
+
version = get_version(path)
|
24
|
+
path = path.expand_path.to_ruby
|
25
|
+
puts "Adding: #{version}'\n Located at: #{path}\n"
|
26
|
+
@config[version][:path] = path
|
27
|
+
end
|
28
|
+
else
|
29
|
+
puts "Couldn't find a Ruby version at #{path}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def command_options
|
34
|
+
super
|
35
|
+
options.banner += "[path_to_ruby]"
|
36
|
+
options.separator ""
|
37
|
+
options.on("--interactive", "-i", "Add interactively") do |value|
|
38
|
+
@interactive = value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_interactive
|
43
|
+
@hl.choose do |menu|
|
44
|
+
menu.prompt = ""
|
45
|
+
menu.choice('e]nter a path'){
|
46
|
+
dir = @hl.ask("Enter a path to a ruby/bin dir (enter to quit)")
|
47
|
+
execute(dir) unless dir.empty? || !@hl.agree("Add '#{dir}'? [Yn] ")
|
48
|
+
add_interactive
|
49
|
+
}
|
50
|
+
menu.choice('s]earch'){
|
51
|
+
search_dir = @hl.ask("Enter a search path")
|
52
|
+
files = ruby_glob(search_dir + '**')
|
53
|
+
files.each{|file|
|
54
|
+
dir = File.dirname(file)
|
55
|
+
add(dir) if @hl.agree("Add '#{dir}'? [Yn] ")
|
56
|
+
}
|
57
|
+
add_interactive
|
58
|
+
}
|
59
|
+
menu.choice('q]uit'){raise QuitError}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Pik
|
2
|
+
|
3
|
+
module BatchFileEditor
|
4
|
+
|
5
|
+
attr_reader :batch
|
6
|
+
|
7
|
+
def initialize(args=ARGV,config=nil)
|
8
|
+
super
|
9
|
+
batch_file = File.join(PIK_HOME, "#{File.basename($0)}_#{$$}.bat")
|
10
|
+
@batch = BatchFile.new( batch_file )
|
11
|
+
editors << @batch
|
12
|
+
end
|
13
|
+
|
14
|
+
def close
|
15
|
+
update_gem_batch
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def set(items)
|
20
|
+
items.each do |k, v|
|
21
|
+
@batch.set(k => v)
|
22
|
+
WindowsEnv.user.set(k => v) if global
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def switch_path_to(new_ver)
|
27
|
+
dir = current_ruby_bin_path
|
28
|
+
new_path = SearchPath.new(ENV['PATH']).replace_or_add(dir, new_ver[:path])
|
29
|
+
if new_ver[:gem_home]
|
30
|
+
new_path.replace_or_add(current_gem_bin_path, Pathname.new(new_ver[:gem_home]) + 'bin')
|
31
|
+
else
|
32
|
+
new_path.remove(current_gem_bin_path)
|
33
|
+
end
|
34
|
+
@batch.set('PATH' => new_path.join )
|
35
|
+
end
|
36
|
+
|
37
|
+
def switch_gem_home_to(gem_home_dir)
|
38
|
+
gem_home_dir ||= ''
|
39
|
+
gem_path = Pathname.new(gem_home_dir).to_windows
|
40
|
+
@batch.set('GEM_PATH' => gem_path )
|
41
|
+
@batch.set('GEM_HOME' => gem_path )
|
42
|
+
end
|
43
|
+
|
44
|
+
def echo_ruby_version(verb='Using')
|
45
|
+
@batch.file_data << "for /f \"delims=\" %%a in ('ruby -v') do @echo #{verb} %%a "
|
46
|
+
end
|
47
|
+
|
48
|
+
def echo_running_with_ruby_version
|
49
|
+
echo_ruby_version('Running with')
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_gem_batch
|
53
|
+
BatchFile.open("#{$0}.bat") do |gem_bat|
|
54
|
+
# call new .pik/pik batch
|
55
|
+
gem_bat.call(%Q("#{@batch.path.to_windows}")) if @batch
|
56
|
+
gem_bat.write
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Pik
|
2
|
+
|
3
|
+
class Checkup < Command
|
4
|
+
|
5
|
+
aka :cu
|
6
|
+
it "Checks your environment for current Ruby best practices."
|
7
|
+
|
8
|
+
def execute
|
9
|
+
home
|
10
|
+
rubyopt
|
11
|
+
path
|
12
|
+
pathext
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
ERB.new(@output.join("\n\n")).result
|
17
|
+
end
|
18
|
+
|
19
|
+
def rubyopt
|
20
|
+
unless WindowsEnv.user['rubyopt'].empty? && WindowsEnv.system['rubyopt'].empty?
|
21
|
+
fail('rubyopt')
|
22
|
+
else
|
23
|
+
pass('rubyopt')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def home
|
28
|
+
if WindowsEnv.user['home'].empty?
|
29
|
+
fail('home')
|
30
|
+
else
|
31
|
+
pass('home')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def path
|
36
|
+
dirs = (WindowsEnv.user['path'] + WindowsEnv.system['path']).split(';')
|
37
|
+
dirs = dirs.select{|dir| File.exist?( File.join(dir,'ruby.exe') ) }
|
38
|
+
unless dirs.size == 1
|
39
|
+
fail('path')
|
40
|
+
else
|
41
|
+
pass('path')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def pathext
|
46
|
+
p_ext = WindowsEnv.system['pathext'].downcase
|
47
|
+
unless p_ext.include?('.rb') && p_ext.include?('.rbw')
|
48
|
+
fail('pathext')
|
49
|
+
else
|
50
|
+
pass('pathext')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def pass(test)
|
55
|
+
print '.'
|
56
|
+
$stdout.flush
|
57
|
+
# @output << @text[test][:pass]
|
58
|
+
end
|
59
|
+
|
60
|
+
def fail(test)
|
61
|
+
print 'F'
|
62
|
+
# @output << @text[test][:fail]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Pik
|
4
|
+
|
5
|
+
class QuitError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class Command
|
9
|
+
|
10
|
+
attr_reader :config
|
11
|
+
|
12
|
+
attr_reader :options
|
13
|
+
|
14
|
+
attr_accessor :output
|
15
|
+
|
16
|
+
def self.cmd_name
|
17
|
+
name.split('::').last.downcase.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.description
|
21
|
+
new.options.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.inherited(subclass)
|
25
|
+
Commands.add(subclass)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.it(str)
|
29
|
+
@summary = str
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.summary
|
33
|
+
@summary
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.aka(*aliases)
|
37
|
+
@names = names + aliases
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.names
|
41
|
+
@names ||= [cmd_name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.clean_gem_batch
|
45
|
+
BatchFile.open("#{$0}.bat") do |gem_bat|
|
46
|
+
# remove old calls to .pik/pik batches
|
47
|
+
gem_bat.remove_line( /call.+pik.+bat/i )
|
48
|
+
gem_bat.write
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.choose_from(patterns, config)
|
53
|
+
if patterns.empty?
|
54
|
+
possibles = config.keys
|
55
|
+
else
|
56
|
+
possibles = patterns.map{|p| config.keys.grep(Regexp.new(Regexp.escape(p.to_s))) }
|
57
|
+
possibles = possibles.inject{|m,v| m & v }.flatten.uniq
|
58
|
+
end
|
59
|
+
case possibles.size
|
60
|
+
when 0
|
61
|
+
return nil
|
62
|
+
when 1
|
63
|
+
return possibles.first
|
64
|
+
else
|
65
|
+
hl.say('Select which Ruby you want:')
|
66
|
+
ver = hl.choose(*possibles)
|
67
|
+
return ver
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.hl
|
72
|
+
@hl ||= HighLine.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(args=ARGV, config_=nil)
|
76
|
+
@args = args
|
77
|
+
@options = OptionParser.new
|
78
|
+
@config = config_ || ConfigFile.new
|
79
|
+
@hl = HighLine.new
|
80
|
+
add_sigint_handler
|
81
|
+
options.program_name = "#{File.basename($0)} #{self.class.names.join('|')}"
|
82
|
+
command_options
|
83
|
+
parse_options
|
84
|
+
create(PIK_HOME) unless PIK_HOME.exist?
|
85
|
+
# Add.new(nil, config).execute if config.empty?
|
86
|
+
delete_old_pik_batches
|
87
|
+
end
|
88
|
+
|
89
|
+
def close
|
90
|
+
editors.each{|e| e.write }
|
91
|
+
end
|
92
|
+
|
93
|
+
def editors
|
94
|
+
@editors ||= []
|
95
|
+
end
|
96
|
+
|
97
|
+
def command_options
|
98
|
+
options.separator ""
|
99
|
+
options.separator self.class.summary
|
100
|
+
options.separator ""
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_options
|
104
|
+
options.parse! @args
|
105
|
+
end
|
106
|
+
|
107
|
+
def current_version?(string)
|
108
|
+
string == get_version
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_version(path=current_ruby_bin_path)
|
112
|
+
cmd = ruby_exe(path).basename
|
113
|
+
cmd = Pathname.new(path) + cmd
|
114
|
+
ruby_ver = `#{cmd} -v`
|
115
|
+
ruby_ver =~ /ruby (\d\.\d\.\d)/
|
116
|
+
major = $1.gsub('.','')
|
117
|
+
"#{major}: #{ruby_ver.strip}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def current_ruby_bin_path
|
121
|
+
Pathname.new(::RbConfig::CONFIG['bindir'] )
|
122
|
+
end
|
123
|
+
|
124
|
+
def ruby_exists_at?(path)
|
125
|
+
!!ruby_exe(path)
|
126
|
+
end
|
127
|
+
|
128
|
+
def ruby_exe(path)
|
129
|
+
ruby_glob(path).first
|
130
|
+
end
|
131
|
+
|
132
|
+
def ruby_glob(path)
|
133
|
+
glob = "#{Pathname.new(path).to_ruby}/{ruby.exe}"
|
134
|
+
Pathname.glob(glob)
|
135
|
+
end
|
136
|
+
|
137
|
+
def current_gem_bin_path
|
138
|
+
default_gem_home + 'bin'
|
139
|
+
end
|
140
|
+
|
141
|
+
def default_gem_home
|
142
|
+
Pathname.new(Gem.default_path.first).to_windows
|
143
|
+
end
|
144
|
+
|
145
|
+
def create(home)
|
146
|
+
puts "creating #{home}"
|
147
|
+
home.mkpath
|
148
|
+
end
|
149
|
+
|
150
|
+
def delete_old_pik_batches( cutoff=(Time.now - (2 * 60 * 60)) )
|
151
|
+
Dir[(PIK_HOME + "*.bat").to_windows.to_s].each do |f|
|
152
|
+
File.delete(f) if File.ctime(f) < cutoff
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Installs a sigint handler.
|
157
|
+
|
158
|
+
def add_sigint_handler
|
159
|
+
trap 'INT' do
|
160
|
+
raise QuitError
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Pik
|
2
|
+
|
3
|
+
class Config < Command
|
4
|
+
|
5
|
+
it "Adds/modifies configuration options."
|
6
|
+
include BatchFileEditor
|
7
|
+
include ConfigFileEditor
|
8
|
+
|
9
|
+
attr_accessor :global
|
10
|
+
|
11
|
+
def execute
|
12
|
+
item, value = @args.shift.downcase.split('=')
|
13
|
+
case item
|
14
|
+
when 'rubyopt'
|
15
|
+
case value
|
16
|
+
when 'on' then set('RUBYOPT' => '-rubygems')
|
17
|
+
when 'off' then set('RUBYOPT' => nil)
|
18
|
+
end
|
19
|
+
when 'gem_home'
|
20
|
+
config[get_version][:gem_home] = @args.include?('default') ? default_gem_home : value
|
21
|
+
else
|
22
|
+
puts "Unknown configuration option"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module Pik
|
3
|
+
|
4
|
+
class Default < Command
|
5
|
+
|
6
|
+
it "switches back to the default settings"
|
7
|
+
|
8
|
+
include BatchFileEditor
|
9
|
+
|
10
|
+
def execute
|
11
|
+
sys = WindowsEnv.system
|
12
|
+
usr = WindowsEnv.user
|
13
|
+
|
14
|
+
@batch.set('PATH' => sys['PATH'] + ';' + usr['PATH'] )
|
15
|
+
@batch.set('GEM_PATH' => usr['GEM_PATH'] || sys['GEM_PATH'] )
|
16
|
+
@batch.set('GEM_HOME' => usr['GEM_HOME'] || sys['GEM_HOME'] )
|
17
|
+
echo_ruby_version
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Pik
|
2
|
+
|
3
|
+
class GemSync < Command
|
4
|
+
|
5
|
+
it "Duplicates gems from the current version to the one specified."
|
6
|
+
include BatchFileEditor
|
7
|
+
|
8
|
+
def execute
|
9
|
+
target = self.class.choose_from(@args, config)
|
10
|
+
current = get_version
|
11
|
+
install_gems(current, target) if target
|
12
|
+
end
|
13
|
+
|
14
|
+
def install_gems(current, target)
|
15
|
+
switch_path_to(config[target])
|
16
|
+
switch_gem_home_to(config[target][:gem_home])
|
17
|
+
target_cache = gem_cache(target)
|
18
|
+
|
19
|
+
gem_cache(current).find do |file|
|
20
|
+
if file.file?
|
21
|
+
if (target_cache + file.basename).exist?
|
22
|
+
@batch.echo "Gem #{file.basename} already installed"
|
23
|
+
else
|
24
|
+
gem_install(file)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
switch_path_to(config[current])
|
29
|
+
switch_gem_home_to(config[target][:gem_home])
|
30
|
+
end
|
31
|
+
|
32
|
+
def gem_cache(version)
|
33
|
+
conf = config[version]
|
34
|
+
path = if conf[:gem_home]
|
35
|
+
Pathname.new( conf[:gem_home] )
|
36
|
+
else
|
37
|
+
cmd = ruby_exe(conf[:path]).to_s + " -rubygems -e \"puts Gem.default_path.last\""
|
38
|
+
Pathname.new( `#{cmd}`.chomp )
|
39
|
+
end
|
40
|
+
puts path + "cache"
|
41
|
+
path + "cache"
|
42
|
+
end
|
43
|
+
|
44
|
+
def gem_install(file)
|
45
|
+
@batch.echo "Installing #{file.basename}"
|
46
|
+
@batch.call "gem install -q --no-rdoc --no-ri #{file}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def command_options
|
50
|
+
super
|
51
|
+
sep =<<SEP
|
52
|
+
Examples:
|
53
|
+
|
54
|
+
C:\\>ruby -v
|
55
|
+
ruby 1.8.6 (2009-03-31 patchlevel 368) [i386-mingw32]
|
56
|
+
|
57
|
+
C:\\>pik gemsync 191 p2
|
58
|
+
Gem ZenTest-4.1.4.gem already installed
|
59
|
+
Installing xml-simple-1.0.12.gem
|
60
|
+
Successfully installed xml-simple-1.0.12
|
61
|
+
1 gem installed
|
62
|
+
...
|
63
|
+
SEP
|
64
|
+
options.separator sep
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|