lib/file/find.rb in file-find-0.2.3 vs lib/file/find.rb in file-find-0.2.4

- old
+ new

@@ -4,11 +4,11 @@ include Config include Sys class File::Find # The version of this library - VERSION = '0.2.3' + VERSION = '0.2.4' # :stopdoc: VALID_OPTIONS = %w/ atime ctime @@ -86,10 +86,12 @@ # Limits searches to files which have permissions that match the octal # value that you provide. For purposes of this comparison, only the user, # group, and world settings are used. Do not use a leading 0 in the values # that you supply, e.g. use 755 not 0755. # + # You may optionally use symbolic permissions, e.g. "g+rw", "u=rwx", etc. + # # Not currently supported on MS Windows. # attr_accessor :perm # Skips files or directories that match the string provided as an argument. @@ -142,14 +144,14 @@ @perm = nil @prune = nil @size = nil @user = nil - validate_and_set_options(options) unless options.empty? - @previous = nil + validate_and_set_options(options) unless options.empty? + @path ||= Dir.pwd @name ||= '*' end # Executes the find based on the rules you set for the File::Find object. @@ -263,11 +265,15 @@ # This currently doesn't work on MS Windows, even in limited # fashion for 0666 and 0664, because File.stat.mode doesn't # return the proper value. # if @perm - next unless sprintf("%o", stat_info.mode & 07777) == @perm.to_s + if @perm.is_a?(String) + next unless stat_info.mode & sym2oct(@perm) == sym2oct(@perm) + else + next unless sprintf("%o", stat_info.mode & 07777) == @perm.to_s + end end # Allow plain numbers, or strings for comparison operators. if @size if @size.is_a?(String) @@ -322,7 +328,43 @@ unless VALID_OPTIONS.include?(key) raise ArgumentError, "invalid option '#{key}'" end send("#{key}=", value) end + end + + # Converts a symoblic permissions mode into its octal equivalent. + #-- + # Taken almost entirely from ruby-talk: 96956 (Hal Fulton). + # + def sym2oct(str) + left = {'u' => 0700, 'g' => 0070, 'o' => 0007, 'a' => 0777} + right = {'r' => 0444, 'w' => 0222, 'x' => 0111} + regex = /([ugoa]+)([+-=])([rwx]+)/ + + cmds = str.split(',') + + perm = 0 + + cmds.each do |cmd| + match = cmd.match(regex) + raise "Invalid symbolic permissions: '#{str}'" if match.nil? + + junk, who, what, how = match.to_a + + who = who.split(//).inject(num=0) { |num,b| num |= left[b]; num } + how = how.split(//).inject(num=0) { |num,b| num |= right[b]; num } + mask = who & how + + case what + when '+' + perm = perm | mask + when '-' + perm = perm & ~mask + when '=' + perm = mask + end + end + + perm end end