file-find 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. data/CHANGES +11 -2
  2. data/README +1 -1
  3. data/test/test_file_find.rb +55 -39
  4. metadata +8 -10
  5. data/lib/file/find.rb +0 -487
data/CHANGES CHANGED
@@ -1,8 +1,17 @@
1
- == 0.3.2 - 20-Feb-2008
1
+ == 0.3.3 - 3-Aug-2009
2
+ * Now compatible with Ruby 1.9.x.
3
+ * Added support for the :links option
4
+ * Updated the :mount accessor to work properly if the value is changed
5
+ after the File::Find object is initially created.
6
+ * Eliminated some 'shadowed variable' warnings in Ruby 1.9.x.
7
+ * Added a fuller description to the gemspec.
8
+ * Minor test refactoring.
9
+
10
+ == 0.3.2 - 20-Feb-2009
2
11
  * Added support for the :mount option.
3
12
  * Added some basic tests for the :mount option.
4
13
 
5
- == 0.3.1 - 9-Jan-2008
14
+ == 0.3.1 - 9-Jan-2009
6
15
  * Now defaults to using Etc instead of Sys::Admin for implementations
7
16
  that don't support building C extensions, e.g. JRuby.
8
17
  * Updated the test suite to work with JRuby.
data/README CHANGED
@@ -99,7 +99,7 @@ http://www.rubyforge.org/projects/shards.
99
99
  * Hal Fulton for his implementation of symbolic permissions.
100
100
 
101
101
  = License
102
- Ruby's
102
+ Artistic 2.0
103
103
 
104
104
  = Copyright
105
105
  (C) 2007-2009, Daniel J. Berger, All Rights Reserved
@@ -23,7 +23,7 @@ include FileUtils
23
23
 
24
24
  class TC_File_Find < Test::Unit::TestCase
25
25
  def self.startup
26
- Dir.chdir('test') unless File.basename(Dir.pwd) == 'test'
26
+ Dir.chdir(File.dirname(File.expand_path(__FILE__)))
27
27
 
28
28
  @@windows = CONFIG['host_os'] =~ /windows|mswin/i
29
29
  @@jruby = RUBY_PLATFORM.match('java')
@@ -40,35 +40,35 @@ class TC_File_Find < Test::Unit::TestCase
40
40
  end
41
41
 
42
42
  def setup
43
- @file1 = 'test1.rb'
44
- @file2 = 'test1.txt'
45
- @file3 = 'foo.txt'
46
- @file4 = 'foo.doc'
47
- @dir1 = 'dir1'
48
- @dir2 = 'dir2'
49
-
50
- File.open(@file1, 'w'){}
51
- File.open(@file2, 'w'){}
52
- File.open(@file3, 'w'){}
53
- File.open(@file4, 'w'){}
43
+ @file_rb = 'test1.rb'
44
+ @file_txt1 = 'test1.txt'
45
+ @file_txt2 = 'foo.txt'
46
+ @file_doc = 'foo.doc'
47
+ @directory1 = 'dir1'
48
+ @directory2 = 'dir2'
49
+
50
+ File.open(@file_rb, 'w'){}
51
+ File.open(@file_txt1, 'w'){}
52
+ File.open(@file_txt2, 'w'){}
53
+ File.open(@file_doc, 'w'){}
54
54
 
55
55
  unless @@windows
56
56
  @link1 = 'link1'
57
- File.symlink(@file1, @link1)
57
+ File.symlink(@file_rb, @link1)
58
58
  end
59
59
 
60
- Dir.mkdir(@dir1) unless File.exists?(@dir1)
61
- Dir.mkdir(@dir2) unless File.exists?(@dir2)
60
+ Dir.mkdir(@directory1) unless File.exists?(@directory1)
61
+ Dir.mkdir(@directory2) unless File.exists?(@directory2)
62
62
 
63
- File.open(File.join(@dir1, 'bar.txt'), 'w'){}
64
- File.open(File.join(@dir2, 'baz.txt'), 'w'){}
63
+ File.open(File.join(@directory1, 'bar.txt'), 'w'){}
64
+ File.open(File.join(@directory2, 'baz.txt'), 'w'){}
65
65
 
66
66
  @rule1 = File::Find.new(:name => '*.txt')
67
67
  @rule2 = File::Find.new
68
68
  end
69
69
 
70
70
  def test_version
71
- assert_equal('0.3.2', File::Find::VERSION)
71
+ assert_equal('0.3.3', File::Find::VERSION)
72
72
  end
73
73
 
74
74
  def test_path
@@ -137,11 +137,11 @@ class TC_File_Find < Test::Unit::TestCase
137
137
  omit_if(@@windows && @@jruby, "Skipping file test on JRuby/Windows")
138
138
 
139
139
  rule = File::Find.new(:name => "*.doc", :writable? => true)
140
- File.chmod(0644, @file4)
140
+ File.chmod(0644, @file_doc)
141
141
 
142
- assert_equal([@file4], rule.find.map{ |f| File.basename(f) })
142
+ assert_equal([@file_doc], rule.find.map{ |f| File.basename(f) })
143
143
 
144
- File.chmod(0444, @file4)
144
+ File.chmod(0444, @file_doc)
145
145
 
146
146
  assert_equal([], rule.find)
147
147
  end
@@ -183,13 +183,13 @@ class TC_File_Find < Test::Unit::TestCase
183
183
  def test_group_with_numeric_id
184
184
  omit_if(@@windows, 'group test skipped on MS Windows')
185
185
  @rule1 = File::Find.new(:name => '*.doc', :group => @@loguser.gid)
186
- assert_equal([File.expand_path(@file4)], @rule1.find)
186
+ assert_equal([File.expand_path(@file_doc)], @rule1.find)
187
187
  end
188
188
 
189
189
  def test_group_with_string
190
190
  omit_if(@@windows, 'group test skipped on MS Windows')
191
191
  @rule1 = File::Find.new(:name => '*.doc', :group => @@logroup.name)
192
- assert_equal([File.expand_path(@file4)], @rule1.find)
192
+ assert_equal([File.expand_path(@file_doc)], @rule1.find)
193
193
  end
194
194
 
195
195
  def test_group_with_bad_id
@@ -212,6 +212,22 @@ class TC_File_Find < Test::Unit::TestCase
212
212
  assert_true(@rule1.follow)
213
213
  end
214
214
 
215
+ def test_links_basic
216
+ assert_respond_to(@rule1, :links)
217
+ assert_respond_to(@rule1, :links=)
218
+ assert_nil(@rule1.links)
219
+ end
220
+
221
+ def test_links
222
+ omit_if(@@windows, 'links test skipped on MS Windows')
223
+
224
+ @rule1 = File::Find.new(:name => '*.rb', :links => 2)
225
+ @rule2 = File::Find.new(:name => '*.doc', :links => 1)
226
+
227
+ assert_equal([], @rule1.find)
228
+ assert_equal([File.expand_path(@file_doc)], @rule2.find)
229
+ end
230
+
215
231
  def test_maxdepth_basic
216
232
  assert_respond_to(@rule1, :maxdepth)
217
233
  assert_respond_to(@rule1, :maxdepth=)
@@ -333,8 +349,8 @@ class TC_File_Find < Test::Unit::TestCase
333
349
 
334
350
  def test_perm
335
351
  omit_if(@@windows, 'perm test skipped on MS Windows')
336
- File.chmod(0664, @file1)
337
- File.chmod(0644, @file2)
352
+ File.chmod(0664, @file_rb)
353
+ File.chmod(0644, @file_txt1)
338
354
  results = File::Find.new(:name => "test1*", :perm => 664).find
339
355
 
340
356
  assert_equal(1, results.length)
@@ -344,8 +360,8 @@ class TC_File_Find < Test::Unit::TestCase
344
360
  def test_perm_with_symbolic_permissions
345
361
  omit_if(@@windows, 'symbolic perm test skipped on MS Windows')
346
362
 
347
- File.chmod(0664, @file1) # test1.rb
348
- File.chmod(0644, @file2) # test1.txt
363
+ File.chmod(0664, @file_rb) # test1.rb
364
+ File.chmod(0644, @file_txt1) # test1.txt
349
365
  results1 = File::Find.new(:name => "test1*", :perm => "g=rw").find
350
366
  results2 = File::Find.new(:name => "test1*", :perm => "u=rw").find
351
367
 
@@ -381,13 +397,13 @@ class TC_File_Find < Test::Unit::TestCase
381
397
  def test_user_with_numeric_id
382
398
  omit_if(@@windows, 'user test skipped on MS Windows')
383
399
  @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.uid)
384
- assert_equal([File.expand_path(@file4)], @rule1.find)
400
+ assert_equal([File.expand_path(@file_doc)], @rule1.find)
385
401
  end
386
402
 
387
403
  def test_user_with_string
388
404
  omit_if(@@windows, 'user test skipped on MS Windows')
389
405
  @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.name)
390
- assert_equal([File.expand_path(@file4)], @rule1.find)
406
+ assert_equal([File.expand_path(@file_doc)], @rule1.find)
391
407
  end
392
408
 
393
409
  def test_user_with_bad_id
@@ -409,12 +425,12 @@ class TC_File_Find < Test::Unit::TestCase
409
425
  end
410
426
 
411
427
  def teardown
412
- rm_rf(@file1)
413
- rm_rf(@file2)
414
- rm_rf(@file3)
415
- rm_rf(@file4)
416
- rm_rf(@dir1)
417
- rm_rf(@dir2)
428
+ rm_rf(@file_rb)
429
+ rm_rf(@file_txt1)
430
+ rm_rf(@file_txt2)
431
+ rm_rf(@file_doc)
432
+ rm_rf(@directory1)
433
+ rm_rf(@directory2)
418
434
  rm_rf(@link1) unless @@windows
419
435
  rm_rf('a')
420
436
  rm_rf('a1')
@@ -422,10 +438,10 @@ class TC_File_Find < Test::Unit::TestCase
422
438
 
423
439
  @rule1 = nil
424
440
  @rule2 = nil
425
- @file1 = nil
426
- @file2 = nil
427
- @file3 = nil
428
- @file4 = nil
441
+ @file_rb = nil
442
+ @file_txt1 = nil
443
+ @file_txt2 = nil
444
+ @file_doc = nil
429
445
  end
430
446
 
431
447
  def self.shutdown
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file-find
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
@@ -9,18 +9,18 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-20 00:00:00 -07:00
12
+ date: 2009-08-03 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: test-unit
17
- type: :runtime
17
+ type: :development
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 2.0.2
23
+ version: 2.0.3
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sys-admin
@@ -32,7 +32,7 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.4.4
34
34
  version:
35
- description: A better, object oriented way to find files
35
+ description: " The file-find library provides a better, more object oriented approach\n to finding files. It allows you to find files based on a variety of\n properties, such as access time, size, owner, etc. You can also limit\n directory depth.\n"
36
36
  email: djberg96@gmail.com
37
37
  executables: []
38
38
 
@@ -43,16 +43,14 @@ extra_rdoc_files:
43
43
  - CHANGES
44
44
  - MANIFEST
45
45
  files:
46
- - lib/file
47
- - lib/file/find.rb
48
46
  - test/test_file_find.rb
49
47
  - README
50
48
  - CHANGES
51
49
  - MANIFEST
52
50
  has_rdoc: true
53
51
  homepage: http://www.rubyforge.org/projects/shards
54
- licenses: []
55
-
52
+ licenses:
53
+ - Artistic 2.0
56
54
  post_install_message:
57
55
  rdoc_options: []
58
56
 
@@ -73,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
71
  requirements: []
74
72
 
75
73
  rubyforge_project: shards
76
- rubygems_version: 1.3.1
74
+ rubygems_version: 1.3.5
77
75
  signing_key:
78
76
  specification_version: 3
79
77
  summary: A better way to find files
@@ -1,487 +0,0 @@
1
- require 'date'
2
- require 'rbconfig'
3
-
4
- # For alternate implementations of Ruby, such as JRuby, that cannot
5
- # build C extensions fall back to the Etc module.
6
- begin
7
- require 'sys/admin'
8
- rescue LoadError
9
- require 'etc'
10
- end
11
-
12
- class File::Find
13
- # The version of this library
14
- VERSION = '0.3.2'
15
-
16
- # :stopdoc:
17
- VALID_OPTIONS = %w/
18
- atime
19
- ctime
20
- follow
21
- ftype
22
- inum
23
- group
24
- maxdepth
25
- mindepth
26
- mount
27
- mtime
28
- name
29
- pattern
30
- path
31
- perm
32
- prune
33
- size
34
- user
35
- /
36
- # :startdoc:
37
-
38
- # The starting path(s) for the search. The default is the current directory.
39
- # This can be a single path or an array of paths.
40
- #
41
- attr_accessor :path
42
-
43
- # The list of options passed to the constructor and/or used by the
44
- # File::Find#find method.
45
- #
46
- attr_accessor :options
47
-
48
- # Limits searches by file access time, where the value you supply is the
49
- # number of days back from the time that the File::Find#find method was
50
- # called.
51
- #
52
- attr_accessor :atime
53
-
54
- # Limits searches by file change time, where the value you supply is the
55
- # number of days back from the time that the File::Find#find method was
56
- # called.
57
- #
58
- attr_accessor :ctime
59
-
60
- # Limits searches to files that belong to a specific group, where the
61
- # group can be either a group name or ID.
62
- #
63
- # Not currently supported on MS Windows.
64
- #
65
- attr_accessor :group
66
-
67
- # An array of two element arrays for storing FileTest methods and their
68
- # boolean value.
69
- #
70
- attr_accessor :filetest
71
-
72
- # Controls the behavior of how symlinks are followed. If set to true (the
73
- # default), then follows the file pointed to. If false, it considers the
74
- # symlink itself.
75
- #
76
- attr_accessor :follow
77
-
78
- # Limits searches to specific types of files. The possible values here are
79
- # those returned by the File.ftype method.
80
- #
81
- attr_accessor :ftype
82
-
83
- # Limits search to a file with a specific inode number. Ignored on MS
84
- # Windows.
85
- #
86
- attr_accessor :inum
87
-
88
- # Limits search to a maximum depth into the tree relative to the starting
89
- # search directory.
90
- #
91
- attr_accessor :maxdepth
92
-
93
- # Limits searches to a minimum depth into the tree relative to the starting
94
- # search directory.
95
- #
96
- attr_accessor :mindepth
97
-
98
- # Limits searches to the same filesystem as the specified directory. For
99
- # Windows users, this refers to the volume.
100
- #
101
- attr_accessor :mount
102
-
103
- # Limits searches by file modification time, where the value you supply is
104
- # the number of days back from the time that the File::Find#find method was
105
- # called.
106
- #
107
- attr_accessor :mtime
108
-
109
- # The name pattern used to limit file searches. The patterns that are legal
110
- # for Dir.glob are legal here. The default is '*', i.e. everything.
111
- #
112
- attr_accessor :name
113
-
114
- # Limits searches to files which have permissions that match the octal
115
- # value that you provide. For purposes of this comparison, only the user,
116
- # group, and world settings are used. Do not use a leading 0 in the values
117
- # that you supply, e.g. use 755 not 0755.
118
- #
119
- # You may optionally use symbolic permissions, e.g. "g+rw", "u=rwx", etc.
120
- #
121
- # Not currently supported on MS Windows.
122
- #
123
- attr_accessor :perm
124
-
125
- # Skips files or directories that match the string provided as an argument.
126
- #
127
- attr_accessor :prune
128
-
129
- # If the value passed is an integer, this option limits searches to files
130
- # that match the size, in bytes, exactly. If a string is passed, you can
131
- # use the standard comparable operators to match files, e.g. ">= 200" would
132
- # limit searches to files greater than or equal to 200 bytes.
133
- #
134
- attr_accessor :size
135
-
136
- # Limits searches to files that belong to a specific user, where the user
137
- # can be either a user name or an ID.
138
- #
139
- # Not currently supported on MS Windows.
140
- #
141
- attr_accessor :user
142
-
143
- # The file that matched previously in the current search.
144
- #
145
- attr_reader :previous
146
-
147
- alias pattern name
148
- alias pattern= name=
149
-
150
- # Creates and returns a new File::Find object. The options set for this
151
- # object serve as the rules for determining what files the File::Find#find
152
- # method will search for.
153
- #
154
- # In addition to the standard list of valid options, you may also use
155
- # FileTest methods as options, setting their value to true or false.
156
- #
157
- # Example:
158
- #
159
- # rule = File::Find.new(
160
- # :name => "*.rb",
161
- # :follow => false,
162
- # :path => ['/usr/local/lib', '/opt/local/lib'],
163
- # :readable? => true
164
- # )
165
- #
166
- def initialize(options = {})
167
- @options = options
168
-
169
- @atime = nil
170
- @ctime = nil
171
- @ftype = nil
172
- @group = nil
173
- @follow = true
174
- @inum = nil
175
- @mount = nil
176
- @mtime = nil
177
- @perm = nil
178
- @prune = nil
179
- @size = nil
180
- @user = nil
181
-
182
- @previous = nil
183
- @maxdepth = nil
184
- @mindepth = nil
185
- @filetest = []
186
-
187
- validate_and_set_options(options) unless options.empty?
188
-
189
- @filesystem = File.stat(@mount).dev if @mount
190
-
191
- @path ||= Dir.pwd
192
- @name ||= '*'
193
- end
194
-
195
- # Executes the find based on the rules you set for the File::Find object.
196
- # In block form, yields each file in turn that matches the specified rules.
197
- # In non-block form it will return an array of matches instead.
198
- #
199
- # Example:
200
- #
201
- # rule = File::Find.new(
202
- # :name => "*.rb",
203
- # :follow => false,
204
- # :path => ['/usr/local/lib', '/opt/local/lib']
205
- # )
206
- #
207
- # rule.find{ |f|
208
- # puts f
209
- # }
210
- #
211
- def find
212
- results = [] unless block_given?
213
- paths = @path.to_a
214
-
215
- if @prune
216
- prune_regex = Regexp.new(@prune)
217
- else
218
- prune_regex = nil
219
- end
220
-
221
- paths.each{ |path|
222
- begin
223
- Dir.foreach(path){ |file|
224
- next if file == '.'
225
- next if file == '..'
226
-
227
- if prune_regex
228
- next if prune_regex.match(file)
229
- end
230
-
231
- orig = file.dup
232
- file = File.join(path, file)
233
-
234
- stat_method = @follow ? :lstat : :stat
235
-
236
- # Skip files we cannot access, stale links, etc.
237
- begin
238
- stat_info = File.send(stat_method, file)
239
- rescue Errno::ENOENT, Errno::EACCES
240
- next
241
- rescue Errno::ELOOP
242
- stat_method = :lstat # Handle recursive symlinks
243
- retry if stat_method.to_s != 'lstat'
244
- end
245
-
246
- glob = File.join(File.dirname(file), @name)
247
-
248
- # Dir[] doesn't like backslashes
249
- if File::ALT_SEPARATOR
250
- file.tr!(File::ALT_SEPARATOR, File::SEPARATOR)
251
- glob.tr!(File::ALT_SEPARATOR, File::SEPARATOR)
252
- end
253
-
254
- if @mount
255
- next unless stat_info.dev == @filesystem
256
- end
257
-
258
- if @maxdepth || @mindepth
259
- file_depth = file.split(File::SEPARATOR).length
260
- path_depth = @path.split(File::SEPARATOR).length
261
- depth = file_depth - path_depth
262
-
263
- if @maxdepth && (depth > @maxdepth)
264
- if File.directory?(file)
265
- unless paths.include?(file) && depth > @maxdepth
266
- paths << file
267
- end
268
- end
269
-
270
- next
271
- end
272
-
273
- if @mindepth && (depth < @mindepth)
274
- if File.directory?(file)
275
- unless paths.include?(file) && depth < @mindepth
276
- paths << file
277
- end
278
- end
279
-
280
- next
281
- end
282
- end
283
-
284
- # Add directories back onto the list of paths to search unless
285
- # they've already been added
286
- #
287
- if stat_info.directory?
288
- paths << file unless paths.include?(file)
289
- end
290
-
291
- next unless Dir[glob].include?(file)
292
-
293
- unless @filetest.empty?
294
- file_test = true
295
-
296
- @filetest.each{ |array|
297
- meth = array[0]
298
- bool = array[1]
299
-
300
- unless File.send(meth, file) == bool
301
- file_test = false
302
- break
303
- end
304
- }
305
-
306
- next unless file_test
307
- end
308
-
309
- if @atime || @ctime || @mtime
310
- date1 = Date.parse(Time.now.to_s)
311
-
312
- if @atime
313
- date2 = Date.parse(stat_info.atime.to_s)
314
- next unless (date1 - date2).numerator == @atime
315
- end
316
-
317
- if @ctime
318
- date2 = Date.parse(stat_info.ctime.to_s)
319
- next unless (date1 - date2).numerator == @ctime
320
- end
321
-
322
- if @mtime
323
- date2 = Date.parse(stat_info.mtime.to_s)
324
- next unless (date1 - date2).numerator == @mtime
325
- end
326
- end
327
-
328
- if @ftype
329
- next unless File.ftype(file) == @ftype
330
- end
331
-
332
- if @group
333
- if @group.is_a?(String)
334
- next unless get_group(stat_info.gid).name == @group
335
- else
336
- next unless stat_info.gid == @group
337
- end
338
- end
339
-
340
- unless Config::CONFIG['host_os'] =~ /windows|mswin/i
341
- if @inum
342
- next unless stat_info.ino == @inum
343
- end
344
- end
345
-
346
- # This currently doesn't work on MS Windows, even in limited
347
- # fashion for 0666 and 0664, because File.stat.mode doesn't
348
- # return the proper value.
349
- #
350
- if @perm
351
- if @perm.is_a?(String)
352
- octal_perm = sym2oct(@perm)
353
- next unless stat_info.mode & octal_perm == octal_perm
354
- else
355
- next unless sprintf("%o", stat_info.mode & 07777) == @perm.to_s
356
- end
357
- end
358
-
359
- # Allow plain numbers, or strings for comparison operators.
360
- if @size
361
- if @size.is_a?(String)
362
- regex = /^([><=]+)\s*?(\d+)$/
363
- match = regex.match(@size)
364
-
365
- if match.nil? || match.captures.include?(nil)
366
- raise ArgumentError, "invalid size string: '#{@size}'"
367
- end
368
-
369
- operator = match.captures.first.strip
370
- number = match.captures.last.strip.to_i
371
-
372
- next unless stat_info.size.send(operator, number)
373
- else
374
- next unless stat_info.size == @size
375
- end
376
- end
377
-
378
- if @user
379
- if @user.is_a?(String)
380
- next unless get_user(stat_info.uid).name == @user
381
- else
382
- next unless stat_info.uid == @user
383
- end
384
- end
385
-
386
- if block_given?
387
- yield file
388
- else
389
- results << file
390
- end
391
-
392
- @previous = file unless @previous == file
393
- }
394
- rescue Errno::EACCES
395
- next # Skip inaccessible directories
396
- end
397
- }
398
-
399
- block_given? ? nil : results
400
- end
401
-
402
- private
403
-
404
- # This validates that the keys are valid. If they are, it sets the value
405
- # of that key's corresponding method to the given value. If a key ends
406
- # with a '?', it's validated as a File method.
407
- #
408
- def validate_and_set_options(options)
409
- options.each do |key, value|
410
- key = key.to_s.downcase
411
-
412
- if key[-1].chr == '?'
413
- sym = key.to_sym
414
-
415
- unless File.respond_to?(sym)
416
- raise ArgumentError, "invalid option '#{key}'"
417
- end
418
-
419
- @filetest << [sym, value]
420
- else
421
- unless VALID_OPTIONS.include?(key)
422
- raise ArgumentError, "invalid option '#{key}'"
423
- end
424
-
425
- send("#{key}=", value)
426
- end
427
- end
428
- end
429
-
430
- # Converts a symoblic permissions mode into its octal equivalent.
431
- #--
432
- # Taken almost entirely from ruby-talk: 96956 (Hal Fulton).
433
- #
434
- def sym2oct(str)
435
- left = {'u' => 0700, 'g' => 0070, 'o' => 0007, 'a' => 0777}
436
- right = {'r' => 0444, 'w' => 0222, 'x' => 0111}
437
- regex = /([ugoa]+)([+-=])([rwx]+)/
438
-
439
- cmds = str.split(',')
440
-
441
- perm = 0
442
-
443
- cmds.each do |cmd|
444
- match = cmd.match(regex)
445
- raise "Invalid symbolic permissions: '#{str}'" if match.nil?
446
-
447
- junk, who, what, how = match.to_a
448
-
449
- who = who.split(//).inject(num=0) { |num,b| num |= left[b]; num }
450
- how = how.split(//).inject(num=0) { |num,b| num |= right[b]; num }
451
- mask = who & how
452
-
453
- case what
454
- when '+'
455
- perm = perm | mask
456
- when '-'
457
- perm = perm & ~mask
458
- when '='
459
- perm = mask
460
- end
461
- end
462
-
463
- perm
464
- end
465
-
466
- # Returns the group object based on the group id. Implemented for the
467
- # sake of platforms that cannot build extensions, such as JRuby.
468
- #
469
- def get_group(gid)
470
- if defined? Sys::Admin
471
- Sys::Admin.get_group(gid)
472
- else
473
- Etc.getgrgid(gid)
474
- end
475
- end
476
-
477
- # Returns the user object based on the group id. Implemented for the
478
- # sake of platforms that cannot build extensions, such as JRuby.
479
- #
480
- def get_user(uid)
481
- if defined? Sys::Admin
482
- Sys::Admin.get_user(uid)
483
- else
484
- Etc.getpwuid(uid)
485
- end
486
- end
487
- end