rip 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.markdown +18 -19
  2. data/lib/rip.rb +12 -6
  3. data/lib/rip/commands.rb +23 -8
  4. data/lib/rip/commands/build.rb +12 -3
  5. data/lib/rip/commands/core.rb +1 -3
  6. data/lib/rip/commands/install.rb +3 -1
  7. data/lib/rip/commands/ruby.rb +15 -0
  8. data/lib/rip/commands/setup.rb +21 -0
  9. data/lib/rip/commands/uninstall.rb +8 -1
  10. data/lib/rip/env.rb +18 -2
  11. data/lib/rip/installer.rb +13 -12
  12. data/lib/rip/package.rb +5 -1
  13. data/lib/rip/package_api.rb +8 -0
  14. data/lib/rip/package_manager.rb +21 -5
  15. data/lib/rip/packages/file_package.rb +7 -3
  16. data/lib/rip/packages/gem_package.rb +7 -3
  17. data/lib/rip/packages/git_package.rb +8 -3
  18. data/lib/rip/packages/http_package.rb +0 -1
  19. data/lib/rip/packages/remote_gem_package.rb +5 -1
  20. data/lib/rip/packages/ripfile_package.rb +23 -5
  21. data/lib/rip/setup.rb +120 -36
  22. data/lib/rip/sh/git.rb +6 -2
  23. data/lib/rip/version.rb +1 -1
  24. data/setup.rb +15 -1
  25. data/test/env_test.rb +23 -1
  26. data/test/file_test.rb +34 -0
  27. data/test/git_test.rb +20 -3
  28. data/test/mock_git.rb +7 -3
  29. data/test/repos/simple-file-3.2.1.rb +1 -0
  30. data/test/repos/simple.rip +2 -0
  31. data/test/repos/simple_c/dot_git/index +0 -0
  32. data/test/repos/simple_c/dot_git/logs/HEAD +1 -0
  33. data/test/repos/simple_c/dot_git/logs/refs/heads/master +1 -0
  34. data/test/repos/simple_c/dot_git/objects/4f/3f9a42a24970fb72e8a828d95652c08465b3a4 +0 -0
  35. data/test/repos/simple_c/dot_git/objects/64/38cb2cf06f0a0e96326f4223202bece66540a4 +0 -0
  36. data/test/repos/simple_c/dot_git/objects/9f/88aea8cd1b0da9b4d42188b7cf2014392344e6 +0 -0
  37. data/test/repos/simple_c/dot_git/objects/f1/050d684f583a32338ffd77ec37e1196e0d2cc7 +0 -0
  38. data/test/repos/simple_c/dot_git/refs/heads/master +1 -1
  39. data/test/ripfile_test.rb +19 -0
  40. data/test/test_helper.rb +35 -0
  41. metadata +19 -5
@@ -1,8 +1,8 @@
1
1
  Rip: Ruby's Intelligent Packaging
2
2
  =================================
3
3
 
4
- Rip is an attempt to create an intelligent packaging system
5
- for Ruby.
4
+ Rip is an attempt to create a next generation packaging
5
+ system for Ruby.
6
6
 
7
7
  For more thorough documentation please see the Rip site:
8
8
 
@@ -36,14 +36,14 @@ None. Really? Let's try to require Grit.
36
36
 
37
37
  Whoops. Not found. Let's install the latest using rip.
38
38
 
39
- $ rip install git://github.com/mojombo/grit.git v1.1.1
39
+ $ rip install git://github.com/defunkt/grit.git v1.1.1b
40
40
  Successfully installed grit v1.1.1
41
41
  $ rip list
42
42
  ripenv: base
43
43
 
44
- diff-lcs (5621f02)
44
+ diff-lcs (491fbc0)
45
+ mime-types (v1.16)
45
46
  grit (v1.1.1)
46
- mime-types (0fd8958)
47
47
 
48
48
  Great, now we have Grit and all its dependencies.
49
49
 
@@ -190,12 +190,11 @@ dependents, use `-d` (for dependents).
190
190
  Extensions
191
191
  ----------
192
192
 
193
- Installing a package that is not Rip aware but needs an extension
194
- built? Use `rip build`.
193
+ Rip will attempt to build extensions during installation through the
194
+ `rip build` command.
195
195
 
196
- Rip will attempt to run `rake rip:install` in your library if a
197
- Rakefile is found. If you need to compile your C extension or do
198
- any other work, this is the place.
196
+ You can also run `rip build PACKAGE` to try and build a package
197
+ manually.
199
198
 
200
199
  Rip Directory Structure
201
200
  -----------------------
@@ -222,14 +221,14 @@ Here is a typical directory structure for Rip:
222
221
  - lib/
223
222
  - thunderhorse.ripenv
224
223
 
225
- The above contains three ripenvs: `base`, `cheat`, and `thunderhose`. Each
224
+ The above contains three ripenvs: `base`, `cheat`, and `thunderhorse`. Each
226
225
  ripenv contains directories for executable binaries and Ruby source files.
227
226
  They also include a generated `.ripenv` file containing metadata about
228
227
  the ripenev and its packages.
229
228
 
230
229
  This individual may use `base` for general tomfoolery (it's the
231
230
  default), `cheat` for developing their Cheat application, and
232
- `thunderhorse` for working on their new Thunderhose project.
231
+ `thunderhorse` for working on their new Thunderhorse project.
233
232
 
234
233
  `active` is a symlink to the current, active ripenv. We also see a
235
234
  `rip-packages` directory. This is where Rip stores the raw repositories.
@@ -287,13 +286,13 @@ As a result, the setup script expects you to be running bash or zshell.
287
286
  Contributors
288
287
  ------------
289
288
 
290
- * Chris Wanstrath (that's me!)
291
- * Jeff Hodges
292
- * Tom Preston-Werner
293
- * John Barnette
294
- * Blake Mizerany
295
- * Ryan Tomayko
296
- * Pat Nakajima
289
+ * [Chris Wanstrath](http://github.com/defunkt) (that's me!)
290
+ * [Jeff Hodges](http://github.com/jmhodges/)
291
+ * [Tom Preston-Werner](http://github.com/mojombo/)
292
+ * [John Barnette](http://github.com/jbarnette)
293
+ * [Blake Mizerany](http://github.com/bmizerany)
294
+ * [Ryan Tomayko](http://github.com/rtomayko)
295
+ * [Pat Nakajima](http://github.com/nakajima)
297
296
 
298
297
  Special Thanks
299
298
  --------------
data/lib/rip.rb CHANGED
@@ -1,16 +1,18 @@
1
1
  require 'fileutils'
2
2
 
3
3
  module Rip
4
+ # Returns the Rip data directory. That is, the directory which contains
5
+ # all the Rip environment directories.
4
6
  def self.dir
5
7
  return @dir if @dir
6
8
 
7
- dir = ENV['RIPDIR'].to_s
8
-
9
- if dir.empty?
10
- abort "RIPDIR env variable not found. did you run setup.rb?"
9
+ env = ENV['RIPDIR'].to_s
10
+ if env.empty?
11
+ dir = File.join(user_home, ".rip")
12
+ else
13
+ dir = File.expand_path(env)
11
14
  end
12
-
13
- dir = File.expand_path(dir)
15
+
14
16
  FileUtils.mkdir_p dir unless File.exists? dir
15
17
  @dir = dir
16
18
  end
@@ -26,6 +28,10 @@ module Rip
26
28
  def self.ui=(io)
27
29
  @ui = Rip::UI.new(io)
28
30
  end
31
+
32
+ def self.user_home
33
+ @home ||= ENV['HOME']
34
+ end
29
35
  end
30
36
 
31
37
  # load rip files
@@ -5,7 +5,11 @@ module Rip
5
5
  def invoke(args)
6
6
  command, options, args = parse_args(args)
7
7
 
8
- if command.nil? || command == ''
8
+ if command.nil? && (options[:v] || options[:version])
9
+ command = :version
10
+ end
11
+
12
+ if command.nil? || command == '' || options[:h] || options[:help]
9
13
  command = :help
10
14
  end
11
15
 
@@ -23,8 +27,17 @@ module Rip
23
27
  end
24
28
  end
25
29
 
30
+ def load_plugin(file)
31
+ begin
32
+ require file
33
+ rescue Exception => e
34
+ ui.puts "rip: plugin not loaded (#{file})"
35
+ ui.puts "-> #{e.message}", ''
36
+ end
37
+ end
38
+
26
39
  def public_instance_methods
27
- super - %w( invoke public_instance_methods )
40
+ super - %w( invoke load_plugin public_instance_methods )
28
41
  end
29
42
 
30
43
  private
@@ -35,7 +48,7 @@ module Rip
35
48
  @next_usage = usage
36
49
  end
37
50
 
38
- def x(help)
51
+ def x(help = '')
39
52
  @help ||= {}
40
53
  @next_help ||= []
41
54
  @next_help.push help
@@ -62,6 +75,8 @@ module Rip
62
75
  end
63
76
 
64
77
  if matches.size == 0
78
+ ui.puts "Could not find the command: #{command.inspect}"
79
+ ui.puts
65
80
  :help
66
81
  elsif matches.size == 1
67
82
  matches.first
@@ -71,16 +86,16 @@ module Rip
71
86
  end
72
87
 
73
88
  def parse_args(args)
74
- command = args.shift
75
89
  options = args.select { |piece| piece =~ /^-/ }
76
90
  args -= options
91
+ command = args.shift
77
92
  options = options.inject({}) do |hash, flag|
78
93
  key, value = flag.split('=')
79
94
  hash[key.sub(/^--?/,'').intern] = value.nil? ? true : value
80
95
  hash
81
96
  end
82
97
 
83
- [command, options, args]
98
+ [ command, options, args ]
84
99
  end
85
100
  end
86
101
  end
@@ -93,14 +108,14 @@ end
93
108
  # load ~/.rip/rip-commands/*.rb
94
109
  if File.exists? dir = File.join(Rip.dir, 'rip-commands')
95
110
  Dir[dir + '/*.rb'].each do |file|
96
- require file
111
+ Rip::Commands.load_plugin(file)
97
112
  end
98
113
  end
99
114
 
100
115
  # load lib/rip/commands/*.rb from the active ripenv
101
116
  if File.exists? dir = File.join(Rip::Env.active_dir, 'lib', 'rip', 'commands')
102
117
  Dir[dir + '/*.rb'].each do |file|
103
- require file
118
+ Rip::Commands.load_plugin(file)
104
119
  end
105
120
  end
106
121
 
@@ -108,6 +123,6 @@ end
108
123
  # load lib/rip/commands/*.rb from rip itself
109
124
  if File.exists? dir = File.join(File.dirname(__FILE__), 'commands')
110
125
  Dir[dir + '/*.rb'].each do |file|
111
- require file
126
+ Rip::Commands.load_plugin(file)
112
127
  end
113
128
  end
@@ -7,15 +7,24 @@ module Rip
7
7
  module Commands
8
8
  def build(options={}, *packages)
9
9
  packages.each do |package_name|
10
- ui.puts "rip: building package: #{package_name}"
11
10
  package = manager.package(package_name)
11
+ alerted = false
12
12
 
13
13
  Dir["#{package.cache_path}/**/extconf.rb"].each do |build_file|
14
+ if !alerted
15
+ ui.puts "rip: building #{package_name}"
16
+ alerted = true
17
+ end
18
+
14
19
  build_dir = File.dirname(build_file)
15
- Dir.chdir(build_dir) {
20
+ Dir.chdir(build_dir) do
16
21
  system "ruby extconf.rb"
17
22
  system "make install RUBYARCHDIR=#{manager.dir}/lib"
18
- }
23
+ end
24
+ end
25
+
26
+ if !alerted && !options[:quiet]
27
+ ui.puts "rip: don't know how to build #{package_name}"
19
28
  end
20
29
  end
21
30
  end
@@ -27,7 +27,7 @@ module Rip
27
27
  x 'Commands for managing your ripenvs.'
28
28
  x 'Type rip env to see valid options.'
29
29
  def env(options = {}, command = nil, *args)
30
- if command && Rip::Env.respond_to?(command)
30
+ if command && Rip::Env.commands.include?(command)
31
31
  ui.puts 'ripenv: ' + Rip::Env.call(command, *args).to_s
32
32
  else
33
33
  show_help :env, Rip::Env.commands
@@ -48,8 +48,6 @@ module Rip
48
48
  def version(options = {}, *args)
49
49
  ui.puts "Rip #{Rip::Version}"
50
50
  end
51
- alias_method "-v", :version
52
- alias_method "--version", :version
53
51
 
54
52
  private
55
53
  def show_help(command, commands)
@@ -4,8 +4,10 @@ module Rip
4
4
  def check(*args)
5
5
  Setup.check_installation
6
6
  ui.puts "All systems go."
7
+ rescue Setup::StaleEnvironmentError, Setup::InstallationError => e
8
+ ui.puts e.message
7
9
  rescue => e
8
- ui.abort "Installation failed: #{e.message}"
10
+ ui.puts "Installation failed: #{e.message}"
9
11
  end
10
12
 
11
13
  o 'rip install SOURCE [options]'
@@ -0,0 +1,15 @@
1
+ module Rip
2
+ module Commands
3
+ o 'ruby ENV ARGS'
4
+ x 'Runs a Ruby instance in a particular environment.'
5
+ def ruby(options={}, *args)
6
+ selected_env = File.join(Rip.dir, ARGV.shift, "lib")
7
+ path = (ENV["RUBYLIB"] || "").split(":")
8
+ active_env = File.join(Rip.dir, "active", "lib")
9
+ path -= [active_env]
10
+ path += [selected_env]
11
+ ENV["RUBYLIB"] = path.join(":")
12
+ exec(ENV['RUBYBIN'] || "ruby", *ARGV)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Rip
2
+ module Commands
3
+
4
+ # Generate necessary envs etc. in ~/.{bash,zsh,...}rc.
5
+ #
6
+ o "rip setup [script to modify]"
7
+ x "Inserts required environment variables into your startup script."
8
+ x
9
+ x "Pass it the startup script you want to modify, otherwise it will"
10
+ x "guess one."
11
+ def setup(options = {}, script = nil)
12
+ require "rip/setup"
13
+
14
+ if Setup.setup_startup_script(script)
15
+ ui.puts "rip: Your #{Setup.startup_script} script has been modified."
16
+ ui.puts "rip: Please restart your shell or type `source #{Rip::Setup.startup_script}` for the changes to become effective."
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -1,7 +1,7 @@
1
1
  module Rip
2
2
  module Commands
3
3
  o 'rip uninstall PACKAGE [options]'
4
- x 'Uninstalls a single Rip package.'
4
+ x 'Uninstalls a single Rip package (or rip itself).'
5
5
  x '-y removes the package no matter what.'
6
6
  x '-d removes the package and its dependents.'
7
7
  def uninstall(options = {}, name = nil, *args)
@@ -9,6 +9,13 @@ module Rip
9
9
  ui.abort "Please tell me what to uninstall."
10
10
  end
11
11
 
12
+ if name == 'rip' && !options[:y]
13
+ ui.abort "Are you sure you want to uninstall rip? Pass -y if so."
14
+ elsif name == 'rip' && options[:y]
15
+ require 'rip/setup'
16
+ return Rip::Setup.uninstall(true)
17
+ end
18
+
12
19
  force = options[:y] || options[:d]
13
20
  package = manager.package(name)
14
21
 
@@ -1,6 +1,7 @@
1
1
  module Rip
2
2
  module Env
3
3
  extend self
4
+ PRIVATE_ENV = /^(rip-|active)/i
4
5
 
5
6
  def commands
6
7
  instance_methods - %w( call active_dir commands ui )
@@ -13,6 +14,10 @@ module Rip
13
14
  return "must give a ripenv to create"
14
15
  end
15
16
 
17
+ if env.strip =~ PRIVATE_ENV
18
+ return "invalid environment name"
19
+ end
20
+
16
21
  if File.exists? dir
17
22
  "#{env} exists"
18
23
  else
@@ -29,6 +34,10 @@ module Rip
29
34
  return "must give a ripenv to use"
30
35
  end
31
36
 
37
+ if env.strip =~ PRIVATE_ENV
38
+ return "invalid environment name"
39
+ end
40
+
32
41
  if !File.exists?(target = File.join(Rip.dir, env))
33
42
  return "#{env} doesn't exist"
34
43
  end
@@ -51,6 +60,10 @@ module Rip
51
60
  return "must give a ripenv to delete"
52
61
  end
53
62
 
63
+ if env.strip =~ PRIVATE_ENV
64
+ return "invalid environment name"
65
+ end
66
+
54
67
  if File.exists?(target = File.join(Rip.dir, env))
55
68
  FileUtils.rm_rf target
56
69
  "deleted #{env}"
@@ -64,7 +77,7 @@ module Rip
64
77
  env.split('/').last
65
78
  end
66
79
 
67
- envs.reject! { |env| env =~ /^(rip-|active)/ }
80
+ envs.reject! { |env| env =~ PRIVATE_ENV }
68
81
 
69
82
  if envs.empty?
70
83
  "none. make one with `rip env create <env>`"
@@ -95,6 +108,7 @@ module Rip
95
108
 
96
109
  if File.exists? ripfile = File.join(dest, "#{env}.ripenv")
97
110
  FileUtils.cp ripfile, File.join(dest, "#{new}.ripenv")
111
+ FileUtils.rm ripfile
98
112
  end
99
113
 
100
114
  use new
@@ -112,8 +126,10 @@ module Rip
112
126
  send(meth, *args)
113
127
  elsif arity == 0
114
128
  send(meth)
129
+ elsif args.empty?
130
+ send(meth, '')
115
131
  else
116
- send(meth, args[0, arity])
132
+ send(meth, *args[0, arity])
117
133
  end
118
134
  end
119
135
 
@@ -15,7 +15,7 @@ module Rip
15
15
 
16
16
  def install(package, parent = nil)
17
17
  if !package.exists?
18
- error = package.name
18
+ error = package.to_s
19
19
  error += " requested by #{parent} but" if parent
20
20
  error += " not found at #{package.source}"
21
21
  ui.abort error
@@ -30,17 +30,18 @@ module Rip
30
30
  return if installed
31
31
  @installed[package.name] = package
32
32
 
33
- if !package.version
33
+ if !package.meta_package? && !package.version
34
34
  ui.abort "can't install #{package} - it has no version"
35
35
  end
36
36
 
37
37
  package.fetch
38
38
  package.unpack
39
39
  install_dependencies(package)
40
- run_install_hook(package)
40
+ build_extensions(package)
41
41
  copy_files(package)
42
42
  cleanup(package)
43
43
  ui.puts "Successfully installed #{package}" unless package.meta_package?
44
+ true
44
45
 
45
46
  rescue VersionConflict => e
46
47
  ui.puts e.message
@@ -56,17 +57,13 @@ module Rip
56
57
 
57
58
  def install_dependencies(package)
58
59
  package.dependencies.each do |dependency|
59
- install(dependency, package)
60
+ success = install(dependency, package)
61
+ package.run_hook(:dependency_installed, dependency, success)
60
62
  end
61
63
  end
62
64
 
63
- def run_install_hook(package)
64
- return unless File.exists? File.join(package.cache_path, 'Rakefile')
65
-
66
- Dir.chdir package.cache_path do
67
- ui.puts "running install hook for #{package.name}"
68
- system "rake -s rip:install >& /dev/null"
69
- end
65
+ def build_extensions(package)
66
+ Rip::Commands.build({:quiet => true}, package)
70
67
  end
71
68
 
72
69
  def copy_files(package)
@@ -82,7 +79,7 @@ module Rip
82
79
  end
83
80
 
84
81
  if File.exists? package_bin
85
- FileUtils.cp_r package_bin + '/.', dest_bin
82
+ FileUtils.cp_r package_bin + '/.', dest_bin, :preserve => true
86
83
  end
87
84
  end
88
85
 
@@ -123,6 +120,10 @@ module Rip
123
120
  end
124
121
  end
125
122
 
123
+ def rakebin
124
+ ENV['RAKEBIN'] || 'rake'
125
+ end
126
+
126
127
  def ui
127
128
  Rip.ui
128
129
  end