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
@@ -0,0 +1,90 @@
1
+ # With ziprequire you can load ruby modules from a zip file. This means
2
+ # ruby's module include path can include zip-files.
3
+ #
4
+ # The following example creates a zip file with a single entry
5
+ # <code>log/simplelog.rb</code> that contains a single function
6
+ # <code>simpleLog</code>:
7
+ #
8
+ # require 'zip/zipfilesystem'
9
+ #
10
+ # Zip::ZipFile.open("my.zip", true) {
11
+ # |zf|
12
+ # zf.file.open("log/simplelog.rb", "w") {
13
+ # |f|
14
+ # f.puts "def simpleLog(v)"
15
+ # f.puts ' Kernel.puts "INFO: #{v}"'
16
+ # f.puts "end"
17
+ # }
18
+ # }
19
+ #
20
+ # To use the ruby module stored in the zip archive simply require
21
+ # <code>zip/ziprequire</code> and include the <code>my.zip</code> zip
22
+ # file in the module search path. The following command shows one
23
+ # way to do this:
24
+ #
25
+ # ruby -rzip/ziprequire -Imy.zip -e " require 'log/simplelog'; simpleLog 'Hello world' "
26
+
27
+ #$: << 'data/rubycode.zip' << 'data/rubycode2.zip'
28
+
29
+
30
+ require 'zip/zip'
31
+
32
+ class ZipList #:nodoc:all
33
+ def initialize(zipFileList)
34
+ @zipFileList = zipFileList
35
+ end
36
+
37
+ def get_input_stream(entry, &aProc)
38
+ @zipFileList.each {
39
+ |zfName|
40
+ Zip::ZipFile.open(zfName) {
41
+ |zf|
42
+ begin
43
+ return zf.get_input_stream(entry, &aProc)
44
+ rescue Errno::ENOENT
45
+ end
46
+ }
47
+ }
48
+ raise Errno::ENOENT,
49
+ "No matching entry found in zip files '#{@zipFileList.join(', ')}' "+
50
+ " for '#{entry}'"
51
+ end
52
+ end
53
+
54
+
55
+ module Kernel #:nodoc:all
56
+ alias :oldRequire :require
57
+
58
+ def require(moduleName)
59
+ zip_require(moduleName) || oldRequire(moduleName)
60
+ end
61
+
62
+ def zip_require(moduleName)
63
+ return false if already_loaded?(moduleName)
64
+ get_resource(ensure_rb_extension(moduleName)) {
65
+ |zis|
66
+ eval(zis.read); $" << moduleName
67
+ }
68
+ return true
69
+ rescue Errno::ENOENT => ex
70
+ return false
71
+ end
72
+
73
+ def get_resource(resourceName, &aProc)
74
+ zl = ZipList.new($:.grep(/\.zip$/))
75
+ zl.get_input_stream(resourceName, &aProc)
76
+ end
77
+
78
+ def already_loaded?(moduleName)
79
+ moduleRE = Regexp.new("^"+moduleName+"(\.rb|\.so|\.dll|\.o)?$")
80
+ $".detect { |e| e =~ moduleRE } != nil
81
+ end
82
+
83
+ def ensure_rb_extension(aString)
84
+ aString.sub(/(\.rb)?$/i, ".rb")
85
+ end
86
+ end
87
+
88
+ # Copyright (C) 2002 Thomas Sondergaard
89
+ # rubyzip is free software; you can redistribute it and/or
90
+ # modify it under the terms of the ruby license.
@@ -1,15 +1,28 @@
1
1
 
2
2
  class Pathname
3
3
 
4
- def to_windows
5
- @path.gsub!('/','\\')
6
- self
4
+ def to_s
5
+ @path.gsub('/','\\')
7
6
  end
7
+ alias to_windows to_s
8
8
 
9
9
  def to_ruby
10
- @path.gsub!('\\','/')
11
- self
10
+ @path.gsub('\\','/')
12
11
  end
13
-
12
+
13
+ def ruby
14
+ Pathname(self.to_ruby)
15
+ end
16
+
17
+ def windows
18
+ Pathname(self.to_s)
19
+ end
20
+
21
+ def ==(other)
22
+ return false unless Pathname === other
23
+ self_ = self.dup.to_ruby.downcase
24
+ other = other.dup.to_ruby.downcase
25
+ self_ == other
26
+ end
27
+
14
28
  end
15
-
@@ -1,38 +1,46 @@
1
1
 
2
2
  class SearchPath
3
3
 
4
+ include Enumerable
5
+
4
6
  def initialize(path)
5
- @path = path.to_s.split(';')
7
+ @path = path.to_s.split(';').reject{|i| i.empty? }
6
8
  end
7
9
 
8
10
  def remove(old_path)
9
- old = Pathname.new(old_path).to_windows
10
- @path.reject!{|dir| dir =~ regex(old.to_s) }
11
+ old = Pathname(old_path).expand_path.to_windows
12
+ @path = @path.reject{|dir| Pathname(dir) == old }
13
+ @path = @path.uniq
11
14
  self
12
15
  end
13
16
 
14
17
  def replace(old_path, new_path)
15
-
16
- old_path = Pathname.new(old_path)
17
- new_path = Pathname.new(new_path)
18
+ old_path = Pathname(old_path)
19
+ new_path = Pathname(new_path)
18
20
  @path.map!{|dir|
19
- case dir
20
- when regex(old_path.to_windows)
21
- new_path.to_windows.to_s
22
- else
23
- dir
21
+ if Pathname(dir) == old_path
22
+ new_path.to_windows.to_s
23
+ else
24
+ dir
24
25
  end
25
- }.uniq.compact
26
+ }
27
+ @path = @path.uniq.compact
26
28
  self
27
29
  end
30
+
31
+ def each
32
+ @path.each{|path| yield path }
33
+ end
28
34
 
29
35
  def add(new_path)
30
- new_path = Pathname.new(new_path)
36
+ new_path = Pathname(new_path)
31
37
  @path << new_path.to_windows.to_s
32
38
  self
33
39
  end
34
40
 
35
41
  def replace_or_add(old_path, new_path)
42
+ old_path = Pathname(old_path)
43
+ new_path = Pathname(new_path)
36
44
  return self if old_path == new_path
37
45
  old_search_path = @path.dup
38
46
  replace(old_path, new_path)
@@ -0,0 +1,52 @@
1
+
2
+ module Which
3
+
4
+ class Base
5
+
6
+ class << self
7
+ def find(search_path=ENV['PATH'])
8
+ path = SearchPath.new(search_path)
9
+ path = path.find{|dir| exist?(dir)}
10
+ Pathname(path) rescue nil
11
+ end
12
+
13
+ def exist?(path)
14
+ !!exe(path)
15
+ end
16
+
17
+ def exe(path=find)
18
+ glob(path).first
19
+ end
20
+ alias :bat :exe
21
+
22
+ def glob(path)
23
+ return [] if path.nil?
24
+ glob = "#{Pathname.new(path).to_ruby}/{#{executables.join(',')}}"
25
+ Pathname.glob(glob)
26
+ end
27
+ end
28
+ end
29
+
30
+ class Ruby < Base
31
+
32
+ def self.executables
33
+ ['ruby.exe', 'ir.exe', 'jruby.exe', 'jruby.bat']
34
+ end
35
+
36
+ end
37
+
38
+ class Gem < Base
39
+
40
+ def self.executables
41
+ ['gem.bat', 'igem.bat']
42
+ end
43
+
44
+ end
45
+
46
+ class SevenZip < Base
47
+ def self.executables
48
+ ['7za.exe']
49
+ end
50
+ end
51
+
52
+ end
@@ -1,17 +1,25 @@
1
- require 'win32ole'
1
+ require 'win32/registry'
2
+ require 'Win32API'
3
+
2
4
 
3
5
  class WindowsEnv
4
6
 
5
7
  def self.system
6
- @system ||= new('SYSTEM', shell)
8
+ key = :HKEY_LOCAL_MACHINE
9
+ subkey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
10
+ new(key, subkey)
7
11
  end
8
12
 
9
13
  def self.user
10
- @user ||= new('User', shell)
14
+ key = :HKEY_CURRENT_USER
15
+ subkey = 'Environment'
16
+ new(key, subkey)
11
17
  end
12
18
 
13
- def initialize(account, shell)
14
- @env = shell.environment(account)
19
+ def initialize(key, subkey)
20
+ @key = key
21
+ @subkey = subkey
22
+ @reg = Reg.new
15
23
  end
16
24
 
17
25
  def set(items)
@@ -19,7 +27,7 @@ class WindowsEnv
19
27
  end
20
28
 
21
29
  def [](name)
22
- @env.item(name)
30
+ @reg.open(@key, @subkey, name)
23
31
  end
24
32
 
25
33
  def []=(name, other)
@@ -34,31 +42,62 @@ class WindowsEnv
34
42
  !!self[key]
35
43
  end
36
44
 
37
- private
38
-
39
- def self.shell
40
- @shell ||= WIN32OLE.new('WScript.Shell')
41
- end
42
-
43
45
  end
44
46
 
45
- # env = WindowsEnv.user
46
-
47
- # home = env['home']
48
- # p home
49
-
50
- # env['home'] = nil
47
+ class Reg
48
+
49
+ def initialize(user=User.new)
50
+ @user = user
51
+ end
51
52
 
52
- # p env['home']
53
+ # reads the registry hive that the installer would write to
54
+ # based on user rights
55
+ def install_hkey(subkey, name='')
56
+ @user.admin? ? hklm(subkey,name) : hkcu(subkey,name)
57
+ end
53
58
 
54
- # env['rubyopt'] = '-rubygems'
59
+ def hklm(subkey, name='')
60
+ open(:HKEY_LOCAL_MACHINE, subkey, name)
61
+ end
62
+
63
+ def hkcu(subkey,name='')
64
+ open(:HKEY_CURRENT_USER, subkey, name)
65
+ end
66
+
67
+ def hkcr(subkey,name='')
68
+ open(:HKEY_CLASSES_ROOT, subkey, name)
69
+ end
70
+
71
+ def open(key, subkey, name)
72
+ key = Win32::Registry.const_get(key)
55
73
 
56
- # env['home'] = home
57
- # p env['home']
74
+ key.open(subkey) do |reg|
75
+ reg_typ, reg_val = reg.read(name) rescue nil
76
+ return reg_val
77
+ end
78
+ end
79
+ end
58
80
 
59
- # p env['path']
81
+ class User
60
82
 
61
- # p env.has_key?('path')
62
- # p env.has_key?('rubyopt')
83
+ IsUserAnAdmin = Win32API.new('shell32', 'IsUserAnAdmin', 'v', 'i')
84
+
85
+ # the logged on user's name
86
+ def name
87
+ ENV['username']
88
+ end
63
89
 
90
+ # the logged on user's domain
91
+ def domain
92
+ ENV['userdomain']
93
+ end
94
+
95
+ # determines if the user has admin rights
96
+ # not if the user is a member of the local admins group
97
+ # (allows for nested groups)
98
+ def admin?
99
+ true if IsUserAnAdmin.call.nonzero?
100
+ end
64
101
 
102
+ end
103
+
@@ -10,6 +10,4 @@ describe Pik::Add do
10
10
  add.interactive.should be_true
11
11
  end
12
12
 
13
- it "should exit with a message if nothing is found"
14
-
15
13
  end
@@ -12,9 +12,9 @@ describe BatchFile do
12
12
  @bf.to_s.should == string
13
13
  end
14
14
 
15
- it "should generate an ftype command for ruby.exe and rubyw.exe" do
16
- @bf.ftype.to_s.should match(/FTYPE rbfile\=ruby\.exe \"%1\" \%\*\n\nFTYPE rbwfile\=rubyw\.exe \"\%1\" \%\*/)
17
- end
15
+ # it "should generate an ftype command for ruby.exe and rubyw.exe" do
16
+ # @bf.ftype.to_s.should match(/FTYPE rbfile\=ruby\.exe \"%1\" \%\*\n\nFTYPE rbwfile\=rubyw\.exe \"\%1\" \%\*/)
17
+ # end
18
18
 
19
19
  it "should generate a path command with the updated ruby path" do
20
20
  @bf.set('PATH' => "C:\\ruby\\191\\bin").to_s.should match(/SET PATH\=C:\\ruby\\191\\bin/)
@@ -24,11 +24,4 @@ describe Pik::Command do
24
24
  end
25
25
  end
26
26
 
27
- describe "current_ruby_bin_path" do
28
- it "should be a Pathname" do
29
- @cmd.current_ruby_bin_path.should be_a(Pathname)
30
- @cmd.current_ruby_bin_path.basename.to_s.should == "bin"
31
- end
32
- end
33
-
34
27
  end
@@ -9,7 +9,7 @@ describe Pik::GemSync do
9
9
  gemsync = Pik::GemSync.new([])
10
10
  gemsync.gem_install(Pathname.new('c:/fake/file.gem'))
11
11
  gemsync.batch.file_data.should include( "ECHO Installing file.gem" )
12
- gemsync.batch.file_data.should include( "CALL gem install -q --no-rdoc --no-ri c:/fake/file.gem\n" )
12
+ gemsync.batch.file_data.should include( "CALL gem install -q --no-rdoc --no-ri c:\\fake\\file.gem\n" )
13
13
  end
14
14
  end
15
15
  end
@@ -2,7 +2,7 @@
2
2
  describe Pik::Help do
3
3
 
4
4
  before do
5
- @cmd = 'bin\\pik.bat'
5
+ @cmd = 'tools\\pik.bat'
6
6
  end
7
7
 
8
8
  it "should have a summary" do
@@ -1,7 +1,7 @@
1
1
  describe Pik::List do
2
2
 
3
3
  before do
4
- @cmd = 'bin\\pik.bat'
4
+ @cmd = 'tools\\pik.bat'
5
5
  Pik::Commands.clear
6
6
  Pik::Commands.add(Pik::List)
7
7
  #Pik::ConfigFile.stub!(:new).and_return({})
@@ -0,0 +1,30 @@
1
+
2
+ describe Pathname do
3
+
4
+ describe '==' do
5
+ it 'should test for equality' do
6
+ path1 = Pathname('Z:/This/is/to/test/EQUALITY')
7
+ path2 = Pathname('Z:\\this\\is\\to\\test\\equality')
8
+ path1.should == path2
9
+ end
10
+ end
11
+
12
+ describe 'to_windows' do
13
+ it 'should change the file separator' do
14
+ path = Pathname('Z:/This/is/to/test/separators')
15
+ result = "Z:\\This\\is\\to\\test\\separators"
16
+ path.to_windows.should eql(result)
17
+ p = "C:\\Doc\\gthiesfeld/.pik/dl/ir.zip"
18
+ Pathname(p).to_windows.should eql("C:\\Doc\\gthiesfeld\\.pik\\dl\\ir.zip")
19
+ end
20
+ end
21
+
22
+ describe 'to_ruby' do
23
+ it 'should change the file separator' do
24
+ path = Pathname("Z:\\This\\is\\to\\test\\separators")
25
+ result = 'Z:/This/is/to/test/separators'
26
+ path.to_ruby.should eql(result)
27
+ end
28
+ end
29
+
30
+ end