filepath 0.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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