pik 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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]}