fun_with_files 0.0.9 → 0.0.12
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.
- checksums.yaml +8 -8
- data/VERSION +1 -1
- data/lib/fun_with/files/core_extensions/array.rb +11 -4
- data/lib/fun_with/files/core_extensions/false.rb +10 -4
- data/lib/fun_with/files/core_extensions/hash.rb +22 -4
- data/lib/fun_with/files/core_extensions/nil.rb +11 -4
- data/lib/fun_with/files/core_extensions/object.rb +12 -6
- data/lib/fun_with/files/core_extensions/string.rb +16 -6
- data/lib/fun_with/files/file_manipulation_methods.rb +50 -8
- data/lib/fun_with/files/file_path.rb +131 -41
- data/lib/fun_with/files/file_permission_methods.rb +2 -2
- data/lib/fun_with/files/file_requirements.rb +24 -0
- data/lib/fun_with/files/gem_api.rb +10 -0
- data/lib/fun_with/files/string_extensions.rb +2 -0
- data/lib/fun_with_files.rb +16 -7
- data/test/helper.rb +14 -4
- data/test/test_core_extensions.rb +31 -0
- data/test/test_directory_builder.rb +13 -11
- data/test/test_file_manipulation.rb +6 -0
- data/test/test_file_path.rb +1 -0
- data/test/test_fun_with_files.rb +3 -0
- data/test/test_globbing.rb +28 -2
- data/test/test_symlinking.rb +23 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzBiYWRhY2FhYmU2ZjExYzFlOWJmY2QzMjAzZDMyOTkzZTRmYmY0Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTA2OWE0NTc4NTY1ODk1M2Q2YjAzYTNiYjUyN2E4ODVmYWI4MDViYQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YWU0NzU0YTU1Y2QxMjU0MDJlMGVhMDBkNTBkNmQzNTYzN2FjMjRmMzRiNGIz
|
10
|
+
YjRhYmJkMjBkNDE5YjBhNTM4ODE1NjA3YjQ4MDY1YWZiOWI2NzExM2M4MTZj
|
11
|
+
MGMwYzRmZDZkMWY2Yjc5ZjAwYmNjZWVmZWEyYjhkMWU3M2YwZDY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjVkMmMwYzI0ODJmMmY1NTNkZTFiODlhZjI0NjA5NjIyODA0YmYzYWU4NmEy
|
14
|
+
OTY4OWE2ZjhlMTM2MjExOTdmOGQ2NTI5MjVjOTVkNzk4MWEzZGMyYTNlYjJj
|
15
|
+
MWNhNDU3ZTkzMWNhOTU5MjY0ZGU0Yjc5NmYzZWEwOTkyYmZlZTM=
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.12
|
@@ -1,5 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module FunWith
|
2
|
+
module Files
|
3
|
+
module CoreExtensions
|
4
|
+
module Hash
|
5
|
+
def fwf_blank?
|
6
|
+
self.length == 0
|
7
|
+
end
|
8
|
+
|
9
|
+
# Stolen from: activesupport/lib/active_support/core_ext/hash/reverse_merge.rb, line 12
|
10
|
+
def fwf_reverse_merge( other_hash )
|
11
|
+
other_hash.merge( self )
|
12
|
+
end
|
13
|
+
|
14
|
+
# File activesupport/lib/active_support/core_ext/hash/reverse_merge.rb, line 17
|
15
|
+
def fwf_reverse_merge!(other_hash)
|
16
|
+
# right wins if there is no left
|
17
|
+
merge!( other_hash ){|key,left,right| left }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
4
21
|
end
|
5
|
-
end
|
22
|
+
end
|
23
|
+
|
@@ -1,9 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module FunWith
|
2
|
+
module Files
|
3
|
+
module CoreExtensions
|
4
|
+
module Object
|
5
|
+
def fwf_blank?
|
6
|
+
false
|
7
|
+
end
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
def fwf_present?
|
10
|
+
! self.fwf_blank?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
8
14
|
end
|
9
15
|
end
|
@@ -1,9 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module FunWith
|
2
|
+
module Files
|
3
|
+
module CoreExtensions
|
4
|
+
module String
|
5
|
+
def fwf_blank?
|
6
|
+
self.strip.length == 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def fwf_filepath( *args )
|
10
|
+
FunWith::Files::FilePath.new( self, *args )
|
11
|
+
end
|
5
12
|
|
6
|
-
|
7
|
-
|
13
|
+
def to_pathname
|
14
|
+
Pathname.new( self )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
8
18
|
end
|
9
19
|
end
|
@@ -15,17 +15,24 @@ module FunWith
|
|
15
15
|
# ln_s(list, destdir, options)
|
16
16
|
# ln_sf(src, dest, options)
|
17
17
|
|
18
|
-
#
|
18
|
+
# opts are the last argument, and are passed to FileUtils.cp_r
|
19
19
|
# returns the destination path.
|
20
20
|
# How to detect failure? What to return on failure?
|
21
|
+
#
|
22
|
+
#
|
21
23
|
def cp( *args )
|
22
24
|
dest, opts = self.destination_and_options( args )
|
23
|
-
FileUtils.cp_r( self, dest, opts )
|
25
|
+
FileUtils.cp_r( self, dest, narrow_options( opts, FileUtils::OPT_TABLE["cp_r"] ) )
|
24
26
|
dest.fwf_filepath
|
25
27
|
end
|
26
28
|
|
27
29
|
alias :copy :cp
|
28
30
|
|
31
|
+
def mv( *args )
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
29
36
|
# self is the target, link is the thing linking to self
|
30
37
|
# returns filepath of the new link. Will fall back to symbolic
|
31
38
|
# link if self is a directory
|
@@ -34,18 +41,21 @@ module FunWith
|
|
34
41
|
symlink = self.directory? || opts[:symbolic] || opts[:sym] || opts[:soft]
|
35
42
|
|
36
43
|
if symlink
|
37
|
-
FileUtils.ln_s( self, link, opts )
|
44
|
+
FileUtils.ln_s( self, link, narrow_options( opts, FileUtils::OPT_TABLE["ln_s"] ) )
|
38
45
|
else
|
39
|
-
FileUtils.ln( self, link, opts )
|
46
|
+
FileUtils.ln( self, link, narrow_options( opts, FileUtils::OPT_TABLE["ln"] ) )
|
40
47
|
end
|
41
|
-
|
48
|
+
|
42
49
|
link.fwf_filepath
|
43
50
|
end
|
44
51
|
end
|
45
52
|
|
53
|
+
alias :link :ln
|
54
|
+
|
55
|
+
|
46
56
|
def ln_s( *args )
|
47
57
|
link, opts = self.destination_and_options( args )
|
48
|
-
FileUtils.ln_s( self, link, opts )
|
58
|
+
FileUtils.ln_s( self, link, narrow_options( opts, FileUtils::OPT_TABLE["ln_s"] ) )
|
49
59
|
link.fwf_filepath
|
50
60
|
end
|
51
61
|
|
@@ -53,6 +63,8 @@ module FunWith
|
|
53
63
|
|
54
64
|
|
55
65
|
def file_gsub( *args, &block )
|
66
|
+
_must_be_a_file
|
67
|
+
|
56
68
|
lines = []
|
57
69
|
self.each_line do |line|
|
58
70
|
lines << line.gsub( *args, &block )
|
@@ -62,7 +74,10 @@ module FunWith
|
|
62
74
|
end
|
63
75
|
|
64
76
|
def file_gsub!( *args, &block )
|
65
|
-
|
77
|
+
_must_be_a_file # raises error
|
78
|
+
_must_be_writable # raises error
|
79
|
+
|
80
|
+
self.write( self.file_gsub( *args, &block ) )
|
66
81
|
end
|
67
82
|
|
68
83
|
def empty!
|
@@ -73,8 +88,34 @@ module FunWith
|
|
73
88
|
end
|
74
89
|
end
|
75
90
|
|
91
|
+
# TODO: If it's truncated to a longer length than the original file,
|
92
|
+
# pad with zeros? That's how the UNIX truncate command works.
|
76
93
|
def truncate( len )
|
77
|
-
|
94
|
+
_must_be_a_file # raises error
|
95
|
+
_must_be_writable # raises error
|
96
|
+
|
97
|
+
old_size = self.size
|
98
|
+
padding = len > old_size ? "\0" * (len - old_size) : ""
|
99
|
+
|
100
|
+
self.write( self.read( len ) + padding )
|
101
|
+
end
|
102
|
+
|
103
|
+
# File manipulation
|
104
|
+
def rename( filename )
|
105
|
+
raise "NOT WORKING"
|
106
|
+
end
|
107
|
+
|
108
|
+
def rename_all( pattern, gsubbed )
|
109
|
+
raise "NOT WORKING"
|
110
|
+
end
|
111
|
+
|
112
|
+
# pass options?
|
113
|
+
def rm( secure = false )
|
114
|
+
if self.file?
|
115
|
+
FileUtils.rm( self )
|
116
|
+
elsif self.directory?
|
117
|
+
FileUtils.rmtree( self )
|
118
|
+
end
|
78
119
|
end
|
79
120
|
|
80
121
|
protected
|
@@ -161,6 +202,7 @@ module FunWith
|
|
161
202
|
# chown(user, group, list, options)
|
162
203
|
# chown_R(user, group, list, options)
|
163
204
|
# touch(list, options)
|
205
|
+
|
164
206
|
end
|
165
207
|
end
|
166
208
|
end
|
@@ -8,6 +8,8 @@ module FunWith
|
|
8
8
|
super( File.join( *args ) )
|
9
9
|
end
|
10
10
|
|
11
|
+
attr_accessor :path
|
12
|
+
|
11
13
|
# If block given, temporary directory is deleted at the end of the block, and the
|
12
14
|
# value given by the block is returned.
|
13
15
|
#
|
@@ -24,15 +26,30 @@ module FunWith
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def join( *args, &block )
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self.class.new( super(*args) )
|
31
|
-
end
|
29
|
+
joined_path = self.class.new( super(*args) )
|
30
|
+
yield joined_path if block_given?
|
31
|
+
joined_path
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
|
+
def join!( *args, &block )
|
35
|
+
@path = self.join( *args, &block ).to_str
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def / arg
|
40
|
+
self.join( arg )
|
41
|
+
end
|
42
|
+
|
43
|
+
def [] *args
|
44
|
+
self.join(*args)
|
45
|
+
end
|
46
|
+
|
34
47
|
alias :exists? :exist?
|
35
48
|
|
49
|
+
def doesnt_exist?
|
50
|
+
self.exist? == false
|
51
|
+
end
|
52
|
+
|
36
53
|
# If called on a file instead of a directory,
|
37
54
|
# has the same effect as path.dirname
|
38
55
|
def up
|
@@ -75,11 +92,13 @@ module FunWith
|
|
75
92
|
# @path.glob( "css", "*.css" ) # Picks up all css files in the css folder
|
76
93
|
# @path.glob( "css", :ext => :css ) # same
|
77
94
|
# @path.glob # Picks up all directories, subdirectories, and files
|
78
|
-
# @path.glob(:all) # same. Note: :all cannot be used in conjunction with :ext
|
95
|
+
# @path.glob(:all) # same. Note: :all cannot be used in conjunction with :ext or any other arguments. Which may be a mistake on my part.
|
79
96
|
# @path.glob("**", "*") # same
|
80
97
|
# @path.entries # synonym for :all, :recursive => false
|
81
98
|
#
|
82
|
-
|
99
|
+
# TODO: depth argument? depth should override recurse. When extention given, recursion should default to true?
|
100
|
+
# the find -depth argument says depth(0) is the root of the searched directory, any files beneath would be depth(1)
|
101
|
+
def glob( *args, &block )
|
83
102
|
args.push( :all ) if args.fwf_blank?
|
84
103
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
85
104
|
|
@@ -93,7 +112,7 @@ module FunWith
|
|
93
112
|
flags = case (flags_given = opts.delete(:flags))
|
94
113
|
when NilClass
|
95
114
|
0
|
96
|
-
when Array # should be an array of integers
|
115
|
+
when Array # should be an array of integers or File::FNM_<FLAGNAME>s
|
97
116
|
flags_given.inject(0) do |memo, obj|
|
98
117
|
memo | obj
|
99
118
|
end
|
@@ -102,7 +121,7 @@ module FunWith
|
|
102
121
|
end
|
103
122
|
|
104
123
|
flags |= File::FNM_DOTMATCH if opts[:dots]
|
105
|
-
flags |= File::FNM_CASEFOLD if opts[:sensitive]
|
124
|
+
flags |= File::FNM_CASEFOLD if opts[:sensitive] # case sensitive. Only applies to Windows.
|
106
125
|
|
107
126
|
recurse = if all_arg_given
|
108
127
|
if opts[:recursive] == false || opts[:recurse] == false
|
@@ -145,7 +164,13 @@ module FunWith
|
|
145
164
|
files = Dir.glob( self.join(*args), flags ).map{ |f| class_to_return.new( f ) }
|
146
165
|
files.reject!{ |f| f.basename.to_s.match( /^\.\.?$/ ) } unless opts[:parent_and_current]
|
147
166
|
|
148
|
-
|
167
|
+
if block_given?
|
168
|
+
for file in files
|
169
|
+
yield file
|
170
|
+
end
|
171
|
+
else
|
172
|
+
files
|
173
|
+
end
|
149
174
|
end
|
150
175
|
|
151
176
|
def entries
|
@@ -159,29 +184,40 @@ module FunWith
|
|
159
184
|
# Raises error if self is a file and args present.
|
160
185
|
# Raises error if the file is not accessible for writing, or cannot be created.
|
161
186
|
# attempts to create a directory
|
162
|
-
|
187
|
+
#
|
188
|
+
# Takes an options hash as the last argument, allowing same options as FileUtils.touch
|
189
|
+
def touch( *args, &block )
|
190
|
+
args, opts = extract_opts_from_args( args )
|
191
|
+
|
163
192
|
raise "Cannot create subdirectory to a file" if self.file? && args.length > 0
|
164
193
|
touched = self.join(*args)
|
194
|
+
|
165
195
|
dir_for_touched_file = case args.length
|
166
196
|
when 0
|
167
197
|
self.up
|
168
198
|
when 1
|
169
199
|
self
|
170
|
-
when 2..
|
200
|
+
when 2..Float::INFINITY
|
171
201
|
self.join( *(args[0..-2] ) )
|
172
202
|
end
|
173
203
|
|
174
|
-
self.touch_dir( dir_for_touched_file ) unless dir_for_touched_file.directory?
|
175
|
-
FileUtils.touch( touched )
|
204
|
+
self.touch_dir( dir_for_touched_file, opts ) unless dir_for_touched_file.directory?
|
205
|
+
FileUtils.touch( touched, narrow_options( opts, FileUtils::OPT_TABLE["touch"] ) )
|
206
|
+
|
207
|
+
yield touched if block_given?
|
176
208
|
return touched
|
177
209
|
end
|
178
210
|
|
211
|
+
# Takes the options of both FileUtils.touch and FileUtils.mkdir_p
|
212
|
+
# mkdir_p options will only matter if the directory is being created.
|
179
213
|
def touch_dir( *args, &block )
|
214
|
+
args, opts = extract_opts_from_args( args )
|
215
|
+
|
180
216
|
touched = self.join(*args)
|
181
217
|
if touched.directory?
|
182
|
-
FileUtils.touch( touched ) # update access time
|
218
|
+
FileUtils.touch( touched, narrow_options( opts, FileUtils::OPT_TABLE["touch"] ) ) # update access time
|
183
219
|
else
|
184
|
-
FileUtils.mkdir_p( touched ) # create directory (and any needed parents)
|
220
|
+
FileUtils.mkdir_p( touched, narrow_options( opts, FileUtils::OPT_TABLE["mkdir_p"] ) ) # create directory (and any needed parents)
|
185
221
|
end
|
186
222
|
|
187
223
|
yield touched if block_given?
|
@@ -206,17 +242,23 @@ module FunWith
|
|
206
242
|
end
|
207
243
|
end
|
208
244
|
|
209
|
-
# Returns a [list] of the lines in the file matching the given file
|
210
|
-
|
245
|
+
# Returns a [list] of the lines in the file matching the given file. Contrast with
|
246
|
+
|
247
|
+
def grep( regex, &block )
|
211
248
|
return [] unless self.file?
|
212
249
|
matching = []
|
213
250
|
self.each_line do |line|
|
214
251
|
matching.push( line ) if line.match( regex )
|
252
|
+
yield line if block_given?
|
215
253
|
end
|
254
|
+
|
255
|
+
|
216
256
|
matching
|
217
257
|
end
|
218
258
|
|
219
|
-
#
|
259
|
+
# empty? has different meanings depending on whether you're talking about a file
|
260
|
+
# or a directory. A directory must not have any files or subdirectories. A file
|
261
|
+
# must not have any data in it.
|
220
262
|
def empty?
|
221
263
|
raise Exceptions::FileDoesNotExist unless self.exist?
|
222
264
|
|
@@ -255,7 +297,10 @@ module FunWith
|
|
255
297
|
[self.basename_no_ext, self.ext]
|
256
298
|
end
|
257
299
|
|
300
|
+
|
301
|
+
|
258
302
|
def dirname_and_basename
|
303
|
+
warn("FilePath#dirname_and_basename() is deprecated. Pathname#split() already existed, and should be used instead.")
|
259
304
|
[self.dirname, self.basename]
|
260
305
|
end
|
261
306
|
|
@@ -341,10 +386,19 @@ module FunWith
|
|
341
386
|
end
|
342
387
|
|
343
388
|
|
344
|
-
def timestamp( format = true )
|
345
|
-
self.succ( :timestamp => format )
|
389
|
+
def timestamp( format = true, &block )
|
390
|
+
nxt = self.succ( :timestamp => format )
|
391
|
+
yield nxt if block_given?
|
392
|
+
nxt
|
346
393
|
end
|
347
394
|
|
395
|
+
# puts a string between the main part of the basename and the extension
|
396
|
+
# or after the basename if there is no extension. Used to describe some
|
397
|
+
# file variant.
|
398
|
+
# Example "/home/docs/my_awesome_screenplay.txt".fwf_filepath.specifier("final_draft")
|
399
|
+
# => FunWith::Files::FilePath:/home/docs/my_awesome_screenplay.final_draft.txt
|
400
|
+
#
|
401
|
+
# Oh hush. *I* find it useful.
|
348
402
|
def specifier( str )
|
349
403
|
str = str.to_s
|
350
404
|
chunks = self.to_s.split(".")
|
@@ -399,25 +453,6 @@ module FunWith
|
|
399
453
|
# TODO: succ_last : find the last existing file of the given sequence.
|
400
454
|
# TODO: succ_next : find the first free file of the given sequence
|
401
455
|
|
402
|
-
|
403
|
-
# File manipulation
|
404
|
-
def rename( filename )
|
405
|
-
|
406
|
-
end
|
407
|
-
|
408
|
-
def rename_all( pattern, gsubbed )
|
409
|
-
|
410
|
-
end
|
411
|
-
|
412
|
-
def rm( secure = false )
|
413
|
-
if self.file?
|
414
|
-
FileUtils.rm( self )
|
415
|
-
elsif self.directory?
|
416
|
-
FileUtils.rmtree( self )
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
|
421
456
|
def load
|
422
457
|
if self.directory?
|
423
458
|
self.glob( :recursive => true, :ext => "rb" ).map(&:load)
|
@@ -496,6 +531,61 @@ module FunWith
|
|
496
531
|
self.up.ascend( &block )
|
497
532
|
end
|
498
533
|
end
|
534
|
+
|
535
|
+
def to_pathname
|
536
|
+
Pathname.new( @path )
|
537
|
+
end
|
538
|
+
|
539
|
+
# TODO : Not working as intended.
|
540
|
+
# def separator( s = nil )
|
541
|
+
# # If s is nil, then we're asking for the separator
|
542
|
+
# if s.nil?
|
543
|
+
# @separator || File::SEPARATOR
|
544
|
+
# else
|
545
|
+
# @separator = s
|
546
|
+
# end
|
547
|
+
# # otherwise we're installing a separator
|
548
|
+
# end
|
549
|
+
|
550
|
+
protected
|
551
|
+
# TODO: Need a separate API for user to call
|
552
|
+
def _must_be_a_file
|
553
|
+
unless self.file?
|
554
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
555
|
+
raise Errno::EACCESS.new( "Can only call FunWith::Files::FilePath##{calling_method}() on an existing file.")
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
def _must_be_a_directory
|
560
|
+
unless self.directory?
|
561
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
562
|
+
raise Errno::EACCESS.new( "Can only call FunWith::Files::FilePath##{calling_method}() on an existing directory.")
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
def _must_be_writable
|
567
|
+
unless self.writable?
|
568
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
569
|
+
raise Errno::EACCESS.new( "Error in FunWith::Files::FilePath##{calling_method}(): #{@path} not writable.")
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
def narrow_options( opts, keys )
|
574
|
+
opts.keep_if{ |k,v| keys.include?( k ) }
|
575
|
+
end
|
576
|
+
|
577
|
+
def extract_opts_from_args( args )
|
578
|
+
if args.last.is_a?( Hash )
|
579
|
+
[args[0..-2], args.last ]
|
580
|
+
else
|
581
|
+
[args, {}]
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
def yield_and_return( obj, &block )
|
586
|
+
yield obj if block_given?
|
587
|
+
obj
|
588
|
+
end
|
499
589
|
end
|
500
590
|
end
|
501
591
|
end
|
@@ -14,8 +14,8 @@ module FunWith
|
|
14
14
|
File.executable?( self )
|
15
15
|
end
|
16
16
|
|
17
|
-
def chmod( mode,
|
18
|
-
FileUtils.chmod( mode, self,
|
17
|
+
def chmod( mode, opts = {} )
|
18
|
+
FileUtils.chmod( mode, self, narrow_options( opts, FileUtils::OPT_TABLE["chmod"] ) )
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FunWith
|
2
|
+
module Files
|
3
|
+
module FileRequirements
|
4
|
+
def _raise_error_if_not test, msg, error_class
|
5
|
+
if test
|
6
|
+
raise error_class.new( msg + "(file: #{self})" )
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def needs_to_be_a_file error_msg = "Path is not a file"
|
11
|
+
_raise_error_if_not self.file?, error_msg, Errno::ENOENT
|
12
|
+
end
|
13
|
+
|
14
|
+
def needs_to_be_writable error_msg = "Path is not writable"
|
15
|
+
_raise_error_if_not self.writable?, error_msg, Errno::ENOENT
|
16
|
+
end
|
17
|
+
|
18
|
+
def needs_to_be_empty error_msg = "Path needs to point to"
|
19
|
+
_raise_error_if_not self.empty?, error_msg, Errno::ENOENT
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
data/lib/fun_with_files.rb
CHANGED
@@ -8,22 +8,31 @@ for fil in ["string", "array", "false", "hash", "nil", "object"]
|
|
8
8
|
require_relative File.join( "fun_with", "files", "core_extensions", fil )
|
9
9
|
end
|
10
10
|
|
11
|
-
for
|
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"]
|
12
17
|
require_relative File.join( "fun_with", "files", fil )
|
13
18
|
end
|
14
19
|
|
20
|
+
|
15
21
|
# These have some FilePath methods required by .requir()
|
16
|
-
for
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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 )
|
21
28
|
end
|
22
29
|
|
23
|
-
lib_dir = File.
|
30
|
+
lib_dir = File.dirname(__FILE__).fwf_filepath( "fun_with" )
|
24
31
|
|
25
32
|
# And requir() everything else
|
26
33
|
lib_dir.requir
|
27
34
|
|
28
35
|
FunWith::Files::RootPath.rootify( FunWith::Files, __FILE__.fwf_filepath.dirname.up )
|
29
36
|
FunWith::Files::FilePath.extend( FunWith::Files::FilePathClassMethods )
|
37
|
+
|
38
|
+
FunWith::Files.extend( FunWith::Files::GemAPI )
|
data/test/helper.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
# require 'rubygems'
|
2
|
-
# require 'bundler'
|
3
|
-
# require 'debugger'
|
4
1
|
require 'fun_with_testing'
|
5
2
|
|
6
3
|
|
@@ -35,10 +32,23 @@ class FunWith::Files::TestCase < FunWith::Testing::TestCase
|
|
35
32
|
end
|
36
33
|
|
37
34
|
def empty_temp_directory
|
38
|
-
tmp = FunWith::Files.root("test", "tmp")
|
35
|
+
tmp = FunWith::Files.root( "test", "tmp" )
|
39
36
|
tmp.empty!
|
40
37
|
assert_directory tmp
|
41
38
|
puts tmp.glob(:all)
|
42
39
|
assert_empty_directory tmp
|
43
40
|
end
|
41
|
+
|
42
|
+
def if_internet_works( &block )
|
43
|
+
`ping -c 1 google.com 2>&1 >> /dev/null` # TODO: Portability issue
|
44
|
+
connection_detected = $?.success?
|
45
|
+
|
46
|
+
if block_given?
|
47
|
+
if connection_detected # TODO: How to tell difference between "no internet" and "no ping utility?"
|
48
|
+
yield
|
49
|
+
else
|
50
|
+
puts "No internet connection. Skipping."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
44
54
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestCoreExtensions < FunWith::Files::TestCase
|
4
|
+
context "testing hash" do
|
5
|
+
should "fwf_reverse_merge nicely" do
|
6
|
+
h = { "1" => 1, "2" => 2 }.fwf_reverse_merge( "3" => 3, "1" => 0 )
|
7
|
+
|
8
|
+
assert_equal 1, h["1"]
|
9
|
+
assert_equal 2, h["2"]
|
10
|
+
assert_equal 3, h["3"]
|
11
|
+
|
12
|
+
h.fwf_reverse_merge!( "1" => "one", "2" => "two", "3" => "three" )
|
13
|
+
|
14
|
+
assert_equal 1, h["1"]
|
15
|
+
assert_equal 2, h["2"]
|
16
|
+
assert_equal 3, h["3"]
|
17
|
+
|
18
|
+
h.fwf_reverse_merge!( "1" => "one", "2" => "two", "3" => "three", "4" => "four" )
|
19
|
+
|
20
|
+
assert_equal 1, h["1"]
|
21
|
+
assert_equal 2, h["2"]
|
22
|
+
assert_equal 3, h["3"]
|
23
|
+
assert_equal "four", h["4"]
|
24
|
+
end
|
25
|
+
|
26
|
+
should "fwf_blank? nicely." do
|
27
|
+
assert_equal false, { 1 => 2 }.fwf_blank?
|
28
|
+
assert_equal true, {}.fwf_blank?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -64,19 +64,21 @@ class TestDirectoryBuilder < FunWith::Files::TestCase
|
|
64
64
|
end
|
65
65
|
|
66
66
|
should "download random crap from all over the Internet" do
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
if_internet_works do
|
68
|
+
DirectoryBuilder.tmpdir do |b|
|
69
|
+
gist_url = "http://bannedsorcery.com/downloads/testfile.txt"
|
70
|
+
gist_text = "This is a file\n==============\n\n**silent**: But _bold_! [Link](http://slashdot.org)\n"
|
71
|
+
b.download( gist_url, "gist.txt" )
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
b.file( "gist.txt.2" ) do
|
74
|
+
b.download( gist_url )
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
assert b.current_file.nil?
|
78
|
+
assert b.current_path.join("gist.txt").exist?
|
79
|
+
assert b.current_path.join("gist.txt.2").exist?
|
80
|
+
assert_equal gist_text, b.current_path.join("gist.txt").read
|
81
|
+
end
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
@@ -95,5 +95,11 @@ class TestFileManipulation < FunWith::Files::TestCase
|
|
95
95
|
|
96
96
|
assert_file_contents( clone_of_clone, /This is the/ )
|
97
97
|
end
|
98
|
+
|
99
|
+
should "do nothing when opts[:noop]" do
|
100
|
+
file = @dir.join( "not_exist.txt" )
|
101
|
+
file.touch( :noop => true, :this_invalid_option_is_ignored => true, :also_this_one => "also ignored" )
|
102
|
+
assert_no_file file
|
103
|
+
end
|
98
104
|
end
|
99
105
|
end
|
data/test/test_file_path.rb
CHANGED
data/test/test_fun_with_files.rb
CHANGED
@@ -24,6 +24,9 @@ class TestFunWithFiles < FunWith::Files::TestCase
|
|
24
24
|
|
25
25
|
should "respond to api" do
|
26
26
|
assert_respond_to( FunWith::Files, :root )
|
27
|
+
assert_respond_to( FunWith::Files, :version )
|
28
|
+
|
29
|
+
assert_equal "0.0.11", FunWith::Files.version # Gotta change with every point release. Ick.
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
data/test/test_globbing.rb
CHANGED
@@ -3,9 +3,10 @@ require 'helper'
|
|
3
3
|
class TestGlobbing < FunWith::Files::TestCase
|
4
4
|
context "testing globbing" do
|
5
5
|
setup do
|
6
|
-
@loadable_dir = FunWith::Files.root
|
6
|
+
@loadable_dir = FunWith::Files.root "test", "loadable_dir"
|
7
|
+
@glob_dir = FunWith::Files.root "test", "glob_dir"
|
7
8
|
assert @loadable_dir.directory?
|
8
|
-
|
9
|
+
assert @glob_dir.directory?
|
9
10
|
end
|
10
11
|
|
11
12
|
should "glob some ruby files from the test/loadable_dir directory" do
|
@@ -33,5 +34,30 @@ class TestGlobbing < FunWith::Files::TestCase
|
|
33
34
|
globs = @loadable_dir.glob( :recurse => true, :ext => :rb )
|
34
35
|
assert_equal( 8, globs.length )
|
35
36
|
end
|
37
|
+
|
38
|
+
should "not search subdirectories when :recurse => false" do
|
39
|
+
globs = @loadable_dir.glob( :recurse => false, :ext => :rb )
|
40
|
+
assert_length 0, globs
|
41
|
+
end
|
42
|
+
|
43
|
+
should "NOT search subdirectories when :recurse is unspecified" do
|
44
|
+
globs = @loadable_dir.glob :ext => :rb
|
45
|
+
assert_length 0, globs
|
46
|
+
end
|
47
|
+
|
48
|
+
should "glob a dot file" do
|
49
|
+
globs = @glob_dir.glob( :recurse => false, :dots => true )
|
50
|
+
assert_length 1, globs
|
51
|
+
end
|
52
|
+
|
53
|
+
should "not glob a dot file when :dots => false" do
|
54
|
+
globs = @glob_dir.glob( :recurse => false, :dots => false )
|
55
|
+
assert_length( 0, globs )
|
56
|
+
end
|
57
|
+
|
58
|
+
should "ignore a dot file by default" do
|
59
|
+
globs = @glob_dir.glob( :recurse => false ) # no dots by default
|
60
|
+
assert_length( 0, globs )
|
61
|
+
end
|
36
62
|
end
|
37
63
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTouching < FunWith::Files::TestCase
|
4
|
+
context "inside a tmpdir" do
|
5
|
+
setup do
|
6
|
+
@dir = FilePath.tmpdir
|
7
|
+
end
|
8
|
+
|
9
|
+
teardown do
|
10
|
+
@dir.rm
|
11
|
+
assert_equal false, @dir.directory?
|
12
|
+
end
|
13
|
+
|
14
|
+
should "create a file and link to it" do
|
15
|
+
file = @dir.touch( "Movies", "Basketball", "Shaquille", "cryptohash.dat" )
|
16
|
+
assert_fwf_filepath file.directory
|
17
|
+
assert_empty_file file
|
18
|
+
|
19
|
+
link = file.link( file.up.up.up.join( "hash.dat"), :soft => true )
|
20
|
+
assert link.symlink?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fun_with_files
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryce Anderson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xdg
|
@@ -67,10 +67,13 @@ files:
|
|
67
67
|
- ./lib/fun_with/files/file_path.rb
|
68
68
|
- ./lib/fun_with/files/file_path_class_methods.rb
|
69
69
|
- ./lib/fun_with/files/file_permission_methods.rb
|
70
|
+
- ./lib/fun_with/files/file_requirements.rb
|
71
|
+
- ./lib/fun_with/files/gem_api.rb
|
70
72
|
- ./lib/fun_with/files/pathname_extensions.rb
|
71
73
|
- ./lib/fun_with/files/remote_path.rb
|
72
74
|
- ./lib/fun_with/files/root_path.rb
|
73
75
|
- ./lib/fun_with/files/string_behavior.rb
|
76
|
+
- ./lib/fun_with/files/string_extensions.rb
|
74
77
|
- ./lib/fun_with/files/xdg_extensions.rb
|
75
78
|
- ./lib/fun_with_files.rb
|
76
79
|
- ./test/data/empty.txt
|
@@ -88,6 +91,7 @@ files:
|
|
88
91
|
- ./test/loadable_dir/dir5/c.rb
|
89
92
|
- ./test/loadable_dir/dir5/d.rb
|
90
93
|
- ./test/test_copying.rb
|
94
|
+
- ./test/test_core_extensions.rb
|
91
95
|
- ./test/test_descent.rb
|
92
96
|
- ./test/test_digest.rb
|
93
97
|
- ./test/test_directory_builder.rb
|
@@ -97,6 +101,7 @@ files:
|
|
97
101
|
- ./test/test_globbing.rb
|
98
102
|
- ./test/test_loading.rb
|
99
103
|
- ./test/test_root_path.rb
|
104
|
+
- ./test/test_symlinking.rb
|
100
105
|
- ./test/test_touching.rb
|
101
106
|
- Gemfile
|
102
107
|
- LICENSE.txt
|