fun_with_files 0.0.14 → 0.0.18

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 (58) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.markdown +15 -3
  3. data/Gemfile +17 -7
  4. data/{README.rdoc → README.markdown} +12 -11
  5. data/Rakefile +3 -3
  6. data/VERSION +1 -1
  7. data/lib/fun_with/files/bootstrapper.rb +87 -0
  8. data/lib/fun_with/files/core_extensions/file.rb +15 -3
  9. data/lib/fun_with/files/core_extensions/set.rb +12 -0
  10. data/lib/fun_with/files/core_extensions/true_class.rb +11 -0
  11. data/lib/fun_with/files/digest_methods.rb +50 -17
  12. data/lib/fun_with/files/directory_builder.rb +9 -4
  13. data/lib/fun_with/files/downloader.rb +29 -16
  14. data/lib/fun_with/files/errors.rb +9 -1
  15. data/lib/fun_with/files/file_manipulation_methods.rb +25 -15
  16. data/lib/fun_with/files/file_orderer.rb +2 -0
  17. data/lib/fun_with/files/file_path.rb +242 -156
  18. data/lib/fun_with/files/file_path_class_methods.rb +23 -2
  19. data/lib/fun_with/files/file_permission_methods.rb +18 -7
  20. data/lib/fun_with/files/file_requirements.rb +63 -7
  21. data/lib/fun_with/files/requirements/manager.rb +104 -0
  22. data/lib/fun_with/files/root_path.rb +3 -3
  23. data/lib/fun_with/files/stat_methods.rb +33 -0
  24. data/lib/fun_with/files/string_behavior.rb +6 -2
  25. data/lib/fun_with/files/utils/byte_size.rb +143 -0
  26. data/lib/fun_with/files/utils/opts.rb +26 -0
  27. data/lib/fun_with/files/utils/succession.rb +47 -0
  28. data/lib/fun_with/files/utils/timestamp.rb +47 -0
  29. data/lib/fun_with/files/utils/timestamp_format.rb +31 -0
  30. data/lib/fun_with/files/watcher.rb +157 -0
  31. data/lib/fun_with/files/watchers/directory_watcher.rb +67 -0
  32. data/lib/fun_with/files/watchers/file_watcher.rb +45 -0
  33. data/lib/fun_with/files/watchers/missing_watcher.rb +23 -0
  34. data/lib/fun_with/files/watchers/node_watcher.rb +44 -0
  35. data/lib/fun_with/testing/assertions/fun_with_files.rb +91 -0
  36. data/lib/fun_with/testing/test_case_extensions.rb +12 -0
  37. data/lib/fun_with_files.rb +5 -31
  38. data/test/helper.rb +13 -5
  39. data/test/test_core_extensions.rb +6 -0
  40. data/test/test_descent.rb +2 -2
  41. data/test/test_directory_builder.rb +29 -10
  42. data/test/test_extension_methods.rb +62 -0
  43. data/test/test_file_manipulation.rb +4 -4
  44. data/test/test_file_path.rb +83 -56
  45. data/test/test_file_requirements.rb +36 -0
  46. data/test/test_fun_with_files.rb +1 -1
  47. data/test/test_fwf_assertions.rb +62 -0
  48. data/test/test_moving_files.rb +111 -0
  49. data/test/test_permission_methods.rb +22 -0
  50. data/test/test_root_path.rb +9 -0
  51. data/test/test_stat_methods.rb +17 -0
  52. data/test/test_timestamping.rb +74 -0
  53. data/test/test_utils_bytesize.rb +71 -0
  54. data/test/test_utils_succession.rb +30 -0
  55. data/test/test_watchers.rb +196 -0
  56. metadata +59 -13
  57. /data/lib/fun_with/files/core_extensions/{false.rb → false_class.rb} +0 -0
  58. /data/lib/fun_with/files/core_extensions/{nil.rb → nil_class.rb} +0 -0
@@ -0,0 +1,157 @@
1
+ # You want to watch a list of files or directories for changes
2
+ # (files created, deleted, or modified), and then return a... list?
3
+ # of changes.
4
+ #
5
+ # Tricky part is, what constitutes a "change" for a directory.
6
+ # or a file, for that matter.
7
+ #
8
+ # Cool expansion: customize the sorts of changes that trigger actions.
9
+ # You can already do that to some extent with the user-code that the
10
+ # change list is delivered to
11
+ #
12
+ # usr/ (modified, watched)
13
+ # bin/ (modified)
14
+ # new_directory/ (created)
15
+ # README.txt (created)
16
+ # bash (unchanged)
17
+ #
18
+ # lib/ (modified)
19
+ # libgpg.so (unchanged)
20
+ # libmysql.so (deleted)
21
+ # libzip.so (modified)
22
+ # libjpeg.so (file_created)
23
+ # you_have_been_hacked_by_chinese.txt (file_created)
24
+ # cache/ (deleted)
25
+ # firefox/ (deleted)
26
+ # cached_item.jpg (deleted)
27
+ # cached_folder/ (deleted)
28
+ # cache_file.csv (deleted)
29
+ #
30
+ # When you find a change in a subdirector/file, the :modified status
31
+ # propagates up the tree.
32
+ # Feels like a job for a visitor.
33
+ #
34
+ # If you create the top-level watcher, it could create any sub-watchers
35
+ # for the files and folders. It asks its watchers to update their
36
+ # statuses and report back.
37
+ #
38
+ # But the top-level one should know that it's the top level, so it
39
+ # shouldn't be deleting its watchers that might be, for example,
40
+ # waiting for a file to come into being.
41
+ #
42
+ # Hence, anyone using this code probably ought to stick to using the main Watcher
43
+ # class, and not worry about the ones it uses in the background
44
+ #
45
+ # Filters can be added
46
+ module FunWith
47
+ module Files
48
+ class Watcher
49
+ def self.watch( *paths, interval: 1.0, notice: [], ignore: [], &block )
50
+ watcher = self.new( paths ).sleep_interval( interval ).filter( notice: notice, ignore: ignore )
51
+
52
+ if block_given?
53
+ watcher.watch( &block )
54
+ else
55
+ watcher
56
+ end
57
+ end
58
+
59
+ def self.factory( path )
60
+ path = path.fwf_filepath
61
+
62
+ if path.exist?
63
+ if path.directory?
64
+ Watchers::DirectoryWatcher.new( path )
65
+ elsif path.file?
66
+ Watchers::FileWatcher.new( path )
67
+ end
68
+ else
69
+ Watchers::MissingWatcher.new( path )
70
+ end
71
+ end
72
+
73
+ def initialize( paths )
74
+ @sleep_interval = 1.0
75
+ @notice_filters = []
76
+ @ignore_filters = []
77
+
78
+ # Create a watcher for every single thing that we're
79
+ # asking it to watch
80
+ @watchers = paths.inject({}) do |watchers, path|
81
+ watchers[path.fwf_filepath] = self.class.factory( path )
82
+ watchers
83
+ end
84
+ end
85
+
86
+ def sleep_interval( i )
87
+ @sleep_interval = i
88
+ self
89
+ end
90
+
91
+ def watch( &block )
92
+ while true
93
+ sleep( @sleep_interval )
94
+ yield self.update
95
+ end
96
+ end
97
+
98
+ def filter( notice: [], ignore: [] )
99
+ @notice_filters += [notice].flatten
100
+ @ignore_filters += [ignore].flatten
101
+
102
+ self
103
+ end
104
+
105
+ # returns a hash of the changes that have happened in the file system being monitored,
106
+ def update
107
+ {}.tap do |changes|
108
+ for path, watcher in @watchers
109
+ changes.merge!( watcher.update )
110
+ replace_watcher( path, changes[path] ) # a DirectoryWatcher might need to be replaced with a MissingWatcher, for example, or vice-versa
111
+
112
+ # corner case: if a directory is created, everything created under the directory
113
+ # is deemed to have also been created at the same time
114
+ if path.directory? && changes[path] == :created
115
+ changes.merge!( path.glob(:all).inject({}){ |memo,path| memo[path] = :created ; memo } )
116
+ end
117
+ end
118
+
119
+ apply_filters( changes )
120
+ end
121
+ end
122
+
123
+ def replace_watcher( path, change )
124
+ case change
125
+ when nil
126
+ # didn't change
127
+ when :deleted, :created
128
+ @watchers[path] = self.class.factory( path )
129
+ end
130
+ end
131
+
132
+ #
133
+ def apply_filters( changes )
134
+ apply_notice_filters( changes )
135
+ apply_ignore_filters( changes )
136
+ changes
137
+ end
138
+
139
+ def apply_notice_filters( changes )
140
+ for filter in @notice_filters
141
+ for path in changes.keys
142
+ changes.delete( path ) if path !~ filter
143
+ end
144
+ end
145
+ end
146
+
147
+ def apply_ignore_filters( changes )
148
+ for filter in @ignore_filters
149
+ for path in changes.keys
150
+ changes.delete( path ) if path =~ filter
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
@@ -0,0 +1,67 @@
1
+ module FunWith
2
+ module Files
3
+ module Watchers
4
+ class DirectoryWatcher < NodeWatcher
5
+ def initialize( path )
6
+ set_path( path )
7
+ @watchers = create_watchers( self.path.entries )
8
+ end
9
+
10
+
11
+ # returns a hash of changes
12
+ def update
13
+ new_changeset do
14
+ if self.path.exist?
15
+ update_existing_files
16
+ find_new_files
17
+ else
18
+ # If the directory is gone, you can assume the same is true
19
+ # for all the files it held.
20
+ report_files( self.all_paths, :deleted )
21
+ end
22
+ end
23
+ end
24
+
25
+ def update_existing_files
26
+ # first, check on the files we're supposed to be keeping track of
27
+ for path, watcher in @watchers
28
+ @changes[path] = :deleted unless path.exist?
29
+ @changes.merge!( watcher.update )
30
+
31
+ # While the main Watcher will continue to monitor the places it's
32
+ # been told, even if they're missing, the subwatchers just disappear
33
+ # when the files they're watching do.
34
+ @watchers.delete( path ) unless path.exist?
35
+ end
36
+ end
37
+
38
+ def find_new_files
39
+ # next, get the updated list of files/folders beneath this directory
40
+ current_paths = self.path.entries
41
+
42
+ for path in current_paths
43
+ unless @watchers.has_key?( path )
44
+ w = Watcher.factory( path )
45
+
46
+ report_files( w.all_paths, :created )
47
+
48
+ @watchers[path] = w
49
+ end
50
+ end
51
+ end
52
+
53
+ # modify the current list of changes by adding "deleted" for
54
+ # every file/folder below this one.
55
+ def report_files( paths, status )
56
+ for path in paths
57
+ @changes[path] = status
58
+ end
59
+ end
60
+
61
+ def all_paths
62
+ @watchers.map{|path, watcher| watcher.all_paths }.flatten + [self.path]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+
2
+ module FunWith
3
+ module Files
4
+ module Watchers
5
+ class FileWatcher < NodeWatcher
6
+ attr_accessor :last_modified
7
+
8
+ def initialize( path )
9
+ set_path( path )
10
+ refresh_last_modified
11
+ end
12
+
13
+ def refresh_last_modified
14
+ self.last_modified = self.path.stat.mtime if self.path.exist?
15
+ end
16
+
17
+ def modified?
18
+ self.path.exist? && self.last_modified < self.path.stat.mtime
19
+ end
20
+
21
+ def deleted?
22
+ ! self.path.exist?
23
+ end
24
+
25
+ def update
26
+ if deleted?
27
+ { self.path => :deleted }
28
+ elsif modified?
29
+ refresh_last_modified
30
+ { self.path => :modified }
31
+ else
32
+ {}
33
+ end
34
+ end
35
+
36
+ # returns all paths below it in the hierarchy, including
37
+ # the path of the node itself. In this case, there's
38
+ # only one path to return.
39
+ def all_paths
40
+ [self.path]
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ module FunWith
2
+ module Files
3
+ module Watchers
4
+ # Watches a path where nothing currently exists, and reports a change if
5
+ # something appears there.
6
+ class MissingWatcher < NodeWatcher
7
+ def initialize( path )
8
+ set_path( path )
9
+ end
10
+
11
+ # The fact that the watcher now needs to be replaced with a File/DirectoryWatcher
12
+ # must be handled elsewhere.
13
+ def update
14
+ self.path.exist? ? {self.path => :created } : {}
15
+ end
16
+
17
+ def all_paths
18
+ []
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ module FunWith
14
+ module Files
15
+ module Watchers
16
+ class NodeWatcher
17
+ attr_accessor :path
18
+
19
+ def set_path( path )
20
+ self.path = path.fwf_filepath
21
+ end
22
+
23
+ def create_watchers( paths )
24
+ {}.tap do |watchers|
25
+ for path in paths
26
+ watchers[path.fwf_filepath] = Watcher.factory( path )
27
+ end
28
+ end
29
+ end
30
+
31
+ # sets up an object variable for changes, then clears it and returns
32
+ # the changes. I got sick of passing the changes hash around.
33
+ def new_changeset( &block )
34
+ @changes = {}
35
+ yield
36
+
37
+ changes = @changes
38
+ @changes = {}
39
+ changes
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,91 @@
1
+ module FunWith
2
+ module Testing
3
+ module Assertions
4
+ module FunWithFiles
5
+ # The object given must be an instance of class FilePath
6
+ def assert_fwf_filepath( file, msg = nil )
7
+ msg = message(msg){ "File <#{file}> should be a FunWith::Files::FilePath" }
8
+ assert_kind_of FunWith::Files::FilePath, file, msg
9
+ end
10
+
11
+ # The object given is an instance of class FilePath, and points to
12
+ # a file that exists.
13
+ def assert_file( file, msg = nil )
14
+ assert_fwf_filepath( file, message(nil){ "...is not a file." } )
15
+
16
+ msg = message(msg){ "File should exist at <#{file}>." }
17
+ assert file.file?, msg
18
+ end
19
+
20
+ # The object given is a filepath, but doesn't point to
21
+ # an existing file or directory.
22
+ def assert_no_file( file, msg = nil )
23
+ assert_fwf_filepath( file, message )
24
+ msg = message(msg){ "No file/directory should exist at <#{file}>." }
25
+ refute file.file?, msg
26
+ end
27
+
28
+ # The object given is a filepath, and points to a directory
29
+ def assert_directory( file, msg = nil )
30
+ assert_fwf_filepath( file, msg )
31
+ msg = message(msg){ "<#{file}> should be a directory." }
32
+ assert file.directory?, msg
33
+ end
34
+
35
+ # The object given is a filepath, but doesn't point to a directory.
36
+ def assert_not_directory( file, msg = nil )
37
+ assert_fwf_filepath( file, message )
38
+ msg = message(msg){ "<#{file}> shouldn't be a directory." }
39
+ refute file.directory?
40
+ end
41
+
42
+ # The object given is a filepath.
43
+ # It points to a file that exists.
44
+ # That file is empty.
45
+ def assert_empty_file( file, msg = nil )
46
+ assert_fwf_filepath( file )
47
+ msg = message(msg){ "Empty file should exist at <#{file}>." }
48
+ assert file.file? && file.empty?, msg
49
+ end
50
+
51
+ # The object given is a filepath.
52
+ # It points to a directory that exists.
53
+ # That directory is empty.
54
+ def assert_empty_directory( file, msg = nil )
55
+ assert_fwf_filepath( file )
56
+ msg = message(msg){ "Empty directory should exist at <#{file}>." }
57
+ assert file.directory? && file.empty?, msg
58
+ end
59
+
60
+
61
+ # The object given is a filepath.
62
+ # It points to a file that exists.
63
+ # That file contains content.
64
+ def assert_file_has_content( file, msg = nil )
65
+ assert_fwf_filepath( file, message )
66
+ msg = message(msg){ "File should exist at <#{file}>, and have content." }
67
+ assert file.exist?, msg.call + "(file does not exist)"
68
+ assert file.file?, msg.call + "(not a file)"
69
+ refute file.empty?, msg.call + "(file is not empty)"
70
+ end
71
+
72
+ alias :assert_file_not_empty :assert_file_has_content
73
+
74
+
75
+ def assert_file_contents( file, content, msg = nil )
76
+ assert_file( file )
77
+
78
+ case content
79
+ when String
80
+ # message = build_message( message, "File <#{file}> contents should be #{content[0..99].inspect}#{'...(truncated)' if content.length > 100}" )
81
+ assert_equal( content, file.read, msg )
82
+ when Regexp
83
+ assert_match( content, file.read, msg )
84
+ end
85
+ end
86
+
87
+
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,12 @@
1
+ # The bulk of FunWith::Testing::TestCase can be found in the fun_with_testing gem.
2
+
3
+ module FunWith
4
+ module Testing
5
+ module TestCaseExtensions
6
+ def install_fun_with_files_assertions
7
+ include FunWith::Testing::Assertions::Basics # some of the FWF assertions rely on these
8
+ include FunWith::Testing::Assertions::FunWithFiles
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,38 +1,12 @@
1
1
  require 'xdg'
2
2
  require 'digest' # stdlib
3
3
  require 'pathname' # stdlib
4
+ require 'set'
4
5
  require 'tmpdir' # Dir.tmpdir
5
6
 
7
+ require 'debug'
6
8
 
7
- for fil in ["string", "array", "false", "hash", "nil", "object"]
8
- require_relative File.join( "fun_with", "files", "core_extensions", fil )
9
- end
9
+ require_relative 'fun_with/files/bootstrapper'
10
+ # sets up everything needed to load .requir(), which loads everything else
11
+ FunWith::Files::Bootstrapper.bootstrap
10
12
 
11
- for klass in ["String", "Object", "NilClass", "Hash", "FalseClass", "Array"]
12
- Kernel.const_get(klass).send( :include, FunWith::Files::CoreExtensions.const_get(klass))
13
- end
14
-
15
-
16
- for fil in ["file_path", "string_behavior", "file_manipulation_methods", "file_permission_methods", "digest_methods", "file_requirements"]
17
- require_relative File.join( "fun_with", "files", fil )
18
- end
19
-
20
-
21
- # These have some FilePath methods required by .requir()
22
- for mod in [ FunWith::Files::StringBehavior,
23
- FunWith::Files::FileManipulationMethods,
24
- FunWith::Files::FilePermissionMethods,
25
- FunWith::Files::DigestMethods,
26
- FunWith::Files::FileRequirements ]
27
- FunWith::Files::FilePath.send( :include, mod )
28
- end
29
-
30
- lib_dir = File.dirname(__FILE__).fwf_filepath( "fun_with" )
31
-
32
- # And requir() everything else
33
- lib_dir.requir
34
-
35
- FunWith::Files::RootPath.rootify( FunWith::Files, __FILE__.fwf_filepath.dirname.up )
36
- FunWith::Files::FilePath.extend( FunWith::Files::FilePathClassMethods )
37
-
38
- FunWith::Files.extend( FunWith::Files::GemAPI )
data/test/helper.rb CHANGED
@@ -21,13 +21,21 @@ require 'fun_with_files'
21
21
 
22
22
  class FunWith::Files::TestCase < FunWith::Testing::TestCase
23
23
  include FunWith::Files
24
- include FunWith::Testing::Assertions::FunWithFiles
25
- include FunWith::Testing::Assertions::Basics
24
+ include FunWith::Files::Errors
25
+
26
+
27
+ self.install_fun_with_files_assertions
28
+ # include FunWith::Testing::Assertions::FunWithFiles
29
+ # include FunWith::Testing::Assertions::Basics
26
30
 
27
31
  def tmpdir( &block )
28
- FilePath.tmpdir do |d|
29
- @tmpdir = d
30
- yield
32
+ if block_given?
33
+ FilePath.tmpdir do |d|
34
+ @tmpdir = d
35
+ yield
36
+ end
37
+ else
38
+ @tmpdir = FilePath.tmpdir # remember to remove the directory when you're done
31
39
  end
32
40
  end
33
41
 
@@ -26,6 +26,12 @@ class TestCoreExtensions < FunWith::Files::TestCase
26
26
  should "fwf_blank? nicely." do
27
27
  assert_equal false, { 1 => 2 }.fwf_blank?
28
28
  assert_equal true, {}.fwf_blank?
29
+ assert_equal true, true.fwf_present?
30
+ end
31
+
32
+ should "respond to fwf_filepath" do
33
+ assert_respond_to ".", :fwf_filepath
34
+ assert_respond_to ".".fwf_filepath, :fwf_filepath
29
35
  end
30
36
  end
31
37
  end
data/test/test_descent.rb CHANGED
@@ -7,11 +7,11 @@ class TestDescent < FunWith::Files::TestCase
7
7
  ascent = []
8
8
  descent = []
9
9
 
10
- FunWith::Files.root.ascend do |path|
10
+ root.ascend do |path|
11
11
  ascent << path
12
12
  end
13
13
 
14
- FunWith::Files.root.descend do |path|
14
+ root.descend do |path|
15
15
  descent << path
16
16
  end
17
17
 
@@ -54,7 +54,7 @@ class TestDirectoryBuilder < FunWith::Files::TestCase
54
54
  gemfile = b.current_path.join("Gemfile")
55
55
  assert gemfile.exist?
56
56
  assert !gemfile.zero?
57
- assert_equal 1, gemfile.grep( /jeweler/ ).length
57
+ assert_equal 1, gemfile.grep( /fun_with_testing/ ).length
58
58
  end
59
59
  end
60
60
 
@@ -70,18 +70,37 @@ class TestDirectoryBuilder < FunWith::Files::TestCase
70
70
  should "download random crap from all over the Internet" do
71
71
  if_internet_works do
72
72
  DirectoryBuilder.tmpdir do |b|
73
- gist_url = "http://bannedsorcery.com/downloads/testfile.txt"
74
- gist_text = "This is a file\n==============\n\n**silent**: But _bold_! [Link](http://slashdot.org)\n"
75
- b.download( gist_url, "gist.txt" )
73
+ # The file Bryce uses on Github to prove to Keybase that he owns this Github account
74
+ # I used to host a test file on my own site, but apparently if you stop paying DigitalOcean
75
+ # for a few measly months your website goes away. Github will probably provide a more
76
+ # stable target.
77
+ url = "https://gist.githubusercontent.com/darthschmoo/ac3ca60338ed41e87b94448f9e851fd3/raw" +
78
+ "/3cba6b60b552266f4d5aa92d307ef2cda0cf228b/fun_with_files.download.txt"
79
+
80
+ dest_file = "download.01.txt"
81
+ dest_file2 = "download.02.txt"
82
+
83
+ downloaded_text = "You have successfully downloaded a file. Huzzah!"
84
+ downloaded_text_md5 = "2e9d3a924ea36c860c3dd491166ec1ce"
85
+ downloaded_text_sha1 = "d9be1d5b5c8bd1de6b1dcb99e02cab8e35ed9659"
86
+ downloaded_text_sha256 = "dc9a6e5d571b39b9754b9592a3b586db8186121d37ec72f7fcbf45241cc43aa6"
87
+
88
+ b.download( url, dest_file,
89
+ :md5 => downloaded_text_md5,
90
+ :sha1 => downloaded_text_sha1,
91
+ :sha256 => downloaded_text_sha256
92
+ )
93
+
76
94
 
77
- b.file( "gist.txt.2" ) do
78
- b.download( gist_url )
95
+ b.file( dest_file2 ) do
96
+ b.download( url )
79
97
  end
80
98
 
81
99
  assert b.current_file.nil?
82
- assert b.current_path.join("gist.txt").exist?
83
- assert b.current_path.join("gist.txt.2").exist?
84
- assert_equal gist_text, b.current_path.join("gist.txt").read
100
+ assert b.current_path.join( dest_file ).exist?
101
+ assert b.current_path.join( dest_file2 ).exist?
102
+ assert_equal downloaded_text, b.current_path.join( dest_file ).read
103
+ assert_equal downloaded_text, b.current_path.join( dest_file2 ).read
85
104
  end
86
105
  end
87
106
  end
@@ -112,7 +131,7 @@ class TestDirectoryBuilder < FunWith::Files::TestCase
112
131
  end
113
132
  end
114
133
 
115
- assert "Hello", b.current_path.join("earth", "air", "fire", "water", "hello.txt").read
134
+ assert_equal "Hello", b.current_path.join("earth", "air", "fire", "water", "hello.txt").read
116
135
 
117
136
  b.dir( "fire", "water", "earth", "air" ) do
118
137
  assert b.current_path.exist?
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+
3
+ class TestExtensionMethods < FunWith::Files::TestCase
4
+ context "Testing extension methods" do
5
+ setup do
6
+ @bash = "/bin/bash".fwf_filepath
7
+ @log = "/var/log/apache/access.log".fwf_filepath
8
+ @older_log = "/var/log/apache/access.log.9"
9
+ end
10
+
11
+ context "Testing ext?()" do
12
+ should "correctly identify the extension" do
13
+ assert_true @bash.ext?("")
14
+
15
+ assert_true @log.ext?(".log")
16
+ assert_true @log.ext?(:log)
17
+ assert_false @log.ext?(".blog")
18
+ assert_true @log.ext?(:blog, :flog, :frog, :log)
19
+ end
20
+
21
+ should "run a block if the extension matches" do
22
+ var = 5
23
+
24
+ @log.ext?(:log) do |f|
25
+ assert_equal @log, f
26
+ var = 6
27
+ end
28
+
29
+ assert_equal 6, var
30
+ end
31
+ end
32
+
33
+ context "Testing file.ext()" do
34
+
35
+ should "draw a blank on bash file" do
36
+ assert_blank @bash.ext
37
+ assert_equal "", @bash.ext
38
+ end
39
+
40
+ should "add an extension when an extension is given as an argument" do
41
+ bash2 = @bash.ext( 12 )
42
+
43
+ assert_fwf_filepath bash2
44
+ assert_equal "12", bash2.ext
45
+
46
+ for ext in [:exe, "exe"]
47
+ bash2 = @bash.ext( ext )
48
+ assert_fwf_filepath bash2
49
+ assert_equal "exe", bash2.ext
50
+ end
51
+ end
52
+
53
+ should "add multiple extensions when multiple extensions are given" do
54
+ for args in [ [:tar, :gz], ["tar", "gz"], [".tar", ".gz"] ]
55
+ bash2 = @bash.ext( *args )
56
+ assert_equal "gz", bash2.ext
57
+ assert_equal "/bin/bash.tar.gz", bash2.path
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end