fun_with_files 0.0.14 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cf6595c5de6273e8d7fb668ddc70d161a1354c4c
4
- data.tar.gz: 4938516e5ad413f8ffa722985d963fcb6eb1f039
2
+ SHA256:
3
+ metadata.gz: d22de5c44faf70d934da05efbd93f17373e8317bbc6304c5674c2f79183d45b2
4
+ data.tar.gz: 89d022cd00c4e14be9c82fc62045e82db6095e9a16239e29c085a605c0c0cde9
5
5
  SHA512:
6
- metadata.gz: 09db56d93b3cde0407d1f0e7d8691ab0373158301828ee5af974c1cb259369c2f8a5c43c79eb37352760bede2d5d4d4f310887b9129aba917100109643138787
7
- data.tar.gz: 06690ccc56d90230e7d8c55a9f9372cc74dc9f6ff1104fe7f8ea26c1efdb601b5ff221a0c4250630d40ab7e2a065cc71ff124545de1ed1a66405fc591ffbc49a
6
+ metadata.gz: b8fb4d70f1bc7c29439b7237e38e79f5661334fd7c8c3457f5ae1bde20b053eb95dccd5d8c5ad3bf3a4f16443375ace9f889822116680b136d154e53ab118411
7
+ data.tar.gz: fdd5d8bc41b89c5e0a4f3c83580f4f45679cb3bc38ee9539f332f1a26572cf68ffd549b7118787f6068d1247711cafe175cf7389a0aff1532cf6407c96384ba7
data/CHANGELOG.markdown CHANGED
@@ -1,13 +1,25 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ v0.0.18
5
+ -------
6
+
7
+ * restricted the use of the file.succ() method, and removed timestamp functionality from it. Now it only works if the initial file has an extension (no trailing counter, like file.000001 ). Still fills in
8
+
9
+ v0.0.17
10
+ -------
11
+
12
+ * `.without_ext()` now takes an argument, will only strip that extension.
13
+ * updated `fun_with_testing` dependency, moved FunWith::Files-related stuff from that gem to this one.
14
+
15
+
4
16
  v0.0.14
5
- =======
17
+ -------
6
18
 
7
- Make symlinking actually work in a sensible way.
19
+ ???
8
20
 
9
21
  v0.0.12
10
- =======
22
+ -------
11
23
 
12
24
  FilePath.touch() takes same options as FileUtils.touch()
13
25
  FilePath.glob() now takes a block (yields files one at a time)
data/Gemfile CHANGED
@@ -7,12 +7,22 @@ source "http://rubygems.org"
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
 
9
9
  group :development do
10
- # gem "shoulda", "~> 3", ">= 3.5"
11
- # gem "rdoc", "~> 3.12"
12
- # gem "bundler", "~> 1.5"
13
- # gem "jeweler", "~> 2.0"
14
- # gem "debugger", "~> 1.6"
15
- gem "fun_with_testing", "~> 0.0"
10
+ gem "debug"
11
+ gem "fun_with_testing", "~> 0.0", ">= 0.0.7"
16
12
  end
17
13
 
18
- gem "xdg", "~> 2"
14
+
15
+ xdg_version = case RUBY_VERSION
16
+ when /^2\.7/
17
+ 3
18
+ when /^3\.0/
19
+ 5
20
+ when /^3\.2/
21
+ 7
22
+ end
23
+
24
+
25
+
26
+ gem "xdg", "~> #{xdg_version}"
27
+
28
+
@@ -1,4 +1,7 @@
1
- = fun_with_files =
1
+ # `fun_with_files`
2
+
3
+
4
+
2
5
 
3
6
  FunWith::Files adds a bit of whimsy to your file manipulations, if that's what you're looking for.
4
7
 
@@ -36,18 +39,17 @@ To the code!
36
39
 
37
40
 
38
41
 
39
- === Linking files ===
42
+ ### Linking files ###
40
43
 
41
44
  While fwf.symlink and fwf.link are both backed by FileUtils.ln / FileUtils.ln_s, the defaults are somewhat different
42
45
 
43
46
 
44
47
 
45
- == DirectoryBuilder ==
48
+ ## DirectoryBuilder ##
46
49
 
47
50
  DirectoryBuilder is a class for defining and populating a file hierarchy with relative ease. DirectoryBuilder is probably most easily demonstrated by example. Sample code:
48
51
 
49
- # starts by creating directory. If parent
50
- # directories don't exist, they will soon.
52
+ # starts by creating directory. If parent directories don't exist, they will soon.
51
53
  DirectoryBuilder.create( '~/project' ) do |b|
52
54
  b.dir("images") do # creates subdirectory "images", which gets populated within the block
53
55
  for img in src_dir.entries.select{|img| img.extension == ".png"}
@@ -60,7 +62,7 @@ DirectoryBuilder is a class for defining and populating a file hierarchy with re
60
62
 
61
63
  b.dir("text", "scenes") do # creates ~/project/text/scenes subdir (creating two new directories text/ and text/scene/)
62
64
  b.file( "adventure_time.txt" ) do |f|
63
- f << "Fill this in later"
65
+ f << "Fill this in later" # text is written to the file
64
66
  end
65
67
 
66
68
  # calling .file without feeding it a block leaves it open for writing,
@@ -106,9 +108,9 @@ DirectoryBuilder is a class for defining and populating a file hierarchy with re
106
108
 
107
109
 
108
110
 
109
- == Contributing to fun_with_files
111
+ ## Contributing to fun_with_files ##
110
112
 
111
- Boilerplate from Jeweler, but seems to make sense.
113
+ Boilerplate from Juwelier, but seems to make sense.
112
114
 
113
115
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
114
116
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
@@ -118,8 +120,7 @@ Boilerplate from Jeweler, but seems to make sense.
118
120
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
119
121
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
120
122
 
121
- == Copyright
123
+ ## Copyright ##
122
124
 
123
- Copyright (c) 2013 Bryce Anderson. See LICENSE.txt for
124
- further details.
125
+ Copyright (c) 2020 Bryce Anderson. See LICENSE.txt for further details.
125
126
 
data/Rakefile CHANGED
@@ -14,8 +14,8 @@ end
14
14
 
15
15
  require 'rake'
16
16
 
17
- # require 'jeweler'
18
- Jeweler::Tasks.new do |gem|
17
+ # require 'juwelier'
18
+ Juwelier::Tasks.new do |gem|
19
19
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
20
20
  gem.name = "fun_with_files"
21
21
  gem.homepage = "http://github.com/darthschmoo/fun_with_files"
@@ -50,7 +50,7 @@ DESC
50
50
  ]
51
51
  end
52
52
 
53
- Jeweler::RubygemsDotOrgTasks.new
53
+ Juwelier::RubygemsDotOrgTasks.new
54
54
 
55
55
  require 'rake/testtask'
56
56
  Rake::TestTask.new(:test) do |test|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.14
1
+ 0.0.18
@@ -0,0 +1,87 @@
1
+ module FunWith
2
+ module Files
3
+ class Bootstrapper
4
+ def self.bootstrap
5
+ self.new.bootstrap
6
+ end
7
+
8
+ def bootstrap
9
+ load_core_extensions
10
+ install_minimal_requir_functionality
11
+ run_requir
12
+ rootify
13
+ add_filepath_class_methods
14
+ extend_gem_api
15
+ end
16
+
17
+ protected
18
+ # gets all the core-extending modules from fun_with/files/core_extensions and uses them to
19
+ # beef up the core classes
20
+ def load_core_extensions
21
+ for file in Dir.glob( File.join( __dir__, "core_extensions", "*.rb" ) )
22
+ # remove trailing extension to make it require-friendly.
23
+ file = file.gsub(/\.rb$/,'')
24
+
25
+ require_relative file
26
+
27
+ # convert filename into class name
28
+ target_class_str = filename_to_class_name( file )
29
+
30
+ # get the core class that needs extending, and the
31
+ target_class = Kernel.const_get( target_class_str )
32
+ mixin_class = Kernel.const_get( "FunWith::Files::CoreExtensions::#{target_class_str}" )
33
+
34
+ target_class.send( :include, mixin_class )
35
+ end
36
+ end
37
+
38
+ def install_minimal_requir_functionality
39
+ for fil in %w( file_path
40
+ string_behavior
41
+ file_manipulation_methods
42
+ file_permission_methods
43
+ digest_methods
44
+ file_requirements
45
+ requirements/manager
46
+ stat_methods )
47
+ require_relative fil
48
+ end
49
+
50
+ # These have some FilePath methods required by .requir()
51
+ for mod in [ FunWith::Files::StringBehavior,
52
+ FunWith::Files::FileManipulationMethods,
53
+ FunWith::Files::FilePermissionMethods,
54
+ FunWith::Files::DigestMethods,
55
+ FunWith::Files::FileRequirements,
56
+ FunWith::Files::StatMethods ]
57
+ FunWith::Files::FilePath.send( :include, mod )
58
+ end
59
+ end
60
+
61
+ def run_requir
62
+ lib_dir = __dir__.fwf_filepath.up
63
+
64
+ # And requir() everything else
65
+ lib_dir.requir
66
+ end
67
+
68
+ def rootify
69
+ root_dir = __dir__.fwf_filepath.up.up.up
70
+ FunWith::Files::RootPath.rootify( FunWith::Files, root_dir )
71
+ end
72
+
73
+ def add_filepath_class_methods
74
+ FunWith::Files::FilePath.extend( FunWith::Files::FilePathClassMethods )
75
+ end
76
+
77
+ def extend_gem_api
78
+ FunWith::Files.extend( FunWith::Files::GemAPI )
79
+ end
80
+
81
+
82
+ def filename_to_class_name( str )
83
+ File.basename( str ).split( "_" ).map(&:capitalize).join("")
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,5 +1,17 @@
1
- class File < IO
2
- def fwf_filepath( *args )
3
- FunWith::Files::FilePath.new( self.path, *args )
1
+ module FunWith
2
+ module Files
3
+ module CoreExtensions
4
+ module File
5
+ def fwf_filepath( *args )
6
+ FunWith::Files::FilePath.new( self.path, *args )
7
+ end
8
+
9
+ # I'm not sure this is the most intuitive meaning, but it seems better than
10
+ # delegating to Object.
11
+ def fwf_blank?
12
+ ! self.fwf_filepath.exist?
13
+ end
14
+ end
15
+ end
4
16
  end
5
17
  end
@@ -0,0 +1,12 @@
1
+ module FunWith
2
+ module Files
3
+ module CoreExtensions
4
+ module Set
5
+ def fwf_blank?
6
+ self.length == 0
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,11 @@
1
+ module FunWith
2
+ module Files
3
+ module CoreExtensions
4
+ module TrueClass
5
+ def fwf_blank?
6
+ false
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,37 +1,70 @@
1
1
  module FunWith
2
2
  module Files
3
+ DIGEST_METHODS = [:md5, :sha1, :sha2, :sha224, :sha256, :sha384, :sha512]
4
+
3
5
  module DigestMethods
4
- def md5
5
- digest( Digest::MD5 )
6
+ def md5( bytes = :all, offset = 0 )
7
+ digest( Digest::MD5, bytes, offset )
6
8
  end
7
9
 
8
- def sha1
9
- digest( Digest::SHA1 )
10
+ def sha1( bytes = :all, offset = 0 )
11
+ digest( Digest::SHA1, bytes, offset )
10
12
  end
11
13
 
12
- def sha2
13
- digest( Digest::SHA2 )
14
+ def sha2( bytes = :all, offset = 0 )
15
+ digest( Digest::SHA2, bytes, offset )
14
16
  end
15
17
 
16
- def sha224
17
- digest( Digest::SHA224 )
18
+ def sha224( bytes = :all, offset = 0 )
19
+ digest( Digest::SHA224, bytes, offset )
18
20
  end
19
21
 
20
- def sha256
21
- digest( Digest::SHA256 )
22
+ def sha256( bytes = :all, offset = 0 )
23
+ digest( Digest::SHA256, bytes, offset )
22
24
  end
23
25
 
24
- def sha384
25
- digest( Digest::SHA384 )
26
+ def sha384( bytes = :all, offset = 0 )
27
+ digest( Digest::SHA384, bytes, offset )
26
28
  end
27
29
 
28
- def sha512
29
- digest( Digest::SHA512 )
30
+ def sha512( bytes = :all, offset = 0 )
31
+ digest( Digest::SHA512, bytes, offset )
30
32
  end
31
-
32
- def digest( digest_class = Digest::MD5 )
33
- self.file? ? digest_class.hexdigest( self.read ) : ""
33
+
34
+ def digest( digest_class = Digest::MD5, bytes = :all, offset = 0 )
35
+ if self.file? && self.readable?
36
+ if bytes == :all
37
+ digest_class.hexdigest( self.read )
38
+ elsif bytes.is_a?( Integer )
39
+ digest_class.hexdigest( self.read( bytes, offset ) )
40
+ else
41
+ raise ArgumentError.new( "FunWith::Files::DigestMethods.digest() error: bytes argument must be an integer or :all")
42
+ end
43
+ else
44
+ raise IOError.new( "Not a file: #{self.path}" ) unless self.file?
45
+ raise IOError.new( "Not readable: #{self.path}" ) unless self.readable?
46
+ end
34
47
  end
48
+
49
+ # Takes any of the above-named digest functions, determines
50
+ # whether the file matches a given digest string.
51
+ #
52
+ # Multiple digests can be given simultaneously. All must pass.
53
+ #
54
+ # TODO: how to get around the :md6 problem? That is, where the
55
+ # user is sending the wrong key, and hence not getting false back
56
+ def valid_digest?( opts )
57
+ digest_opts = Utils::Opts.narrow_options( opts, DIGEST_METHODS )
58
+
59
+
60
+ for method, digest in opts
61
+ if DIGEST_METHODS.include?( method )
62
+ return false unless self.send( method ) == digest
63
+ end
64
+ end
65
+
66
+ return true
67
+ end
35
68
  end
36
69
  end
37
70
  end
@@ -9,6 +9,7 @@ module FunWith
9
9
  def initialize( path )
10
10
  @paths = []
11
11
  @current_path = path.fwf_filepath
12
+ @current_file = nil
12
13
  make_path
13
14
  end
14
15
 
@@ -40,6 +41,9 @@ module FunWith
40
41
 
41
42
  # Copies the given source file into a file in the current_path.
42
43
  # If a dest_name is given, the new file will be given that name.
44
+ #
45
+ # TODO: Improve testing, explain behavior better, need a way to distinguish between
46
+ # forceful and gentle copying
43
47
  def copy( src_filepath, dst_name = nil )
44
48
  dst_filepath = dst_name ? @current_path.join( dst_name ) : @current_path
45
49
  FileUtils.copy( src_filepath, dst_filepath )
@@ -79,7 +83,7 @@ module FunWith
79
83
  # end
80
84
 
81
85
  # if file not given, the result is appended to the current file.
82
- def download( url, file = nil )
86
+ def download( url, file = nil, opts = {} )
83
87
  if file
84
88
  if file.fwf_filepath.relative?
85
89
  file = FunWith::Files::FilePath.new( @current_path, file )
@@ -89,12 +93,13 @@ module FunWith
89
93
  download_to_target( url, f )
90
94
  end
91
95
  elsif @current_file
92
- download_to_target( url, @current_file )
96
+ download_to_target( url, @current_file, opts )
93
97
  else
94
98
  puts "No current file to append #{url} to."
95
99
  end
96
100
  end
97
101
 
102
+ # The actual method is installed by 'fun_with_templates'
98
103
  def template( *args )
99
104
  raise "DirectoryBuilder cannot use template() function. require 'fun_with_templates' to enable."
100
105
  end
@@ -132,8 +137,8 @@ module FunWith
132
137
  @current_file = nil
133
138
  end
134
139
 
135
- def download_to_target( url, file )
136
- Downloader.new.download( url, file )
140
+ def download_to_target( url, file, signatures = {} )
141
+ Downloader.new.download( url, file, signatures )
137
142
  end
138
143
  end
139
144
  end
@@ -1,36 +1,49 @@
1
1
  require 'open-uri' # needed by Utils::Downloader
2
2
  require 'net/http'
3
+ require 'net/https'
4
+ require 'openssl'
3
5
  require 'timeout'
4
6
 
5
7
 
6
8
  module FunWith
7
9
  module Files
8
10
  class Downloader
11
+ def self.download( *args )
12
+ self.new.download( *args )
13
+ end
14
+
9
15
  # stolen from:
10
16
  # http://stackoverflow.com/questions/2263540/how-do-i-download-a-binary-file-over-http-using-ruby
11
- def download( url, io )
17
+
18
+ # options:
19
+ # :md5 => <digest> : Running md5 on the downloaded file should result in an error
20
+ # :sha256 => <digest> :
21
+ def download( url, io, opts = {} )
12
22
  @uri = URI.parse( url )
13
23
  @io = io
14
24
 
15
- open( url ) do |f|
25
+ URI.open( url ) do |f|
16
26
  @io << f.read
17
27
  end
18
-
19
- # @io << Net::HTTP.get( @uri )
20
-
21
- # Net::HTTP.start( @uri.host, @uri.port ) do |http|
22
- # http.request_get( @uri.path ) do |request|
23
- # request.read_body do |seg|
24
- # puts "============================== #{seg} ============================="
25
- # io << seg
26
- # #hack -- adjust to suit:
27
- # sleep 0.005
28
- # end
29
- # end
30
- # end
31
- rescue Exception => e
28
+
29
+ io_path = @io.fwf_filepath
30
+
31
+ if io_path.file?
32
+ if io_path.valid_digest?( opts )
33
+ true
34
+ else
35
+ warn( "File may not have downloaded correctly, or is validating against a bad hash #{io_path} #{opts.inspect}")
36
+ false
37
+
38
+ end
39
+ else
40
+ warn( "File did not download correctly, or was deleted: #{io_path}")
41
+ false
42
+ end
43
+ rescue StandardError => e
32
44
  handle_network_errors( e )
33
45
  end
46
+
34
47
 
35
48
  def handle_network_errors( e )
36
49
  raise e
@@ -1,5 +1,13 @@
1
1
  module FunWith
2
2
  module Files
3
- class NoSuchFile < Exception; end
3
+ # Useful... why, exactly?
4
+ module Errors
5
+ class Error < StandardError; end
6
+ class SuccessionFormattingError < Error; end
7
+ class TimestampFormatUnrecognized < Error; end
8
+ class FileNotEmpty < Error; end
9
+ class NotADirectory < Error; end
10
+ class NotAFile < Error; end
11
+ end
4
12
  end
5
13
  end
@@ -15,6 +15,12 @@ module FunWith
15
15
  # ln_s(list, destdir, options)
16
16
  # ln_sf(src, dest, options)
17
17
 
18
+ #
19
+
20
+
21
+ # => [:alias_method, :ancestors, :attr, :attr_accessor, :attr_reader, :attr_writer, :autoload, :autoload?, :cd, :chdir, :chmod, :chmod_R, :chown, :chown_R, :class_eval, :class_exec, :class_variable_defined?, :class_variable_get, :class_variable_set, :class_variables, :cmp, :collect_method, :commands, :compare_file, :compare_stream, :const_defined?, :const_get, :const_missing, :const_set, :constants, :copy, :copy_entry, :copy_file, :copy_stream, :cp, :cp_r, :define_method, :deprecate_constant, :getwd, :have_option?, :identical?, :include, :include?, :included_modules, :install, :instance_method, :instance_methods, :link, :ln, :ln_s, :ln_sf, :makedirs, :method_defined?, :mkdir, :mkdir_p, :mkpath, :module_eval, :module_exec, :move, :mv, :name, :options, :options_of, :prepend, :private_class_method, :private_constant, :private_instance_methods, :private_method_defined?, :private_module_function, :protected_instance_methods, :protected_method_defined?, :public_class_method, :public_constant, :public_instance_method, :public_instance_methods, :public_method_defined?, :pwd, :remove, :remove_class_variable, :remove_dir, :remove_entry, :remove_entry_secure, :remove_file, :remove_method, :rm, :rm_f, :rm_r, :rm_rf, :rmdir, :rmtree, :safe_unlink, :singleton_class?, :symlink, :touch, :undef_method, :uptodate?]
22
+
23
+
18
24
  # opts are the last argument, and are passed to FileUtils.cp_r
19
25
  # returns the destination path.
20
26
  # How to detect failure? What to return on failure?
@@ -22,16 +28,22 @@ module FunWith
22
28
  #
23
29
  def cp( *args )
24
30
  destination_and_options( args ) do |dest, opts|
25
- FileUtils.cp_r( self, dest, narrow_options( opts, FileUtils::OPT_TABLE["cp_r"] ) )
31
+ FileUtils.cp_r( self, dest, ** Utils::Opts.narrow_file_utils_options( opts, :cp_r ) )
26
32
  dest.fwf_filepath
27
33
  end
28
34
  end
29
35
 
30
36
  alias :copy :cp
31
37
 
32
- # Treat as a copy then a delete? Nah, that's a lot slower in some cases. Should be much more in tune with what the command line program does
33
- def mv( *args )
34
-
38
+ # Treat as a copy then a delete? Nah, that's a lot slower especially for larger files. Should be much more in tune with what the command line program does.
39
+ # Treat it as syntactic sugar for FileUtils.mv?
40
+ # Also want to update the path to the new location - not implemented yet
41
+ #
42
+ #
43
+ def mv( dst, options = {} )
44
+ # what does FileUtils.rm actually return? Glancing an the source, it
45
+ # seems to only throw errors.
46
+ FileUtils.mv( self, dst, **options )
35
47
  end
36
48
 
37
49
  alias :move :mv
@@ -45,13 +57,11 @@ module FunWith
45
57
  def link *args
46
58
  self.destination_and_options( args ) do |lnk, opts|
47
59
  symlink_requested = self.directory? || opts[:symbolic] || opts[:sym] || opts[:soft]
48
-
60
+
49
61
  if symlink_requested
50
62
  self.symlink lnk, opts
51
63
  else
52
- opts = narrow_options opts, FileUtils::OPT_TABLE["ln"]
53
-
54
- FileUtils.ln self, lnk, opts
64
+ FileUtils.ln self, lnk, ** Utils::Opts.narrow_file_utils_options( opts, :ln )
55
65
  end
56
66
 
57
67
  lnk.fwf_filepath
@@ -78,7 +88,7 @@ module FunWith
78
88
  lnk = lnk.fwf_filepath
79
89
  end
80
90
 
81
- FileUtils.ln_s( self, lnk, narrow_options( opts, FileUtils::OPT_TABLE["ln_s"] ) )
91
+ FileUtils.ln_s( self, lnk, ** Utils::Opts.narrow_file_utils_options( opts, :ln_s ) )
82
92
  lnk.fwf_filepath
83
93
  end
84
94
 
@@ -86,7 +96,7 @@ module FunWith
86
96
 
87
97
 
88
98
  def file_gsub( *args, &block )
89
- _must_be_a_file
99
+ must_be_file
90
100
 
91
101
  lines = []
92
102
  self.each_line do |line|
@@ -97,8 +107,8 @@ module FunWith
97
107
  end
98
108
 
99
109
  def file_gsub!( *args, &block )
100
- _must_be_a_file # raises error
101
- _must_be_writable # raises error
110
+ must_be_file # raises error
111
+ must_be_writable # raises error
102
112
 
103
113
  self.write( self.file_gsub( *args, &block ) )
104
114
  end
@@ -113,9 +123,9 @@ module FunWith
113
123
 
114
124
  # TODO: If it's truncated to a longer length than the original file,
115
125
  # pad with zeros? That's how the UNIX truncate command works.
116
- def truncate( len )
117
- _must_be_a_file # raises error
118
- _must_be_writable # raises error
126
+ def truncate( len = 0 )
127
+ must_be_file # raises error
128
+ must_be_writable # raises error
119
129
 
120
130
  old_size = self.size
121
131
  padding = len > old_size ? "\0" * (len - old_size) : ""
@@ -38,6 +38,8 @@ module FunWith
38
38
 
39
39
  collector
40
40
  end
41
+
42
+ ordered_files
41
43
  end
42
44
  end
43
45
  end