pik 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.txt +36 -0
  2. data/Manifest.txt +42 -0
  3. data/README.rdoc +174 -0
  4. data/Rakefile +37 -0
  5. data/bin/pik +33 -0
  6. data/lib/pik.rb +30 -0
  7. data/lib/pik/batch_file.rb +70 -0
  8. data/lib/pik/checkup.rb +11 -0
  9. data/lib/pik/commands.rb +35 -0
  10. data/lib/pik/commands/add_command.rb +65 -0
  11. data/lib/pik/commands/batch_file_editor.rb +62 -0
  12. data/lib/pik/commands/checkup_command.rb +67 -0
  13. data/lib/pik/commands/command.rb +166 -0
  14. data/lib/pik/commands/config_command.rb +28 -0
  15. data/lib/pik/commands/config_file_editor.rb +12 -0
  16. data/lib/pik/commands/default_command.rb +22 -0
  17. data/lib/pik/commands/gemsync_command.rb +69 -0
  18. data/lib/pik/commands/help_command.rb +44 -0
  19. data/lib/pik/commands/implode_command.rb +16 -0
  20. data/lib/pik/commands/list_command.rb +34 -0
  21. data/lib/pik/commands/remove_command.rb +29 -0
  22. data/lib/pik/commands/run_command.rb +37 -0
  23. data/lib/pik/commands/switch_command.rb +49 -0
  24. data/lib/pik/config_file.rb +21 -0
  25. data/lib/pik/core_ext/pathname.rb +15 -0
  26. data/lib/pik/options.rb +56 -0
  27. data/lib/pik/runner.rb +16 -0
  28. data/lib/pik/search_path.rb +51 -0
  29. data/lib/pik/windows_env.rb +64 -0
  30. data/spec/add_command_spec.rb +15 -0
  31. data/spec/batch_file_spec.rb +31 -0
  32. data/spec/command_spec.rb +34 -0
  33. data/spec/commands_spec.rb +44 -0
  34. data/spec/default_command_spec.rb +6 -0
  35. data/spec/gemsync_command_spec.rb +15 -0
  36. data/spec/help_command_spec.rb +30 -0
  37. data/spec/list_command_spec.rb +33 -0
  38. data/spec/remove_command_spec.rb +25 -0
  39. data/spec/run_command_spec.rb +36 -0
  40. data/spec/search_path_spec.rb +121 -0
  41. data/spec/spec.opts +3 -0
  42. data/spec/switch_command_spec.rb +44 -0
  43. 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,12 @@
1
+ module Pik
2
+
3
+ module ConfigFileEditor
4
+
5
+ def initialize(args=ARGV,config=nil)
6
+ super
7
+ editors << @config
8
+ end
9
+
10
+ end
11
+
12
+ 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