<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,2 +1,4 @@
 fails:Kernel#open opens an io when path starts with a pipe
 fails:Kernel#open opens an io when called with a block
+fails:Kernel#open sets the file as writable if perm is nil
+fails:Kernel#open allows nil for perm</diff>
      <filename>Merlin/External.LCA_RESTRICTED/Languages/IronRuby/mspec/ironruby-tags/core/kernel/open_tags.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,28 +8,43 @@ describe &quot;Kernel#open&quot; do
   
   before :each do
     @file = &quot;test.txt&quot;
+    @newfile = &quot;test.new&quot;
+    @fh = nil
     File.open(@file, &quot;w&quot;){ |f| f.puts &quot;This is a test&quot; }
   end
   
   after :each do
-    File.delete(@file) 
+    @fh.close if @fh and not @fh.closed?
+    File.delete(@file)
+    File.delete(@newfile) if File.exist? @newfile
   end
   
   it &quot;opens a file when given a valid filename&quot; do
-    @output = open(&quot;test.txt&quot;)
-    @output.class.should == File
-    @output.close
+    @fh = open(@file)
+    @fh.class.should == File
   end
   
   it &quot;opens a file when called with a block&quot; do
-    @output = open(&quot;test.txt&quot;, &quot;r&quot;) { |f| f.gets }
-    @output.should == &quot;This is a test\n&quot;
+    open(@file, &quot;r&quot;) { |f| f.gets }.should == &quot;This is a test\n&quot;
   end
   
-  it &quot;opens a file to write with permission&quot; do
-	open(&quot;test.txt&quot;, &quot;w&quot;, 0644){ |f| f.puts &quot;This is a test2&quot; }
-	File.readable?(@file).should == true
-    File.writable?(@file).should == true
+  it &quot;sets a default permission of writable&quot; do
+    File.writable?(@file).should be_true  
+  end
+  
+  it &quot;sets permissions of newly created file&quot; do
+	open(@newfile, &quot;w&quot;, 0444){ }
+    File.writable?(@newfile).should be_false
+  end
+  
+  it &quot;sets the file as writable if perm is nil&quot; do
+	open(@newfile, &quot;w&quot;, nil){ }
+    File.writable?(@newfile).should be_true
+  end
+  
+  it &quot;ignores perm for existing file&quot; do
+    open(@file, &quot;r&quot;, 0444) { }
+    File.writable?(@file).should be_true  
   end
   
   platform_is_not :windows do
@@ -40,8 +55,7 @@ describe &quot;Kernel#open&quot; do
     end
     
     it &quot;opens an io when called with a block&quot; do
-      @output = open(&quot;|date&quot;) { |f| f.gets }
-      @output.should_not == ''
+      open(&quot;|date&quot;) { |f| f.gets }.should_not == ''
     end
   
   end
@@ -54,21 +68,49 @@ describe &quot;Kernel#open&quot; do
     end
     
     it &quot;opens an io when called with a block&quot; do
-      @output = open(&quot;|date /t&quot;) { |f| f.gets }
-      @output.should_not == ''
+      open(&quot;|date /t&quot;) { |f| f.gets }.should_not == ''
     end
   
   end
     
-  
+  it &quot;returns block return value&quot; do
+    open(@file) { :end_of_block }.should == :end_of_block
+  end
+    
   it &quot;raises an ArgumentError if not passed one argument&quot; do
     lambda { open }.should raise_error(ArgumentError)
   end
   
-  it &quot;raises a TypeError if not passed a String type&quot; do
-    lambda { open(nil)       }.should raise_error(TypeError)
-    lambda { open(7)         }.should raise_error(TypeError)
-    lambda { open(mock('x')) }.should raise_error(TypeError)
+  it &quot;raises a TypeError if passed nil for path&quot; do
+    lambda { open(nil) }.should raise_error(TypeError)
+  end
+  
+  it &quot;accepts String-like objects for path&quot; do
+    file = mock('filename')
+    file.should_receive(:to_str).and_return(@file)
+    open(file) { :in_block }.should == :in_block
+  end
+  
+  it &quot;allows nil for mode&quot; do
+    open(@file, nil) { |f| lambda { f &lt;&lt; &quot;some output&quot; }.should raise_error(IOError) }
+  end
+  
+  it &quot;allows String-like objects for mode&quot; do
+    mode = mock('mode')
+    mode.should_receive(:to_str).and_return(&quot;r&quot;)
+    open(@file, mode) { :in_block }.should == :in_block
+  end
+  
+  it &quot;allows nil for perm&quot; do
+    open(@newfile, &quot;w&quot;, nil) { }
+    File.writable?(@file).should be_true
+  end
+  
+  it &quot;allows Integer-like objects for perm&quot; do
+    perm = mock('perm')
+    perm.should_receive(:to_int).and_return(0444)
+    open(@newfile, &quot;w&quot;, perm) { }
+    File.writable?(@newfile).should be_false
   end
 end
 </diff>
      <filename>Merlin/External.LCA_RESTRICTED/Languages/IronRuby/mspec/rubyspec/core/kernel/open_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -150,6 +150,9 @@ namespace IronRuby.Builtins {
 
         #endregion
 
+        internal const int WriteModeMask = 0x80; // Oct 0200
+        internal const int ReadWriteMode = 0x1B6; // Oct 0666
+
         #region Public Singleton Methods
 
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PublicSingleton)]
@@ -240,7 +243,7 @@ namespace IronRuby.Builtins {
         internal static void Chmod(string path, int permission) {
 #if !SILVERLIGHT
             FileAttributes oldAttributes = File.GetAttributes(path);
-            if ((permission &amp; 0x80) == 0) {
+            if ((permission &amp; WriteModeMask) == 0) {
                 File.SetAttributes(path, oldAttributes | FileAttributes.ReadOnly);
             } else {
                 File.SetAttributes(path, oldAttributes &amp; ~FileAttributes.ReadOnly);
@@ -267,7 +270,7 @@ namespace IronRuby.Builtins {
             return RubyStatOps.CreateTime(RubyStatOps.Create(self.Context, path));
         }
 
-        private static bool FileExists(RubyContext/*!*/ context, string/*!*/ path) {
+        internal static bool FileExists(RubyContext/*!*/ context, string/*!*/ path) {
             return context.DomainManager.Platform.FileExists(path);
         }
 </diff>
      <filename>Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/FileOps.cs</filename>
    </modified>
    <modified>
      <diff>@@ -466,24 +466,38 @@ namespace IronRuby.Builtins {
 
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PrivateInstance)]
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PublicSingleton)]
-        public static RubyIO/*!*/ Open(RubyContext/*!*/ context, object self,
-            [DefaultProtocol, NotNull]MutableString/*!*/ path, [DefaultProtocol, Optional]MutableString mode, [DefaultProtocol, Optional]int permission) {
+        public static RubyIO/*!*/ Open(
+            RubyContext/*!*/ context, 
+            object self,
+            [DefaultProtocol, NotNull]MutableString/*!*/ path, 
+            [DefaultProtocol, Optional]MutableString mode, 
+            [DefaultProtocol, DefaultParameterValue(RubyFileOps.ReadWriteMode)]int permission) {
 
             string fileName = path.ConvertToString();
             if (fileName.Length &gt; 0 &amp;&amp; fileName[0] == '|') {
                 throw new NotImplementedError();
             }
+
+            bool existingFile = RubyFileOps.FileExists(context, path.ConvertToString());
+
             RubyIO file = new RubyFile(context, fileName, (mode != null) ? mode.ToString() : &quot;r&quot;);
-            if (permission &gt; 0) {
+
+            if (!existingFile) {
                 RubyFileOps.Chmod(fileName, permission);
             }
+
             return file;
         }
 
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PrivateInstance)]
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PublicSingleton)]
-        public static object Open(RubyContext/*!*/ context, [NotNull]BlockParam/*!*/ block, object self,
-            [DefaultProtocol, NotNull]MutableString/*!*/ path, [DefaultProtocol, Optional]MutableString mode, [DefaultProtocol, Optional]int permission) {
+        public static object Open(
+            RubyContext/*!*/ context, 
+            [NotNull]BlockParam/*!*/ block, 
+            object self,
+            [DefaultProtocol, NotNull]MutableString/*!*/ path, 
+            [DefaultProtocol, Optional]MutableString mode, 
+            [DefaultProtocol, DefaultParameterValue(RubyFileOps.ReadWriteMode)]int permission) {
 
             RubyIO file = Open(context, self, path, mode, permission);
             return OpenWithBlock(block, file);
@@ -491,15 +505,23 @@ namespace IronRuby.Builtins {
 
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PrivateInstance)]
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PublicSingleton)]
-        public static RubyIO/*!*/ Open(RubyContext/*!*/ context, object self,
-            [DefaultProtocol, NotNull]MutableString/*!*/ path, int mode, [DefaultProtocol, Optional]int permission) {
+        public static RubyIO/*!*/ Open(
+            RubyContext/*!*/ context, 
+            object self,
+            [DefaultProtocol, NotNull]MutableString/*!*/ path, 
+            int mode,
+            [DefaultProtocol, DefaultParameterValue(RubyFileOps.ReadWriteMode)]int permission) {
 
             string fileName = path.ConvertToString();
             if (fileName.Length &gt; 0 &amp;&amp; fileName[0] == '|') {
                 throw new NotImplementedError();
             }
+
+            bool existingFile = RubyFileOps.FileExists(context, path.ConvertToString());
+
             RubyIO file = new RubyFile(context, fileName, (RubyFileMode)mode);
-            if (permission &gt; 0) {
+
+            if (!existingFile) {
                 RubyFileOps.Chmod(fileName, permission);
             }
             return file;
@@ -507,8 +529,13 @@ namespace IronRuby.Builtins {
 
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PrivateInstance)]
         [RubyMethod(&quot;open&quot;, RubyMethodAttributes.PublicSingleton)]
-        public static object Open(RubyContext/*!*/ context, [NotNull]BlockParam/*!*/ block, object self,
-            [DefaultProtocol, NotNull]MutableString/*!*/ path, int mode, [DefaultProtocol, Optional]int permission) {
+        public static object Open(
+            RubyContext/*!*/ context, 
+            [NotNull]BlockParam/*!*/ block, 
+            object self,
+            [DefaultProtocol, NotNull]MutableString/*!*/ path, 
+            int mode,
+            [DefaultProtocol, DefaultParameterValue(RubyFileOps.ReadWriteMode)]int permission) {
 
             RubyIO file = Open(context, self, path, mode, permission);
             return OpenWithBlock(block, file);</diff>
      <filename>Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs</filename>
    </modified>
    <modified>
      <diff>@@ -87,7 +87,7 @@ namespace IronRuby.Runtime.Calls {
                 return factory.Conversion&lt;ConvertToStrAction&gt;();
             }
 
-            // TODO: nullable int (see Array#fill, Sockets:ConvertToSocketFlag)
+            // TODO: nullable int (see Array#fill, Sockets:ConvertToSocketFlag, Kernel#open(perm=nil))
             if (parameterType == typeof(int)) {
                 return factory.Conversion&lt;ConvertToFixnumAction&gt;();
             }</diff>
      <filename>Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ProtocolConversionAction.cs</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b2bda3cb06176b89cb2a36938f7522f813877c59</id>
    </parent>
  </parents>
  <author>
    <name>Shri Borde</name>
    <email>sborde@microsoft.com</email>
  </author>
  <url>http://github.com/shri/ironruby/commit/5e8c6b232a3c952985adbf1b9cda5c456d503cea</url>
  <id>5e8c6b232a3c952985adbf1b9cda5c456d503cea</id>
  <committed-date>2009-04-10T15:39:36-07:00</committed-date>
  <authored-date>2009-04-10T15:39:36-07:00</authored-date>
  <message>Fixes on top of Jirapong's fix for Kernel.open</message>
  <tree>fc462aff498d8efa1ed5050a40f0e55fc9fc418d</tree>
  <committer>
    <name>Shri Borde</name>
    <email>sborde@microsoft.com</email>
  </committer>
</commit>
