fun_with_files 0.0.7 → 0.0.8

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTg3ZGQzMDAxYTczMjBjNTc5NjU2ZDA0MDRlNzQ0YTc5MzBjMmE2OQ==
4
+ YjBjMTU1NDdlNDRhMmM5YmRhOGQ2MDJiMTFhM2QwMjZmM2ZjMmQwYw==
5
5
  data.tar.gz: !binary |-
6
- NTBhOGNkNTcyZGRlNGNjYTFjNzMyYzVhYzhmNWE0NmU3ODMwODFjMw==
6
+ NmRiMGRmZmE1YzRkYTRhZjMyNzI4MDYyZTkyMWFjNmVhMTQ4ZGJjZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- M2VhMTIwMDRjNDRiODQ3MTcwNDJiYmJlYmExODA3ZmVlOTQwYzI3ODFkNGI4
10
- MTNkZGUxYTRkNjE5ZmZjYjMwYzUyNDdkYjNmN2MxNjU3NmY5YmVlMTQ5NzZj
11
- NzY5ODZlNWIyMGU4MjI4MDI4ZGM2MTRkZDg4NzEzMThlY2FmMjU=
9
+ NzAxZjhmYTA2NzIyNjkwNmVlNTMwMjNiZmQ3MjhlYTc5ZWM5ZDMyOTUwNmY1
10
+ YTAyMTNiMDkwZTgzY2FiMTMyMzMwMTk2NzBiMTcyNDBiNTQ2YTMyNmQwNjMw
11
+ MmM0ODdiYWM3Yjk3ZDBkZTI4ZjA1MDdmYWYxYzM0NDBhODE3MTI=
12
12
  data.tar.gz: !binary |-
13
- YzI5ZGYyZDgwYzQ0ODg0MjNjNjVhYTI4OGEzZDcwODk4MjI0OGZlNmMzZWRi
14
- ZGQyZjUwN2M0MjBmYzQzMTY3YWZhYmNhNDdhNGE5M2NhM2MyNzYxZGQ3NDA3
15
- YjRjNWM5NWRiZGUxODc2MTFlM2ZmMGZlNGJlZDZjNjQ0ODJjMDk=
13
+ YjhlYjRhODBmMzc3NDNkZGE4NDM3MzgwMTFlMDgyMWZjY2U5MTdjZjI0NDU5
14
+ M2VmNzAxOGU2NmQ4N2ZlN2Y4NTE4NWQ1OWUwZDMxODE3ODJkYmNhMGU3MWRh
15
+ YjFhMDc3NTZkODRkMTBiMDc4N2I4YTZiYTVhZGFhNDQ4MmZlZDY=
data/Gemfile CHANGED
@@ -7,11 +7,12 @@ 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.5"
11
- gem "rdoc", "~> 3.12"
12
- gem "bundler", "~> 1.5"
13
- gem "jeweler", "~> 2.0"
10
+ # gem "shoulda", "~> 3", ">= 3.5"
11
+ # gem "rdoc", "~> 3.12"
12
+ # gem "bundler", "~> 1.5"
13
+ # gem "jeweler", "~> 2.0"
14
14
  # gem "debugger", "~> 1.6"
15
+ gem "fun_with_testing", "~> 0.0"
15
16
  end
16
17
 
17
- gem "xdg"
18
+ gem "xdg", "~> 2"
data/Rakefile CHANGED
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubygems'
4
- require 'bundler'
3
+ require 'fun_with_testing'
4
+ # require 'rubygems'
5
+ # require 'bundler'
5
6
 
6
7
  begin
7
8
  Bundler.setup(:default, :development)
@@ -13,7 +14,7 @@ end
13
14
 
14
15
  require 'rake'
15
16
 
16
- require 'jeweler'
17
+ # require 'jeweler'
17
18
  Jeweler::Tasks.new do |gem|
18
19
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
20
  gem.name = "fun_with_files"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
@@ -2,7 +2,35 @@ module FunWith
2
2
  module Files
3
3
  module DigestMethods
4
4
  def md5
5
- self.file? ? Digest::MD5.hexdigest( self.read ) : ""
5
+ digest( Digest::MD5 )
6
+ end
7
+
8
+ def sha1
9
+ digest( Digest::SHA1 )
10
+ end
11
+
12
+ def sha2
13
+ digest( Digest::SHA2 )
14
+ end
15
+
16
+ def sha224
17
+ digest( Digest::SHA224 )
18
+ end
19
+
20
+ def sha256
21
+ digest( Digest::SHA256 )
22
+ end
23
+
24
+ def sha384
25
+ digest( Digest::SHA384 )
26
+ end
27
+
28
+ def sha512
29
+ digest( Digest::SHA512 )
30
+ end
31
+
32
+ def digest( digest_class = Digest::MD5 )
33
+ self.file? ? digest_class.hexdigest( self.read ) : ""
6
34
  end
7
35
  end
8
36
  end
@@ -15,11 +15,13 @@ module FunWith
15
15
  # ln_s(list, destdir, options)
16
16
  # ln_sf(src, dest, options)
17
17
 
18
+ # Opts are same as for FileUtils.cp_r
19
+ # returns the destination path.
20
+ # How to detect failure? What to return on failure?
18
21
  def cp( *args )
19
- self.destination_and_options( args ) do |dest, opts|
20
- FileUtils.cp_r( self, dest, opts )
21
- dest.fwf_filepath
22
- end
22
+ dest, opts = self.destination_and_options( args )
23
+ FileUtils.cp_r( self, dest, opts )
24
+ dest.fwf_filepath
23
25
  end
24
26
 
25
27
  alias :copy :cp
@@ -41,11 +43,15 @@ module FunWith
41
43
  end
42
44
  end
43
45
 
44
- def ln_s( link, options = {} )
45
- FileUtils.ln_s( self, link, options )
46
+ def ln_s( *args )
47
+ link, opts = self.destination_and_options( args )
48
+ FileUtils.ln_s( self, link, opts )
46
49
  link.fwf_filepath
47
50
  end
48
51
 
52
+ alias :symlink :ln_s
53
+
54
+
49
55
  def file_gsub( *args, &block )
50
56
  lines = []
51
57
  self.each_line do |line|
@@ -59,6 +65,18 @@ module FunWith
59
65
  self.write( self.file_gsub(*args,&block) )
60
66
  end
61
67
 
68
+ def empty!
69
+ if self.directory?
70
+ FileUtils.rm_rf( self.entries, secure: true )
71
+ else
72
+ self.write( "" )
73
+ end
74
+ end
75
+
76
+ def truncate( len )
77
+ self.write( self.read( len ) )
78
+ end
79
+
62
80
  protected
63
81
  def destination_and_options( args, &block )
64
82
  options = args.last.is_a?(Hash) ? args.pop : {}
@@ -72,19 +90,33 @@ module FunWith
72
90
  end
73
91
 
74
92
 
75
-
76
93
  # logic should be shared by various manipulators
94
+ #
95
+ # You can describe the destination as either a filepath or a bunch of strings for arguments.
96
+ # If the FilePath is relative, or if string args are given, then the destination will be
97
+ # relative to the path being copied (or in the case of a file, its parent directory).
98
+ #
99
+ # If dest doesn't exist, and src (self) is a file, dest is taken to be the complete path.
100
+ # If dest doesn't exist, and src (self) is a directory, then dest is taken to be
101
+ # If dest is a directory and the source is a file, then the file will be copied into dest with the src's basename
77
102
  def find_destination_from_args( args )
103
+ raise ArgumentError.new("File #{self} must exist.") unless self.exist?
104
+
78
105
  if args.first.is_a?(Pathname)
106
+ raise ArgumentError.new( "accepts a FilePath or string args, not both" ) unless args.length == 1
79
107
  dest = args.first
80
- elsif self.directory?
81
- # what if they're trying to define an absolute dest, but being splitty?
82
- dest = self.join( *args )
108
+ dest = dest.directory.join( dest ).expand if dest.relative?
83
109
  else
84
- # ......
85
- dest = self.dirname.join( *args )
86
- dest = dest.join( self.basename ) if dest.directory?
110
+ dest = self.directory.join(*args).expand # expand gets rid of /../ (parent_dir)
111
+ end
112
+
113
+ if self.file? && dest.directory?
114
+ dest = dest.join( self.basename )
115
+ elsif self.directory? && dest.file?
116
+ raise ArgumentError.new( "cannot overwrite a file with a directory" )
87
117
  end
118
+
119
+ dest
88
120
  end
89
121
 
90
122
  # rm(list, options)
@@ -1,19 +1,13 @@
1
1
  module FunWith
2
2
  module Files
3
3
  class FilePath < Pathname
4
+ SUCC_DIGIT_COUNT = 6
5
+ DEFAULT_TIMESTAMP_FORMAT = "%Y%m%d%H%M%S%L"
6
+
4
7
  def initialize( *args )
5
8
  super( File.join( *args ) )
6
9
  end
7
10
 
8
- # args implicitly joined to cwd
9
- def self.cwd( *args )
10
- Dir.pwd.fwf_filepath.join( *args )
11
- end
12
-
13
- def self.pwd( *args )
14
- self.cwd( *args )
15
- end
16
-
17
11
  # If block given, temporary directory is deleted at the end of the block, and the
18
12
  # value given by the block is returned.
19
13
  #
@@ -29,10 +23,6 @@ module FunWith
29
23
  end
30
24
  end
31
25
 
32
- def self.home( *args )
33
- Dir.home.fwf_filepath.join( *args )
34
- end
35
-
36
26
  def join( *args, &block )
37
27
  if block_given?
38
28
  yield self.class.new( super(*args) )
@@ -61,11 +51,11 @@ module FunWith
61
51
  # Can be given as an integer: (File::FNM_DOTMATCH | File::FNM_NOESCAPE)
62
52
  # or as an array: [File::FNM_CASEFOLD, File::FNM_DOTMATCH]
63
53
  #
64
- # :class => [self.class] The class of objects you want returned (String, FilePath, ClassLoader, etc.)
54
+ # :class => [self.class] The class of objects you want returned (String, FilePath, etc.)
65
55
  # Should probably be a subclass of FilePath or String. Class.initialize() must accept a string
66
56
  # [representing a file path] as the sole argument.
67
57
  #
68
- # :recurse => [false]
58
+ # :recurse => [defaults true]
69
59
  # :recursive (synonym for :recurse)
70
60
  #
71
61
  # :ext => [] A single symbol, or a list containing strings/symbols representing file name extensions.
@@ -80,48 +70,88 @@ module FunWith
80
70
  # results explicitly with arguments like .glob("**", "*.rb")
81
71
  #
82
72
  # :all : if :all is the only argument, this is the same as .glob("**", "*")
73
+ #
74
+ # Examples:
75
+ # @path.glob( "css", "*.css" ) # Picks up all css files in the css folder
76
+ # @path.glob( "css", :ext => :css ) # same
77
+ # @path.glob # Picks up all directories, subdirectories, and files
78
+ # @path.glob(:all) # same. Note: :all cannot be used in conjunction with :ext
79
+ # @path.glob("**", "*") # same
80
+ # @path.entries # synonym for :all, :recursive => false
81
+ #
83
82
  def glob( *args )
83
+ args.push( :all ) if args.fwf_blank?
84
84
  opts = args.last.is_a?(Hash) ? args.pop : {}
85
85
 
86
- flags = case opts[:flags]
87
- when NilClass
88
- 0
89
- when Array # should be an array of integers
90
- opts[:flags].inject(0) do |memo, obj|
91
- memo | obj
92
- end
93
- when Integer
94
- opts[:flags]
86
+ if args.last == :all
87
+ all_arg_given = true
88
+ args.pop
89
+ else
90
+ all_arg_given = false
95
91
  end
96
92
 
93
+ flags = case (flags_given = opts.delete(:flags))
94
+ when NilClass
95
+ 0
96
+ when Array # should be an array of integers
97
+ flags_given.inject(0) do |memo, obj|
98
+ memo | obj
99
+ end
100
+ when Integer
101
+ flags_given
102
+ end
103
+
97
104
  flags |= File::FNM_DOTMATCH if opts[:dots]
98
105
  flags |= File::FNM_CASEFOLD if opts[:sensitive]
106
+
107
+ recurse = if all_arg_given
108
+ if opts[:recursive] == false || opts[:recurse] == false
109
+ false
110
+ else
111
+ true
112
+ end
113
+ else
114
+ opts[:recursive] == true || opts[:recurse] == true || false
115
+ end
99
116
 
100
- if args.first == :all
101
- args = ["**", "*"]
117
+ if all_arg_given
118
+ if recurse
119
+ args = ["**", "*"]
120
+ else
121
+ args = ["*"]
122
+ end
102
123
  else
103
- recurser = (opts[:recurse] || opts[:recursive]) ? "**" : nil
124
+ args.push("**") if recurse
125
+
104
126
  extensions = case opts[:ext]
105
127
  when Symbol, String
106
128
  "*.#{opts[:ext]}"
107
129
  when Array
108
130
  extensions = opts[:ext].map(&:to_s).join(',')
109
- "*.{#{extensions}}"
131
+ "*.{#{extensions}}" # The Dir.glob format for this is '.{ext1,ext2,ext3}'
110
132
  when NilClass
111
- nil
133
+ if args.fwf_blank?
134
+ "*"
135
+ else
136
+ nil
137
+ end
112
138
  end
113
139
 
114
- args += [recurser, extensions]
115
- args.compact!
140
+ args.push( extensions ) if extensions
116
141
  end
117
142
 
118
- opts[:class] ||= self.class
143
+ class_to_return = opts[:class] || self.class
144
+
145
+ files = Dir.glob( self.join(*args), flags ).map{ |f| class_to_return.new( f ) }
146
+ files.reject!{ |f| f.basename.to_s.match( /^\.\.?$/ ) } unless opts[:parent_and_current]
119
147
 
120
- files = Dir.glob( self.join(*args), flags ).map{ |f| opts[:class].new(f) }
121
- files.reject!{ |f| f.basename.to_s.match(/^\.{1,2}$/) } unless opts[:parent_and_current]
122
148
  files
123
149
  end
124
150
 
151
+ def entries
152
+ self.glob( :recurse => false )
153
+ end
154
+
125
155
  def expand
126
156
  self.class.new( File.expand_path( self ) )
127
157
  end
@@ -193,7 +223,7 @@ module FunWith
193
223
  if self.file?
194
224
  File.size( self ) == 0
195
225
  elsif self.directory?
196
- self.glob( "**", "*" ).fwf_blank?
226
+ self.glob( :all ).fwf_blank?
197
227
  end
198
228
  end
199
229
 
@@ -206,11 +236,18 @@ module FunWith
206
236
  self.gsub(/\.#{self.ext}$/, '')
207
237
  end
208
238
 
239
+ # Two separate modes. With no arguments given, returns the current extension as a string (not a filepath)
240
+ # With an argument, returns the path with a .(arg) tacked onto the end. The leading period is wholly optional.
209
241
  # Does not return a filepath.
210
242
  # Does not include leading period
211
- def ext
212
- split_basename = self.basename.to_s.split(".")
213
- split_basename.length > 1 ? split_basename.last : ""
243
+ def ext( *args )
244
+ if args.length == 0
245
+ split_basename = self.basename.to_s.split(".")
246
+ split_basename.length > 1 ? split_basename.last : ""
247
+ elsif args.length == 1
248
+ ext = args.first.to_s.gsub(/^\./,'')
249
+ self.class.new( @path.dup + ".#{ext}" )
250
+ end
214
251
  end
215
252
 
216
253
  # base, ext = @path.basename_and_ext
@@ -226,6 +263,20 @@ module FunWith
226
263
  [self.dirname, self.basename_no_ext, self.ext]
227
264
  end
228
265
 
266
+ # if it's a file, returns the immediate parent directory.
267
+ # if it's not a file, returns itself
268
+ def directory
269
+ self.directory? ? self : self.dirname
270
+ end
271
+
272
+ def original?
273
+ !self.symlink?
274
+ end
275
+
276
+ def original
277
+ self.symlink? ? self.readlink.original : self
278
+ end
279
+
229
280
  # Basically Pathname.relative_path_from, but you can pass in strings
230
281
  def relative_path_from( dir )
231
282
  dir = super( Pathname.new( dir ) )
@@ -245,10 +296,12 @@ module FunWith
245
296
  # You can change the length of the sequence string by passing
246
297
  # in an argument, but it should always be the same value for
247
298
  # a given set of files.
248
- SUCC_DIGIT_COUNT = 6
299
+ #
300
+ # TODO: Need to get this relying on the specifier() method.
249
301
  def succ( opts = { digit_count: SUCC_DIGIT_COUNT, timestamp: false } )
250
- if opts[:timestamp]
251
- timestamp = Time.now.strftime("%Y%m%d%H%M%S%L")
302
+ if timestamp = opts[:timestamp]
303
+ timestamp_format = timestamp.is_a?(String) ? timestamp : DEFAULT_TIMESTAMP_FORMAT
304
+ timestamp = Time.now.strftime( timestamp_format )
252
305
  digit_count = timestamp.length
253
306
  else
254
307
  timestamp = false
@@ -287,6 +340,10 @@ module FunWith
287
340
  self.up.join( chunks.join(".") )
288
341
  end
289
342
 
343
+
344
+ def timestamp( format = true )
345
+ self.succ( :timestamp => format )
346
+ end
290
347
 
291
348
  def specifier( str )
292
349
  str = str.to_s
@@ -334,7 +391,7 @@ module FunWith
334
391
  stamped = [ chunks[0..-2], glob_stamp_matcher, chunks[-1] ].flatten.join(".")
335
392
  end
336
393
 
337
- [self.dirname.glob(original), self.dirname.glob(stamped)].flatten
394
+ [self.dirname.join(original), self.dirname.glob(stamped)].flatten
338
395
  end
339
396
 
340
397
 
@@ -394,7 +451,7 @@ module FunWith
394
451
  successfully_required += 1
395
452
  rescue Exception => e
396
453
  failed_requirements << requirement
397
- error_messages << "#{e.message} (#{e.class})"
454
+ error_messages << "Error while requiring #{requirement} : #{e.message} (#{e.class})"
398
455
  end
399
456
  end
400
457
 
@@ -0,0 +1,38 @@
1
+ module FunWith
2
+ module Files
3
+ module FilePathLocationMethods
4
+ # args implicitly joined to cwd
5
+ def cwd( *args )
6
+ Dir.pwd.fwf_filepath.join( *args )
7
+ end
8
+
9
+ def pwd( *args )
10
+ self.cwd( *args )
11
+ end
12
+
13
+ def home( *args )
14
+ Dir.home.fwf_filepath.join( *args )
15
+ end
16
+
17
+ def config_dir( *args )
18
+ XDG['CONFIG'].fwf_filepath.join( *args )
19
+ end
20
+
21
+ def data_dir( *args )
22
+ XDG['DATA'].fwf_filepath.join( *args )
23
+ end
24
+
25
+ # Honestly this is a token attempt at Windows compatibility.
26
+ # This could go wrong all sorts of ways, and hasn't been tested
27
+ # on Windows. More to the point, when a Windows machine has
28
+ # multiple drives mounted, what do you even call the root?
29
+ def root( *args )
30
+ if self.home =~ /^[a-zA-Z]:/
31
+ self.home.to_s[0..3].fwf_filepath.join( *args )
32
+ else
33
+ "/".fwf_filepath.join( *args )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -17,7 +17,11 @@ module FunWith
17
17
 
18
18
  class RootPath
19
19
  def self.rootify( target, path )
20
- raise "#{target} already responds to :root" if target.respond_to?(:root)
20
+ if target.respond_to?(:root)
21
+ warn( "#{target} already responds to :root, skipping installation" )
22
+ return nil
23
+ end
24
+
21
25
  target.extend( RootPathExtensions )
22
26
  target.set_root_path( FilePath.new( path ) )
23
27
  end
@@ -23,6 +23,11 @@ module FunWith
23
23
  def scan( *args, &block )
24
24
  @path.scan( *args, &block )
25
25
  end
26
+
27
+ # Lets it be a string when a string is called for. Replacement argument in .gsub(), for example.
28
+ def to_str
29
+ @path.dup
30
+ end
26
31
  end
27
32
  end
28
33
  end
@@ -1,6 +1,7 @@
1
- require 'digest/md5' # stdlib
2
- require 'pathname' # stdlib
3
- require 'tmpdir'
1
+ require 'xdg'
2
+ require 'digest' # stdlib
3
+ require 'pathname' # stdlib
4
+ require 'tmpdir' # Dir.tmpdir
4
5
 
5
6
  files = Dir.glob( File.join( File.dirname(__FILE__), "fun_with", "**", "*.rb" ) )
6
7
 
@@ -13,12 +14,14 @@ FunWith::Files::RootPath.rootify( FunWith::Files, __FILE__.fwf_filepath.dirname.
13
14
  module FunWith
14
15
  module Files
15
16
  class FilePath
16
- for mod in [ StringBehavior,
17
- FileManipulationMethods,
18
- FilePermissionMethods,
19
- DigestMethods ]
20
- include mod
17
+ for moduul in [ StringBehavior,
18
+ FileManipulationMethods,
19
+ FilePermissionMethods,
20
+ DigestMethods ]
21
+ include moduul
21
22
  end
22
23
  end
23
24
  end
24
25
  end
26
+
27
+ FunWith::Files::FilePath.extend( FunWith::Files::FilePathLocationMethods )
data/test/helper.rb CHANGED
@@ -1,31 +1,44 @@
1
- require 'rubygems'
2
- require 'bundler'
1
+ # require 'rubygems'
2
+ # require 'bundler'
3
+ # require 'debugger'
4
+ require 'fun_with_testing'
3
5
 
4
- begin
5
- Bundler.setup(:default, :development)
6
- rescue Bundler::BundlerError => e
7
- $stderr.puts e.message
8
- $stderr.puts "Run `bundle install` to install missing gems"
9
- exit e.status_code
10
- end
11
6
 
12
- require 'test/unit'
13
- require 'shoulda'
7
+ # begin
8
+ # Bundler.setup(:default, :development)
9
+ # rescue Bundler::BundlerError => e
10
+ # $stderr.puts e.message
11
+ # $stderr.puts "Run `bundle install` to install missing gems"
12
+ # exit e.status_code
13
+ # end
14
+ #
15
+ # require 'test/unit'
16
+ # require 'shoulda'
14
17
 
15
18
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
19
  $LOAD_PATH.unshift(File.dirname(__FILE__))
17
20
  require 'fun_with_files'
18
21
 
19
- class Test::Unit::TestCase
20
- end
22
+ # class Test::Unit::TestCase
23
+ # end
21
24
 
22
- class FunWith::Files::TestCase < Test::Unit::TestCase
25
+ class FunWith::Files::TestCase < FunWith::Testing::TestCase
23
26
  include FunWith::Files
27
+ include FunWith::Testing::Assertions::FunWithFiles
28
+ include FunWith::Testing::Assertions::Basics
24
29
 
25
30
  def tmpdir( &block )
26
- FunWith::Files::FilePath.tmpdir do |d|
31
+ FilePath.tmpdir do |d|
27
32
  @tmpdir = d
28
33
  yield
29
34
  end
30
35
  end
36
+
37
+ def empty_temp_directory
38
+ tmp = FunWith::Files.root("test", "tmp")
39
+ tmp.empty!
40
+ assert_directory tmp
41
+ puts tmp.glob(:all)
42
+ assert_empty_directory tmp
43
+ end
31
44
  end
data/test/test_copying.rb CHANGED
@@ -1,52 +1,4 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestCopying < FunWith::Files::TestCase
4
- context "inside a tmpdir" do
5
- setup do
6
- @dir = FilePath.tmpdir
7
- assert @dir.exist?
8
- end
9
-
10
- teardown do
11
- @dir.rm
12
- assert_equal false, @dir.directory?
13
- end
14
-
15
- should "copy a single file" do
16
- outdir = @dir.join( "down", "down", "down", "to", "the", "depths" )
17
- assert !outdir.exist?
18
- outdir.touch_dir
19
- assert outdir.exist?
20
-
21
- infile = FunWith::Files.root( "test", "helper.rb" )
22
- assert infile.exist?
23
-
24
- outfile = outdir.join("copy_of_helper.rb")
25
- assert !outfile.exist?
26
-
27
- infile.cp( outdir )
28
- assert outdir.join("helper.rb").exist?
29
-
30
- infile.cp( outfile )
31
- assert outfile.exist?
32
- end
33
-
34
- should "copy a directory structure" do
35
- outdir = @dir.join( "down", "down", "abandon", "all", "hope" )
36
- indir = FunWith::Files.root( "test" )
37
- outdir.touch_dir
38
- indir.cp( outdir )
39
-
40
- assert outdir.exist?
41
- helper_file = outdir.join( "test", "helper.rb" )
42
- assert helper_file.exist?
43
- assert_equal indir.join( "helper.rb" ).grep( /FunWith::Files/ ).length, helper_file.grep( /FunWith::Files/ ).length
44
-
45
- assert_equal indir.glob(:all).length, outdir.join("test").glob(:all).length
46
- end
47
-
48
- should "symlink masterfully" do
49
-
50
- end
51
- end
52
4
  end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ class TestDigest < 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 "digest a blank file" do
15
+ blankfile = @dir.touch('blank.dat')
16
+ assert_empty_file blankfile
17
+
18
+ results = { :md5 => "d41d8cd98f00b204e9800998ecf8427e",
19
+ :sha1 => "da39a3ee5e6b4b0d3255bfef95601890afd80709",
20
+ :sha2 => "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
21
+ :sha256 => "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
22
+ :sha384 => "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
23
+ :sha512 => "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
24
+ }
25
+
26
+ for h in %w(md5 sha1 sha2 sha256 sha384 sha512).map(&:to_sym)
27
+ assert_equal( results[h], blankfile.send(h), "A blank file should have a #{h}() digest of #{results[h]}" )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,13 +4,18 @@ class TestFileManipulation < FunWith::Files::TestCase
4
4
  context "testing gsubs" do
5
5
  setup do
6
6
  @license = FunWith::Files.root("LICENSE.txt")
7
+ @tmp_dir = FunWith::Files.root("test", "tmp")
8
+ end
9
+
10
+ teardown do
11
+ empty_temp_directory
7
12
  end
8
13
 
9
14
  should "copy LICENSE.txt" do
10
15
  copied = @license.cp( "test", "tmp" )
11
16
  assert_match /LICENSE\.txt/, copied.to_s
12
- assert copied.exist?
13
- assert copied.read.length > 0
17
+ assert_file copied
18
+ assert_file_has_content copied
14
19
  end
15
20
 
16
21
  should "gsub copy of license.txt" do
@@ -18,7 +23,77 @@ class TestFileManipulation < FunWith::Files::TestCase
18
23
  copied.file_gsub!( /Bryce Anderson/, "Wilford Brimley" )
19
24
  assert copied.size > 1000
20
25
 
21
- assert_equal 1, copied.grep("Wilford Brimley").length
26
+ assert_file_contents copied, /Wilford Brimley/
27
+ end
28
+
29
+ should "empty files and directories" do
30
+ license_copy = @license.cp( @tmp_dir )
31
+ assert_file( license_copy )
32
+ assert_equal( FunWith::Files.root("test", "tmp", "LICENSE.txt"), license_copy )
33
+ assert_file_has_content( license_copy )
34
+ license_copy.empty!
35
+ assert_empty_file( license_copy )
36
+ assert_zero( license_copy.read.length )
37
+
38
+
39
+ end
40
+ end
41
+
42
+ context "inside a tmpdir" do
43
+ setup do
44
+ @dir = FilePath.tmpdir
45
+ assert_directory @dir
46
+ end
47
+
48
+ teardown do
49
+ @dir.rm
50
+ assert_not_directory @dir
51
+ end
52
+
53
+ should "copy a single file" do
54
+ outdir = @dir.join( "down", "down", "down", "to", "the", "depths" )
55
+ assert_no_file outdir
56
+ outdir.touch_dir
57
+ assert outdir.exist?
58
+
59
+ infile = FunWith::Files.root( "test", "helper.rb" )
60
+ assert infile.exist?
61
+
62
+ outfile = outdir.join("copy_of_helper.rb")
63
+ assert !outfile.exist?
64
+
65
+ infile.cp( outdir )
66
+ assert outdir.join("helper.rb").exist?
67
+
68
+ infile.cp( outfile )
69
+ assert outfile.exist?
70
+ end
71
+
72
+ should "copy test directory structure to a temporary directory" do
73
+ outdir = @dir.join( "down", "down", "abandon", "all", "hope" )
74
+ indir = FunWith::Files.root( "test" )
75
+ outdir.touch_dir
76
+ indir.cp( outdir )
77
+
78
+ assert outdir.exist?
79
+ helper_file = outdir.join( "test", "helper.rb" )
80
+ assert_file_has_content helper_file
81
+ assert_equal indir.join( "helper.rb" ).grep( /FunWith::Files/ ).length, helper_file.grep( /FunWith::Files/ ).length
82
+
83
+ assert_equal indir.glob(:all).length, outdir.join("test").glob(:all).length
84
+ end
85
+
86
+ should "symlink masterfully" do
87
+ file = @dir.join( "original.txt" )
88
+ file.write( "This is the original file" )
89
+
90
+ clone = file.symlink( "clone.txt" )
91
+ clone_of_clone = clone.symlink( "clone_of_clone.txt" )
92
+ assert_false( clone_of_clone.original? )
93
+ assert( clone_of_clone.symlink? )
94
+ assert_equal( file, clone_of_clone.original )
95
+
96
+ assert_file_contents( clone_of_clone, /This is the/ )
22
97
  end
23
98
  end
24
99
  end
@@ -2,15 +2,25 @@ require 'helper'
2
2
 
3
3
  class TestFilePath < FunWith::Files::TestCase
4
4
  context "testing basics" do
5
- setup do
6
-
7
- end
8
-
9
5
  should "initialize kindly" do
10
6
  f1 = FilePath.new( "/", "bin", "bash" )
11
7
  f2 = "/".fwf_filepath( "bin", "bash" )
12
- assert f1.exist?
13
- assert f2.exist?
8
+ assert_file f1
9
+ assert_file f2
10
+ end
11
+
12
+ should "have location class methods available" do
13
+ assert_respond_to( FunWith::Files::FilePath, :home )
14
+ assert_respond_to( FunWith::Files::FilePath, :config_dir )
15
+ assert_respond_to( FunWith::Files::FilePath, :root )
16
+ assert_respond_to( FunWith::Files::FilePath, :data_dir )
17
+ end
18
+
19
+
20
+ should "join smoothly" do
21
+ bin_dir = "/bin".fwf_filepath
22
+ assert_equal( "/bin/bash", bin_dir.join("bash").to_s )
23
+ assert_equal( "/bin/bash", bin_dir.join("bash".fwf_filepath).to_s )
14
24
  end
15
25
 
16
26
  should "go up/down when asked" do
@@ -27,8 +37,8 @@ class TestFilePath < FunWith::Files::TestCase
27
37
  assert_equal f1, f2.down( "monkeylips" ).down( "ask_for_floyd" )
28
38
  assert_equal f1, f2.down( "monkeylips", "ask_for_floyd" )
29
39
 
30
- #invoking down didn't change original
31
- assert_no_match /ask_for_floyd/, f2.to_s
40
+ # invoking down didn't change original
41
+ refute_match( /ask_for_floyd/, f2.to_s )
32
42
  end
33
43
 
34
44
  should "convert from string" do
@@ -94,12 +104,12 @@ class TestFilePath < FunWith::Files::TestCase
94
104
  seqfile = seqfile.succ
95
105
  end
96
106
 
97
- assert @tmp_dir.join("sequence.txt").exist?
98
- assert @tmp_dir.join("sequence.000000.txt").exist?
99
- assert @tmp_dir.join("sequence.000008.txt").exist?
107
+ assert_file @tmp_dir.join("sequence.txt")
108
+ assert_file @tmp_dir.join("sequence.000000.txt")
109
+ assert_file @tmp_dir.join("sequence.000008.txt")
100
110
 
101
- assert_equal "0", @tmp_dir.join("sequence.txt").read
102
- assert_equal "9", @tmp_dir.join("sequence.000008.txt").read
111
+ assert_file_contents @tmp_dir.join("sequence.txt"), "0"
112
+ assert_file_contents @tmp_dir.join("sequence.000008.txt"), "9"
103
113
  end
104
114
 
105
115
  should "sequence files with custom stamp length" do
@@ -110,12 +120,12 @@ class TestFilePath < FunWith::Files::TestCase
110
120
  seqfile = seqfile.succ( digit_count: 4 )
111
121
  end
112
122
 
113
- assert @tmp_dir.join("sequence.txt").exist?
114
- assert @tmp_dir.join("sequence.0000.txt").exist?
115
- assert @tmp_dir.join("sequence.0008.txt").exist?
123
+ assert_file @tmp_dir.join("sequence.txt")
124
+ assert_file @tmp_dir.join("sequence.0000.txt")
125
+ assert_file @tmp_dir.join("sequence.0008.txt")
116
126
 
117
- assert_equal "0", @tmp_dir.join("sequence.txt").read
118
- assert_equal "9", @tmp_dir.join("sequence.0008.txt").read
127
+ assert_file_contents @tmp_dir.join("sequence.txt"), "0"
128
+ assert_file_contents @tmp_dir.join("sequence.0008.txt"), "9"
119
129
  end
120
130
 
121
131
  should "sequence files with datestamps" do
@@ -131,15 +141,26 @@ class TestFilePath < FunWith::Files::TestCase
131
141
  assert files.length == 10
132
142
 
133
143
  files.each_with_index do |file, i|
134
- assert file.exist?
135
- assert_equal i.to_s, file.read
144
+ assert_file file
145
+ assert_file_contents file, i.to_s
136
146
  end
137
147
 
138
148
  file_name_strings = files.map(&:to_s)
139
149
  assert_equal file_name_strings[1..-1], file_name_strings[1..-1].sort
140
150
  end
151
+
152
+ should "timestamp files using the timestamp() method" do
153
+ timestampable_file = @tmp_dir.join( "timestamped.dat" )
154
+ timestamped_file1 = timestampable_file.timestamp
155
+ timestamped_file2 = timestampable_file.timestamp("%Y")
156
+
157
+ assert timestamped_file1 =~ /timestamped.\d{17}.dat$/
158
+ assert timestamped_file2 =~ /timestamped.\d{4}.dat$/
159
+ end
141
160
  end
142
161
 
162
+
163
+
143
164
  context "test specify()" do
144
165
  should "just friggin' work" do
145
166
  fil = "resume.doc".fwf_filepath
@@ -163,7 +184,7 @@ class TestFilePath < FunWith::Files::TestCase
163
184
  end
164
185
 
165
186
  teardown do
166
- `rm -rf #{@tmp_dir.join('*')}`
187
+ empty_temp_directory
167
188
  end
168
189
 
169
190
  should "md5hash a file" do
@@ -179,4 +200,18 @@ class TestFilePath < FunWith::Files::TestCase
179
200
  assert_equal( nilhashhash, file.md5 )
180
201
  end
181
202
  end
203
+
204
+ context "test access" do
205
+ should "receive an electric shock when it tries to touch an unwritable file" do
206
+ @read_only_file = "/bin/bash".fwf_filepath # This usually exists. I don't know enough Windows to think of a similarly ubiquitous file.
207
+
208
+ if @read_only_file.file? && ! @read_only_file.writable?
209
+ assert_raises( Errno::EACCES ) do
210
+ @read_only_file.touch
211
+ end
212
+ else
213
+ skip
214
+ end
215
+ end
216
+ end
182
217
  end
@@ -2,7 +2,7 @@ require 'helper'
2
2
 
3
3
  class TestFunWithFiles < FunWith::Files::TestCase
4
4
  context "testing basics" do
5
- should "have core extensions working" do
5
+ should "have fwf_blank?() working" do
6
6
  assert [].fwf_blank?
7
7
  assert false.fwf_blank?
8
8
  assert Hash.new.fwf_blank?
@@ -11,5 +11,19 @@ class TestFunWithFiles < FunWith::Files::TestCase
11
11
  refute true.fwf_blank?
12
12
  refute Object.new.fwf_blank?
13
13
  end
14
+
15
+ should "have fwf_present?() working" do
16
+ refute [].fwf_present?
17
+ refute false.fwf_present?
18
+ refute Hash.new.fwf_present?
19
+ refute "".fwf_present?
20
+ refute " ".fwf_present?
21
+ assert true.fwf_present?
22
+ assert Object.new.fwf_present?
23
+ end
24
+
25
+ should "respond to api" do
26
+ assert_respond_to( FunWith::Files, :root )
27
+ end
14
28
  end
15
29
  end
@@ -1,11 +1,37 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestGlobbing < FunWith::Files::TestCase
4
- should "glob some ruby files from the test/loadable_dir directory" do
5
- assert FunWith::Files.respond_to?(:root)
6
- @loadable_dir = FunWith::Files.root("test", "loadable_dir")
7
- assert @loadable_dir.directory?
8
- @globs = @loadable_dir.glob( :recursive => true, :ext => "rb" )
9
- assert_equal 8, @globs.length
4
+ context "testing globbing" do
5
+ setup do
6
+ @loadable_dir = FunWith::Files.root("test", "loadable_dir")
7
+ assert @loadable_dir.directory?
8
+
9
+ end
10
+
11
+ should "glob some ruby files from the test/loadable_dir directory" do
12
+ globs = @loadable_dir.glob( :recursive => true, :ext => "rb" )
13
+ assert_equal 8, globs.length
14
+ end
15
+
16
+ should "only glob the top-level when recurse is false" do
17
+ globs = @loadable_dir.glob( :recurse => false )
18
+ assert_equal( 5, globs.length )
19
+
20
+ globs = @loadable_dir.glob( :all, :recurse => false )
21
+ assert_equal( 5, globs.length )
22
+ end
23
+
24
+ should "glob everything in the tree by default" do
25
+ globs = @loadable_dir.glob
26
+ assert_equal( 13, globs.length )
27
+
28
+ globs = @loadable_dir.glob(:all)
29
+ assert_equal( 13, globs.length )
30
+ end
31
+
32
+ should "glob only files when an extension is given" do
33
+ globs = @loadable_dir.glob( :recurse => true, :ext => :rb )
34
+ assert_equal( 8, globs.length )
35
+ end
10
36
  end
11
37
  end
@@ -13,13 +13,14 @@ class TestTouching < FunWith::Files::TestCase
13
13
 
14
14
  should "touch a subdirectory" do
15
15
  @subdir = @dir.touch_dir( "Movies", "Basketball", "Shaquille" )
16
- assert_kind_of FilePath, @subdir
17
- assert @subdir.directory?
16
+ assert_fwf_filepath @subdir
17
+ assert_directory @subdir
18
18
  assert_equal @dir, @subdir.up.up.up
19
19
 
20
20
  @subdir_file = @dir.join( "Movies", "Basketball", "Shaquille", "JamNinja.m4v" ).touch
21
- assert_kind_of FilePath, @subdir_file
22
- assert @subdir_file.file?
21
+
22
+ assert_fwf_filepath @subdir_file
23
+ assert_empty_file @subdir_file
23
24
  assert_equal @dir, @subdir_file.dirname.up.up.up
24
25
  end
25
26
 
metadata CHANGED
@@ -1,85 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fun_with_files
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryce Anderson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-04 00:00:00.000000000 Z
11
+ date: 2014-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xdg
15
15
  requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ! '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ! '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: shoulda
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: '3.5'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ! '>='
39
- - !ruby/object:Gem::Version
40
- version: '3.5'
41
- - !ruby/object:Gem::Dependency
42
- name: rdoc
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ~>
46
- - !ruby/object:Gem::Version
47
- version: '3.12'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
16
  requirements:
52
17
  - - ~>
53
18
  - !ruby/object:Gem::Version
54
- version: '3.12'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.5'
62
- type: :development
19
+ version: '2'
20
+ type: :runtime
63
21
  prerelease: false
64
22
  version_requirements: !ruby/object:Gem::Requirement
65
23
  requirements:
66
24
  - - ~>
67
25
  - !ruby/object:Gem::Version
68
- version: '1.5'
26
+ version: '2'
69
27
  - !ruby/object:Gem::Dependency
70
- name: jeweler
28
+ name: fun_with_testing
71
29
  requirement: !ruby/object:Gem::Requirement
72
30
  requirements:
73
31
  - - ~>
74
32
  - !ruby/object:Gem::Version
75
- version: '2.0'
33
+ version: '0.0'
76
34
  type: :development
77
35
  prerelease: false
78
36
  version_requirements: !ruby/object:Gem::Requirement
79
37
  requirements:
80
38
  - - ~>
81
39
  - !ruby/object:Gem::Version
82
- version: '2.0'
40
+ version: '0.0'
83
41
  description: ! " A more intuitive syntax for performing a variety of file actions.
84
42
  Examples:\n \"/\".fwf_filepath.join('usr', 'bin', 'bash').touch\n FunWith::Files::FilePath.home(\"Music\").glob(:ext
85
43
  => \"mp3\", :recurse => true)\n home = FunWith::Files::FilePath.home\n home.touch(
@@ -107,6 +65,7 @@ files:
107
65
  - ./lib/fun_with/files/file_manipulation_methods.rb
108
66
  - ./lib/fun_with/files/file_orderer.rb
109
67
  - ./lib/fun_with/files/file_path.rb
68
+ - ./lib/fun_with/files/file_path_location_methods.rb
110
69
  - ./lib/fun_with/files/file_permission_methods.rb
111
70
  - ./lib/fun_with/files/pathname_extensions.rb
112
71
  - ./lib/fun_with/files/remote_path.rb
@@ -131,6 +90,7 @@ files:
131
90
  - ./test/loadable_dir/dir5/d.rb
132
91
  - ./test/test_copying.rb
133
92
  - ./test/test_descent.rb
93
+ - ./test/test_digest.rb
134
94
  - ./test/test_directory_builder.rb
135
95
  - ./test/test_file_manipulation.rb
136
96
  - ./test/test_file_path.rb