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 +8 -8
- data/.appveyor.yml +20 -0
- data/.rubocop.yml +8 -2
- data/.travis.yml +3 -3
- data/LICENSE.txt +1 -1
- data/README.markdown +34 -8
- data/fspath.gemspec +1 -1
- data/lib/fspath.rb +55 -7
- data/spec/fspath_spec.rb +224 -93
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWYxMDFiMmI4MTkyOGMyYTEzNjkwODA4Njk0ZDRlOTc3MTZjYTIzZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGYwZDllNTE0MDdkYmY1NWMyYmFmMjIwMTRiZjg3ZmEzMjk4YjM4OQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZmVmOGJkY2NjMzlkODE2N2M4MjI0ZDViZTdjMTdlYzIyYTRmNTk1ZDE1ZGYz
|
10
|
+
NGIwMWE5ZmEwODQ5NGEyYzQ5MWZjYzI3ZDgwMmZlMzI0MjFlM2EyM2JiYjVm
|
11
|
+
MTkyZDYyMzkzODcyMWU3ZmY3ZjlkZDIzY2UwMmMxMTM3YWJmYjM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
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:
|
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/
|
61
|
+
Style/TrailingCommaInArguments:
|
62
|
+
EnforcedStyleForMultiline: no_comma
|
63
|
+
|
64
|
+
Style/TrailingCommaInLiteral:
|
59
65
|
EnforcedStyleForMultiline: comma
|
data/.travis.yml
CHANGED
data/LICENSE.txt
CHANGED
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](
|
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
|
-
|
28
|
+
Temp file (args are passed to `Tempfile.new`):
|
28
29
|
|
29
|
-
FSPath
|
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
|
-
|
44
|
+
Temp directory (args are passed to `Dir.mktmpdir`):
|
32
45
|
|
33
|
-
FSPath
|
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
|
-
|
56
|
+
Read/write:
|
36
57
|
|
37
|
-
FSPath('a').
|
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-
|
89
|
+
Copyright (c) 2010-2016 Ivan Kuchin. See LICENSE.txt for details.
|
data/fspath.gemspec
CHANGED
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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)
|
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
|
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
|
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 '
|
23
|
+
describe '.~' do
|
16
24
|
it 'returns current user home directory' do
|
17
|
-
expect(
|
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(
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
55
|
-
|
56
|
-
|
71
|
+
it 'returns result of block' do
|
72
|
+
expect(FSPath.temp_file{ :result }).to eq(:result)
|
73
|
+
end
|
57
74
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
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
|
71
|
-
|
72
|
-
expect(
|
73
|
-
|
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
|
78
|
-
|
79
|
-
|
80
|
-
|
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 '
|
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 '
|
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 '
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
149
|
-
|
191
|
+
def binread(path)
|
192
|
+
path.open('rb', &:read)
|
150
193
|
end
|
151
194
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
160
|
-
|
228
|
+
path.send(described_method, 'data')
|
229
|
+
expect(path.read).to eq('data')
|
161
230
|
end
|
162
231
|
|
163
|
-
it 'returns
|
164
|
-
expect(
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
180
|
-
expect(
|
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
|
-
|
213
|
-
|
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(
|
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(
|
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(
|
231
|
-
ascendants <<
|
232
|
-
end).to eq(
|
233
|
-
expect(ascendants).to eq(
|
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
|
-
|
240
|
-
|
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(
|
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(
|
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(
|
258
|
-
descendants <<
|
259
|
-
end).to eq(
|
260
|
-
expect(descendants).to eq(
|
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
|
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:
|
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:
|
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
|
77
|
+
rubygems_version: 2.6.4
|
77
78
|
signing_key:
|
78
79
|
specification_version: 4
|
79
80
|
summary: Better than Pathname
|