aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fileutils.rb
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-01 16:16:05 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-01 16:16:05 +0000
commit0a1e7d1568584f22f743347c5e3b64dbf705dd83 (patch)
treeca5212186edf7edf56bde3e4f8540979061f220a /lib/fileutils.rb
parent0468df6249fa9ec94217f87f4213a8e1032c67f5 (diff)
downloadruby-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
Diffstat (limited to 'lib/fileutils.rb')
-rw-r--r--lib/fileutils.rb92
1 files changed, 90 insertions, 2 deletions
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