pathutil 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 312093b72daeed797421e82320e9b69dbe8cca1c
4
+ data.tar.gz: be2774aba80baf6d8ec0638ba69a5014d5ca2bdf
5
+ SHA512:
6
+ metadata.gz: c66c018dc735686f536246dd21ada663d5e676add05f1eca73a351bbd636c49a0aaf1bc0269294266d4922a591feeddeef8114c8d33b032cacc1cfdda1d73004
7
+ data.tar.gz: 9103cd6a157ae019af799844af46116158500317942575a4f8e1f939fabed3003f8af1bbe06eac26f8f0d1b8758758154bea80fbf7f457bb9aa1a7313a8155ad
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ # Frozen-string-literal: true
2
+ # Copyright: 2015-2016 Jordon Bedwell - MIT License
3
+ # Encoding: utf-8
4
+
5
+ source "https://rubygems.org"
6
+ gem "rake", :require => false
7
+ gemspec
8
+
9
+ group :test do
10
+ gem "codeclimate-test-reporter", :require => false
11
+ gem "safe_yaml", :require => false
12
+ end
13
+
14
+ group :development do
15
+ gem "rspec", :require => false
16
+ gem "rspec-helpers", :require => false
17
+ gem "rubocop", :github => "bbatsov/rubocop", :require => false
18
+ gem "luna-rspec-formatters", :require => false
19
+ gem "benchmark-ips", :require => false
20
+ gem "simple-ansi", :require => false
21
+ gem "pry", :require => false
22
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015-2016 Jordon Bedwell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ # Frozen-string-literal: true
2
+ # Copyright: 2015-2016 Jordon Bedwell - MIT License
3
+ # Encoding: utf-8
4
+
5
+ require "open3"
6
+ require "rspec/core/rake_task"
7
+ require_relative "benchmark/support/task"
8
+ require "simple/ansi"
9
+ require "pathutil"
10
+ require "json"
11
+
12
+ task :default => [:spec]
13
+ RSpec::Core::RakeTask.new :spec
14
+ BenchmarkTask.new :benchmark
15
+ task :test => :spec
16
+
17
+ namespace :diff do
18
+ desc "List methods we have that Pathname doesn't."
19
+ task :methods do
20
+ methods = Pathutil.instance_methods - Pathname.instance_methods - Object.instance_methods
21
+ methods.each do |method|
22
+ $stdout.print "- ", "`", method, "`", "\n"
23
+ end
24
+ end
25
+ end
26
+
27
+ namespace :missing do
28
+ desc "List methods we are missing."
29
+ task :methods do
30
+ methods = Pathname.instance_methods - Pathutil.instance_methods - Object.instance_methods
31
+ methods-= [
32
+ :cleanpath
33
+ ]
34
+
35
+ methods.each do |method|
36
+ $stdout.puts method
37
+ end
38
+ end
39
+ end
40
+
41
+ namespace :pathname do
42
+ desc "List all of Pathnames methods."
43
+ task :methods do
44
+ methods = Pathname.instance_methods - Object.instance_methods
45
+ methods.each_with_index do |method, index|
46
+ $stdout.print method
47
+ unless index == methods.size - 1
48
+ $stdout.print ", "
49
+ end
50
+ end
51
+
52
+ $stdout.puts
53
+ end
54
+ end
55
+
56
+ desc "List all of Pathutils methods."
57
+ task :methods do
58
+ methods = Pathutil.instance_methods - Object.instance_methods
59
+ methods.each_with_index do |method, index|
60
+ $stdout.print "`", method, "`"
61
+ $stdout.print ", " unless index == methods.size - 1
62
+ end
63
+
64
+ $stdout.puts
65
+ end
data/lib/pathutil.rb ADDED
@@ -0,0 +1,783 @@
1
+ # ----------------------------------------------------------------------------
2
+ # Frozen-string-literal: true
3
+ # Copyright: 2015-2016 Jordon Bedwell - MIT License
4
+ # Encoding: utf-8
5
+ # ----------------------------------------------------------------------------
6
+
7
+ require "forwardable/extended"
8
+ require "find"
9
+
10
+ #
11
+
12
+ class Pathutil
13
+ extend Forwardable::Extended
14
+ self.class.send(:attr_writer, :encoding)
15
+ attr_writer :encoding
16
+
17
+ #
18
+
19
+ class << self
20
+
21
+ # ------------------------------------------------------------------------
22
+ # Aliases the default system encoding to us so that we can do most read
23
+ # and write operations with that encoding, instead of being crazy.
24
+ # @note you are encouraged to override this if you need to.
25
+ # ------------------------------------------------------------------------
26
+
27
+ def encoding
28
+ return @encoding ||= begin
29
+ Encoding.default_external
30
+ end
31
+ end
32
+
33
+ # ------------------------------------------------------------------------
34
+ # Normalize CRLF -> LF on Windows reads, to ease your troubles.
35
+ # Normalize LF -> CLRF on Windows write, to ease their troubles.
36
+ # ------------------------------------------------------------------------
37
+
38
+ def normalize
39
+ return @normalize ||= {
40
+ :read => Gem.win_platform?,
41
+ :write => Gem.win_platform?
42
+ }
43
+ end
44
+ end
45
+
46
+ # --------------------------------------------------------------------------
47
+
48
+ def initialize(path)
49
+ @path = path.to_s
50
+ end
51
+
52
+ # --------------------------------------------------------------------------
53
+
54
+ def to_pathname
55
+ Pathname.new(
56
+ self
57
+ )
58
+ end
59
+
60
+ # --------------------------------------------------------------------------
61
+
62
+ def read_yaml(safe: true, whitelist_classes: [], throw_missing: false)
63
+ require "yaml"
64
+
65
+ unless safe
66
+ return YAML.load(
67
+ read
68
+ )
69
+ end
70
+
71
+ if !YAML.respond_to?(:safe_load)
72
+ setup_safe_yaml whitelist_classes
73
+ SafeYAML.load(read, {
74
+ :raise_on_unknown_tag => true
75
+ })
76
+
77
+ else
78
+ YAML.safe_load(read, {
79
+ :whitelist_classes => whitelist_classes
80
+ })
81
+ end
82
+ rescue Errno::ENOENT
83
+ throw_missing ? raise : (
84
+ return {}
85
+ )
86
+ end
87
+
88
+ # --------------------------------------------------------------------------
89
+
90
+ def read_json(throw_missing: false)
91
+ JSON.parse(
92
+ read
93
+ )
94
+
95
+ rescue Errno::ENOENT
96
+ throw_missing ? raise : (
97
+ return {}
98
+ )
99
+ end
100
+
101
+ # --------------------------------------------------------------------------
102
+ # Splits the path into all parts so that you can do step by step comparisons
103
+ # @note The blank part is intentionally left there so that you can rejoin.
104
+ #
105
+ # @example
106
+ # Pathutil.new("/my/path").split_path # => [
107
+ # "", "my", "path"
108
+ # ]
109
+ # --------------------------------------------------------------------------
110
+
111
+ def split_path
112
+ @path.split(
113
+ File::SEPARATOR
114
+ )
115
+ end
116
+
117
+ # --------------------------------------------------------------------------
118
+ # @see `String#==` for more details.
119
+ # A stricter version of `==` that also makes sure the object matches.
120
+ # @param [Pathutil] other the comparee.
121
+ # @return true, false
122
+ # --------------------------------------------------------------------------
123
+
124
+ def ===(other)
125
+ other.is_a?(self.class) && @path == other
126
+ end
127
+
128
+ # --------------------------------------------------------------------------
129
+ # @example Pathutil.new("/hello") >= Pathutil.new("/") # => true
130
+ # @example Pathutil.new("/hello") >= Pathutil.new("/hello") # => true
131
+ # Checks to see if a path falls within a path and deeper or is the other.
132
+ # @param path the path that should be above the object.
133
+ # @return true, false
134
+ # --------------------------------------------------------------------------
135
+
136
+ def >=(other)
137
+ mine, other = expanded_paths(other)
138
+ return true if other == mine
139
+ mine.in_path?(other)
140
+ end
141
+
142
+ # --------------------------------------------------------------------------
143
+ # @example Pathutil.new("/hello/world") > Pathutil.new("/hello") # => true
144
+ # Strictly checks to see if a path is deeper but within the path of the other.
145
+ # @param path the path that should be above the object.
146
+ # @return true, false
147
+ # --------------------------------------------------------------------------
148
+
149
+ def >(other)
150
+ mine, other = expanded_paths(other)
151
+ return false if other == mine
152
+ mine.in_path?(other)
153
+ end
154
+
155
+ # --------------------------------------------------------------------------
156
+ # @example Pathutil.new("/") < Pathutil.new("/hello") # => true
157
+ # Strictly check to see if a path is behind other path but within it.
158
+ # @param path the path that should be below the object.
159
+ # @return true, false
160
+ # --------------------------------------------------------------------------
161
+
162
+ def <(other)
163
+ mine, other = expanded_paths(other)
164
+ return false if other == mine
165
+ other.in_path?(mine)
166
+ end
167
+
168
+ # --------------------------------------------------------------------------
169
+ # Check to see if a path is behind the other path butt within it.
170
+ # @example Pathutil.new("/hello") < Pathutil.new("/hello") # => true
171
+ # @example Pathutil.new("/") < Pathutil.new("/hello") # => true
172
+ # @param path the path that should be below the object.
173
+ # @return true, false
174
+ # --------------------------------------------------------------------------
175
+
176
+ def <=(other)
177
+ mine, other = expanded_paths(other)
178
+ return true if other == mine
179
+ other.in_path?(mine)
180
+ end
181
+
182
+ # --------------------------------------------------------------------------
183
+ # @note "./" is considered relative.
184
+ # Check to see if the path is absolute, as in: starts with "/"
185
+ # @return true, false
186
+ # --------------------------------------------------------------------------
187
+
188
+ def absolute?
189
+ @path.start_with?("/")
190
+ end
191
+
192
+ # --------------------------------------------------------------------------
193
+ # Break apart the path and yield each with the previous parts.
194
+ # @return Enumerator if no block is given.
195
+ #
196
+ # @example
197
+ # Pathutil.new("/hello/world").ascend.to_a # => [
198
+ # "/", "/hello", "/hello/world"
199
+ # ]
200
+ #
201
+ # @example
202
+ # Pathutil.new("/hello/world").ascend do |path|
203
+ # $stdout.puts path
204
+ # end
205
+ #
206
+ # /
207
+ # /hello
208
+ # /hello/world
209
+ # --------------------------------------------------------------------------
210
+
211
+ def ascend
212
+ unless block_given?
213
+ return to_enum(
214
+ __method__
215
+ )
216
+ end
217
+
218
+ yield(
219
+ path = self
220
+ )
221
+
222
+ while (new_path = path.dirname)
223
+ if path == new_path || new_path == "."
224
+ break
225
+ else
226
+ path = new_path
227
+ yield new_path
228
+ end
229
+ end
230
+
231
+ nil
232
+ end
233
+
234
+ # --------------------------------------------------------------------------
235
+ # Break apart the path in reverse order and descend into the path.
236
+ # @return Enumerator if no block is given.
237
+ #
238
+ # @example
239
+ # Pathutil.new("/hello/world").descend.to_a # => [
240
+ # "/hello/world", "/hello", "/"
241
+ # ]
242
+ #
243
+ # @example
244
+ # Pathutil.new("/hello/world").descend do |path|
245
+ # $stdout.puts path
246
+ # end
247
+ #
248
+ # /hello/world
249
+ # /hello
250
+ # /
251
+ # --------------------------------------------------------------------------
252
+
253
+ def descend
254
+ return ascend.to_a.reverse.to_enum unless block_given?
255
+ ascend.to_a.reverse_each do |val|
256
+ yield val
257
+ end
258
+
259
+ nil
260
+ end
261
+
262
+ # --------------------------------------------------------------------------
263
+ # Wraps `readlines` and allows you to yield on the result.
264
+ #
265
+ # @example
266
+ # Pathutil.new("/hello/world").each_line do |line|
267
+ # $stdout.puts line
268
+ # end
269
+ #
270
+ # Hello
271
+ # World
272
+ # --------------------------------------------------------------------------
273
+
274
+ def each_line
275
+ return to_enum(__method__) unless block_given?
276
+ readlines.each do |line|
277
+ yield line
278
+ end
279
+
280
+ nil
281
+ end
282
+
283
+ # --------------------------------------------------------------------------
284
+ # @see `File#fnmatch` for more information.
285
+ # Unlike traditional `fnmatch`, with this one `Regexp` is allowed.
286
+ # @param [String, Regexp] matcher the matcher used, can be a `Regexp`
287
+ # @example Pathutil.new("/hello").fnmatch?("/hello") # => true
288
+ # @example Pathutil.new("/hello").fnmatch?(/h/) # => true
289
+ # @return true, false
290
+ # --------------------------------------------------------------------------
291
+
292
+ def fnmatch?(matcher)
293
+ matcher.is_a?(Regexp) ? !!(self =~ matcher) : \
294
+ File.fnmatch(self, matcher)
295
+ end
296
+
297
+ # --------------------------------------------------------------------------
298
+ # Allows you to quickly determine if the file is the root folder.
299
+ # @return true, false
300
+ # --------------------------------------------------------------------------
301
+
302
+ def root?
303
+ self == File::SEPARATOR
304
+ end
305
+
306
+ # --------------------------------------------------------------------------
307
+ # @param [Pathutil, String] path the reference.
308
+ # Allows you to check if the current path is in the path you want.
309
+ # @return true, false
310
+ # --------------------------------------------------------------------------
311
+
312
+ def in_path?(path)
313
+ path = self.class.new(path).expand_path.split_path
314
+ mine = (symlink?? expand_path.realpath : expand_path).split_path
315
+ path.each_with_index { |part, index| return false if mine[index] != part }
316
+ true
317
+ end
318
+
319
+ # --------------------------------------------------------------------------
320
+
321
+ def inspect
322
+ "#<#{self.class}:#{@path}>"
323
+ end
324
+
325
+ # --------------------------------------------------------------------------
326
+ # Grab all of the children from the current directory, including hidden.
327
+ # @return Array<Pathutils>
328
+ # --------------------------------------------------------------------------
329
+
330
+ def children
331
+ ary = []
332
+
333
+ Dir.foreach(@path) do |path|
334
+ if path == "." || path == ".."
335
+ next
336
+ else
337
+ path = self.class.new(File.join(@path, path))
338
+ yield path if block_given?
339
+ ary.push(
340
+ path
341
+ )
342
+ end
343
+ end
344
+
345
+ ary
346
+ end
347
+
348
+ # --------------------------------------------------------------------------
349
+ # @see `File::Constants` for a list of flags.
350
+ # Allows you to glob however you wish to glob in the current `Pathutils`
351
+ # @param [String] flags the flags you want to ship to the glob.
352
+ # @param [String] pattern the pattern A.K.A: "**/*"
353
+ # @return Enumerator unless a block is given.
354
+ # --------------------------------------------------------------------------
355
+
356
+ def glob(pattern, flags = 0)
357
+ unless block_given?
358
+ return to_enum(
359
+ __method__, pattern, flags
360
+ )
361
+ end
362
+
363
+ chdir do
364
+ Dir.glob(pattern, flags).each do |file|
365
+ yield self.class.new(
366
+ File.join(@path, file)
367
+ )
368
+ end
369
+ end
370
+
371
+ nil
372
+ end
373
+
374
+ # --------------------------------------------------------------------------
375
+ # @note you do not need to ship a block at all.
376
+ # Move to the current directory temporarily (or for good) and do work son.
377
+ # @return 0, 1 if no block given
378
+ # --------------------------------------------------------------------------
379
+
380
+ def chdir
381
+ if !block_given?
382
+ Dir.chdir(
383
+ @path
384
+ )
385
+
386
+ else
387
+ Dir.chdir @path do
388
+ yield
389
+ end
390
+ end
391
+ end
392
+
393
+ # --------------------------------------------------------------------------
394
+ # @return Enumerator if no block is given.
395
+ # Find all files without care and yield the given block.
396
+ # @see Find.find
397
+ # --------------------------------------------------------------------------
398
+
399
+ def find
400
+ return to_enum(__method__) unless block_given?
401
+ Find.find @path do |val|
402
+ yield self.class.new(val)
403
+ end
404
+ end
405
+
406
+ # --------------------------------------------------------------------------
407
+ # Splits the path returning each part (filename) back to you.
408
+ # @return Enumerator if no block is given.
409
+ # --------------------------------------------------------------------------
410
+
411
+ def each_filename
412
+ return to_enum(__method__) unless block_given?
413
+ @path.split(File::SEPARATOR).delete_if(&:empty?).each do |file|
414
+ yield file
415
+ end
416
+ end
417
+
418
+ # --------------------------------------------------------------------------
419
+
420
+ def parent
421
+ self.class.new(File.join(
422
+ @path, ".."
423
+ ))
424
+ end
425
+
426
+ # --------------------------------------------------------------------------
427
+ # Split the file into its dirname and basename, so you can do stuff.
428
+ # @return File.dirname, File.basename
429
+ # --------------------------------------------------------------------------
430
+
431
+ def split
432
+ File.split(@path).collect! do |path|
433
+ self.class.new(path)
434
+ end
435
+ end
436
+
437
+ # --------------------------------------------------------------------------
438
+ # Replace a files extension with your given extension.
439
+ # --------------------------------------------------------------------------
440
+
441
+ def sub_ext(ext)
442
+ self.class.new(
443
+ "#{@path.gsub(/\..+$/, "")}#{ext}"
444
+ )
445
+ end
446
+
447
+ # --------------------------------------------------------------------------
448
+ # A less complex version of `relative_path_from` that simply uses a
449
+ # `Regexp` and returns the full path if it cannot be relatively determined.
450
+ # @return Pathutils the relative path if it can be determined or is relative.
451
+ # @return Pathutils the full path if relative path cannot be determined
452
+ # --------------------------------------------------------------------------
453
+
454
+ def relative_path_from(from)
455
+ from = self.class.new(from).expand_path.gsub(%r!/$!, "")
456
+ self.class.new(expand_path.gsub(%r!^#{from.regexp_escape}/!, ""))
457
+ end
458
+
459
+ # --------------------------------------------------------------------------
460
+ # Expands the path and left joins the root to the path.
461
+ # @param [String, Pathutil] root the root you wish to enforce on it.
462
+ # @return Pathutil the enforced path with given root.
463
+ # --------------------------------------------------------------------------
464
+
465
+ def enforce_root(root)
466
+ curr, root = expanded_paths(root)
467
+ if curr.in_path?(root)
468
+ return curr
469
+
470
+ else
471
+ File.join(
472
+ root, curr
473
+ )
474
+ end
475
+ end
476
+
477
+ # --------------------------------------------------------------------------
478
+ # Copy a directory, allowing symlinks if the link falls inside of the root.
479
+ # --------------------------------------------------------------------------
480
+
481
+ def safe_copy(to, root: nil)
482
+ raise ArgumentError, "must give a root" unless root
483
+ to = self.class.new(to)
484
+
485
+ root = self.class.new(root)
486
+ return safe_copy_directory(to, :root => root) if directory?
487
+ safe_copy_file(to, :root => root)
488
+ end
489
+
490
+ # --------------------------------------------------------------------------
491
+ # @see `self.class.normalize` as this is an alias.
492
+ # --------------------------------------------------------------------------
493
+
494
+ def normalize
495
+ return @normalize ||= begin
496
+ self.class.normalize
497
+ end
498
+ end
499
+
500
+ # --------------------------------------------------------------------------
501
+ # @see `self.class.encoding` as this is an alias.
502
+ # --------------------------------------------------------------------------
503
+
504
+ def encoding
505
+ return @encoding ||= begin
506
+ self.class.encoding
507
+ end
508
+ end
509
+
510
+ # --------------------------------------------------------------------------
511
+ # Read took two steroid shots: it can normalize your string, and encode.
512
+ # --------------------------------------------------------------------------
513
+
514
+ def read(*args, **kwd)
515
+ kwd[:encoding] ||= encoding
516
+
517
+ if normalize[:read]
518
+ File.read(self, *args, kwd).encode({
519
+ :universal_newline => true
520
+ })
521
+
522
+ else
523
+ File.read(
524
+ self, *args, kwd
525
+ )
526
+ end
527
+ end
528
+
529
+ # --------------------------------------------------------------------------
530
+ # Binread took two steroid shots: it can normalize your string, and encode.
531
+ # --------------------------------------------------------------------------
532
+
533
+ def binread(*args, **kwd)
534
+ kwd[:encoding] ||= encoding
535
+
536
+ if normalize[:read]
537
+ File.binread(self, *args, kwd).encode({
538
+ :universal_newline => true
539
+ })
540
+
541
+ else
542
+ File.read(
543
+ self, *args, kwd
544
+ )
545
+ end
546
+ end
547
+
548
+ # --------------------------------------------------------------------------
549
+ # Readlines took two steroid shots: it can normalize your string, and encode.
550
+ # --------------------------------------------------------------------------
551
+
552
+ def readlines(*args, **kwd)
553
+ kwd[:encoding] ||= encoding
554
+
555
+ if normalize[:read]
556
+ File.readlines(self, *args, kwd).encode({
557
+ :universal_newline => true
558
+ })
559
+
560
+ else
561
+ File.readlines(
562
+ self, *args, kwd
563
+ )
564
+ end
565
+ end
566
+
567
+ # --------------------------------------------------------------------------
568
+ # Write took two steroid shots: it can normalize your string, and encode.
569
+ # --------------------------------------------------------------------------
570
+
571
+ def write(data, *args, **kwd)
572
+ kwd[:encoding] ||= encoding
573
+
574
+ if normalize[:write]
575
+ File.write(self, data.encode(
576
+ :crlf_newline => true
577
+ ), *args, kwd)
578
+
579
+ else
580
+ File.write(
581
+ self, data, *args, kwd
582
+ )
583
+ end
584
+ end
585
+
586
+ # --------------------------------------------------------------------------
587
+ # Binwrite took two steroid shots: it can normalize your string, and encode.
588
+ # --------------------------------------------------------------------------
589
+
590
+ def binwrite(data, *args, **kwd)
591
+ kwd[:encoding] ||= encoding
592
+
593
+ if normalize[:write]
594
+ File.binwrite(self, data.encode(
595
+ :crlf_newline => true
596
+ ), *args, kwd)
597
+
598
+ else
599
+ File.binwrite(
600
+ self, data, *args, kwd
601
+ )
602
+ end
603
+ end
604
+
605
+ # --------------------------------------------------------------------------
606
+ # @api returns the current objects expanded path and their expanded path.
607
+ # --------------------------------------------------------------------------
608
+
609
+ private
610
+ def expanded_paths(path)
611
+ return expand_path, self.class.new(path).expand_path
612
+ end
613
+
614
+ # --------------------------------------------------------------------------
615
+
616
+ private
617
+ def safe_copy_file(to, root: nil)
618
+ raise Errno::EPERM, "#{self} not in #{root}" unless in_path?(root)
619
+ FileUtils.cp(self, to, {
620
+ :preserve => true
621
+ })
622
+ end
623
+
624
+ # --------------------------------------------------------------------------
625
+
626
+ private
627
+ def safe_copy_directory(to, root: nil)
628
+ if !in_path?(root)
629
+ raise Errno::EPERM, "#{self} not in #{
630
+ root
631
+ }"
632
+
633
+ else
634
+ to.mkdir_p unless to.exist?
635
+ children do |file|
636
+ if !file.in_path?(root)
637
+ raise Errno::EPERM, "#{file} not in #{
638
+ root
639
+ }"
640
+
641
+ elsif file.file?
642
+ FileUtils.cp(file, to, {
643
+ :preserve => true
644
+ })
645
+
646
+ else
647
+ path = file.realpath
648
+ path.safe_copy(to.join(file.basename), {
649
+ :root => root
650
+ })
651
+ end
652
+ end
653
+ end
654
+ end
655
+
656
+ # --------------------------------------------------------------------------
657
+
658
+ private
659
+ def setup_safe_yaml(whitelist_classes)
660
+ warn "WARN: SafeYAML will be removed when Ruby 2.0 goes EOL."
661
+ require "safe_yaml/load"
662
+
663
+ SafeYAML.restore_defaults!
664
+ whitelist_classes.map(&SafeYAML.method(
665
+ :whitelist_class!
666
+ ))
667
+ end
668
+
669
+ # --------------------------------------------------------------------------
670
+
671
+ rb_delegate :sub, :to => :@path, :wrap => true
672
+ rb_delegate :chomp, :to => :@path, :wrap => true
673
+ rb_delegate :gsub, :to => :@path, :wrap => true
674
+ rb_delegate :=~, :to => :@path
675
+ rb_delegate :==, :to => :@path
676
+ rb_delegate :to_s, :to => :@path
677
+ rb_delegate :freeze, :to => :@path
678
+ rb_delegate :frozen?, :to => :@path
679
+ rb_delegate :to_str, :to => :@path
680
+ rb_delegate :"!~", :to => :@path
681
+ rb_delegate :<=>, :to => :@path
682
+
683
+ # --------------------------------------------------------------------------
684
+
685
+ rb_delegate :basename, :to => :File, :args => :@path, :wrap => true
686
+ rb_delegate :dirname, :to => :File, :args => :@path, :wrap => true
687
+ rb_delegate :readlink, :to => :File, :args => :@path, :wrap => true
688
+ rb_delegate :expand_path, :to => :File, :args => :@path, :wrap => true
689
+ rb_delegate :realdirpath, :to => :File, :args => :@path, :wrap => true
690
+ rb_delegate :realpath, :to => :File, :args => :@path, :wrap => true
691
+ rb_delegate :rename, :to => :File, :args => :@path, :wrap => true
692
+ rb_delegate :join, :to => :File, :args => :@path, :wrap => true
693
+ rb_delegate :size, :to => :File, :args => :@path
694
+ rb_delegate :link, :to => :File, :args => :@path
695
+ rb_delegate :atime, :to => :File, :args => :@path
696
+ rb_delegate :chown, :to => :File, :args => :@path
697
+ rb_delegate :ctime, :to => :File, :args => :@path
698
+ rb_delegate :lstat, :to => :File, :args => :@path
699
+ rb_delegate :utime, :to => :File, :args => :@path
700
+ rb_delegate :lchmod, :to => :File, :args => :@path
701
+ rb_delegate :sysopen, :to => :File, :args => :@path
702
+ rb_delegate :birthtime, :to => :File, :args => :@path
703
+ rb_delegate :mountpoint?, :to => :File, :args => :@path
704
+ rb_delegate :truncate, :to => :File, :args => :@path
705
+ rb_delegate :symlink, :to => :File, :args => :@path
706
+ rb_delegate :extname, :to => :File, :args => :@path
707
+ rb_delegate :lchown, :to => :File, :args => :@path
708
+ rb_delegate :zero?, :to => :File, :args => :@path
709
+ rb_delegate :ftype, :to => :File, :args => :@path
710
+ rb_delegate :chmod, :to => :File, :args => :@path
711
+ rb_delegate :mtime, :to => :File, :args => :@path
712
+ rb_delegate :open, :to => :File, :args => :@path
713
+ rb_delegate :stat, :to => :File, :args => :@path
714
+
715
+ # --------------------------------------------------------------------------
716
+
717
+ rb_delegate :pipe?, :to => :FileTest, :args => :@path
718
+ rb_delegate :file?, :to => :FileTest, :args => :@path
719
+ rb_delegate :owned?, :to => :FileTest, :args => :@path
720
+ rb_delegate :setgid?, :to => :FileTest, :args => :@path
721
+ rb_delegate :socket?, :to => :FileTest, :args => :@path
722
+ rb_delegate :readable?, :to => :FileTest, :args => :@path
723
+ rb_delegate :blockdev?, :to => :FileTest, :args => :@path
724
+ rb_delegate :directory?, :to => :FileTest, :args => :@path
725
+ rb_delegate :readable_real?, :to => :FileTest, :args => :@path
726
+ rb_delegate :world_readable?, :to => :FileTest, :args => :@path
727
+ rb_delegate :executable_real?, :to => :FileTest, :args => :@path
728
+ rb_delegate :world_writable?, :to => :FileTest, :args => :@path
729
+ rb_delegate :writable_real?, :to => :FileTest, :args => :@path
730
+ rb_delegate :executable?, :to => :FileTest, :args => :@path
731
+ rb_delegate :writable?, :to => :FileTest, :args => :@path
732
+ rb_delegate :grpowned?, :to => :FileTest, :args => :@path
733
+ rb_delegate :chardev?, :to => :FileTest, :args => :@path
734
+ rb_delegate :symlink?, :to => :FileTest, :args => :@path
735
+ rb_delegate :sticky?, :to => :FileTest, :args => :@path
736
+ rb_delegate :setuid?, :to => :FileTest, :args => :@path
737
+ rb_delegate :exist?, :to => :FileTest, :args => :@path
738
+ rb_delegate :size?, :to => :FileTest, :args => :@path
739
+
740
+ # --------------------------------------------------------------------------
741
+
742
+ rb_delegate :rm_rf, :to => :FileUtils, :args => :@path
743
+ rb_delegate :rm_r, :to => :FileUtils, :args => :@path
744
+ rb_delegate :rm, :to => :FileUtils, :args => :@path
745
+ rb_delegate :cp_r, :to => :FileUtils, :args => :@path
746
+ rb_delegate :touch, :to => :FileUtils, :args => :@path
747
+ rb_delegate :mkdir_p, :to => :FileUtils, :args => :@path
748
+ rb_delegate :mkpath, :to => :FileUtils, :args => :@path
749
+ rb_delegate :cp, :to => :FileUtils, :args => :@path
750
+
751
+ # --------------------------------------------------------------------------
752
+
753
+ rb_delegate :each_child, :to => :children
754
+ rb_delegate :each_entry, :to => :children
755
+ rb_delegate :to_a, :to => :children
756
+
757
+ # --------------------------------------------------------------------------
758
+
759
+ rb_delegate :opendir, :to => :Dir, :alias_of => :open
760
+ rb_delegate :relative?, :to => :self, :alias_of => :absolute?, :bool => :reverse
761
+ rb_delegate :regexp_escape, :to => :Regexp, :args => :@path, :alias_of => :escape
762
+ rb_delegate :to_regexp, :to => :Regexp, :args => :@path, :alias_of => :new
763
+ rb_delegate :shellescape, :to => :Shellwords, :args => :@path
764
+ rb_delegate :mkdir, :to => :Dir, :args => :@path
765
+
766
+ # --------------------------------------------------------------------------
767
+ # alias last basename, alias first dirname, alias ext extname
768
+ # --------------------------------------------------------------------------
769
+
770
+ alias + join
771
+ alias delete rm
772
+ alias rmtree rm_r
773
+ alias to_path to_s
774
+ alias last basename
775
+ alias entries children
776
+ alias make_symlink symlink
777
+ alias fnmatch fnmatch?
778
+ alias make_link link
779
+ alias first dirname
780
+ alias rmdir rm_r
781
+ alias unlink rm
782
+ alias / join
783
+ end
@@ -0,0 +1,9 @@
1
+ # ----------------------------------------------------------------------------
2
+ # Frozen-string-literal: true
3
+ # Copyright: 2015-2016 Jordon Bedwell - MIT License
4
+ # Encoding: utf-8
5
+ # ----------------------------------------------------------------------------
6
+
7
+ class Pathutil
8
+ VERSION = "0.0.1"
9
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pathutil
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jordon Bedwell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: forwardable-extended
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.4'
27
+ description: Like Pathname but a little less insane.
28
+ email:
29
+ - jordon@envygeeks.io
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Gemfile
35
+ - LICENSE
36
+ - Rakefile
37
+ - lib/pathutil.rb
38
+ - lib/pathutil/version.rb
39
+ homepage: http://github.com/envygeeks/pathutils
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.5.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Almost like Pathname but just a little less insane.
63
+ test_files: []