pik 0.1.1 → 0.2.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 (68) hide show
  1. data/History.txt +13 -0
  2. data/Manifest.txt +35 -1
  3. data/README.rdoc +99 -39
  4. data/Rakefile +49 -8
  5. data/bin/pik_install +23 -0
  6. data/features/add_command.feature +28 -0
  7. data/features/checkup_command.feature +0 -0
  8. data/features/config_command.feature +12 -0
  9. data/features/default_command.feature +12 -0
  10. data/features/env.rb +52 -0
  11. data/features/gemsync_command.feature +0 -0
  12. data/features/help_command.feature +13 -0
  13. data/features/implode_command.feature +12 -0
  14. data/features/install_command.feature +13 -0
  15. data/features/list_command.feature +18 -0
  16. data/features/remove_command.feature +18 -0
  17. data/features/run_command.feature +22 -0
  18. data/features/step_definitions/pik_commands.rb +140 -0
  19. data/features/switch_command.feature +35 -0
  20. data/features/tag_command.feature +18 -0
  21. data/features/version.feature +9 -0
  22. data/lib/pik.rb +17 -3
  23. data/lib/pik/commands/add_command.rb +6 -6
  24. data/lib/pik/commands/batch_file_editor.rb +22 -8
  25. data/lib/pik/commands/checkup_command.rb +5 -2
  26. data/lib/pik/commands/command.rb +30 -26
  27. data/lib/pik/commands/config_command.rb +54 -2
  28. data/lib/pik/commands/default_command.rb +19 -5
  29. data/lib/pik/commands/help_command.rb +1 -1
  30. data/lib/pik/commands/implode_command.rb +12 -1
  31. data/lib/pik/commands/install_command.rb +182 -0
  32. data/lib/pik/commands/list_command.rb +3 -2
  33. data/lib/pik/commands/remove_command.rb +6 -6
  34. data/lib/pik/commands/run_command.rb +70 -10
  35. data/lib/pik/commands/switch_command.rb +10 -10
  36. data/lib/pik/commands/tag_command.rb +56 -0
  37. data/lib/pik/config_file.rb +26 -2
  38. data/lib/pik/contrib/progressbar.rb +237 -0
  39. data/lib/pik/contrib/unzip.rb +14 -0
  40. data/lib/pik/contrib/uri_ext.rb +296 -0
  41. data/lib/pik/contrib/zip/ioextras.rb +155 -0
  42. data/lib/pik/contrib/zip/stdrubyext.rb +111 -0
  43. data/lib/pik/contrib/zip/tempfile_bugfixed.rb +195 -0
  44. data/lib/pik/contrib/zip/zip.rb +1846 -0
  45. data/lib/pik/contrib/zip/zipfilesystem.rb +609 -0
  46. data/lib/pik/contrib/zip/ziprequire.rb +90 -0
  47. data/lib/pik/core_ext/pathname.rb +20 -7
  48. data/lib/pik/search_path.rb +21 -13
  49. data/lib/pik/which.rb +52 -0
  50. data/lib/pik/windows_env.rb +64 -25
  51. data/spec/add_command_spec.rb +0 -2
  52. data/spec/batch_file_spec.rb +3 -3
  53. data/spec/command_spec.rb +0 -7
  54. data/spec/gemsync_command_spec.rb +1 -1
  55. data/spec/help_command_spec.rb +1 -1
  56. data/spec/list_command_spec.rb +1 -1
  57. data/spec/pathname_spec.rb +30 -0
  58. data/spec/remove_command_spec.rb +6 -6
  59. data/spec/run_command_spec.rb +2 -30
  60. data/spec/search_path_spec.rb +9 -0
  61. data/spec/switch_command_spec.rb +14 -2
  62. data/spec/which_spec.rb +7 -0
  63. data/tools/pik.bat +2 -0
  64. data/tools/pik/pik +45 -0
  65. data/tools/pik/pik.exe +0 -0
  66. data/tools/pik/pik.exy +198 -0
  67. metadata +50 -21
  68. data/bin/pik +0 -33
@@ -4,7 +4,10 @@ module Pik
4
4
 
5
5
  class QuitError < StandardError
6
6
  end
7
-
7
+
8
+ class VersionUnknown < StandardError
9
+ end
10
+
8
11
  class Command
9
12
 
10
13
  attr_reader :config
@@ -13,6 +16,8 @@ module Pik
13
16
 
14
17
  attr_accessor :output
15
18
 
19
+ attr_accessor :version
20
+
16
21
  def self.cmd_name
17
22
  name.split('::').last.downcase.to_sym
18
23
  end
@@ -42,7 +47,7 @@ module Pik
42
47
  end
43
48
 
44
49
  def self.clean_gem_batch
45
- BatchFile.open("#{$0}.bat") do |gem_bat|
50
+ BatchFile.open(PIK_BATCH) do |gem_bat|
46
51
  # remove old calls to .pik/pik batches
47
52
  gem_bat.remove_line( /call.+pik.+bat/i )
48
53
  gem_bat.write
@@ -82,7 +87,6 @@ module Pik
82
87
  command_options
83
88
  parse_options
84
89
  create(PIK_HOME) unless PIK_HOME.exist?
85
- # Add.new(nil, config).execute if config.empty?
86
90
  delete_old_pik_batches
87
91
  end
88
92
 
@@ -101,45 +105,45 @@ module Pik
101
105
  end
102
106
 
103
107
  def parse_options
104
- options.parse! @args
108
+ options.on("--version", "-V", "Pik version") do |value|
109
+ puts "pik " + Pik::VERSION
110
+ @version = true
111
+ end
112
+ options.parse! @args
105
113
  end
106
114
 
107
115
  def current_version?(string)
108
116
  string == get_version
109
117
  end
110
118
 
111
- def get_version(path=current_ruby_bin_path)
112
- cmd = ruby_exe(path).basename
113
- cmd = Pathname.new(path) + cmd
119
+ def get_version(path=Which::Ruby.find)
120
+ cmd = Which::Ruby.exe(path)
114
121
  ruby_ver = `#{cmd} -v`
115
- ruby_ver =~ /ruby (\d\.\d\.\d)/
122
+ ruby_ver =~ /ruby (\d\.\d\.\d)/i
116
123
  major = $1.gsub('.','')
117
124
  "#{major}: #{ruby_ver.strip}"
118
125
  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
126
 
128
- def ruby_exe(path)
129
- ruby_glob(path).first
130
- end
127
+ # def current_path?(config_path)
128
+ # @path ||= SearchPath.new(ENV['PATH'])
129
+ # @path.find{|dir| Pathname(dir) == Pathname(config_path) }
130
+ # end
131
131
 
132
- def ruby_glob(path)
133
- glob = "#{Pathname.new(path).to_ruby}/{ruby.exe}"
134
- Pathname.glob(glob)
132
+ def find_config_from_path(path=Which::Ruby.find)
133
+ config.find{|k,v|
134
+ Pathname(v[:path])== Pathname(path)
135
+ }.first rescue nil
135
136
  end
136
137
 
137
138
  def current_gem_bin_path
138
- default_gem_home + 'bin'
139
+ cfg = config[find_config_from_path]
140
+ p = cfg[:gem_home] || default_gem_home
141
+ p + 'bin'
139
142
  end
140
143
 
141
144
  def default_gem_home
142
- Pathname.new(Gem.default_path.first).to_windows
145
+ path = `#{Which::Ruby.exe} -rubygems -e\"require 'rubygems' ; puts Gem.default_path.first\"`
146
+ Pathname.new(path.chomp).to_windows
143
147
  end
144
148
 
145
149
  def create(home)
@@ -148,7 +152,7 @@ module Pik
148
152
  end
149
153
 
150
154
  def delete_old_pik_batches( cutoff=(Time.now - (2 * 60 * 60)) )
151
- Dir[(PIK_HOME + "*.bat").to_windows.to_s].each do |f|
155
+ Dir[(PIK_HOME + "*.bat").to_ruby.to_s].each do |f|
152
156
  File.delete(f) if File.ctime(f) < cutoff
153
157
  end
154
158
  end
@@ -163,4 +167,4 @@ module Pik
163
167
 
164
168
  end
165
169
 
166
- end
170
+ end
@@ -9,6 +9,7 @@ module Pik
9
9
  attr_accessor :global
10
10
 
11
11
  def execute
12
+ return list if @args.empty?
12
13
  item, value = @args.shift.downcase.split('=')
13
14
  case item
14
15
  when 'rubyopt'
@@ -17,12 +18,63 @@ module Pik
17
18
  when 'off' then set('RUBYOPT' => nil)
18
19
  end
19
20
  when 'gem_home'
20
- config[get_version][:gem_home] = @args.include?('default') ? default_gem_home : value
21
+ config[find_config_from_path][:gem_home] = if @args.include?('default')
22
+ Pathname.new(default_gem_home)
23
+ else
24
+ Pathname.new(value)
25
+ end
26
+ when 'downloads', 'download_dir'
27
+ config.global[:download_dir] = Pathname.new(value)
28
+ when 'installs', 'install_dir'
29
+ config.global[:install_dir] = Pathname.new(value)
30
+ when 'list'
31
+ list
21
32
  else
22
33
  puts "Unknown configuration option"
23
34
  end
24
35
  end
36
+
37
+ def list
38
+ version = find_config_from_path
39
+ puts "** CURRENT CONFIGURATION **"
40
+ puts
41
+ puts version + ' *'
42
+ config[version].each{|k,v| puts " %s: %s" % [k, v]}
43
+ puts
44
+ puts "** GLOBAL CONFIGURATION **"
45
+ puts
46
+ cfg = stringify(config.global.dup)
47
+ puts cfg.to_yaml.gsub(/"/, '')
48
+ end
49
+
50
+ def stringify(item)
51
+ case item
52
+ when Array
53
+ item.map{|i| stringify(i) }
54
+ when Hash
55
+ h = {}
56
+ item.map{|k,v| h[stringify(k)] = stringify(v)}
57
+ h
58
+ else
59
+ item.to_s
60
+ end
61
+ end
62
+
63
+ def command_options
64
+ super
65
+ sep =<<SEP
66
+ Configuration options are:
67
+
68
+ rubyopt on = -rubygems, off = blank
69
+ gem_home Location of current version's GEM_HOME env. var.
70
+ downloads Location where 'pik install' will download new versions
71
+ installs Location where 'pik install' will install new versions
25
72
 
73
+ SEP
74
+ options.separator sep
75
+ end
76
+
26
77
  end
27
78
 
28
- end
79
+ end
80
+
@@ -3,20 +3,34 @@ module Pik
3
3
 
4
4
  class Default < Command
5
5
 
6
- it "switches back to the default settings"
6
+ it "Switches back to the default settings."
7
+
8
+ attr_accessor :verbose
7
9
 
8
10
  include BatchFileEditor
9
11
 
10
12
  def execute
13
+ unless User.new.admin?
14
+ raise "You must have admin rights for the default command"
15
+ end
11
16
  sys = WindowsEnv.system
12
17
  usr = WindowsEnv.user
13
-
14
- @batch.set('PATH' => sys['PATH'] + ';' + usr['PATH'] )
18
+ new_path = [sys['PATH'],usr['PATH']].compact.join(';')
19
+ @batch.set('PATH' => new_path )
15
20
  @batch.set('GEM_PATH' => usr['GEM_PATH'] || sys['GEM_PATH'] )
16
21
  @batch.set('GEM_HOME' => usr['GEM_HOME'] || sys['GEM_HOME'] )
17
- echo_ruby_version
22
+ echo_ruby_version(Which::Ruby.find(new_path)) if verbose
23
+ end
24
+
25
+ def command_options
26
+ super
27
+ @options.on("--verbose", "-v",
28
+ "Verbose output"
29
+ ) do |value|
30
+ @verbose = value
31
+ end
18
32
  end
19
33
 
20
34
  end
21
35
 
22
- end
36
+ end
@@ -5,7 +5,7 @@ module Pik
5
5
  it 'Displays help information.'
6
6
 
7
7
  def execute
8
- puts options if @args.empty?
8
+ puts options if @args.empty? && !version
9
9
 
10
10
  @args.each do |a|
11
11
  @msg = case a.to_sym
@@ -5,11 +5,22 @@ module Pik
5
5
 
6
6
  it "Removes your pik configuration."
7
7
 
8
+ attr_reader :force
9
+
8
10
  def execute
9
- if @hl.agree("Are you sure you want pik to implode? This will remove '#{PIK_HOME.to_ruby}'. [Yn] ")
11
+ msg = "Are you sure you want pik to implode? "
12
+ msg << "This will remove '#{PIK_HOME.to_ruby}'. [Yn] "
13
+ if @force || @hl.agree(msg)
10
14
  PIK_HOME.rmtree
11
15
  end
12
16
  end
17
+
18
+ def command_options
19
+ super
20
+ options.on("--force", "-f", "Force") do |value|
21
+ @force = value
22
+ end
23
+ end
13
24
 
14
25
  end
15
26
 
@@ -0,0 +1,182 @@
1
+ require 'pik/contrib/uri_ext'
2
+ require 'pik/contrib/unzip'
3
+ require 'pik/contrib/progressbar'
4
+
5
+ module Pik
6
+
7
+ class Install < Command
8
+
9
+ aka :in
10
+ it "Downloads and installs different ruby versions."
11
+
12
+ def versions
13
+ {
14
+ 'ruby' => {
15
+ '1.8.6-p383' =>
16
+ 'http://rubyforge.org/frs/download.php/62267/ruby-1.8.6-p383-i386-mingw32.7z',
17
+ '1.9.1-p243' =>
18
+ 'http://rubyforge.org/frs/download.php/62269/ruby-1.9.1-p243-i386-mingw32.7z'
19
+ },
20
+ 'ironruby' => {
21
+ '0.9.1' =>
22
+ 'http://rubyforge.org/frs/download.php/64504/ironruby-0.9.1.zip',
23
+ '0.9.0' =>
24
+ 'http://rubyforge.org/frs/download.php/61382/ironruby-0.9.0.zip'
25
+ },
26
+ 'jruby' => {
27
+ '1.4.0RC1' =>
28
+ 'http://dist.codehaus.org/jruby/1.4.0RC1/jruby-bin-1.4.0RC1.zip'
29
+ }
30
+ }
31
+ end
32
+
33
+ def execute
34
+ target = ''
35
+ @download_dir = config.global[:download_dir] || PIK_HOME + 'downloads'
36
+ FileUtils.mkdir_p @download_dir.to_s
37
+ version = @args.shift
38
+ if versions[version]
39
+ target += version
40
+ version = versions[version]
41
+ @args.each{ |i| version = version.select{|k,v| k =~ Regexp.new(Regexp.escape(i)) } }
42
+ t, version = most_recent(version)
43
+ target += "_#{t}"
44
+ elsif URI.parse(version.to_s) === URI::HTTP
45
+ version = URI.parse(version.to_s)
46
+ target = @args.shift
47
+ else
48
+ raise VersionUnknown
49
+ end
50
+ install_root = config.global[:install_dir] || PIK_BATCH.dirname + 'pik'
51
+ target = install_root + target.gsub('.','')
52
+ FileUtils.mkdir_p target
53
+ file = download(version)
54
+ extract(target, file)
55
+ add( Pathname(target) + 'bin' )
56
+ rescue VersionUnknown
57
+ puts 'unknown'
58
+ end
59
+
60
+ def command_options
61
+ super
62
+ sep =<<SEP
63
+ Choices are: ruby, jruby, or ironruby
64
+
65
+ If no version is specified, the latest version will be installed.
66
+ Download and install locations can be configured with 'pik config'.
67
+
68
+ Examples:
69
+
70
+ # install the latest version of JRuby (currently 1.4.0RC1)
71
+ >pik install jruby
72
+
73
+ # install the latest 1.8 version of MinGW Ruby
74
+ >pik install ruby 1.8
75
+
76
+ SEP
77
+ options.separator sep
78
+ end
79
+
80
+ def most_recent(version)
81
+ version.sort.last
82
+ end
83
+
84
+ def download(version, download_dir=@download_dir)
85
+ target = download_dir + version.split('/').last
86
+ puts "** Downloading: #{version}\n to: #{target.windows}\n\n"
87
+ URI.download(version,target.to_s, {:progress => true})
88
+ puts
89
+ return target
90
+ end
91
+
92
+ def extract(target, file)
93
+ if Which::SevenZip.exe
94
+ extract_(file, target)
95
+ else
96
+ file = download_seven_zip
97
+ extract(target, file)
98
+ end
99
+ end
100
+
101
+ def add(path)
102
+ puts
103
+ p = Pik::Add.new([path], config)
104
+ p.execute
105
+ p.close
106
+ end
107
+
108
+ def seven_zip(target, file)
109
+ file = Pathname(file)
110
+ seven_zip = Which::SevenZip.exe.basename
111
+ puts "** Extracting: #{file.windows}\n to: #{target}" #if verbose
112
+ system("#{seven_zip} x -y -o\"#{target}\" \"#{file.windows}\" > NUL")
113
+ puts 'done'
114
+ end
115
+
116
+ def download_seven_zip
117
+ question = "You need the 7zip utility to extract this file.\n"
118
+ question << "Would you like me to download it? [Yn]"
119
+ if @hl.agree question
120
+ uri = 'http://downloads.sourceforge.net/sevenzip/7za465.zip'
121
+ file = download(uri)
122
+ Zip.fake_unzip(file.to_s, /\.exe|\.dll$/, PIK_BATCH.dirname.to_s)
123
+ else
124
+ raise QuitError
125
+ end
126
+ end
127
+
128
+ def extract_(file, target, options = {})
129
+ fail unless File.directory?(target)
130
+
131
+ # create a temporary folder used to extract files there
132
+ tmpdir = File.expand_path(File.join(Dir.tmpdir, "extract_sandbox_#{$$}"))
133
+ FileUtils.mkpath(tmpdir) unless File.exist?(tmpdir)
134
+
135
+ # based on filetypes, extract the intermediate file into the temporary folder
136
+ case file
137
+ # tar.z, tar.gz and tar.bz2 contains .tar files inside, extract into
138
+ # temp first
139
+ when /(^.+\.tar)\.z$/, /(^.+\.tar)\.gz$/, /(^.+\.tar)\.bz2$/
140
+ seven_zip tmpdir, file
141
+ seven_zip target, File.join(tmpdir, File.basename($1))
142
+ when /(^.+)\.tgz$/
143
+ seven_zip tmpdir, file
144
+ seven_zip target, File.join(tmpdir, "#{File.basename($1)}.tar")
145
+ when /(^.+\.zip$)/, /(^.+\.7z$)/
146
+ seven_zip(target, $1)
147
+ else
148
+ raise "Unknown file extension! (for file #{file})"
149
+ end
150
+
151
+ # after extraction, lookup for a folder that contains '-' (version number or datestamp)
152
+ folders_in_target = []
153
+ Dir.chdir(target) { folders_in_target = Dir.glob('*') }
154
+
155
+ # the package was created inside another folder
156
+ # exclude folders packagename-X.Y.Z or packagename-DATE
157
+ # move all the folders within that into target directly.
158
+ folders_in_target.each do |folder|
159
+ next unless File.directory?(File.join(target, folder)) && folder =~ /\-/
160
+
161
+ # take the folder contents out!, now!
162
+ contents = []
163
+ Dir.chdir(File.join(target, folder)) { contents = Dir.glob('*') }
164
+
165
+ contents.each do |c|
166
+ #puts "** Moving out #{c} from #{folder} and drop into #{target}" if Rake.application.options.trace
167
+ FileUtils.mv File.join(target, folder, c), target, :force => true
168
+ end
169
+
170
+ # remove the now empty folder
171
+ # puts "** Removing #{folder}" if Rake.application.options.trace
172
+ FileUtils.rm_rf File.join(target, folder)
173
+ end
174
+
175
+ # remove the temporary directory
176
+ # puts "** Removing #{tmpdir}" if Rake.application.options.trace
177
+ FileUtils.rm_rf tmpdir
178
+ end
179
+
180
+ end
181
+
182
+ end
@@ -7,9 +7,10 @@ module Pik
7
7
 
8
8
  attr_reader :verbose
9
9
 
10
- def execute
10
+ def execute
11
+ current_path = Which::Ruby.find
11
12
  config.sort.each do |name, conf|
12
- name += ' *' if current_version?(name)
13
+ name += ' *' if current_path == conf[:path]
13
14
  puts name
14
15
  if verbose
15
16
  conf.each{|k,v| puts " %s: %s" % [k, v]}