Permalink
Browse files

Adds support for ENV['HOME'] by setting the HOME environment variable…

… on startup. I have confirmed that MRI does actually set the process environment variable (and not just some value on a Ruby object)

Modifies the algorithm to calculate the value to set for HOME so that it passes the new tests
KernelOps.GetShell had to be modified to be able to span processes even after doing ENV.clear (like MRI)
Removes logic to calculate HOME from dev.bat
  • Loading branch information...
1 parent 53c0953 commit 0696a772f7f9708a15f18a5966125943cafb2010 Shri Borde committed Jul 21, 2009
View
2 ...LCA_RESTRICTED/Languages/IronRuby/mspec/ironruby-tags/core/env/element_reference_tags.txt
@@ -0,0 +1,2 @@
+fails:ENV.[] does not set HOME if none of %HOMEDRIVE%, %HOMEPATH% or %USERPROFILE% are set
+fails:ENV.[] sets HOME to %HOMEPATH% if %HOME% is not set
View
66 ...ernal.LCA_RESTRICTED/Languages/IronRuby/mspec/rubyspec/core/env/element_reference_spec.rb
@@ -1,4 +1,5 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/fixtures/classes'
describe "ENV.[]" do
before :each do
@@ -15,4 +16,69 @@
it "returns nil if the variable isn't found" do
ENV["this_var_is_never_set"].should == nil
end
+
+ platform_is :windows do
+ it "does not expand %HOME% if it is already set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOME'] = 'x:\Dummy\..\User\Jane Doe'
+ ruby_exe("puts ENV['HOME']").chomp.should == 'x:\Dummy\..\User\Jane Doe'
+ end
+ end
+
+ it "sets HOME to %HOMEDRIVE%/%HOMEPATH% if %HOME% is not set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOMEDRIVE'] = 'x:'
+ ENV['HOMEPATH'] = '\User\Jane Doe'
+ ENV['USERPROFILE'] = 'y:\User\John Doe'
+ ruby_exe("puts ENV['HOME']").chomp.should == 'x:/User/Jane Doe'
+ end
+ end
+
+ it "sets HOME to %HOMEDRIVE% if %HOME% is not set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOMEDRIVE'] = 'x:'
+ ENV['USERPROFILE'] = 'y:\User\John Doe'
+ ruby_exe("puts ENV['HOME']").chomp.should == "x:/"
+ end
+ end
+
+ it "sets HOME to %HOMEPATH% if %HOME% is not set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOMEPATH'] = '\User\Jane Doe'
+ ENV['USERPROFILE'] = 'y:\User\John Doe'
+ ruby_exe("puts ENV['HOME']").chomp.should == "/User/Jane Doe"
+ end
+ end
+
+ it "sets HOME to %USERPROFILE% if %HOMEDRIVE% or %HOMEPATH% are not set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['USERPROFILE'] = 'y:\User\John Doe'
+ ruby_exe("puts ENV['HOME']").chomp.should == "y:/User/John Doe"
+ end
+ end
+
+ ruby_version_is "" ... "1.9" do
+ it "does not set HOME if none of %HOMEDRIVE%, %HOMEPATH% or %USERPROFILE% are set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOME'] = nil
+ ENV['HOMEDRIVE'] = nil
+ ENV['HOMEPATH'] = nil
+ ENV['USERPROFILE'] = nil
+ ruby_exe("puts puts ENV['HOME'], ENV['HOME'].nil?").chomp.should =~ /^true$/
+ end
+ end
+ end
+
+ ruby_version_is "1.9" do
+ it "does set HOME if none of %HOMEDRIVE%, %HOMEPATH% or %USERPROFILE% are set" do
+ EnvSpecs.with_temp_ENV do
+ ENV['HOME'] = nil
+ ENV['HOMEDRIVE'] = nil
+ ENV['HOMEPATH'] = nil
+ ENV['USERPROFILE'] = nil
+ ruby_exe("puts puts ENV['HOME'], ENV['HOME'].nil?").chomp.should =~ /^false$/
+ end
+ end
+ end
+ end
end
View
12 ...in/External.LCA_RESTRICTED/Languages/IronRuby/mspec/rubyspec/core/env/fixtures/classes.rb
@@ -0,0 +1,12 @@
+module EnvSpecs
+ def self.with_temp_ENV()
+ orig = ENV.to_hash
+ comspec = ENV['COMSPEC']
+ begin
+ ENV.clear
+ yield
+ ensure
+ ENV.replace orig
+ end
+ end
+end
View
2 Merlin/Main/Languages/Ruby/ClassInitGenerator/Libraries/LibraryDef.cs
@@ -850,6 +850,8 @@ private class ConstantDef {
// primitives:
if (Builtins) {
+ _output.WriteLine("EnvironmentSingletonOps.Initialize(Context);");
+
_output.WriteLine("Context.RegisterPrimitives(");
_output.Indent++;
View
14 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/EnvironmentSingletonOps.cs
@@ -29,6 +29,20 @@ namespace IronRuby.Builtins {
[RubySingleton, Includes(typeof(Enumerable))]
public static class EnvironmentSingletonOps {
+ internal static void Initialize(RubyContext/*!*/ context) {
+#if !SILVERLIGHT // SetEnvironmentVariable
+ try {
+ string homeDir = RubyFileOps.GetHomeDirectory(context);
+ context.DomainManager.Platform.SetEnvironmentVariable("HOME", homeDir);
+ } catch (System.Security.SecurityException e) {
+ // Ignore EnvironmentPermission exception
+ if (e.PermissionType != typeof(System.Security.Permissions.EnvironmentPermission)) {
+ throw;
+ }
+ }
+#endif
+ }
+
#region Public Instance Methods
[RubyMethod("[]", RubyMethodAttributes.PublicInstance)]
View
43 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/FileOps.cs
@@ -497,27 +497,34 @@ public static class Constants {
PlatformAdaptationLayer pal = context.DomainManager.Platform;
string result = pal.GetEnvironmentVariable("HOME");
- if (result == null) {
- string homeDrive = pal.GetEnvironmentVariable("HOMEDRIVE");
- string homePath = pal.GetEnvironmentVariable("HOMEPATH");
- if (homeDrive == null && homePath == null) {
- string userEnvironment = pal.GetEnvironmentVariable("USERPROFILE");
- if (userEnvironment == null) {
- // This will always succeed with a non-null string, but it can fail
- // if the Personal folder was renamed or deleted. In this case it returns
- // an empty string.
- result = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
- } else {
- result = userEnvironment;
- }
- } else if (homeDrive == null) {
- result = homePath;
- } else if (homePath == null) {
- result = homeDrive;
+ if (result != null) {
+ return result;
+ }
+
+ string homeDrive = pal.GetEnvironmentVariable("HOMEDRIVE");
+ string homePath = pal.GetEnvironmentVariable("HOMEPATH");
+ if (homeDrive == null && homePath == null) {
+ string userEnvironment = pal.GetEnvironmentVariable("USERPROFILE");
+ if (userEnvironment == null) {
+ // This will always succeed with a non-null string, but it can fail
+ // if the Personal folder was renamed or deleted. In this case it returns
+ // an empty string.
+ result = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
} else {
- result = Path.Combine(homeDrive, homePath);
+ result = userEnvironment;
}
+ } else if (homeDrive == null) {
+ result = homePath;
+ } else if (homePath == null) {
+ result = homeDrive + Path.DirectorySeparatorChar;
+ } else {
+ result = homeDrive + homePath;
}
+
+ if (result != null) {
+ result = ExpandPath(context, null, MutableString.Create(result)).ConvertToString();
+ }
+
return result;
}
View
9 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs
@@ -134,14 +134,19 @@ public static class KernelOps {
#if !SILVERLIGHT
// Looks for RUBYSHELL and then COMSPEC under Windows
- // It appears that COMSPEC is a special environment variable that cannot be undefined
internal static ProcessStartInfo/*!*/ GetShell(RubyContext/*!*/ context, MutableString/*!*/ command) {
PlatformAdaptationLayer pal = context.DomainManager.Platform;
string shell = pal.GetEnvironmentVariable("RUBYSHELL");
if (shell == null) {
shell = pal.GetEnvironmentVariable("COMSPEC");
}
- return new ProcessStartInfo(shell, String.Format("/C \"{0}\"", command.ConvertToString()));
+
+ if (shell == null) {
+ string [] commandParts = command.ConvertToString().Split(new char[] { ' ' }, 2);
+ return new ProcessStartInfo(commandParts[0], commandParts.Length == 2 ? commandParts[1] : null);
+ } else {
+ return new ProcessStartInfo(shell, String.Format("/C \"{0}\"", command.ConvertToString()));
+ }
}
private static MutableString/*!*/ JoinArguments(MutableString/*!*/[]/*!*/ args) {
View
9 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs
@@ -31,6 +31,7 @@
namespace IronRuby.Builtins {
public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitializer {
protected override void LoadModules() {
+ EnvironmentSingletonOps.Initialize(Context);
Context.RegisterPrimitives(
Load__ClassSingleton_Instance,
Load__ClassSingletonSingleton_Instance,
@@ -2944,8 +2945,8 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
#if !SILVERLIGHT
module.DefineLibraryMethod("trap", 0x52,
- new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
- new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap)
+ new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap),
+ new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap)
);
#endif
@@ -3179,8 +3180,8 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
#if !SILVERLIGHT
module.DefineLibraryMethod("trap", 0x61,
- new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
- new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap)
+ new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap),
+ new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap)
);
#endif
View
2 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/StringIO/StringIO.cs
@@ -107,7 +107,7 @@ public StringIO(RubyContext/*!*/ context, MutableStringStream/*!*/ stream, strin
return;
}
- self.Data.String.SetByte((int)(offset - 1), (byte)ch);
+ self.Data.String.SetByte((int)(offset - 1), unchecked((byte)ch));
self.Data.Seek(-1, System.IO.SeekOrigin.Current);
}
View
14 Merlin/Main/Languages/Ruby/Scripts/Dev.bat
@@ -42,20 +42,6 @@ if exist "%PROGRAM_FILES_32%\Microsoft.NET\SDK\v2.0\Bin\sdkvars.bat" (
set PATH=%PATH%;%MERLIN_ROOT%\Languages\Ruby\Scripts;%MERLIN_ROOT%\Languages\Ruby\Scripts\bin;%RUBY18_BIN%;%MERLIN_ROOT%\..\External.LCA_RESTRICTED\Languages\IronRuby\mspec\mspec\bin
-if not DEFINED HOME (
- if DEFINED HOMEDRIVE (
- if DEFINED HOMEPATH (
- set HOME=%HOMEDRIVE%\%HOMEPATH%
- goto SetRubyEnv
- )
- )
- if not DEFINED USERPROFILE (
- echo Error: One of HOME, HOMEDRIVE,HOMEPATH, or USERPROFILE needs to be set
- goto END
- )
- set HOME=%USERPROFILE%
-)
-
:SetRubyEnv
if NOT exist "%HOME%\.mspecrc" (

0 comments on commit 0696a77

Please sign in to comment.