[前][次][番号順一覧][スレッド一覧]

ruby-changes:19367

From: kosaki <ko1@a...>
Date: Mon, 2 May 2011 01:16:12 +0900 (JST)
Subject: [ruby-changes:19367] Ruby:r31407 (trunk): * lib/fileutils.rb (FileUtils#chmod): accept symbolic mode argument.

kosaki	2011-05-02 01:16:05 +0900 (Mon, 02 May 2011)

  New Revision: 31407

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31407

  Log:
    * lib/fileutils.rb (FileUtils#chmod): accept symbolic mode argument.
      The patch was written by takkanm. [ruby-core:26029][Feature #2190]
    
    * lib/fileutils.rb (FileUtils#fu_mode): new helper function.
    * lib/fileutils.rb (FileUtils#symbolic_modes_to_i): ditto.
    * lib/fileutils.rb (FileUtils#mode_mask): ditto.
    * lib/fileutils.rb (FileUtils#user_mask): ditto.
    
    * test/fileutils/test_fileutils.rb (TestFileUtils#test_chmod_symbol_mode):
      new test for the above symbolic mode.
    * test/fileutils/test_fileutils.rb (TestFileUtils#test_chmod_R): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/lib/fileutils.rb
    trunk/test/fileutils/test_fileutils.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31406)
+++ ChangeLog	(revision 31407)
@@ -1,3 +1,17 @@
+Mon May  2 01:02:04 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* lib/fileutils.rb (FileUtils#chmod): accept symbolic mode argument.
+	  The patch was written by takkanm. [ruby-core:26029][Feature #2190]
+
+	* lib/fileutils.rb (FileUtils#fu_mode): new helper function.
+	* lib/fileutils.rb (FileUtils#symbolic_modes_to_i): ditto.
+	* lib/fileutils.rb (FileUtils#mode_mask): ditto.
+	* lib/fileutils.rb (FileUtils#user_mask): ditto.
+
+	* test/fileutils/test_fileutils.rb (TestFileUtils#test_chmod_symbol_mode):
+	  new test for the above symbolic mode.
+	* test/fileutils/test_fileutils.rb (TestFileUtils#test_chmod_R): ditto.
+
 Mon May  2 00:36:12 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* ext/socket/init.c (rsock_connect): add to care EINTR. based
Index: lib/fileutils.rb
===================================================================
--- lib/fileutils.rb	(revision 31406)
+++ lib/fileutils.rb	(revision 31407)
@@ -860,23 +860,110 @@
 
   OPT_TABLE['install'] = [:mode, :preserve, :noop, :verbose]
 
+  def user_mask(target)
+    mask = 0
+    target.each_byte do |byte_chr|
+      case byte_chr.chr
+        when "u"
+          mask |= 04700
+        when "g"
+          mask |= 02070
+        when "o"
+          mask |= 01007
+        when "a"
+          mask |= 07777
+      end
+    end
+    mask
+  end
+  private_module_function :user_mask
+
+  def mode_mask(mode, path)
+    mask = 0
+    mode.each_byte do |byte_chr|
+      case byte_chr.chr
+        when "r"
+          mask |= 0444
+        when "w"
+          mask |= 0222
+        when "x"
+          mask |= 0111
+        when "X"
+          mask |= 0111 if FileTest::directory? path
+        when "s"
+          mask |= 06000
+        when "t"
+          mask |= 01000
+      end
+    end
+    mask
+  end
+  private_module_function :mode_mask
+
+  def symbolic_modes_to_i(modes, path)
+    current_mode = (File.stat(path).mode & 07777)
+    modes.split(/,/).inject(0) do |mode, mode_sym|
+      mode_sym = "a#{mode_sym}" if mode_sym =~ %r!^[+-=]!
+      target, mode = mode_sym.split %r![+-=]!
+      user_mask = user_mask(target)
+      mode_mask = mode_mask(mode ? mode : "", path)
+
+      case mode_sym
+        when /=/
+          current_mode &= ~(user_mask)
+          current_mode |= user_mask & mode_mask
+        when /\+/
+          current_mode |= user_mask & mode_mask
+        when /-/
+          current_mode &= ~(user_mask & mode_mask)
+      end
+    end
+  end
+  private_module_function :symbolic_modes_to_i
+
+  def fu_mode(mode, path)
+    mode.is_a?(String) ? symbolic_modes_to_i(mode, path) : mode
+  end
+  private_module_function :fu_mode
+
   #
   # Options: noop verbose
   #
   # Changes permission bits on the named files (in +list+) to the bit pattern
   # represented by +mode+.
   #
+  # +mode+ is the symbolic and absolute mode can be used.
+  #
+  # Absolute mode is
   #   FileUtils.chmod 0755, 'somecommand'
   #   FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
   #   FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true
   #
+  # Symbolic mode is
+  #   FileUtils.chmod "u=wrx,go=rx", 'somecommand'
+  #   FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
+  #   FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', :verbose => true
+  #
+  #   "a" is user, group, other mask.
+  #   "u" is user's mask.
+  #   "g" is group's mask.
+  #   "o" is other's mask.
+  #   "w" is write permission.
+  #   "r" is read permission.
+  #   "x" is execute permission.
+  #   "s" is uid, gid.
+  #   "t" is sticky bit.
+  #   "+" is added to a class given the specified mode.
+  #   "-" Is removed from a given class given mode.
+  #   "=" Is the exact nature of the class will be given a specified mode.
+
   def chmod(mode, list, options = {})
     fu_check_options options, OPT_TABLE['chmod']
     list = fu_list(list)
     fu_output_message sprintf('chmod %o %s', mode, list.join(' ')) if options[:verbose]
     return if options[:noop]
     list.each do |path|
-      Entry_.new(path).chmod mode
+      Entry_.new(path).chmod(fu_mode(mode, path))
     end
   end
   module_function :chmod
@@ -890,6 +977,7 @@
   # to the bit pattern represented by +mode+.
   #
   #   FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
+  #   FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
   #
   def chmod_R(mode, list, options = {})
     fu_check_options options, OPT_TABLE['chmod_R']
@@ -901,7 +989,7 @@
     list.each do |root|
       Entry_.new(root).traverse do |ent|
         begin
-          ent.chmod mode
+          ent.chmod(fu_mode(mode, ent.path))
         rescue
           raise unless options[:force]
         end
Index: NEWS
===================================================================
--- NEWS	(revision 31406)
+++ NEWS	(revision 31407)
@@ -143,6 +143,10 @@
     * Zlib.deflate
     * Zlib.inflate
 
+* FileUtils
+  * extended method:
+    * FileUtils#chmod supports symbolic mode argument.
+
 === Language changes
 
 * Regexps now support Unicode 6.0. (new characters and scripts)
Index: test/fileutils/test_fileutils.rb
===================================================================
--- test/fileutils/test_fileutils.rb	(revision 31406)
+++ test/fileutils/test_fileutils.rb	(revision 31407)
@@ -893,6 +893,29 @@
     assert_equal 0500, File.stat('tmp/a').mode & 0777
   end if have_file_perm?
 
+  def test_chmod_symbol_mode
+    check_singleton :chmod
+
+    touch 'tmp/a'
+    chmod "u=wrx,g=,o=", 'tmp/a'
+    assert_equal 0700, File.stat('tmp/a').mode & 0777
+    chmod "u=rx,go=", 'tmp/a'
+    assert_equal 0500, File.stat('tmp/a').mode & 0777
+    chmod "+wrx", 'tmp/a'
+    assert_equal 0777, File.stat('tmp/a').mode & 0777
+    chmod "u+s,o=s", 'tmp/a'
+    assert_equal 04770, File.stat('tmp/a').mode & 07777
+    chmod "u-w,go-wrx", 'tmp/a'
+    assert_equal 04500, File.stat('tmp/a').mode & 07777
+    chmod "+s", 'tmp/a'
+    assert_equal 06500, File.stat('tmp/a').mode & 07777
+    chmod "u+t,o+t", 'tmp/a'
+    assert_equal 07500, File.stat('tmp/a').mode & 07777
+    chmod "a-t,a-s", 'tmp/a'
+    assert_equal 0500, File.stat('tmp/a').mode & 07777
+  end if have_file_perm?
+
+
   def test_chmod_R
     check_singleton :chmod_R
 
@@ -911,6 +934,24 @@
     chmod_R 0700, 'tmp/dir'   # to remove
   end if have_file_perm?
 
+  def test_chmod_symbol_mode_R
+    check_singleton :chmod_R
+
+    mkdir_p 'tmp/dir/dir'
+    touch %w( tmp/dir/file tmp/dir/dir/file )
+    chmod_R "u=wrx,g=,o=", 'tmp/dir'
+    assert_equal 0700, File.stat('tmp/dir').mode & 0777
+    assert_equal 0700, File.stat('tmp/dir/file').mode & 0777
+    assert_equal 0700, File.stat('tmp/dir/dir').mode & 0777
+    assert_equal 0700, File.stat('tmp/dir/dir/file').mode & 0777
+    chmod_R "u=xr,g+X,o=", 'tmp/dir'
+    assert_equal 0510, File.stat('tmp/dir').mode & 0777
+    assert_equal 0500, File.stat('tmp/dir/file').mode & 0777
+    assert_equal 0510, File.stat('tmp/dir/dir').mode & 0777
+    assert_equal 0500, File.stat('tmp/dir/dir/file').mode & 0777
+    chmod_R 0700, 'tmp/dir'   # to remove
+  end if have_file_perm?
+
   # FIXME: How can I test this method?
   def test_chown
     check_singleton :chown

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]