rvm 0.1.41 → 0.1.42

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 (58) hide show
  1. data/binscripts/rvm +1 -1
  2. data/binscripts/rvm-shell +32 -0
  3. data/binscripts/rvmsudo +1 -6
  4. data/config/db +2 -2
  5. data/config/known +2 -2
  6. data/config/md5 +6 -5
  7. data/contrib/install-system-wide +81 -0
  8. data/install +23 -24
  9. data/lib/VERSION.yml +1 -1
  10. data/lib/rvm.rb +156 -1
  11. data/lib/rvm/capistrano.rb +45 -0
  12. data/lib/rvm/environment.rb +62 -0
  13. data/lib/rvm/environment/alias.rb +69 -0
  14. data/lib/rvm/environment/cleanup.rb +54 -0
  15. data/lib/rvm/environment/configuration.rb +60 -0
  16. data/lib/rvm/environment/env.rb +52 -0
  17. data/lib/rvm/environment/gemset.rb +222 -0
  18. data/lib/rvm/environment/info.rb +13 -0
  19. data/lib/rvm/environment/list.rb +124 -0
  20. data/lib/rvm/environment/rubies.rb +50 -0
  21. data/lib/rvm/environment/sets.rb +123 -0
  22. data/lib/rvm/environment/tools.rb +41 -0
  23. data/lib/rvm/environment/utility.rb +167 -0
  24. data/lib/rvm/environment/wrapper.rb +23 -0
  25. data/lib/rvm/errors.rb +28 -0
  26. data/lib/rvm/shell.rb +21 -10
  27. data/lib/rvm/shell/abstract_wrapper.rb +145 -0
  28. data/lib/rvm/shell/result.rb +42 -0
  29. data/lib/rvm/shell/shell_wrapper.sh +10 -0
  30. data/lib/rvm/shell/single_shot_wrapper.rb +56 -0
  31. data/lib/rvm/shell/utility.rb +37 -0
  32. data/lib/rvm/version.rb +12 -8
  33. data/rvm.gemspec +27 -4
  34. data/scripts/cd +17 -32
  35. data/scripts/cli +46 -16
  36. data/scripts/completion +1 -1
  37. data/scripts/disk-usage +52 -0
  38. data/scripts/fetch +8 -2
  39. data/scripts/gemsets +15 -4
  40. data/scripts/initialize +3 -3
  41. data/scripts/install +23 -24
  42. data/scripts/list +16 -8
  43. data/scripts/log +4 -1
  44. data/scripts/man +0 -0
  45. data/scripts/manage +51 -34
  46. data/scripts/md5 +4 -5
  47. data/scripts/package +28 -6
  48. data/scripts/rubygems +2 -2
  49. data/scripts/rvm +2 -2
  50. data/scripts/rvm-install +23 -24
  51. data/scripts/selector +2 -2
  52. data/scripts/tools +34 -0
  53. data/scripts/update +23 -24
  54. data/scripts/utility +54 -12
  55. data/scripts/wrapper +21 -18
  56. metadata +29 -6
  57. data/lib/rvm/open4.rb +0 -395
  58. data/lib/rvm/rvm.rb +0 -14
@@ -0,0 +1,23 @@
1
+ module RVM
2
+ class Environment
3
+
4
+ # Generates wrappers with the specified prefix, pointing
5
+ # to ruby_string.
6
+ def wrapper(ruby_string, wrapper_prefix, *binaries)
7
+ rvm(:wrapper, ruby_string, wrapper_prefix, *binaries).successful?
8
+ end
9
+
10
+ # Generates the default wrappers.
11
+ def default_wrappers(ruby_string, *binaries)
12
+ wrapper ruby_string, '', *binaries
13
+ end
14
+
15
+ # If available, return the path to the wrapper for
16
+ # the given executable. Will return ni if the wrapper
17
+ # is unavailable.
18
+ def wrapper_path_for(executable)
19
+ raise NotImplementedError
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module RVM
2
+
3
+ # Generic error in RVM
4
+ class Error < StandardError; end
5
+
6
+ # Generic error with the shell command output attached.
7
+ # The RVM::Shell::Result instance is available via +#result+.
8
+ class ErrorWithResult < Error
9
+ attr_reader :result
10
+
11
+ def initialize(result, message = nil)
12
+ @result = result
13
+ super message
14
+ end
15
+
16
+ end
17
+
18
+ # Something occured processing the command and rvm couldn't parse the results.
19
+ class IncompleteCommandError < Error; end
20
+
21
+ # The given action can't replace the env for the current process.
22
+ # Typically raised by RVM::Environment#gemset_use when the gemset
23
+ # is for another, incompatible ruby interpreter.
24
+ #
25
+ # Provides access to the output of the shell command via +#result+.
26
+ class IncompatibleRubyError < ErrorWithResult; end
27
+
28
+ end
@@ -1,14 +1,25 @@
1
1
  module RVM
2
- class Shell
3
- attr_reader :errors, :output
4
-
5
- def initialize(command)
6
- @command = (command =~ /^rvm /) ? command : "rvm #{command}"
7
- Open4::popen4("/bin/bash -l -c '#{@command.tr("'","\\'")}'") do |pid, stdin, stdout, stderr|
8
- stdin.close
9
- @output = stdout.readlines.join
10
- @errors = stderr.readlines.join
11
- end
2
+ # Provides Generic access to a more ruby-like shell interface.
3
+ # For more details, see AbstractWrapper.
4
+ module Shell
5
+
6
+ autoload :AbstractWrapper, 'rvm/shell/abstract_wrapper'
7
+ autoload :SingleShotWrapper, 'rvm/shell/single_shot_wrapper'
8
+ # Current unimplemented
9
+ #autoload :PersistingWrapper, 'rvm/shell/persisting_wrapper'
10
+ autoload :TestWrapper, 'rvm/shell/test_wrapper'
11
+ autoload :Utility, 'rvm/shell/utility'
12
+ autoload :Result, 'rvm/shell/result'
13
+
14
+ # Returns the default shell wrapper class to use
15
+ def self.default_wrapper
16
+ @@default_wrapper ||= SingleShotWrapper
12
17
  end
18
+
19
+ # Sets the default shell wrapper class to use.
20
+ def self.default_wrapper=(wrapper)
21
+ @@default_wrapper = wrapper
22
+ end
23
+
13
24
  end
14
25
  end
@@ -0,0 +1,145 @@
1
+ require 'yaml'
2
+
3
+ module RVM
4
+ module Shell
5
+ # Provides the most common functionality expected of a shell wrapper.
6
+ # Namely, implements general utility methods and tools to extract output
7
+ # from a given command but doesn't actually run any commands itself,
8
+ # leaving that up to concrete implementations.
9
+ #
10
+ # == Usage
11
+ #
12
+ # Commands are run inside of a shell (usually bash) and can either be exectuted in
13
+ # two situations (each with wrapper methods available) - silently or verbosely.
14
+ #
15
+ # Silent commands (via run_silently and run_command) do exactly as
16
+ # they say - that can modify the environment etc but anything they print (to stdout
17
+ # or stderr) will be discarded.
18
+ #
19
+ # Verbose commands will run the command and then print the command epilog (which
20
+ # contains the output stastus and the current env in yaml format). This allows us
21
+ # to not only capture all output but to also return the exit status and environment
22
+ # variables in a way that makes persisted shell sessions possible.
23
+ #
24
+ # Under the hood, #run and run_silently are the preferred ways of invoking commands - if
25
+ # passed a single command, they'll run it as is (much like system in ruby) but when
26
+ # given multiple arguments anything after the first will be escaped (e.g. you can
27
+ # hence pass code etc). #run will also parse the results of this epilog into a usable
28
+ # RVM::Shell::Result object.
29
+ #
30
+ # run_command and run_command_silently do the actual hard work for these behind the scenes,
31
+ # running a string as the shell command. Hence, these two commands are what must be
32
+ # implemented in non-abstract wrappers.
33
+ #
34
+ # For an example of the shell wrapper functionality in action, see RVM::Environment
35
+ # which delegates most of the work to a shell wrapper.
36
+ class AbstractWrapper
37
+
38
+ # Used the mark the end of a commands output and the start of the rvm env.
39
+ COMMAND_EPILOG_START = "---------------RVM-RESULTS-START---------------"
40
+ # Used to mark the end of the commands epilog.
41
+ COMMAND_EPILOG_END = "----------------RVM-RESULTS-END----------------"
42
+ # The location of the shell file with the epilog function definition.
43
+ WRAPPER_LOCATION = File.expand_path('./shell_wrapper.sh', File.dirname(__FILE__))
44
+
45
+ # Defines the shell exectuable.
46
+ attr_reader :shell_executable
47
+
48
+ # Initializes a new shell wrapper, including setting the
49
+ # default setup block. Implementations must override this method
50
+ # but must ensure that they call super to perform the expected
51
+ # standard setup.
52
+ def initialize(sh = 'bash', &setup_block)
53
+ setup &setup_block
54
+ @shell_executable = sh
55
+ end
56
+
57
+ # Defines a setup block to be run when initiating a wrapper session.
58
+ # Usually used for doing things such as sourcing the rvm file. Please note
59
+ # that the wrapper file is automatically source.
60
+ #
61
+ # The setup block should be automatically run by wrapper implementations.
62
+ def setup(&blk)
63
+ @setup_block = blk
64
+ end
65
+
66
+ # Runs the gives command (with optional arguments), returning an
67
+ # RVM::Shell::Result object, including stdout / stderr streams.
68
+ # Under the hood, uses run_command to actually process it all.
69
+ def run(command, *arguments)
70
+ expanded_command = build_cli_call(command, arguments)
71
+ status, out, err = run_command(expanded_command)
72
+ Result.new(expanded_command, status, out, err)
73
+ end
74
+
75
+ # Wrapper around run_command_silently that correctly escapes arguments.
76
+ # Essentially, #run but using run_command_silently.
77
+ def run_silently(command, *arguments)
78
+ run_command_silently build_cli_call(command, arguments)
79
+ end
80
+
81
+ # Given a command, it will execute it in the current wrapper
82
+ # and once done, will return:
83
+ # - the hash from the epilog output.
84
+ # - a string representing stdout.
85
+ # - a string representing stderr.
86
+ def run_command(full_command)
87
+ raise NotImplementedError.new("run_command is only available in concrete implementations")
88
+ end
89
+
90
+ # Like run_command, but doesn't care about output.
91
+ def run_command_silently(full_command)
92
+ raise NotImplementedError.new("run_command_silently is only available in concrete implementations")
93
+ end
94
+
95
+ # Returns a given environment variables' value.
96
+ def [](var_name)
97
+ run(:true)[var_name]
98
+ end
99
+
100
+ protected
101
+
102
+ # When called, will use the current environment to source the wrapper scripts
103
+ # as well as invoking the current setup block. as defined on initialization / via #setup.
104
+ def invoke_setup!
105
+ source_command_wrapper
106
+ @setup_block.call(self) if @setup_block
107
+ end
108
+
109
+ # Uses run_silently to source the wrapper file.
110
+ def source_command_wrapper
111
+ run_silently :source, WRAPPER_LOCATION
112
+ end
113
+
114
+ # Returns a command followed by the call to show the epilog.
115
+ def wrapped_command(command)
116
+ "#{command}; __rvm_show_command_epilog"
117
+ end
118
+
119
+ # Wraps a command in a way that it prints no output.
120
+ def silent_command(command)
121
+ "{ #{command}; } >/dev/null 2>&1"
122
+ end
123
+
124
+ # Checks whether the given command includes a epilog, marked by
125
+ # epilog start and end lines.
126
+ def command_complete?(c)
127
+ start_index, end_index = c.index(COMMAND_EPILOG_START), c.index(COMMAND_EPILOG_END)
128
+ start_index && end_index && start_index < end_index
129
+ end
130
+
131
+ # Takes a raw string from a processes STDIO and returns three things:
132
+ # 1. The actual stdout, minus epilogue.
133
+ # 2. YAML output of the process results.
134
+ # 3. Any left over from the STDIO text.
135
+ def raw_stdout_to_parts(c)
136
+ raise IncompleteCommandError if !command_complete?(c)
137
+ before, after = c.split(COMMAND_EPILOG_START, 2)
138
+ epilog, after = after.split(COMMAND_EPILOG_END, 2)
139
+ return before, YAML.load(epilog.strip), after
140
+ end
141
+
142
+ include RVM::Shell::Utility
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,42 @@
1
+ module RVM
2
+ module Shell
3
+ # Represents the output of a shell command.
4
+ # This includes the exit status (and the helpful #successful? method)
5
+ # as well accessors for the command and stdout / stderr.
6
+ class Result
7
+
8
+ attr_reader :command, :stdout, :stderr, :raw_status
9
+
10
+ # Creates a new result object with the given details.
11
+ def initialize(command, status, stdout, stderr)
12
+ @command = command.dup.freeze
13
+ @raw_status = status
14
+ @environment = @raw_status["environment"] || {}
15
+ @successful = (exit_status == 0)
16
+ @stdout = stdout.freeze
17
+ @stderr = stderr.freeze
18
+ end
19
+
20
+ # Returns the hash of the environment.
21
+ def env
22
+ @environment
23
+ end
24
+
25
+ # Whether or not the command had a successful exit status.
26
+ def successful?
27
+ @successful
28
+ end
29
+
30
+ # Returns a value from the outputs environment.
31
+ def [](key)
32
+ env[key.to_s]
33
+ end
34
+
35
+ # Returns the exit status for the program
36
+ def exit_status
37
+ @exit_status ||= (Integer(@raw_status["exit_status"]) rescue 1)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ # Prints an epilog to a shell command.
2
+ __rvm_show_command_epilog() {
3
+ local last_command_result="$?"
4
+ echo "---------------RVM-RESULTS-START---------------"
5
+ echo "---"
6
+ echo " exit_status: \"$last_command_result\""
7
+ echo " environment:"
8
+ env | sed "s#'#\\'#" | sed -e 's#"#\\"#' -e "s#\\([^=]*\\)=\\(.*\\)# '\1': \"\2\"#"
9
+ echo "----------------RVM-RESULTS-END----------------"
10
+ }
@@ -0,0 +1,56 @@
1
+ require 'open3'
2
+
3
+ module RVM
4
+ module Shell
5
+ # Implementation of the abstract wrapper class that opens a new
6
+ # instance of bash when a command is run, only keeping it around
7
+ # for the lifetime of the command. Possibly inefficient but for
8
+ # the moment simplest and hence default implementation.
9
+ class SingleShotWrapper < AbstractWrapper
10
+
11
+ attr_accessor :current
12
+
13
+ # Runs a given command in the current shell.
14
+ # Defaults the command to true if empty.
15
+ def run_command(command)
16
+ command = "true" if command.to_s.strip.empty?
17
+ with_shell_instance do
18
+ stdin.puts wrapped_command(command)
19
+ stdin.close
20
+ out, err = stdout.read, stderr.read
21
+ out, status, _ = raw_stdout_to_parts(out)
22
+ return status, out, err
23
+ end
24
+ end
25
+
26
+ # Runs a command, ensuring no output is collected.
27
+ def run_command_silently(command)
28
+ with_shell_instance do
29
+ stdin.puts silent_command(command)
30
+ end
31
+ end
32
+
33
+ protected
34
+
35
+ # yields stdio, stderr and stdin for a shell instance.
36
+ # If there isn't a current shell instance, it will create a new one.
37
+ # In said scenario, it will also cleanup once it is done.
38
+ def with_shell_instance(&blk)
39
+ no_current = @current.nil?
40
+ if no_current
41
+ @current = Open3.popen3(self.shell_executable)
42
+ invoke_setup!
43
+ end
44
+ yield
45
+ ensure
46
+ @current = nil if no_current
47
+ end
48
+
49
+ # Direct access to each of the named descriptors
50
+ def stdin; @current[0]; end
51
+ def stdout; @current[1]; end
52
+ def stderr; @current[2]; end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,37 @@
1
+ module RVM
2
+ module Shell
3
+ module Utility
4
+
5
+ public
6
+
7
+ # Takes an array / number of arguments and converts
8
+ # them to a string useable for passing into a shell call.
9
+ def escape_arguments(*args)
10
+ return '' if args.nil?
11
+ args.flatten.map { |a| escape_argument(a.to_s) }.join(" ")
12
+ end
13
+
14
+ # Given a string, converts to the escaped format. This ensures
15
+ # that things such as variables aren't evaluated into strings
16
+ # and everything else is setup as expected.
17
+ def escape_argument(s)
18
+ return "''" if s.empty?
19
+ s.scan(/('+|[^']+)/).map do |section|
20
+ section = section.first
21
+ if section[0] == ?'
22
+ "\\'" * section.length
23
+ else
24
+ "'#{section}'"
25
+ end
26
+ end.join
27
+ end
28
+
29
+ # From a command, will build up a runnable command. If args isn't provided,
30
+ # it will escape arguments.
31
+ def build_cli_call(command, args = nil)
32
+ "#{command} #{escape_arguments(args)}".strip
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -1,15 +1,19 @@
1
+ require 'yaml'
2
+
1
3
  module RVM
2
4
  module Version
3
5
 
4
- require "yaml"
5
-
6
- YAML = YAML.load_file("#{File.expand_path(File.dirname(__FILE__))}/../VERSION.yml")
7
-
8
- MAJOR = YAML[:major]
9
- MINOR = YAML[:minor]
10
- PATCH = YAML[:patch]
6
+ # YAML of raw version info
7
+ VERSION_YAML = YAML.load_file(File.expand_path("../VERSION.yml", File.dirname(__FILE__)))
11
8
 
12
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
+ # Current major version of rvm
10
+ MAJOR = VERSION_YAML[:major]
11
+ # Current minor version of rvm
12
+ MINOR = VERSION_YAML[:minor]
13
+ # Current patch level of rvm
14
+ PATCH = VERSION_YAML[:patch]
15
+ # A String with the current rvm version
16
+ STRING = [MAJOR, MINOR, PATCH].join(".").freeze
13
17
 
14
18
  end
15
19
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rvm}
8
- s.version = "0.1.41"
8
+ s.version = "0.1.42"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wayne E. Seguin"]
12
- s.date = %q{2010-07-08}
12
+ s.date = %q{2010-07-20}
13
13
  s.default_executable = %q{rvm-install}
14
14
  s.description = %q{Manages Ruby interpreter environments and switching between them.}
15
15
  s.email = %q{wayneeseguin@gmail.com}
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  "README",
23
23
  "binscripts/rvm",
24
24
  "binscripts/rvm-prompt",
25
+ "binscripts/rvm-shell",
25
26
  "binscripts/rvm-update-head",
26
27
  "binscripts/rvm-update-latest",
27
28
  "binscripts/rvmsudo",
@@ -29,6 +30,7 @@ Gem::Specification.new do |s|
29
30
  "config/known",
30
31
  "config/md5",
31
32
  "contrib/gemset_snapshot",
33
+ "contrib/install-system-wide",
32
34
  "examples/rvmrc",
33
35
  "gemsets/default.gems",
34
36
  "gemsets/global.gems",
@@ -61,9 +63,27 @@ Gem::Specification.new do |s|
61
63
  "install",
62
64
  "lib/VERSION.yml",
63
65
  "lib/rvm.rb",
64
- "lib/rvm/open4.rb",
65
- "lib/rvm/rvm.rb",
66
+ "lib/rvm/capistrano.rb",
67
+ "lib/rvm/environment.rb",
68
+ "lib/rvm/environment/alias.rb",
69
+ "lib/rvm/environment/cleanup.rb",
70
+ "lib/rvm/environment/configuration.rb",
71
+ "lib/rvm/environment/env.rb",
72
+ "lib/rvm/environment/gemset.rb",
73
+ "lib/rvm/environment/info.rb",
74
+ "lib/rvm/environment/list.rb",
75
+ "lib/rvm/environment/rubies.rb",
76
+ "lib/rvm/environment/sets.rb",
77
+ "lib/rvm/environment/tools.rb",
78
+ "lib/rvm/environment/utility.rb",
79
+ "lib/rvm/environment/wrapper.rb",
80
+ "lib/rvm/errors.rb",
66
81
  "lib/rvm/shell.rb",
82
+ "lib/rvm/shell/abstract_wrapper.rb",
83
+ "lib/rvm/shell/result.rb",
84
+ "lib/rvm/shell/shell_wrapper.sh",
85
+ "lib/rvm/shell/single_shot_wrapper.rb",
86
+ "lib/rvm/shell/utility.rb",
67
87
  "lib/rvm/version.rb",
68
88
  "rvm.gemspec",
69
89
  "scripts/alias",
@@ -76,6 +96,7 @@ Gem::Specification.new do |s|
76
96
  "scripts/color",
77
97
  "scripts/completion",
78
98
  "scripts/db",
99
+ "scripts/disk-usage",
79
100
  "scripts/docs",
80
101
  "scripts/env",
81
102
  "scripts/fetch",
@@ -91,6 +112,7 @@ Gem::Specification.new do |s|
91
112
  "scripts/list",
92
113
  "scripts/log",
93
114
  "scripts/maglev",
115
+ "scripts/man",
94
116
  "scripts/manage",
95
117
  "scripts/manpages",
96
118
  "scripts/match",
@@ -105,6 +127,7 @@ Gem::Specification.new do |s|
105
127
  "scripts/rvm-install",
106
128
  "scripts/selector",
107
129
  "scripts/set",
130
+ "scripts/tools",
108
131
  "scripts/update",
109
132
  "scripts/utility",
110
133
  "scripts/version",