pik 0.1.0

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.
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