fun_with_files 0.0.7 → 0.0.8

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