filepath 0.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -16,7 +16,7 @@ Features and examples
16
16
 
17
17
  The main purpose of FilePath is to able to write
18
18
 
19
- require __FILE_.as_path / 'spec' / 'tasks'
19
+ require __FILE__.as_path / 'spec' / 'tasks'
20
20
 
21
21
  instad of cumbersome code like
22
22
 
@@ -48,7 +48,7 @@ The main features of FilePath are…
48
48
 
49
49
  converted_img = image.replace_extension("jpeg")
50
50
  converted_img.to_s #=> "/home/gioele/Documents/images/cat.jpeg"
51
- convert(image.to_s, converted_img.to_s)
51
+ convert(image, converted_img)
52
52
 
53
53
  ### Path traversal
54
54
 
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ Bones {
13
13
  email 'gioele@svario.it'
14
14
  url 'http://github.com/gioele/filepath'
15
15
 
16
- version '0.2'
16
+ version '0.3.1'
17
17
 
18
18
  ignore_file '.gitignore'
19
19
 
@@ -12,7 +12,7 @@ class FilePath
12
12
  elsif path.is_a? Array
13
13
  @fragments = path
14
14
  else
15
- @fragments = split_path_string(path.to_s)
15
+ @fragments = split_path_string(path.to_str)
16
16
  end
17
17
  end
18
18
 
@@ -100,7 +100,7 @@ class FilePath
100
100
  msg = "cannot compare: "
101
101
  msg += "`#{self}` is #{self_abs} while "
102
102
  msg += "`#{base}` is #{base_abs}"
103
- raise msg # FIXME: argerror error class
103
+ raise ArgumentError, msg
104
104
  end
105
105
 
106
106
  self_frags = self.normalized_fragments
@@ -231,7 +231,7 @@ class FilePath
231
231
  end
232
232
  end
233
233
 
234
- alias ext? extension?
234
+ alias :ext? :extension?
235
235
 
236
236
 
237
237
  # @overload replace_extension(new_ext)
@@ -338,6 +338,7 @@ class FilePath
338
338
  def normalized
339
339
  return FilePath.join(self.normalized_fragments)
340
340
  end
341
+
341
342
  alias :normalised :normalized
342
343
 
343
344
 
@@ -379,7 +380,7 @@ class FilePath
379
380
  # @return [String] this path converted to a String
380
381
 
381
382
  def to_raw_string
382
- return @fragments.join(SEPARATOR).sub(%r{^//}, SEPARATOR) # FIXME: windows, mac
383
+ @to_raw_string ||= join_fragments(@fragments)
383
384
  end
384
385
 
385
386
  alias :to_raw_str :to_raw_string
@@ -390,7 +391,12 @@ class FilePath
390
391
  # @note this method operates on the normalized path
391
392
 
392
393
  def to_s
393
- return self.normalized_fragments.join(SEPARATOR).sub(%r{^//}, SEPARATOR)
394
+ to_str
395
+ end
396
+
397
+
398
+ def to_str
399
+ @to_str ||= join_fragments(self.normalized_fragments)
394
400
  end
395
401
 
396
402
 
@@ -405,7 +411,21 @@ class FilePath
405
411
  end
406
412
 
407
413
  def ==(other)
408
- return self.to_s == other.as_path.to_s
414
+ return self.normalized_fragments == other.as_path.normalized_fragments
415
+ end
416
+
417
+ def eql?(other)
418
+ if self.equal?(other)
419
+ return true
420
+ elsif self.class != other.class
421
+ return false
422
+ end
423
+
424
+ return self.fragments == other.fragments
425
+ end
426
+
427
+ def hash
428
+ return self.fragments.hash
409
429
  end
410
430
 
411
431
  # @private
@@ -425,7 +445,7 @@ class FilePath
425
445
 
426
446
  # @private
427
447
  def normalized_fragments
428
- normalized_relative_frags(self.fragments)
448
+ @normalized_fragments ||= normalized_relative_frags(self.fragments)
429
449
  end
430
450
 
431
451
  # @private
@@ -453,19 +473,32 @@ class FilePath
453
473
  return frags
454
474
  end
455
475
 
476
+ # @private
477
+ def join_fragments(frags)
478
+ # FIXME: windows, mac
479
+ # FIXME: avoid string substitutions and regexen
480
+ return frags.join(SEPARATOR).sub(%r{^//}, SEPARATOR).sub(/\A\Z/, '.')
481
+ end
482
+
456
483
  module PathResolution
457
484
  def absolute_path(base_dir = Dir.pwd) # FIXME: rename to `#absolute`?
458
- path = if !self.absolute?
459
- self
460
- else
461
- base_dir.as_path / self
485
+ if self.absolute?
486
+ return self
462
487
  end
463
488
 
489
+ return base_dir.as_path / self
490
+ end
491
+
492
+ def real_path(base_dir = Dir.pwd)
493
+ path = absolute_path(base_dir)
494
+
464
495
  return path.resolve_link
465
496
  end
466
497
 
498
+ alias :realpath :real_path
499
+
467
500
  def resolve_link
468
- return File.readlink(self.to_s).as_path
501
+ return File.readlink(self).as_path
469
502
  end
470
503
  end
471
504
 
@@ -474,7 +507,7 @@ class FilePath
474
507
  def self.define_filetest_method(filepath_method, filetest_method = nil)
475
508
  filetest_method ||= filepath_method
476
509
  define_method(filepath_method) do
477
- return FileTest.send(filetest_method, self.to_s)
510
+ return FileTest.send(filetest_method, self)
478
511
  end
479
512
  end
480
513
 
@@ -502,27 +535,28 @@ class FilePath
502
535
  alias :zero? :empty?
503
536
 
504
537
  def hidden?
505
- @fragments.last.start_with('.') # FIXME: windows, mac
538
+ @fragments.last.start_with?('.') # FIXME: windows, mac
506
539
  end
507
540
  end
508
541
 
509
542
  module FileManipulationMethods
510
543
  def open(*args, &block)
511
- File.open(self.to_s, *args, &block)
544
+ File.open(self, *args, &block)
512
545
  end
513
546
 
514
547
  def touch
515
- self.open do ; end
548
+ self.open('a') do ; end
549
+ File.utime(File.atime(self), Time.now, self)
516
550
  end
517
551
  end
518
552
 
519
553
  module DirectoryMethods
520
554
  def entries(pattern = '*')
521
555
  if !self.directory?
522
- raise Errno::ENOTDIR.new(self.to_s)
556
+ raise Errno::ENOTDIR.new(self)
523
557
  end
524
558
 
525
- raw_entries = Dir.glob((self / pattern).to_s)
559
+ raw_entries = Dir.glob((self / pattern))
526
560
  entries = FilePathList.new(raw_entries)
527
561
 
528
562
  return entries
@@ -4,9 +4,11 @@
4
4
  class FilePathList
5
5
  include Enumerable
6
6
 
7
+ SEPARATOR = ':'.freeze
8
+
7
9
  def initialize(raw_entries = nil)
8
10
  raw_entries ||= []
9
- @entries = raw_entries.map { |e| FilePath.new(e) }
11
+ @entries = raw_entries.map { |e| e.as_path }
10
12
  end
11
13
 
12
14
  def select_entries(type)
@@ -26,11 +28,6 @@ class FilePathList
26
28
  return select_entries(:directory)
27
29
  end
28
30
 
29
- def exclude(pattern) # FIXME: block
30
- raw_entries = @entries.delete_if { |e| e =~ pattern }
31
- return FilePathList.new(raw_entries)
32
- end
33
-
34
31
  def /(extra_path)
35
32
  return self.map { |path| path / extra_path }
36
33
  end
@@ -39,7 +36,19 @@ class FilePathList
39
36
  return FilePathList.new(@entries + extra_entries.to_a)
40
37
  end
41
38
 
42
- def <<(extra_path) # TODO: implement
39
+ def -(others) # FIXME: block
40
+ if others.is_a? Regexp # FIXME: support any object that responds to =~
41
+ remaining_entries = @entries.delete_if { |e| e =~ others }
42
+ else
43
+ remaining_entries = @entries - others.as_path_list.to_a
44
+ end
45
+
46
+ return FilePathList.new(remaining_entries)
47
+ end
48
+ alias :exclude :-
49
+
50
+ def <<(extra_path)
51
+ return FilePathList.new(@entries + [extra_path.as_path])
43
52
  end
44
53
 
45
54
  def *(other_list)
@@ -51,24 +60,87 @@ class FilePathList
51
60
  return FilePathList.new(paths)
52
61
  end
53
62
 
54
- # FIXME: delegate :to => @entries
55
- def [](index)
56
- @entries[index]
63
+ def remove_common_fragments
64
+ all_frags = @entries.map(&:fragments)
65
+ max_length = all_frags.map(&:length).min
66
+
67
+ idx_different = nil
68
+
69
+ (0..max_length).each do |i|
70
+ fragment = all_frags.first[i]
71
+
72
+ different = all_frags.any? { |frags| frags[i] != fragment }
73
+ if different
74
+ idx_different = i
75
+ break
76
+ end
77
+ end
78
+
79
+ idx_different ||= max_length
80
+
81
+ remaining_frags = all_frags.map { |frags| frags[idx_different..-1] }
82
+
83
+ return FilePathList.new(remaining_frags)
57
84
  end
58
85
 
59
- def include?(*others)
60
- @entries.include?(*others)
86
+ # @return [FilePathList] the path list itself
87
+
88
+ def as_path_list
89
+ self
61
90
  end
62
91
 
63
- def each(&block)
64
- @entries.each(&block)
92
+ def to_a
93
+ @entries
65
94
  end
66
95
 
67
- def map(&block)
68
- @entries.map(&block)
96
+ def to_s
97
+ @to_s ||= @entries.map(&:to_str).join(SEPARATOR)
69
98
  end
70
99
 
71
100
  def inspect
72
101
  @entries.inspect
73
102
  end
103
+
104
+ def ==(other)
105
+ @entries == other.as_path_list.to_a
106
+ end
107
+
108
+ module ArrayMethods
109
+ def self.define_array_method(name)
110
+ define_method(name) do |*args, &block|
111
+ return @entries.send(name, *args, &block)
112
+ end
113
+ end
114
+
115
+ define_array_method :[]
116
+
117
+ define_array_method :empty?
118
+
119
+ define_array_method :include?
120
+
121
+ define_array_method :each
122
+
123
+ define_array_method :map
124
+ end
125
+
126
+ include ArrayMethods
127
+ end
128
+
129
+ class Array
130
+ # Generates a path list from an array of paths.
131
+ #
132
+ # The elements of the array must respond to `#as_path`.
133
+ #
134
+ # `ary.as_path` is equivalent to `FilePathList.new(ary)`.
135
+ #
136
+ # @return [FilePathList] a new path list containing the elements of
137
+ # the array as FilePaths
138
+ #
139
+ # @see String#as_path
140
+ # @see Array#as_path
141
+ # @see FilePath#as_path
142
+
143
+ def as_path_list
144
+ FilePathList.new(self)
145
+ end
74
146
  end
@@ -23,6 +23,7 @@ describe FilePath do
23
23
  ['foo', '.', 'foo'],
24
24
  ['foo', '..', '.'],
25
25
  ['foo/bar', 'baz', 'foo/bar/baz'],
26
+ ['', 'foo/bar', './foo/bar'],
26
27
  ]
27
28
  test_data.each do |base, extra, result|
28
29
  it "concatenates `#{base}` and `#{extra}` (as String) into `#{result}`" do
@@ -49,6 +50,20 @@ describe FilePath do
49
50
  end
50
51
  end
51
52
 
53
+ describe "#join" do
54
+ test_data = [
55
+ ['', ['bar'], './bar'],
56
+ ['foo/quux', ['bar', 'baz'], 'foo/quux/bar/baz'],
57
+ ['/', ['a', 'b', 'c'], '/a/b/c'],
58
+ ]
59
+ test_data.each do |base, extra, result|
60
+ args = extra.map { |x| x.inspect }.join(',')
61
+ it "appends #{args} to '#{base}' to get <#{result}>" do
62
+ base.as_path.join(*extra).should == result
63
+ end
64
+ end
65
+ end
66
+
52
67
  describe "filename" do
53
68
  test_data = [
54
69
  ['/foo/bar', 'bar'],
@@ -107,7 +122,7 @@ describe FilePath do
107
122
  test_data2.each do |path, base|
108
123
  it "raise an exception because `#{path}` and `#{base}` have different prefixes" do
109
124
  p = FilePath.new(path)
110
- expect { p.relative_to(base) }.to raise_error
125
+ expect { p.relative_to(base) }.to raise_error(ArgumentError)
111
126
  end
112
127
  end
113
128
  end
@@ -160,34 +175,38 @@ describe FilePath do
160
175
  end
161
176
 
162
177
  describe "#extension?" do
163
- it "says that `foo.bar` has an extension" do
164
- FilePath.new('foo.bar').extension?.should be_true
165
- end
166
-
167
- it "says that `foo.` has an extension" do
168
- FilePath.new('foo.').extension?.should be_true
169
- end
170
-
171
- it "says that `foo` has no extension" do
172
- FilePath.new('foo').extension?.should be_false
173
- end
174
-
175
- it "says that `foo.bar/baz` has no extension" do
176
- FilePath.new('foo.bar/baz').extension?.should be_false
177
- end
178
-
179
- it "says that `.foo` has no extension" do
180
- FilePath.new('.foo').extension?.should be_false
178
+ with_extension = [
179
+ 'foo.bar',
180
+ 'foo.',
181
+ '.foo.conf',
182
+ ]
183
+ with_extension.each do |path|
184
+ it "says that <#{path}> has an extension" do
185
+ FilePath.new(path).extension?.should be_true
186
+ end
181
187
  end
182
188
 
183
- it "says that `.foo.conf` has no extension" do
184
- FilePath.new('.foo.conf').extension?.should be_true
189
+ no_extension = [
190
+ 'foo',
191
+ 'foo.bar/baz',
192
+ '.foo',
193
+ ]
194
+ no_extension.each do |path|
195
+ it "says that <#{path}> has no extension" do
196
+ FilePath.new(path).extension?.should be_false
197
+ end
185
198
  end
186
- end
187
199
 
188
- describe "#extension?(String)" do
189
- it "says that `foo.bar` extesions is `bar`" do
190
- FilePath.new('foo.bar').extension?('bar').should be_true
200
+ extension_data = [
201
+ ['foo.bar', 'bar'],
202
+ ['/foo/bar.', ''],
203
+ ['foo/bar.baz.conf', 'conf'],
204
+ ['foo.bar.boom', /oo/],
205
+ ]
206
+ extension_data.each do |path, ext|
207
+ it "says that <#{path}> extesions is #{ext.inspect}" do
208
+ FilePath.new(path).extension?(ext).should be_true
209
+ end
191
210
  end
192
211
 
193
212
  it "says that `foo.bar` extension is not `baz`" do
@@ -341,6 +360,10 @@ describe FilePath do
341
360
  it "returns normalized paths" do
342
361
  FilePath.new("/foo/bar/..").to_s.should eql('/foo')
343
362
  end
363
+
364
+ it "returns '.' for empty paths" do
365
+ FilePath.new('').to_s.should eql('.')
366
+ end
344
367
  end
345
368
 
346
369
  describe "#as_path" do
@@ -369,10 +392,78 @@ describe FilePath do
369
392
  end
370
393
  end
371
394
 
395
+ describe "#eql?" do
396
+ it "is always true when an object is compared to itself" do
397
+ ph = 'foo/bar/baz'.as_path
398
+
399
+ ph.should eql(ph)
400
+ end
401
+
402
+ it "matches two different object representing the same path" do
403
+ p1 = '/foo/bar'.as_path
404
+ p2 = '/foo/bar'.as_path
405
+
406
+ p1.should eql(p2)
407
+ end
408
+
409
+ it "does not match different objects representing different paths" do
410
+ p1 = '/foo/bar'.as_path
411
+ p2 = '/foo/bar/baz'.as_path
412
+
413
+ p1.should_not eql(p2)
414
+ end
415
+
416
+ it "does not match objects that are not FilePaths" do
417
+ p1 = '/foo/bar/baz'.as_path
418
+ p2 = '/foo/bar/baz'
419
+
420
+ p1.should eq(p2)
421
+ p1.should_not eql(p2)
422
+ end
423
+ end
424
+
425
+ describe "#hash" do
426
+ it "has the same value for similar paths" do
427
+ p1 = '/foo/bar'.as_path
428
+ p2 = '/foo/bar'.as_path
429
+
430
+ p1.hash.should == p2.hash
431
+ end
432
+
433
+ it "has different values for different paths" do
434
+ p1 = '/foo/bar'.as_path
435
+ p2 = 'foo/quuz'.as_path
436
+
437
+ p1.hash.should_not == p2.hash
438
+ end
439
+
440
+ it "has different values for different paths with same normalized path" do
441
+ p1 = '/foo/bar/..'.as_path
442
+ p2 = '/foo'.as_path
443
+
444
+ p1.should eq(p2)
445
+ p1.hash.should_not eq(p2.hash)
446
+ end
447
+ end
448
+
372
449
  describe FilePath::PathResolution do
373
450
  describe "#absolute_path" do
374
- it "resolves `d1/l11` to `/dev/null`" do
375
- (@root / 'd1' / 'l11').absolute_path.should == '/dev/null'
451
+ test_data = [
452
+ ['d1/l11', File.expand_path('d1/l11', FIXTURES_DIR), FIXTURES_DIR],
453
+ ['/foo/bar', '/foo/bar', '.'],
454
+ ]
455
+ test_data.each do |path, abs_path, cwd|
456
+ it "resolves <#{path}> to <#{abs_path}> (in #{cwd})" do
457
+ Dir.chdir(cwd) do # FIXME
458
+ FilePath.new(path).absolute_path.should == abs_path
459
+ end
460
+ end
461
+ end
462
+ end
463
+
464
+ describe "#real_path" do
465
+ it "resolves <d1/l11> to </dev/null>" do
466
+ (@root / 'd1' / 'l11').real_path.should == '/dev/null'
376
467
  end
377
468
  end
378
469
  end
@@ -419,10 +510,71 @@ describe FilePath do
419
510
  @root.should be_directory
420
511
  end
421
512
  end
513
+
514
+ describe "#hidden?" do
515
+ hidden_paths = [
516
+ '.foorc',
517
+ 'foo/.bar',
518
+ '.foo.bar',
519
+ ]
520
+ hidden_paths.each do |path|
521
+ it "says that <#{path}> is an hidden file" do
522
+ path.as_path.should be_hidden
523
+ end
524
+ end
525
+
526
+ non_hidden_paths = [
527
+ 'foo.bar',
528
+ 'foo/.bar/baz',
529
+ ]
530
+ non_hidden_paths.each do |path|
531
+ it "says that <#{path}> not an hidden file" do
532
+ path.as_path.should_not be_hidden
533
+ end
534
+ end
535
+ end
536
+ end
537
+
538
+ describe FilePath::FileManipulationMethods do
539
+ describe "#touch" do
540
+ let(:ph) { @root / 'd1' / 'test-touch' }
541
+
542
+ before(:each) do
543
+ ph.should_not exist
544
+ end
545
+
546
+ after(:each) do
547
+ File.delete(ph) if File.exists?(ph)
548
+ end
549
+
550
+ it "creates an empty file" do
551
+ ph.touch
552
+ ph.should exist
553
+ end
554
+
555
+ it "updates the modification date of an existing file", :broken => true do
556
+ File.open(ph, "w+") { |file| file << "abc" }
557
+ File.utime(0, Time.now - 3200, ph)
558
+
559
+ before_stat = File.stat(ph)
560
+ before_time = Time.now
561
+
562
+ #sleep(5) # let Ruby flush its stat buffer to the disk
563
+ ph.touch
564
+
565
+ after_time = Time.now
566
+ after_stat = File.stat(ph)
567
+
568
+ before_stat.should_not eq(after_stat)
569
+
570
+ after_stat.size.should eq(before_stat.size)
571
+ after_stat.mtime.should be_between(before_time, after_time)
572
+ end
573
+ end
422
574
  end
423
575
 
424
- describe "methods that operate on directories" do
425
- describe "#select_entries" do
576
+ describe FilePath::DirectoryMethods do
577
+ describe "#entries" do
426
578
  it "raises when path is not a directory" do
427
579
  expect { (@root / 'f1').entries(:files) }.to raise_error(Errno::ENOTDIR)
428
580
  end
@@ -433,11 +585,11 @@ describe FilePath do
433
585
  @root.files.should have(1).item
434
586
  end
435
587
 
436
- it "finds 2 files in directory `d1`" do
588
+ it "finds 2 files in directory <d1>" do
437
589
  (@root / 'd1').files.should have(2).items
438
590
  end
439
591
 
440
- it "finds no files in directory `d1/d12`" do
592
+ it "finds no files in directory <d1/d12>" do
441
593
  (@root / 'd1' / 'd12').files.should have(0).items
442
594
  end
443
595
  end
@@ -447,11 +599,11 @@ describe FilePath do
447
599
  @root.directories.should have(4).items
448
600
  end
449
601
 
450
- it "finds 2 directories in directory `d2`" do
602
+ it "finds 2 directories in directory <d2>" do
451
603
  (@root / 'd2').directories.should have(2).items
452
604
  end
453
605
 
454
- it "finds no directories in directory `d1/d13" do
606
+ it "finds no directories in directory <d1/d13>" do
455
607
  (@root / 'd1' / 'd13').directories.should have(0).items
456
608
  end
457
609
  end
@@ -461,7 +613,7 @@ describe FilePath do
461
613
  @root.links.should have(0).items
462
614
  end
463
615
 
464
- it "finds 1 link in directory `d1`" do
616
+ it "finds 1 link in directory <d1>" do
465
617
  (@root / 'd1').links.should have(1).item
466
618
  end
467
619
  end
@@ -4,6 +4,44 @@
4
4
  require File.join(File.dirname(__FILE__), 'spec_helper')
5
5
 
6
6
  describe FilePathList do
7
+ describe "#initialize" do
8
+ it "creates an empty FilePathList" do
9
+ list = FilePathList.new()
10
+
11
+ list.should be_empty
12
+ end
13
+
14
+ it "creates a FilePathList from an Array of Strings" do
15
+ paths = %w{a/b c/d e/f}
16
+ list = FilePathList.new(paths)
17
+
18
+ list.should have(3).items
19
+ list.each { |path| path.should be_a(FilePath) }
20
+ end
21
+
22
+ it "creates a FilePathList from an Array of FilePaths" do
23
+ paths = %w{a/b c/d e/f}.map(&:as_path)
24
+ list = FilePathList.new(paths)
25
+
26
+ list.should have(3).items
27
+ list.each { |path| path.should be_a(FilePath) }
28
+ end
29
+
30
+ it "creates a FilePathList from an Array of Arrays" do
31
+ paths = [%w{a b}, %w{c d}, %w{e f}]
32
+ list = FilePathList.new(paths)
33
+
34
+ list.should have(3).items
35
+ list.each { |path| path.should be_a(FilePath) }
36
+ end
37
+ end
38
+
39
+ describe "#exclude" do
40
+ list = FilePathList.new(%w{a.foo b.bar c.foo d.foo b.bar})
41
+ refined = list.exclude(/bar$/)
42
+ refined.each { |path| path.extension.should == 'foo' }
43
+ end
44
+
7
45
  describe "#/" do
8
46
  it "adds the same string to all the paths" do
9
47
  list = FilePathList.new(%w{foo faa}) / 'bar'
@@ -12,6 +50,45 @@ describe FilePathList do
12
50
  end
13
51
  end
14
52
 
53
+ describe "#+" do
54
+ it "concatenates two FilePathLists" do
55
+ list1 = FilePathList.new(%w{a b c})
56
+ list2 = FilePathList.new(%w{d e})
57
+
58
+ list = list1 + list2
59
+ list.should have(5).items
60
+ list[0].should eq('a')
61
+ list[1].should eq('b')
62
+ list[2].should eq('c')
63
+ list[3].should eq('d')
64
+ list[4].should eq('e')
65
+ end
66
+ end
67
+
68
+ describe "#-" do
69
+ it "removes a list (as array of strings) from another list" do
70
+ list1 = FilePathList.new(%w{a/b /a/c e/d})
71
+ list2 = list1 - %w{a/b e/d}
72
+
73
+ list2.should have(1).item
74
+ list2[0].should eq('/a/c')
75
+ end
76
+ end
77
+
78
+ describe "#<<" do
79
+ it "adds a new to path to a existing FilePathList" do
80
+ list1 = FilePathList.new(%w{a/b /c/d})
81
+ list2 = list1 << "e/f"
82
+
83
+ list1.should have(2).items
84
+ list2.should have(3).items
85
+
86
+ list2[0].should eq('a/b')
87
+ list2[1].should eq('/c/d')
88
+ list2[2].should eq('e/f')
89
+ end
90
+ end
91
+
15
92
  describe "#*" do
16
93
  describe "calculates the cartesian product between" do
17
94
  it "two FilePathLists" do
@@ -56,10 +133,81 @@ describe FilePathList do
56
133
  end
57
134
  end
58
135
 
136
+ describe "#remove_common_fragments" do
137
+ it "works on lists of files from the same dir" do
138
+ paths = %w{a/b/x1 a/b/x2 a/b/x3}
139
+ list = FilePathList.new(paths).remove_common_fragments
140
+
141
+ list.should have(3).items
142
+ list.should include(*%w{x1 x2 x3})
143
+ end
144
+
145
+ it "works on lists of files from different dirs" do
146
+ list1 = FilePathList.new(%w{a/b/x1 a/b/c/x2 a/b/d/e/x3})
147
+ list2 = list1.remove_common_fragments
148
+
149
+ list2.should have(3).items
150
+ list2.should include(*%w{x1 c/x2 d/e/x3})
151
+ end
152
+
153
+ it "works on lists of files with no common fragments" do
154
+ paths = %w{a/b a/d g/f}
155
+ list1 = FilePathList.new(paths)
156
+ list2 = list1.remove_common_fragments
157
+
158
+ list1.should == list2
159
+ end
160
+
161
+ it "works on lists that contain duplicates only" do
162
+ paths = %w{a/b a/b a/b}
163
+ list1 = FilePathList.new(paths)
164
+ list2 = list1.remove_common_fragments
165
+
166
+ list2.should == FilePathList.new(['.', '.', '.'])
167
+ end
168
+ end
169
+
59
170
  describe "#include?" do
60
- it "says that `a/c` in included in [<a/b>, <a/c>, </a/d>]" do
171
+ it "says that 'a/c' is included in [<a/b>, <a/c>, </a/d>]" do
61
172
  list = FilePathList.new(%w{a/b a/c /a/d})
62
173
  list.should include("a/c")
63
174
  end
64
175
  end
176
+
177
+ describe "#to_s" do
178
+ it "returns files separated by a comma`" do
179
+ list = FilePathList.new(%w{a/b a/c /a/d})
180
+ list.to_s.should == "a/b:a/c:/a/d"
181
+ end
182
+ end
183
+
184
+ describe "#==" do
185
+ let(:list) { ['a/b', 'c/d', 'e/f'].as_path_list }
186
+
187
+ it "compares a FilePathList to another FilePathList" do
188
+ list2 = FilePathList.new << 'a/b' << 'c/d' << 'e/f'
189
+ list3 = list2 << 'g/h'
190
+
191
+ list.should eq(list2)
192
+ list.should_not eq(list3)
193
+ end
194
+
195
+ it "compares a FilePathList to an Array of Strings" do
196
+ list.should eq(%w{a/b c/d e/f})
197
+ list.should_not eq(%w{a/a b/b c/c})
198
+ end
199
+ end
200
+ end
201
+
202
+
203
+ describe Array do
204
+ describe "#as_path_list" do
205
+ it "generates a FilePathList from an Array" do
206
+ paths = %w{/a/b c/d /f/g}
207
+ list = paths.as_path_list
208
+
209
+ list.should be_a(FilePathList)
210
+ list.should include(*paths)
211
+ end
212
+ end
65
213
  end
@@ -5,6 +5,7 @@ require 'filepath'
5
5
  require 'filepathlist'
6
6
 
7
7
  RSpec.configure do |config|
8
+ config.filter_run_excluding :broken => true
8
9
  end
9
10
 
10
11
  FIXTURES_DIR = File.join(%w{spec fixtures})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filepath
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-15 00:00:00.000000000 Z
12
+ date: 2012-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bones-rspec
16
- requirement: &15445240 !ruby/object:Gem::Requirement
16
+ requirement: &21597840 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.0.1
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *15445240
24
+ version_requirements: *21597840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bones
27
- requirement: &15444620 !ruby/object:Gem::Requirement
27
+ requirement: &21595900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 3.7.3
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *15444620
35
+ version_requirements: *21595900
36
36
  description: ! 'filepath is a small library that helps dealing with files, directories
37
37
  and
38
38