fspath 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjExMmZkYzEwNGJlMDFiZDhkOTJmZjE2Yzg0M2Y0M2ZhNzI3Nzg5NQ==
4
+ YWYxMDFiMmI4MTkyOGMyYTEzNjkwODA4Njk0ZDRlOTc3MTZjYTIzZQ==
5
5
  data.tar.gz: !binary |-
6
- ZjZlNTBlNzQ0ODQzN2ViOWU1NDM1ZDkzZGNkNDAzNzZhMmM2MWM1OA==
6
+ NGYwZDllNTE0MDdkYmY1NWMyYmFmMjIwMTRiZjg3ZmEzMjk4YjM4OQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZmE5ODRjOWZkMjg1ZWM1NDU0M2NhOGM2MmE1YjVkYjg5NjEyNjJmZWNiMjNl
10
- YzdjNzMzZjM4MjkwNGEzMTkyNjY4OTA5MTc0ZDhhOTgzYzZjMDY2YzJmZjYz
11
- Y2MzODM0Mzk5OGU0ZmUxNDIwODYyZGNkNzkzZmI2Mzc4Y2U1YzI=
9
+ ZmVmOGJkY2NjMzlkODE2N2M4MjI0ZDViZTdjMTdlYzIyYTRmNTk1ZDE1ZGYz
10
+ NGIwMWE5ZmEwODQ5NGEyYzQ5MWZjYzI3ZDgwMmZlMzI0MjFlM2EyM2JiYjVm
11
+ MTkyZDYyMzkzODcyMWU3ZmY3ZjlkZDIzY2UwMmMxMTM3YWJmYjM=
12
12
  data.tar.gz: !binary |-
13
- YmQzYzg1NTdlZWM3Y2I1OTg5YzUxMTg3ODcwYjk4YzdkMmQ1ZWE0YTJiOTFk
14
- MDM1NDliNGRjMjFhOGIyNzY4MzY0MTk2YTlhMzFmMjY3ZTNiZTcyYWQ2ZThl
15
- MDFkNjk5NzU0N2I3NjlhMWQwMjZiZTc5ZDgwNDAzYjIzZjFiZDA=
13
+ YmEwNWIzNDdkMTUyNDczZDAyNDQ5MjFkZjBlZjY0OWNmMzFjMDA3NWQ1MWY2
14
+ ZDM4ODI0NDUwM2NmNTNjZGRmYzBkYjQzZmY4ZGU2MDk2NjQzZDFkMzY4ZmJk
15
+ NDQ2MzJhNzJhNGIxYjhjMTRlY2U5OTU4OWQ3ODRiMTE5YzllOGE=
data/.appveyor.yml ADDED
@@ -0,0 +1,20 @@
1
+ version: '{build}-{branch}'
2
+ install:
3
+ - bundle config path vendor/bundle
4
+ - bundle install -j4
5
+ build: off
6
+ test_script:
7
+ - ps: |
8
+ $path = $env:Path
9
+ $rubypaths = ls -Path C:\Ruby*\bin
10
+ $ErrorActionPreference = "Stop"
11
+ foreach ($rubypath in $rubypaths) {
12
+ echo "################################################################################"
13
+ $env:Path = "$rubypath;" + $path
14
+ ruby --version
15
+ bundle exec rspec
16
+ if ($LASTEXITCODE -gt 0) {
17
+ exit 1
18
+ }
19
+ }
20
+ $env:Path = $path
data/.rubocop.yml CHANGED
@@ -6,7 +6,7 @@ Lint/EndAlignment:
6
6
  AlignWith: variable
7
7
 
8
8
  Metrics/ClassLength:
9
- Max: 175
9
+ Max: 200
10
10
 
11
11
  Metrics/MethodLength:
12
12
  Max: 15
@@ -49,11 +49,17 @@ Style/PercentLiteralDelimiters:
49
49
  Style/Semicolon:
50
50
  AllowAsExpressionSeparator: true
51
51
 
52
+ Style/SignalException:
53
+ EnforcedStyle: semantic
54
+
52
55
  Style/SpaceBeforeBlockBraces:
53
56
  EnforcedStyle: no_space
54
57
 
55
58
  Style/SpaceInsideHashLiteralBraces:
56
59
  EnforcedStyle: no_space
57
60
 
58
- Style/TrailingComma:
61
+ Style/TrailingCommaInArguments:
62
+ EnforcedStyleForMultiline: no_comma
63
+
64
+ Style/TrailingCommaInLiteral:
59
65
  EnforcedStyleForMultiline: comma
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
- - 1.9.3
4
+ - '1.8'
5
+ - '1.9'
6
6
  - '2.0'
7
7
  - '2.1'
8
8
  - '2.2'
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2014 Ivan Kuchin
1
+ Copyright (c) 2010-2016 Ivan Kuchin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -1,8 +1,9 @@
1
1
  [![Gem Version](https://img.shields.io/gem/v/fspath.svg?style=flat)](https://rubygems.org/gems/fspath)
2
2
  [![Build Status](https://img.shields.io/travis/toy/fspath/master.svg?style=flat)](https://travis-ci.org/toy/fspath)
3
+ [![AppVeyor Status](https://img.shields.io/appveyor/ci/toy/fspath/master.svg?style=flat&label=windows)](https://ci.appveyor.com/project/toy/fspath)
3
4
  [![Code Climate](https://img.shields.io/codeclimate/github/toy/fspath.svg?style=flat)](https://codeclimate.com/github/toy/fspath)
4
5
  [![Dependency Status](https://img.shields.io/gemnasium/toy/fspath.svg?style=flat)](https://gemnasium.com/toy/fspath)
5
- [![Inch CI](http://inch-ci.org/github/toy/fspath.svg?branch=master&style=flat)](http://inch-ci.org/github/toy/fspath)
6
+ [![Inch CI](https://inch-ci.org/github/toy/fspath.svg?branch=master&style=flat)](https://inch-ci.org/github/toy/fspath)
6
7
 
7
8
  # fspath
8
9
 
@@ -24,17 +25,42 @@ Common dir for paths:
24
25
 
25
26
  FSPath.common_dir('/a/b/c/d/e/f', '/a/b/c/1/hello', '/a/b/c/2/world') # => FSPath('/a/b/c')
26
27
 
27
- Join paths:
28
+ Temp file (args are passed to `Tempfile.new`):
28
29
 
29
- FSPath('a') / 'b' / 'c' # => FSPath('a/b/c')
30
+ FSPath.temp_file{ |f| …; p f.path; }
31
+
32
+ f = FSPath.temp_file
33
+
34
+ f.close
35
+
36
+ Temp file path (args are passed to `Tempfile.new`):
37
+
38
+ FSPath.temp_file_path{ |path| …; p path; … }
39
+
40
+ path = FSPath.temp_file_path
41
+
42
+ # file will be removed on next GC run if reference to path is lost
30
43
 
31
- Write data:
44
+ Temp directory (args are passed to `Dir.mktmpdir`):
32
45
 
33
- FSPath('a').write('data')
46
+ FSPath.temp_dir{ |dir| …; p dir; … }
47
+
48
+ dir = FSPath.temp_dir
49
+
50
+ # the dir is not removed when temp_dir is run without block
51
+
52
+ Join paths:
53
+
54
+ FSPath('a') / 'b' / 'c' # => FSPath('a/b/c')
34
55
 
35
- Append data:
56
+ Read/write:
36
57
 
37
- FSPath('a').append('data')
58
+ FSPath('a.txt').read
59
+ FSPath('b.bin').binread
60
+ FSPath('a.txt').write(text)
61
+ FSPath('b.bin').binwrite(data)
62
+ FSPath('a.txt').append(more_text)
63
+ FSPath('b.bin').binappend(more_data)
38
64
 
39
65
  Escape glob:
40
66
 
@@ -60,4 +86,4 @@ Path parts:
60
86
 
61
87
  ## Copyright
62
88
 
63
- Copyright (c) 2010-2014 Ivan Kuchin. See LICENSE.txt for details.
89
+ Copyright (c) 2010-2016 Ivan Kuchin. See LICENSE.txt for details.
data/fspath.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'fspath'
5
- s.version = '2.1.1'
5
+ s.version = '3.0.0'
6
6
  s.summary = %q{Better than Pathname}
7
7
  s.homepage = "http://github.com/toy/#{s.name}"
8
8
  s.authors = ['Ivan Kuchin']
data/lib/fspath.rb CHANGED
@@ -64,6 +64,7 @@ class FSPath < Pathname
64
64
  def temp_file_path(*args)
65
65
  if block_given?
66
66
  temp_file(*args) do |file|
67
+ file.close
67
68
  yield file.path
68
69
  end
69
70
  else
@@ -104,15 +105,39 @@ class FSPath < Pathname
104
105
  self.class.new(super(self.class.new(other)))
105
106
  end
106
107
 
107
- # Write data to file
108
- def write(data)
109
- open('wb') do |f|
110
- f.write(data)
108
+ unless Pathname.method_defined?(:binread)
109
+ # Read data from file opened in binary mode
110
+ def binread(length = nil, offset = nil)
111
+ open('rb') do |f|
112
+ f.seek(offset) if offset
113
+ f.read(length)
114
+ end
115
+ end
116
+ end
117
+
118
+ unless Pathname.method_defined?(:write)
119
+ # Write data to file
120
+ def write(data, offset = nil)
121
+ _write(data, offset, false)
122
+ end
123
+ end
124
+
125
+ unless Pathname.method_defined?(:binwrite)
126
+ # Write data to file opened in binary mode
127
+ def binwrite(data, offset = nil)
128
+ _write(data, offset, true)
111
129
  end
112
130
  end
113
131
 
114
132
  # Append data to file
115
133
  def append(data)
134
+ open('a') do |f|
135
+ f.write(data)
136
+ end
137
+ end
138
+
139
+ # Append data to file opened in binary mode
140
+ def binappend(data)
116
141
  open('ab') do |f|
117
142
  f.write(data)
118
143
  end
@@ -164,15 +189,22 @@ class FSPath < Pathname
164
189
  end
165
190
 
166
191
  # Returns path parts
192
+ # FSPath('/a/b/c').parts # ['/', 'a', 'b', 'c']
193
+ # FSPath('a/b/c').parts # ['a', 'b', 'c']
194
+ # FSPath('./a/b/c').parts # ['.', 'a', 'b', 'c']
195
+ # FSPath('a/../b/c').parts # ['a', '..', 'b', 'c']
167
196
  def parts
168
- split_names(@path).flatten
197
+ prefix, parts = split_names(@path)
198
+ prefix.empty? ? parts : [prefix] + parts
169
199
  end
170
200
 
171
201
  unless pwd.is_a?(self)
172
202
  # Fixing glob
173
203
  def self.glob(*args)
174
204
  if block_given?
175
- super{ |f| yield new(f) }
205
+ super do |f|
206
+ yield new(f)
207
+ end
176
208
  else
177
209
  super.map{ |f| new(f) }
178
210
  end
@@ -239,7 +271,9 @@ class FSPath < Pathname
239
271
 
240
272
  # Fixing each_entry
241
273
  def each_entry
242
- super{ |f| yield self.class.new(f) }
274
+ super do |f|
275
+ yield self.class.new(f)
276
+ end
243
277
  end
244
278
 
245
279
  # Fixing entries
@@ -260,6 +294,20 @@ private
260
294
  def escape_glob_string
261
295
  @path.gsub(/([\*\?\[\]\{\}])/, '\\\\\1')
262
296
  end
297
+
298
+ def _write(data, offset, binmode)
299
+ mode = if offset
300
+ Fcntl::O_CREAT | Fcntl::O_RDWR # fix for jruby 1.8 truncating with WRONLY
301
+ else
302
+ Fcntl::O_CREAT | Fcntl::O_WRONLY | Fcntl::O_TRUNC
303
+ end
304
+
305
+ open(mode) do |f|
306
+ f.binmode if binmode
307
+ f.seek(offset) if offset
308
+ f.write(data)
309
+ end
310
+ end
263
311
  end
264
312
 
265
313
  # Add FSPath method as alias to FSPath.new
data/spec/fspath_spec.rb CHANGED
@@ -1,7 +1,15 @@
1
1
  require 'fspath'
2
2
 
3
3
  describe FSPath do
4
- class ZPath < FSPath
4
+ class ZPath < FSPath; end
5
+
6
+ # check_have_symlink? from test/fileutils/test_fileutils.rb
7
+ def self.symlinks_supported?
8
+ File.symlink '', ''
9
+ rescue NotImplementedError, Errno::EACCES
10
+ false
11
+ rescue
12
+ true
5
13
  end
6
14
 
7
15
  it 'inherits from Pathname' do
@@ -12,17 +20,23 @@ describe FSPath do
12
20
  expect(FSPath('.')).to eql(FSPath.new('.'))
13
21
  end
14
22
 
15
- describe '~' do
23
+ describe '.~' do
16
24
  it 'returns current user home directory' do
17
- expect(FSPath.~).to eq(FSPath(File.expand_path('~')))
25
+ expect(File).to receive(:expand_path).
26
+ with('~').and_return('/home/this')
27
+
28
+ expect(FSPath.~).to eq(FSPath('/home/this'))
18
29
  end
19
30
 
20
31
  it 'returns other user home directory' do
21
- expect(FSPath.~('root')).to eq(FSPath(File.expand_path('~root')))
32
+ expect(File).to receive(:expand_path).
33
+ with('~root').and_return('/home/root')
34
+
35
+ expect(FSPath.~('root')).to eq(FSPath('/home/root'))
22
36
  end
23
37
  end
24
38
 
25
- describe 'common_dir' do
39
+ describe '.common_dir' do
26
40
  it 'returns dirname if called with one path' do
27
41
  expect(FSPath.common_dir('/a/b/c')).to eq(FSPath('/a/b'))
28
42
  end
@@ -37,52 +51,83 @@ describe FSPath do
37
51
  end
38
52
  end
39
53
 
40
- [FSPath, ZPath].each do |klass|
41
- describe "#{klass}.temp_file" do
42
- it "returns Tempfile with path returning instance of #{klass}" do
43
- expect(klass.temp_file).to be_kind_of(Tempfile)
44
- expect(klass.temp_file.path).to be_kind_of(klass)
45
- end
54
+ describe '.temp_file' do
55
+ [FSPath, ZPath].each do |klass|
56
+ context "when called on #{klass}" do
57
+ it "returns Tempfile with path returning instance of #{klass}" do
58
+ expect(klass.temp_file).to be_kind_of(Tempfile)
59
+ expect(klass.temp_file.path).to be_kind_of(klass)
60
+ end
46
61
 
47
- it "yields Tempfile with path returning instance of #{klass}" do
48
- yielded = nil
49
- klass.temp_file{ |y| yielded = y }
50
- expect(yielded).to be_kind_of(Tempfile)
51
- expect(yielded.path).to be_kind_of(klass)
62
+ it "yields Tempfile with path returning instance of #{klass}" do
63
+ yielded = nil
64
+ klass.temp_file{ |y| yielded = y }
65
+ expect(yielded).to be_kind_of(Tempfile)
66
+ expect(yielded.path).to be_kind_of(klass)
67
+ end
52
68
  end
69
+ end
53
70
 
54
- it 'returns result of block' do
55
- expect(klass.temp_file{ :result }).to eq(:result)
56
- end
71
+ it 'returns result of block' do
72
+ expect(FSPath.temp_file{ :result }).to eq(:result)
73
+ end
57
74
 
58
- it 'calls appropriate initializer (jruby 1.8 mode bug)' do
59
- expect do
60
- klass.temp_file('abc', '.'){}
61
- end.not_to raise_error
75
+ it 'calls appropriate initializer (jruby 1.8 mode bug)' do
76
+ expect do
77
+ FSPath.temp_file('abc', '.'){}
78
+ end.not_to raise_error
79
+ end
80
+ end
81
+
82
+ describe '.temp_file_path' do
83
+ [FSPath, ZPath].each do |klass|
84
+ context "when called on #{klass}" do
85
+ it "returns an instance of #{klass} with temporary path" do
86
+ expect(klass.temp_file_path).to be_kind_of(klass)
87
+ end
88
+
89
+ it "yields an instance of #{klass} with temporary path" do
90
+ yielded = nil
91
+ klass.temp_file_path{ |y| yielded = y }
92
+ expect(yielded).to be_kind_of(klass)
93
+ end
62
94
  end
63
95
  end
64
96
 
65
- describe "#{klass}.temp_file_path" do
66
- it "returns #{klass} with temporary path" do
67
- expect(klass.temp_file_path).to be_kind_of(klass)
97
+ it 'does not allow GC to finalize TempFile' do
98
+ paths = Array.new(1000){ FSPath.temp_file_path }
99
+ expect(paths).to be_all(&:exist?)
100
+ GC.start
101
+ expect(paths).to be_all(&:exist?)
102
+ end
103
+
104
+ it 'returns result of block' do
105
+ expect(FSPath.temp_file_path{ :result }).to eq(:result)
106
+ end
107
+
108
+ describe 'closing file handle' do
109
+ before do
110
+ @tempfile = nil
111
+ allow(FSPath::Tempfile).to receive(:new).once.
112
+ and_wrap_original{ |m, *args| @tempfile = m.call(*args) }
68
113
  end
69
114
 
70
- it 'does not allow GC to finalize TempFile' do
71
- paths = Array.new(1000){ FSPath.temp_file_path }
72
- expect(paths).to be_all(&:exist?)
73
- GC.start
74
- expect(paths).to be_all(&:exist?)
115
+ it 'closes the file handle, but does not unlink path before return' do
116
+ path = FSPath.temp_file_path
117
+ expect(@tempfile).to be_closed
118
+ expect(path).to exist
75
119
  end
76
120
 
77
- it "yields #{klass} with temporary path" do
78
- yielded = nil
79
- klass.temp_file_path{ |y| yielded = y }
80
- expect(yielded).to be_kind_of(klass)
121
+ it 'closes the file handle, but does not unlink path before yield' do
122
+ FSPath.temp_file_path do |path|
123
+ expect(@tempfile).to be_closed
124
+ expect(path).to exist
125
+ end
81
126
  end
82
127
  end
83
128
  end
84
129
 
85
- describe 'temp_dir' do
130
+ describe '.temp_dir' do
86
131
  it 'returns result of running Dir.mktmpdir as FSPath instance' do
87
132
  @path = '/tmp/a/b/1'
88
133
  allow(Dir).to receive(:mktmpdir).and_return(@path)
@@ -100,7 +145,7 @@ describe FSPath do
100
145
  end
101
146
  end
102
147
 
103
- describe '/' do
148
+ describe '#/' do
104
149
  it 'joins path with string' do
105
150
  expect(FSPath('a') / 'b').to eq(FSPath('a/b'))
106
151
  end
@@ -114,7 +159,7 @@ describe FSPath do
114
159
  end
115
160
  end
116
161
 
117
- describe '+' do
162
+ describe '#+' do
118
163
  it 'returns instance of FSPath' do
119
164
  expect(FSPath('a') + 'b').to be_instance_of(FSPath)
120
165
  end
@@ -128,7 +173,7 @@ describe FSPath do
128
173
  end
129
174
  end
130
175
 
131
- describe 'relative_path_from' do
176
+ describe '#relative_path_from' do
132
177
  it 'returns instance of FSPath' do
133
178
  expect(FSPath('a').relative_path_from('b')).to be_instance_of(FSPath)
134
179
  end
@@ -138,58 +183,136 @@ describe FSPath do
138
183
  end
139
184
  end
140
185
 
141
- describe 'writing' do
142
- before do
143
- @path = FSPath.new('test')
144
- @file = double(:file)
145
- @data = double(:data)
146
- @size = double(:size)
186
+ describe 'read/write' do
187
+ let(:path){ FSPath.temp_file_path }
188
+ let(:crlf_text){ "a\nb\rc\r\nd" }
189
+ let(:described_method){ |example| example.full_description[/#(\S+)/, 1] }
147
190
 
148
- allow(@path).to receive(:open).and_yield(@file)
149
- allow(@file).to receive(:write).and_return(@size)
191
+ def binread(path)
192
+ path.open('rb', &:read)
150
193
  end
151
194
 
152
- describe 'write' do
153
- it 'opens file for writing' do
154
- expect(@path).to receive(:open).with('wb')
155
- @path.write(@data)
195
+ def binwrite(path, data)
196
+ path.open('wb'){ |f| f.write(data) }
197
+ end
198
+
199
+ describe '#binread' do
200
+ it 'reads data' do
201
+ binwrite(path, 'data')
202
+ expect(path.binread).to eq('data')
203
+ end
204
+
205
+ it 'limits data when length is set' do
206
+ binwrite(path, 'data')
207
+ expect(path.binread(3)).to eq('dat')
156
208
  end
157
209
 
210
+ it 'skips data when offset is set' do
211
+ binwrite(path, 'data')
212
+ expect(path.binread(nil, 1)).to eq('ata')
213
+ end
214
+
215
+ it 'skips and limits data when length and offset are set' do
216
+ binwrite(path, 'data')
217
+ expect(path.binread(2, 1)).to eq('at')
218
+ end
219
+
220
+ it 'opens file in binary mode' do
221
+ binwrite(path, crlf_text)
222
+ expect(path.binread).to eq(crlf_text)
223
+ end
224
+ end
225
+
226
+ shared_examples 'writing' do
158
227
  it 'writes data' do
159
- expect(@file).to receive(:write).with(@data)
160
- @path.write(@data)
228
+ path.send(described_method, 'data')
229
+ expect(path.read).to eq('data')
161
230
  end
162
231
 
163
- it 'returns result of write' do
164
- expect(@path.write(@data)).to eq(@size)
232
+ it 'returns the length of data written' do
233
+ expect(path.send(described_method, 'data')).to eq(4)
165
234
  end
166
235
  end
167
236
 
168
- describe 'append' do
169
- it 'opens file for writing' do
170
- expect(@path).to receive(:open).with('ab')
171
- @path.append(@data)
237
+ shared_examples 'overwriting' do
238
+ context 'when offset is not specified' do
239
+ it 'overwrites file' do
240
+ path.send(described_method, 'longer data')
241
+ path.send(described_method, 'data')
242
+ expect(path.read).to eq('data')
243
+ end
172
244
  end
173
245
 
174
- it 'writes data' do
175
- expect(@file).to receive(:write).with(@data)
176
- @path.append(@data)
246
+ context 'when offset is specified' do
247
+ it 'overwrites part of file and does not truncate it' do
248
+ path.send(described_method, 'longer data')
249
+ path.send(described_method, 'data', 2)
250
+ expect(path.read).to eq('lodata data')
251
+ end
252
+ end
253
+ end
254
+
255
+ shared_examples 'appending' do
256
+ it 'appends data to the end of file' do
257
+ path.send(described_method, 'data')
258
+ path.send(described_method, 'more data')
259
+ expect(path.read).to eq('datamore data')
260
+ end
261
+ end
262
+
263
+ shared_examples 'writes in text mode' do
264
+ it 'opens file in text mode' do
265
+ test_path = FSPath.temp_file_path
266
+ test_path.open('w'){ |f| f.write(crlf_text) }
267
+
268
+ path.send(described_method, crlf_text)
269
+ expect(binread(path)).to eq(binread(test_path))
177
270
  end
271
+ end
272
+
273
+ shared_examples 'writes in binary mode' do
274
+ it 'opens file in binary mode' do
275
+ test_path = FSPath.temp_file_path
276
+ test_path.open('wb'){ |f| f.write(crlf_text) }
178
277
 
179
- it 'returns result of write' do
180
- expect(@path.append(@data)).to eq(@size)
278
+ path.send(described_method, crlf_text)
279
+ expect(binread(path)).to eq(binread(test_path))
181
280
  end
182
281
  end
282
+
283
+ describe '#write' do
284
+ include_examples 'writing'
285
+ include_examples 'overwriting'
286
+ include_examples 'writes in text mode'
287
+ end
288
+
289
+ describe '#binwrite' do
290
+ include_examples 'writing'
291
+ include_examples 'overwriting'
292
+ include_examples 'writes in binary mode'
293
+ end
294
+
295
+ describe '#append' do
296
+ include_examples 'writing'
297
+ include_examples 'appending'
298
+ include_examples 'writes in text mode'
299
+ end
300
+
301
+ describe '#binappend' do
302
+ include_examples 'writing'
303
+ include_examples 'appending'
304
+ include_examples 'writes in binary mode'
305
+ end
183
306
  end
184
307
 
185
- describe 'escape_glob' do
308
+ describe '#escape_glob' do
186
309
  it 'escapes glob pattern characters' do
187
310
  expect(FSPath('*/**/?[a-z]{abc,def}').escape_glob).
188
311
  to eq(FSPath('\*/\*\*/\?\[a-z\]\{abc,def\}'))
189
312
  end
190
313
  end
191
314
 
192
- describe 'glob' do
315
+ describe '#glob' do
193
316
  it 'joins with arguments and expands glob' do
194
317
  expect(FSPath).to receive(:glob).with('a/b/c/**/*')
195
318
  FSPath('a/b/c').glob('**', '*')
@@ -209,63 +332,71 @@ describe FSPath do
209
332
 
210
333
  describe 'path parts' do
211
334
  describe 'ascending' do
212
- before do
213
- @path = FSPath('/a/b/c')
214
- @ascendants = %w[/a/b/c /a/b /a /].map(&method(:FSPath))
215
- end
335
+ let(:path){ FSPath('/a/b/c') }
336
+ let(:expected){ %w[/a/b/c /a/b /a /].map(&method(:FSPath)) }
216
337
 
217
- describe 'ascendants' do
338
+ describe '#ascendants' do
218
339
  it 'returns list of ascendants' do
219
- expect(@path.ascendants).to eq(@ascendants)
340
+ expect(path.ascendants).to eq(expected)
220
341
  end
221
342
  end
222
343
 
223
- describe 'ascend' do
344
+ describe '#ascend' do
224
345
  it 'returns list of ascendants' do
225
- expect(@path.ascend).to eq(@ascendants)
346
+ expect(path.ascend).to eq(expected)
226
347
  end
227
348
 
228
349
  it 'yields and returns list of ascendants if called with block' do
229
350
  ascendants = []
230
- expect(@path.ascend do |path|
231
- ascendants << path
232
- end).to eq(@ascendants)
233
- expect(ascendants).to eq(@ascendants)
351
+ expect(path.ascend do |sub_path|
352
+ ascendants << sub_path
353
+ end).to eq(expected)
354
+ expect(ascendants).to eq(expected)
234
355
  end
235
356
  end
236
357
  end
237
358
 
238
359
  describe 'descending' do
239
- before do
240
- @path = FSPath('/a/b/c')
241
- @descendants = %w[/ /a /a/b /a/b/c].map(&method(:FSPath))
242
- end
360
+ let(:path){ FSPath('/a/b/c') }
361
+ let(:expected){ %w[/ /a /a/b /a/b/c].map(&method(:FSPath)) }
243
362
 
244
- describe 'descendants' do
363
+ describe '#descendants' do
245
364
  it 'returns list of descendants' do
246
- expect(@path.descendants).to eq(@descendants)
365
+ expect(path.descendants).to eq(expected)
247
366
  end
248
367
  end
249
368
 
250
- describe 'descend' do
369
+ describe '#descend' do
251
370
  it 'returns list of descendants' do
252
- expect(@path.descend).to eq(@descendants)
371
+ expect(path.descend).to eq(expected)
253
372
  end
254
373
 
255
374
  it 'yields and returns list of descendants if called with block' do
256
375
  descendants = []
257
- expect(@path.descend do |path|
258
- descendants << path
259
- end).to eq(@descendants)
260
- expect(descendants).to eq(@descendants)
376
+ expect(path.descend do |sub_path|
377
+ descendants << sub_path
378
+ end).to eq(expected)
379
+ expect(descendants).to eq(expected)
261
380
  end
262
381
  end
263
382
  end
264
383
 
265
- describe 'parts' do
266
- it 'returns path parts as strings' do
384
+ describe '#parts' do
385
+ it 'returns path parts for absolute path' do
267
386
  expect(FSPath('/a/b/c').parts).to eq(%w[/ a b c])
268
387
  end
388
+
389
+ it 'returns path parts for relative path' do
390
+ expect(FSPath('a/b/c').parts).to eq(%w[a b c])
391
+ end
392
+
393
+ it 'returns path parts for path prefixed with .' do
394
+ expect(FSPath('./a/b/c').parts).to eq(%w[. a b c])
395
+ end
396
+
397
+ it 'returns path parts for path containing ..' do
398
+ expect(FSPath('a/../b/c').parts).to eq(%w[a .. b c])
399
+ end
269
400
  end
270
401
  end
271
402
 
@@ -343,7 +474,7 @@ describe FSPath do
343
474
  symlink.make_symlink __FILE__
344
475
  fspath? symlink.readlink
345
476
  end
346
- end
477
+ end if symlinks_supported?
347
478
 
348
479
  it 'uses FSPath for realdirpath' do
349
480
  fspath? FSPath(__FILE__).realdirpath
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fspath
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-26 00:00:00.000000000 Z
11
+ date: 2016-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -44,6 +44,7 @@ executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
+ - .appveyor.yml
47
48
  - .gitignore
48
49
  - .rubocop.yml
49
50
  - .travis.yml
@@ -73,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  version: '0'
74
75
  requirements: []
75
76
  rubyforge_project: fspath
76
- rubygems_version: 2.4.5
77
+ rubygems_version: 2.6.4
77
78
  signing_key:
78
79
  specification_version: 4
79
80
  summary: Better than Pathname