fun_with_files 0.0.9 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|