fspath 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- 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