file-find 0.3.1-universal-java-1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/CHANGES +53 -0
  2. data/MANIFEST +7 -0
  3. data/README +111 -0
  4. data/lib/file/find.rb +474 -0
  5. data/test/test_file_find.rb +431 -0
  6. metadata +69 -0
data/CHANGES ADDED
@@ -0,0 +1,53 @@
1
+ == 0.3.1 - 9-Jan-2008
2
+ * Now defaults to using Etc instead of Sys::Admin for implementations
3
+ that don't support building C extensions, e.g. JRuby.
4
+ * Updated the test suite to work with JRuby.
5
+ * Minor optimizations for symbolic perms and atime/ctime/mtime checks.
6
+ Thanks go in part to Ryan Davis' flay library.
7
+
8
+ == 0.3.0 - 30-Dec-2008
9
+ * Added support for FileTest operations. All options passed to the constructor
10
+ that end with '?' are now validated and treated as FileTest operations.
11
+
12
+ == 0.2.5 - 29-Dec-2008
13
+ * Added maxdepth and mindepth support.
14
+ * Added a 'clean' rake task to cleanup any test-unit results files.
15
+
16
+ == 0.2.4 - 10-Dec-2008
17
+ * Added support for symbolic permissions. Thanks go to Bill Kleb for the
18
+ suggestion and to Hal Fulton for providing the solution.
19
+
20
+ == 0.2.3 - 25-Nov-2008
21
+ * Added mtime support. My previous concerns, which I believe stemmed from
22
+ the find(2) man page on Solaris 10 with regards to atime checks modifying
23
+ the mtime, appear have been unfounded.
24
+
25
+ == 0.2.2 - 19-Nov-2008
26
+ * The :user and :group options now accept a name or a numeric id. Thanks go
27
+ to Bill Kleb for the suggestion.
28
+ * Fixed yet another path bug for MS Windows.
29
+ * Updated platform check to use CONFIG instead of RUBY_PLATFORM, because the
30
+ latter does not work as I intended with other implementations, e.g. JRuby.
31
+ * Added sys-admin and test-unit as prerequisites.
32
+ * Added tests for the :user and :group options.
33
+
34
+ == 0.2.1 - 4-Oct-2007
35
+ * Added the File::Find#previous method, which lets you see the previous
36
+ match, if any.
37
+ * Path name bug fix for MS Windows.
38
+ * Test suite bug fixes for MS Windows (perm test now skipped).
39
+ * Inaccessible directories are now skipped instead of raising an error.
40
+
41
+ == 0.2.0 - 26-Apr-2007
42
+ * Fixed a bug where it was not traversing subdirectories.
43
+ * Added support for the perm and prune options.
44
+
45
+ == 0.1.1 - 25-Apr-2007
46
+ * The default for name is now '*', i.e. everything.
47
+ * Fixed a bug where directories were not matched. Thanks go to Leslie Viljoen
48
+ for the spot.
49
+ * The size option now accepts strings with comparable operators. For example,
50
+ you can now look for files greater than 400 bytes with the string "> 400".
51
+
52
+ == 0.1.0 - 24-Apr-2007
53
+ * Initial release
data/MANIFEST ADDED
@@ -0,0 +1,7 @@
1
+ * CHANGES
2
+ * MANIFEST
3
+ * Rakefile
4
+ * README
5
+ * file-find.gemspec
6
+ * lib/file/find.rb
7
+ * test/test_file_find.rb
data/README ADDED
@@ -0,0 +1,111 @@
1
+ = Description
2
+ This is a drop-in replacement for the find module currently in the standard
3
+ library. It is modeled on a typical 'find' command found on most Unix systems.
4
+
5
+ = Synopsis
6
+ rule = File::Find.new(
7
+ :pattern => "*.rb",
8
+ :follow => false,
9
+ :path => ['/usr/local/lib', '/opt/local/lib']
10
+ )
11
+
12
+ rule.find{ |f|
13
+ puts f
14
+ }
15
+
16
+ = Installation
17
+ * rake test (optional)
18
+ * rake install (non-gem) -OR- rake install_gem (gem)
19
+
20
+ = Rationale
21
+ The current find module in the standard library is inadequate. It is, quite
22
+ frankly, not much more than a plain Dir.glob call. This library provides an
23
+ interface based on options typically available on your command line 'find'
24
+ command, thus allowing you much greater control over how you find your files.
25
+
26
+ I am aware of the find2 library by Motoyuki Kasahara, but it supports very
27
+ few options, hasn't been updated in over six years and isn't packaged properly.
28
+
29
+ = Options
30
+ * atime
31
+ * ctime
32
+ * follow
33
+ * ftype
34
+ * inum (except Windows)
35
+ * group (name or id)
36
+ * maxdepth
37
+ * mindepth
38
+ * mtime
39
+ * name (or 'pattern')
40
+ * path
41
+ * perm (except Windows)
42
+ * prune
43
+ * size
44
+ * user (name or id)
45
+
46
+ In addition to the above options, FileTest methods such as 'readable?' and
47
+ 'writable?' may be used as keys, with true or false for their values.
48
+
49
+ See the RDoc documentation for more details about these options.
50
+
51
+ = Future Plans
52
+ More options will be added as time permits, and requests will definitely be
53
+ considered. Please log any feature requests on the project page at
54
+ http://www.rubyforge.org/projects/shards.
55
+
56
+ Some specific things I plan on adding:
57
+
58
+ * exec
59
+ * links
60
+ * support for :user and :group on MS Windows
61
+
62
+ = Options I won't support
63
+ Generally speaking, anything that would require mucking around with C code
64
+ or is just too difficult to implement in a cross platform manner will not be
65
+ supported. These include the following options:
66
+
67
+ * acl/xattr - Way too difficult to implement in a cross platform manner, and
68
+ a rarely used option in practice.
69
+
70
+ * cpio/ncpio - I will not shell out to this or any other 3rd party application.
71
+
72
+ * ls/print - Use Ruby's builtin printing methods to print as you see fit.
73
+
74
+ * ok - This is not interactive software.
75
+
76
+ = Options I may or may not support
77
+
78
+ * local/mount/xdev - This will probably not be added until I'm satisfied with
79
+ the sys-filesystem library. As of sys-filesystem 0.1.x, I'm not.
80
+
81
+ = Known Issues
82
+ The 'perm' option does not work on MS Windows, even for its limited subset of
83
+ permissions, i.e. 664 and 666. This is arguably a bug in Ruby's
84
+ File::Stat.mode method on MS Windows.
85
+
86
+ The 'user' and 'group' options are not currently supported on MS Windows.
87
+ This can be supported, but will require changes in the win32-file and
88
+ win32-file-stat libraries (which would then become dependencies).
89
+
90
+ There are 3 test failures with JRuby, all related to the 'perm' option. I
91
+ have not been able to reduce them to a simple test case and discern the
92
+ exact cause of the failures, though I suspect a bug in the JRuby
93
+ implementation of File.chmod.
94
+
95
+ = Bugs
96
+ None that I'm aware of. Please log any bug reports on the project page at
97
+ http://www.rubyforge.org/projects/shards.
98
+
99
+ = Acknowledgements
100
+ * Richard Clamp's File::Find::Rule Perl module for additional ideas and
101
+ inspiration.
102
+ * Bill Kleb for ideas regarding name, group and perm enhancements.
103
+
104
+ = License
105
+ Ruby's
106
+
107
+ = Copyright
108
+ (C) 2007-2008, Daniel J. Berger, All Rights Reserved
109
+
110
+ = Author
111
+ Daniel J. Berger
data/lib/file/find.rb ADDED
@@ -0,0 +1,474 @@
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.1'
15
+
16
+ # :stopdoc:
17
+ VALID_OPTIONS = %w/
18
+ atime
19
+ ctime
20
+ follow
21
+ ftype
22
+ inum
23
+ group
24
+ maxdepth
25
+ mindepth
26
+ mtime
27
+ name
28
+ pattern
29
+ path
30
+ perm
31
+ prune
32
+ size
33
+ user
34
+ /
35
+ # :startdoc:
36
+
37
+ # The starting path(s) for the search. The default is the current directory.
38
+ # This can be a single path or an array of paths.
39
+ #
40
+ attr_accessor :path
41
+
42
+ # The list of options passed to the constructor and/or used by the
43
+ # File::Find#find method.
44
+ #
45
+ attr_accessor :options
46
+
47
+ # Limits searches by file access time, where the value you supply is the
48
+ # number of days back from the time that the File::Find#find method was
49
+ # called.
50
+ #
51
+ attr_accessor :atime
52
+
53
+ # Limits searches by file change time, where the value you supply is the
54
+ # number of days back from the time that the File::Find#find method was
55
+ # called.
56
+ #
57
+ attr_accessor :ctime
58
+
59
+ # Limits searches to files that belong to a specific group, where the
60
+ # group can be either a group name or ID.
61
+ #
62
+ # Not currently supported on MS Windows.
63
+ #
64
+ attr_accessor :group
65
+
66
+ # An array of two element arrays for storing FileTest methods and their
67
+ # boolean value.
68
+ #
69
+ attr_accessor :filetest
70
+
71
+ # Controls the behavior of how symlinks are followed. If set to true (the
72
+ # default), then follows the file pointed to. If false, it considers the
73
+ # symlink itself.
74
+ #
75
+ attr_accessor :follow
76
+
77
+ # Limits searches to specific types of files. The possible values here are
78
+ # those returned by the File.ftype method.
79
+ #
80
+ attr_accessor :ftype
81
+
82
+ # Limits search to a file with a specific inode number. Ignored on MS
83
+ # Windows.
84
+ #
85
+ attr_accessor :inum
86
+
87
+ # Limits search to a maximum depth into the tree relative to the starting
88
+ # search directory.
89
+ #
90
+ attr_accessor :maxdepth
91
+
92
+ # Limits search to a minimum depth into the tree relative to the starting
93
+ # search directory.
94
+ #
95
+ attr_accessor :mindepth
96
+
97
+ # Limits searches by file modification time, where the value you supply is
98
+ # the number of days back from the time that the File::Find#find method was
99
+ # called.
100
+ #
101
+ attr_accessor :mtime
102
+
103
+ # The name pattern used to limit file searches. The patterns that are legal
104
+ # for Dir.glob are legal here. The default is '*', i.e. everything.
105
+ #
106
+ attr_accessor :name
107
+
108
+ # Limits searches to files which have permissions that match the octal
109
+ # value that you provide. For purposes of this comparison, only the user,
110
+ # group, and world settings are used. Do not use a leading 0 in the values
111
+ # that you supply, e.g. use 755 not 0755.
112
+ #
113
+ # You may optionally use symbolic permissions, e.g. "g+rw", "u=rwx", etc.
114
+ #
115
+ # Not currently supported on MS Windows.
116
+ #
117
+ attr_accessor :perm
118
+
119
+ # Skips files or directories that match the string provided as an argument.
120
+ #
121
+ attr_accessor :prune
122
+
123
+ # If the value passed is an integer, this option limits searches to files
124
+ # that match the size, in bytes, exactly. If a string is passed, you can
125
+ # use the standard comparable operators to match files, e.g. ">= 200" would
126
+ # limit searches to files greater than or equal to 200 bytes.
127
+ #
128
+ attr_accessor :size
129
+
130
+ # Limits searches to files that belong to a specific user, where the user
131
+ # can be either a user name or an ID.
132
+ #
133
+ # Not currently supported on MS Windows.
134
+ #
135
+ attr_accessor :user
136
+
137
+ # The file that matched previously in the current search.
138
+ #
139
+ attr_reader :previous
140
+
141
+ alias pattern name
142
+ alias pattern= name=
143
+
144
+ # Creates and returns a new File::Find object. The options set for this
145
+ # object serve as the rules for determining what files the File::Find#find
146
+ # method will search for.
147
+ #
148
+ # In addition to the standard list of valid options, you may also use
149
+ # FileTest methods as options, setting their value to true or false.
150
+ #
151
+ # Example:
152
+ #
153
+ # rule = File::Find.new(
154
+ # :name => "*.rb",
155
+ # :follow => false,
156
+ # :path => ['/usr/local/lib', '/opt/local/lib'],
157
+ # :readable? => true
158
+ # )
159
+ #
160
+ def initialize(options = {})
161
+ @options = options
162
+
163
+ @atime = nil
164
+ @ctime = nil
165
+ @ftype = nil
166
+ @group = nil
167
+ @follow = true
168
+ @inum = nil
169
+ @mtime = nil
170
+ @perm = nil
171
+ @prune = nil
172
+ @size = nil
173
+ @user = nil
174
+
175
+ @previous = nil
176
+ @maxdepth = nil
177
+ @mindepth = nil
178
+ @filetest = []
179
+
180
+ validate_and_set_options(options) unless options.empty?
181
+
182
+ @path ||= Dir.pwd
183
+ @name ||= '*'
184
+ end
185
+
186
+ # Executes the find based on the rules you set for the File::Find object.
187
+ # In block form, yields each file in turn that matches the specified rules.
188
+ # In non-block form it will return an array of matches instead.
189
+ #
190
+ # Example:
191
+ #
192
+ # rule = File::Find.new(
193
+ # :name => "*.rb",
194
+ # :follow => false,
195
+ # :path => ['/usr/local/lib', '/opt/local/lib']
196
+ # )
197
+ #
198
+ # rule.find{ |f|
199
+ # puts f
200
+ # }
201
+ #
202
+ def find
203
+ results = [] unless block_given?
204
+ paths = @path.to_a
205
+
206
+ if @prune
207
+ prune_regex = Regexp.new(@prune)
208
+ else
209
+ prune_regex = nil
210
+ end
211
+
212
+ paths.each{ |path|
213
+ begin
214
+ Dir.foreach(path){ |file|
215
+ next if file == '.'
216
+ next if file == '..'
217
+
218
+ if prune_regex
219
+ next if prune_regex.match(file)
220
+ end
221
+
222
+ orig = file.dup
223
+ file = File.join(path, file)
224
+
225
+ stat_method = @follow ? :lstat : :stat
226
+
227
+ # Skip files we cannot access, stale links, etc.
228
+ begin
229
+ stat_info = File.send(stat_method, file)
230
+ rescue Errno::ENOENT, Errno::EACCES
231
+ next
232
+ rescue Errno::ELOOP
233
+ stat_method = :lstat # Handle recursive symlinks
234
+ retry if stat_method.to_s != 'lstat'
235
+ end
236
+
237
+ glob = File.join(File.dirname(file), @name)
238
+
239
+ # Dir[] doesn't like backslashes
240
+ if File::ALT_SEPARATOR
241
+ file.tr!(File::ALT_SEPARATOR, File::SEPARATOR)
242
+ glob.tr!(File::ALT_SEPARATOR, File::SEPARATOR)
243
+ end
244
+
245
+ if @maxdepth || @mindepth
246
+ file_depth = file.split(File::SEPARATOR).length
247
+ path_depth = @path.split(File::SEPARATOR).length
248
+ depth = file_depth - path_depth
249
+
250
+ if @maxdepth && (depth > @maxdepth)
251
+ if File.directory?(file)
252
+ unless paths.include?(file) && depth > @maxdepth
253
+ paths << file
254
+ end
255
+ end
256
+
257
+ next
258
+ end
259
+
260
+ if @mindepth && (depth < @mindepth)
261
+ if File.directory?(file)
262
+ unless paths.include?(file) && depth < @mindepth
263
+ paths << file
264
+ end
265
+ end
266
+
267
+ next
268
+ end
269
+ end
270
+
271
+ # Add directories back onto the list of paths to search unless
272
+ # they've already been added
273
+ #
274
+ if stat_info.directory?
275
+ paths << file unless paths.include?(file)
276
+ end
277
+
278
+ next unless Dir[glob].include?(file)
279
+
280
+ unless @filetest.empty?
281
+ file_test = true
282
+
283
+ @filetest.each{ |array|
284
+ meth = array[0]
285
+ bool = array[1]
286
+
287
+ unless File.send(meth, file) == bool
288
+ file_test = false
289
+ break
290
+ end
291
+ }
292
+
293
+ next unless file_test
294
+ end
295
+
296
+ if @atime || @ctime || @mtime
297
+ date1 = Date.parse(Time.now.to_s)
298
+
299
+ if @atime
300
+ date2 = Date.parse(stat_info.atime.to_s)
301
+ next unless (date1 - date2).numerator == @atime
302
+ end
303
+
304
+ if @ctime
305
+ date2 = Date.parse(stat_info.ctime.to_s)
306
+ next unless (date1 - date2).numerator == @ctime
307
+ end
308
+
309
+ if @mtime
310
+ date2 = Date.parse(stat_info.mtime.to_s)
311
+ next unless (date1 - date2).numerator == @mtime
312
+ end
313
+ end
314
+
315
+ if @ftype
316
+ next unless File.ftype(file) == @ftype
317
+ end
318
+
319
+ if @group
320
+ if @group.is_a?(String)
321
+ next unless get_group(stat_info.gid).name == @group
322
+ else
323
+ next unless stat_info.gid == @group
324
+ end
325
+ end
326
+
327
+ unless Config::CONFIG['host_os'] =~ /windows|mswin/i
328
+ if @inum
329
+ next unless stat_info.ino == @inum
330
+ end
331
+ end
332
+
333
+ # This currently doesn't work on MS Windows, even in limited
334
+ # fashion for 0666 and 0664, because File.stat.mode doesn't
335
+ # return the proper value.
336
+ #
337
+ if @perm
338
+ if @perm.is_a?(String)
339
+ octal_perm = sym2oct(@perm)
340
+ next unless stat_info.mode & octal_perm == octal_perm
341
+ else
342
+ next unless sprintf("%o", stat_info.mode & 07777) == @perm.to_s
343
+ end
344
+ end
345
+
346
+ # Allow plain numbers, or strings for comparison operators.
347
+ if @size
348
+ if @size.is_a?(String)
349
+ regex = /^([><=]+)\s*?(\d+)$/
350
+ match = regex.match(@size)
351
+
352
+ if match.nil? || match.captures.include?(nil)
353
+ raise ArgumentError, "invalid size string: '#{@size}'"
354
+ end
355
+
356
+ operator = match.captures.first.strip
357
+ number = match.captures.last.strip.to_i
358
+
359
+ next unless stat_info.size.send(operator, number)
360
+ else
361
+ next unless stat_info.size == @size
362
+ end
363
+ end
364
+
365
+ if @user
366
+ if @user.is_a?(String)
367
+ next unless get_user(stat_info.uid).name == @user
368
+ else
369
+ next unless stat_info.uid == @user
370
+ end
371
+ end
372
+
373
+ if block_given?
374
+ yield file
375
+ else
376
+ results << file
377
+ end
378
+
379
+ @previous = file unless @previous == file
380
+ }
381
+ rescue Errno::EACCES
382
+ next # Skip inaccessible directories
383
+ end
384
+ }
385
+
386
+ block_given? ? nil : results
387
+ end
388
+
389
+ private
390
+
391
+ # This validates that the keys are valid. If they are, it sets the value
392
+ # of that key's corresponding method to the given value. If a key ends
393
+ # with a '?', it's validated as a File method.
394
+ #
395
+ def validate_and_set_options(options)
396
+ options.each do |key, value|
397
+ key = key.to_s.downcase
398
+
399
+ if key[-1].chr == '?'
400
+ sym = key.to_sym
401
+
402
+ unless File.respond_to?(sym)
403
+ raise ArgumentError, "invalid option '#{key}'"
404
+ end
405
+
406
+ @filetest << [sym, value]
407
+ else
408
+ unless VALID_OPTIONS.include?(key)
409
+ raise ArgumentError, "invalid option '#{key}'"
410
+ end
411
+
412
+ send("#{key}=", value)
413
+ end
414
+ end
415
+ end
416
+
417
+ # Converts a symoblic permissions mode into its octal equivalent.
418
+ #--
419
+ # Taken almost entirely from ruby-talk: 96956 (Hal Fulton).
420
+ #
421
+ def sym2oct(str)
422
+ left = {'u' => 0700, 'g' => 0070, 'o' => 0007, 'a' => 0777}
423
+ right = {'r' => 0444, 'w' => 0222, 'x' => 0111}
424
+ regex = /([ugoa]+)([+-=])([rwx]+)/
425
+
426
+ cmds = str.split(',')
427
+
428
+ perm = 0
429
+
430
+ cmds.each do |cmd|
431
+ match = cmd.match(regex)
432
+ raise "Invalid symbolic permissions: '#{str}'" if match.nil?
433
+
434
+ junk, who, what, how = match.to_a
435
+
436
+ who = who.split(//).inject(num=0) { |num,b| num |= left[b]; num }
437
+ how = how.split(//).inject(num=0) { |num,b| num |= right[b]; num }
438
+ mask = who & how
439
+
440
+ case what
441
+ when '+'
442
+ perm = perm | mask
443
+ when '-'
444
+ perm = perm & ~mask
445
+ when '='
446
+ perm = mask
447
+ end
448
+ end
449
+
450
+ perm
451
+ end
452
+
453
+ # Returns the group object based on the group id. Implemented for the
454
+ # sake of platforms that cannot build extensions, such as JRuby.
455
+ #
456
+ def get_group(gid)
457
+ if defined? Sys::Admin
458
+ Sys::Admin.get_group(gid)
459
+ else
460
+ Etc.getgrgid(gid)
461
+ end
462
+ end
463
+
464
+ # Returns the user object based on the group id. Implemented for the
465
+ # sake of platforms that cannot build extensions, such as JRuby.
466
+ #
467
+ def get_user(uid)
468
+ if defined? Sys::Admin
469
+ Sys::Admin.get_user(uid)
470
+ else
471
+ Etc.getpwuid(uid)
472
+ end
473
+ end
474
+ end
@@ -0,0 +1,431 @@
1
+ ######################################################################
2
+ # test_file_find.rb
3
+ #
4
+ # Test case for the File::Find package. You should run this via the
5
+ # 'rake test' task.
6
+ ######################################################################
7
+ require 'rubygems'
8
+ gem 'test-unit'
9
+
10
+ require 'test/unit'
11
+ require 'fileutils'
12
+ require 'file/find'
13
+ require 'rbconfig'
14
+
15
+ begin
16
+ require 'sys/admin'
17
+ rescue LoadError
18
+ require 'etc'
19
+ end
20
+
21
+ include Config
22
+ include FileUtils
23
+
24
+ class TC_File_Find < Test::Unit::TestCase
25
+ def self.startup
26
+ Dir.chdir('test') unless File.basename(Dir.pwd) == 'test'
27
+
28
+ @@windows = CONFIG['host_os'] =~ /windows|mswin/i
29
+ @@jruby = RUBY_PLATFORM.match('java')
30
+
31
+ unless @@windows
32
+ if @@jruby
33
+ @@loguser = Etc.getpwnam(Etc.getlogin)
34
+ @@logroup = Etc.getgrgid(@@loguser.gid)
35
+ else
36
+ @@loguser = Sys::Admin.get_user(Sys::Admin.get_login)
37
+ @@logroup = Sys::Admin.get_group(@@loguser.gid)
38
+ end
39
+ end
40
+ end
41
+
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'){}
54
+
55
+ unless @@windows
56
+ @link1 = 'link1'
57
+ File.symlink(@file1, @link1)
58
+ end
59
+
60
+ Dir.mkdir(@dir1) unless File.exists?(@dir1)
61
+ Dir.mkdir(@dir2) unless File.exists?(@dir2)
62
+
63
+ File.open(File.join(@dir1, 'bar.txt'), 'w'){}
64
+ File.open(File.join(@dir2, 'baz.txt'), 'w'){}
65
+
66
+ @rule1 = File::Find.new(:name => '*.txt')
67
+ @rule2 = File::Find.new
68
+ end
69
+
70
+ def test_version
71
+ assert_equal('0.3.1', File::Find::VERSION)
72
+ end
73
+
74
+ def test_path
75
+ assert_respond_to(@rule1, :path)
76
+ assert_respond_to(@rule1, :path=)
77
+ assert_equal(Dir.pwd, @rule1.path)
78
+ end
79
+
80
+ def test_options
81
+ assert_respond_to(@rule1, :options)
82
+ assert_respond_to(@rule1, :options=)
83
+ assert_equal({:name => '*.txt'}, @rule1.options)
84
+ end
85
+
86
+ def test_atime_basic
87
+ assert_respond_to(@rule1, :atime)
88
+ assert_respond_to(@rule1, :atime=)
89
+ assert_nil(@rule1.atime)
90
+ end
91
+
92
+ def test_atime
93
+ rule1 = File::Find.new(:name => "*.rb", :atime => 0)
94
+ rule2 = File::Find.new(:name => "*.rb", :atime => 1)
95
+
96
+ assert_false(rule1.find.empty?)
97
+ assert_true(rule2.find.empty?)
98
+ end
99
+
100
+ def test_ctime_basic
101
+ assert_respond_to(@rule1, :ctime)
102
+ assert_respond_to(@rule1, :ctime=)
103
+ assert_nil(@rule1.ctime)
104
+ end
105
+
106
+ def test_ctime
107
+ rule1 = File::Find.new(:name => "*.rb", :ctime => 0)
108
+ rule2 = File::Find.new(:name => "*.rb", :ctime => 1)
109
+
110
+ assert_false(rule1.find.empty?)
111
+ assert_true(rule2.find.empty?)
112
+ end
113
+
114
+ def test_find_basic
115
+ assert_respond_to(@rule1, :find)
116
+ assert_nothing_raised{ @rule1.find }
117
+ end
118
+
119
+ def test_find
120
+ assert_kind_of(Array, @rule1.find)
121
+ assert_nil(@rule1.find{})
122
+ end
123
+
124
+ def test_filetest_basic
125
+ assert_respond_to(@rule1, :filetest)
126
+ assert_respond_to(@rule1, :filetest=)
127
+ assert_nothing_raised{ @rule1.filetest }
128
+ assert_kind_of(Array, @rule1.filetest)
129
+ end
130
+
131
+ def test_filetest_valid_options
132
+ assert_nothing_raised{ File::Find.new(:readable? => true) }
133
+ assert_nothing_raised{ File::Find.new(:writable? => true) }
134
+ end
135
+
136
+ def test_filetest
137
+ omit_if(@@windows && @@jruby, "Skipping file test on JRuby/Windows")
138
+
139
+ rule = File::Find.new(:name => "*.doc", :writable? => true)
140
+ File.chmod(0644, @file4)
141
+
142
+ assert_equal([@file4], rule.find.map{ |f| File.basename(f) })
143
+
144
+ File.chmod(0444, @file4)
145
+
146
+ assert_equal([], rule.find)
147
+ end
148
+
149
+ def test_mtime
150
+ rule1 = File::Find.new(:name => "*.rb", :mtime => 0)
151
+ rule2 = File::Find.new(:name => "*.rb", :mtime => 1)
152
+
153
+ assert_false(rule1.find.empty?)
154
+ assert_true(rule2.find.empty?)
155
+ end
156
+
157
+ def test_mtime_basic
158
+ assert_respond_to(@rule1, :mtime)
159
+ assert_respond_to(@rule1, :mtime=)
160
+ assert_nil(@rule1.mtime)
161
+ end
162
+
163
+ def test_ftype_basic
164
+ assert_respond_to(@rule1, :ftype)
165
+ assert_respond_to(@rule1, :ftype=)
166
+ assert_nil(@rule1.ftype)
167
+ end
168
+
169
+ def test_ftype
170
+ rule1 = File::Find.new(:name => "*.rb", :ftype => "file")
171
+ rule2 = File::Find.new(:name => "*.rb", :ftype => "characterSpecial")
172
+
173
+ assert_false(rule1.find.empty?)
174
+ assert_true(rule2.find.empty?)
175
+ end
176
+
177
+ def test_group_basic
178
+ assert_respond_to(@rule1, :group)
179
+ assert_respond_to(@rule1, :group=)
180
+ assert_nil(@rule1.group)
181
+ end
182
+
183
+ def test_group_with_numeric_id
184
+ omit_if(@@windows, 'group test skipped on MS Windows')
185
+ @rule1 = File::Find.new(:name => '*.doc', :group => @@loguser.gid)
186
+ assert_equal([File.expand_path(@file4)], @rule1.find)
187
+ end
188
+
189
+ def test_group_with_string
190
+ omit_if(@@windows, 'group test skipped on MS Windows')
191
+ @rule1 = File::Find.new(:name => '*.doc', :group => @@logroup.name)
192
+ assert_equal([File.expand_path(@file4)], @rule1.find)
193
+ end
194
+
195
+ def test_group_with_bad_id
196
+ omit_if(@@windows, 'group test skipped on MS Windows')
197
+ @rule1 = File::Find.new(:name => '*.doc', :group => 'totallybogus')
198
+ @rule2 = File::Find.new(:name => '*.doc', :group => 99999999)
199
+ assert_equal([], @rule1.find)
200
+ assert_equal([], @rule2.find)
201
+ end
202
+
203
+ def test_inum_basic
204
+ assert_respond_to(@rule1, :inum)
205
+ assert_respond_to(@rule1, :inum=)
206
+ assert_nil(@rule1.inum)
207
+ end
208
+
209
+ def test_follow_basic
210
+ assert_respond_to(@rule1, :follow)
211
+ assert_respond_to(@rule1, :follow=)
212
+ assert_true(@rule1.follow)
213
+ end
214
+
215
+ def test_maxdepth_basic
216
+ assert_respond_to(@rule1, :maxdepth)
217
+ assert_respond_to(@rule1, :maxdepth=)
218
+ assert_nil(@rule1.maxdepth)
219
+ end
220
+
221
+ def test_maxdepth_file
222
+ mkpath('a1/a2/a3')
223
+ touch('a1/a.foo')
224
+ touch('a1/a2/b.foo')
225
+ touch('a1/a2/c.foo')
226
+ touch('a1/a2/a3/d.foo')
227
+ touch('a1/a2/a3/e.foo')
228
+ touch('a1/a2/a3/f.foo')
229
+
230
+ @rule2.pattern = "*.foo"
231
+ @rule2.maxdepth = 1
232
+ assert_equal([], @rule2.find)
233
+
234
+ @rule2.maxdepth = 2
235
+ assert_equal(['a.foo'], @rule2.find.map{ |e| File.basename(e) })
236
+
237
+ @rule2.maxdepth = 3
238
+ assert_equal(['a.foo', 'b.foo', 'c.foo'], @rule2.find.map{ |e| File.basename(e) })
239
+
240
+ @rule2.maxdepth = nil
241
+ assert_equal(['a.foo', 'b.foo', 'c.foo', 'd.foo', 'e.foo', 'f.foo'], @rule2.find.map{ |e| File.basename(e) })
242
+ end
243
+
244
+ def test_maxdepth_directory
245
+ mkpath('a/b/c')
246
+ @rule2.pattern = "c"
247
+
248
+ @rule2.maxdepth = 1
249
+ assert_equal([], @rule2.find)
250
+
251
+ @rule2.maxdepth = 2
252
+ assert_equal([], @rule2.find)
253
+
254
+ @rule2.maxdepth = 3
255
+ assert_equal(['c'], @rule2.find.map{ |e| File.basename(e) })
256
+ end
257
+
258
+ def test_mindepth_basic
259
+ assert_respond_to(@rule1, :mindepth)
260
+ assert_respond_to(@rule1, :mindepth=)
261
+ assert_nil(@rule1.mindepth)
262
+ end
263
+
264
+ def test_mindepth_file
265
+ mkpath('a1/a2/a3')
266
+ touch('z.min')
267
+ touch('a1/a.min')
268
+ touch('a1/a2/b.min')
269
+ touch('a1/a2/c.min')
270
+ touch('a1/a2/a3/d.min')
271
+ touch('a1/a2/a3/e.min')
272
+ touch('a1/a2/a3/f.min')
273
+
274
+ @rule2.pattern = "*.min"
275
+
276
+ @rule2.mindepth = 0
277
+ assert_equal(['z.min', 'a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min'], @rule2.find.map{ |e| File.basename(e) })
278
+
279
+ @rule2.mindepth = 1
280
+ assert_equal(['z.min', 'a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min'], @rule2.find.map{ |e| File.basename(e) })
281
+
282
+ @rule2.mindepth = 2
283
+ assert_equal(['a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min'], @rule2.find.map{ |e| File.basename(e) })
284
+
285
+ @rule2.mindepth = 3
286
+ assert_equal(['b.min', 'c.min', 'd.min', 'e.min', 'f.min'], @rule2.find.map{ |e| File.basename(e) })
287
+
288
+ @rule2.mindepth = 4
289
+ assert_equal(['d.min', 'e.min', 'f.min'], @rule2.find.map{ |e| File.basename(e) })
290
+
291
+ @rule2.mindepth = 5
292
+ assert_equal([], @rule2.find.map{ |e| File.basename(e) })
293
+ end
294
+
295
+ def test_mindepth_directory
296
+ mkpath('a/b/c')
297
+ @rule2.pattern = "a"
298
+
299
+ @rule2.mindepth = 1
300
+ assert_equal(['a'], @rule2.find.map{ |e| File.basename(e) })
301
+
302
+ @rule2.mindepth = 2
303
+ assert_equal([], @rule2.find)
304
+
305
+ @rule2.mindepth = 3
306
+ assert_equal([], @rule2.find)
307
+ end
308
+
309
+ def test_name_basic
310
+ assert_respond_to(@rule1, :name)
311
+ assert_respond_to(@rule1, :name=)
312
+ assert_equal('*.txt', @rule1.name)
313
+ end
314
+
315
+ def test_pattern_alias
316
+ assert_respond_to(@rule1, :pattern)
317
+ assert_respond_to(@rule1, :pattern=)
318
+ assert_true(@rule1.method(:name) == @rule1.method(:pattern))
319
+ assert_true(@rule1.method(:name=) == @rule1.method(:pattern=))
320
+ end
321
+
322
+ def test_perm_basic
323
+ assert_respond_to(@rule1, :perm)
324
+ assert_respond_to(@rule1, :perm=)
325
+ assert_nil(@rule1.perm)
326
+ end
327
+
328
+ def test_perm
329
+ omit_if(@@windows, 'perm test skipped on MS Windows')
330
+ File.chmod(0664, @file1)
331
+ File.chmod(0644, @file2)
332
+ results = File::Find.new(:name => "test1*", :perm => 664).find
333
+
334
+ assert_equal(1, results.length)
335
+ assert_equal('test1.rb', File.basename(results.first))
336
+ end
337
+
338
+ def test_perm_with_symbolic_permissions
339
+ omit_if(@@windows, 'symbolic perm test skipped on MS Windows')
340
+
341
+ File.chmod(0664, @file1) # test1.rb
342
+ File.chmod(0644, @file2) # test1.txt
343
+ results1 = File::Find.new(:name => "test1*", :perm => "g=rw").find
344
+ results2 = File::Find.new(:name => "test1*", :perm => "u=rw").find
345
+
346
+ assert_equal(1, results1.length)
347
+ assert_equal(2, results2.length)
348
+ assert_equal('test1.rb', File.basename(results1.first))
349
+ assert_equal(['test1.rb', 'test1.txt'], results2.map{ |e| File.basename(e) })
350
+ end
351
+
352
+ def test_prune_basic
353
+ assert_respond_to(@rule1, :prune)
354
+ assert_respond_to(@rule1, :prune=)
355
+ assert_nil(@rule1.prune)
356
+ end
357
+
358
+ def test_prune
359
+ rule = File::Find.new(:name => "*.txt", :prune => 'foo')
360
+ assert_equal('test1.txt', File.basename(rule.find.first))
361
+ end
362
+
363
+ def test_size_basic
364
+ assert_respond_to(@rule1, :size)
365
+ assert_respond_to(@rule1, :size=)
366
+ assert_nil(@rule1.size)
367
+ end
368
+
369
+ def test_user_basic
370
+ assert_respond_to(@rule1, :user)
371
+ assert_respond_to(@rule1, :user=)
372
+ assert_nil(@rule1.user)
373
+ end
374
+
375
+ def test_user_with_numeric_id
376
+ omit_if(@@windows, 'user test skipped on MS Windows')
377
+ @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.uid)
378
+ assert_equal([File.expand_path(@file4)], @rule1.find)
379
+ end
380
+
381
+ def test_user_with_string
382
+ omit_if(@@windows, 'user test skipped on MS Windows')
383
+ @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.name)
384
+ assert_equal([File.expand_path(@file4)], @rule1.find)
385
+ end
386
+
387
+ def test_user_with_bad_id
388
+ omit_if(@@windows, 'user test skipped on MS Windows')
389
+ @rule1 = File::Find.new(:name => '*.doc', :user => 'totallybogus')
390
+ @rule2 = File::Find.new(:name => '*.doc', :user => 99999999)
391
+ assert_equal([], @rule1.find)
392
+ assert_equal([], @rule2.find)
393
+ end
394
+
395
+ def test_previous_basic
396
+ assert_respond_to(@rule1, :previous)
397
+ end
398
+
399
+ def test_expected_errors
400
+ assert_raise(Errno::ENOENT){ File::Find.new(:path => '/bogus/dir').find }
401
+ assert_raise(ArgumentError){ File::Find.new(:bogus => 1) }
402
+ assert_raise(ArgumentError){ File::Find.new(:bogus? => true) }
403
+ end
404
+
405
+ def teardown
406
+ rm_rf(@file1)
407
+ rm_rf(@file2)
408
+ rm_rf(@file3)
409
+ rm_rf(@file4)
410
+ rm_rf(@dir1)
411
+ rm_rf(@dir2)
412
+ rm_rf(@link1) unless @@windows
413
+ rm_rf('a')
414
+ rm_rf('a1')
415
+ rm_rf('z.min') if File.exists?('z.min')
416
+
417
+ @rule1 = nil
418
+ @rule2 = nil
419
+ @file1 = nil
420
+ @file2 = nil
421
+ @file3 = nil
422
+ @file4 = nil
423
+ end
424
+
425
+ def self.shutdown
426
+ @@windows = nil
427
+ @@jruby = nil
428
+ @@loguser = nil unless @@windows
429
+ @@logroup = nil unless @@windows
430
+ end
431
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ extensions: []
3
+
4
+ homepage: http://www.rubyforge.org/projects/shards
5
+ executables: []
6
+
7
+ version: !ruby/object:Gem::Version
8
+ version: 0.3.1
9
+ post_install_message:
10
+ date: 2009-01-09 07:00:00 +00:00
11
+ files:
12
+ - lib/file
13
+ - lib/file/find.rb
14
+ - test/test_file_find.rb
15
+ - README
16
+ - CHANGES
17
+ - MANIFEST
18
+ rubygems_version: 1.3.1
19
+ rdoc_options: []
20
+
21
+ signing_key:
22
+ cert_chain: []
23
+
24
+ name: file-find
25
+ has_rdoc: true
26
+ platform: universal-java-1.5
27
+ summary: A better way to find files
28
+ default_executable:
29
+ bindir: bin
30
+ required_rubygems_version: !ruby/object:Gem::Requirement
31
+ version:
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ version:
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ require_paths:
43
+ - lib
44
+ specification_version: 2
45
+ test_files:
46
+ - test/test_file_find.rb
47
+ dependencies:
48
+ - !ruby/object:Gem::Dependency
49
+ type: :runtime
50
+ name: test-unit
51
+ version_requirement:
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ version:
54
+ requirements:
55
+ - - '>='
56
+ - !ruby/object:Gem::Version
57
+ version: 2.0.2
58
+ description: A better way to find files
59
+ email: djberg96@gmail.com
60
+ authors:
61
+ - Daniel Berger
62
+ extra_rdoc_files:
63
+ - README
64
+ - CHANGES
65
+ - MANIFEST
66
+ requirements: []
67
+
68
+ rubyforge_project: shards
69
+ autorequire: