diff options
author | kosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-05-01 16:16:05 +0000 |
---|---|---|
committer | kosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-05-01 16:16:05 +0000 |
commit | 0a1e7d1568584f22f743347c5e3b64dbf705dd83 (patch) | |
tree | ca5212186edf7edf56bde3e4f8540979061f220a | |
parent | 0468df6249fa9ec94217f87f4213a8e1032c67f5 (diff) | |
download | ruby-0a1e7d1568584f22f743347c5e3b64dbf705dd83.tar.gz |
* 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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | lib/fileutils.rb | 92 | ||||
-rw-r--r-- | test/fileutils/test_fileutils.rb | 41 |
4 files changed, 149 insertions, 2 deletions
@@ -1,3 +1,17 @@ +Mon May 2 01:02:04 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com> + + * 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@gmail.com> * ext/socket/init.c (rsock_connect): add to care EINTR. based @@ -143,6 +143,10 @@ with all sufficient information, see the ChangeLog file. * 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) diff --git a/lib/fileutils.rb b/lib/fileutils.rb index dc956a67ab..423257cd15 100644 --- a/lib/fileutils.rb +++ b/lib/fileutils.rb @@ -860,23 +860,110 @@ module FileUtils 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 @@ module FileUtils # 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 @@ module FileUtils 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 diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb index 290ba21f0d..68f363109d 100644 --- a/test/fileutils/test_fileutils.rb +++ b/test/fileutils/test_fileutils.rb @@ -893,6 +893,29 @@ class TestFileUtils 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 @@ class TestFileUtils 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 |