fs 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 1.9.2
data/README.mdown CHANGED
@@ -37,33 +37,34 @@ using the good old standard library, but providing simple methods in a single pl
37
37
  Although verbose method names are good, there are some aliases for unix shell
38
38
  commands (unsorted).
39
39
 
40
- - ls => list
41
- - mkdir => makedir
42
- - mkdir_p => makedirs
43
- - cd => changedir
44
- - mv => move
45
- - cp => copy
46
- - rm => remove
47
- - ln => link
48
- - cat => read (no concatenate)
40
+ - ls => :list
41
+ - mkdir => :makedir
42
+ - mkdir_p => :makedirs
43
+ - rmdir => :removedir
44
+ - rm_r => :removedirs
45
+ - cd => :changedir
46
+ - pwd => :currentdir
47
+ - mv => :move
48
+ - cp => :copy
49
+ - rm => :remove
50
+ - cat => :read
51
+ - ln => :link
52
+ - dir? => :directory?
53
+ - expand => :expand_path
54
+ - [] => :join
49
55
 
50
56
  ## Todo
51
57
 
52
- Here is my mind … here is my mind …
58
+ Here is my mind …
53
59
 
54
60
  - maybe use underscores (remove_dir)
55
61
  - remove! to force something
56
62
  - maybe makedir! to mkdir -p
63
+ - maybe touch! to mkdir -p && touch
57
64
  - use Find#find in FS#find ;)
58
- - file type
59
- - exist?
65
+ - file type / ftype
60
66
  - list_dirs
61
67
  - list_files
62
68
  - find_dirs
63
69
  - find_files
64
70
  - FS.link('a.txt' => 'b.txt') with a hash
65
-
66
- ## BTW
67
-
68
- If you need a replacement for the shell in pure ruby, than have a look at
69
- [Rush](http://rush.heroku.com/).
data/lib/fs.rb CHANGED
@@ -3,12 +3,15 @@ $LOAD_PATH.unshift(File.dirname(__FILE__)) unless $LOAD_PATH.include?(File.dirna
3
3
  require 'fileutils'
4
4
  require 'etc'
5
5
  require 'tmpdir'
6
+ require 'find'
6
7
 
7
8
  require 'fs/base'
9
+ require 'fs/find'
8
10
  require 'fs/alias'
9
11
 
10
12
  module FS
11
13
  include FS::Base
14
+ include FS::Find
12
15
  include FS::Alias
13
16
  extend self
14
17
  end
data/lib/fs/alias.rb CHANGED
@@ -15,6 +15,7 @@ module FS
15
15
  :ln => :link,
16
16
  :dir? => :directory?,
17
17
  :expand => :expand_path,
18
+ :chop => :chop_path,
18
19
  :[] => :join,
19
20
  }
20
21
 
data/lib/fs/base.rb CHANGED
@@ -31,13 +31,15 @@ module FS
31
31
 
32
32
  # Dir#glob
33
33
  def list(dir='.', pattern='*')
34
- glob(dir, pattern)
34
+ glob(dir, pattern, nil)
35
35
  end
36
36
 
37
- # Dir#glob
38
- # TODO: use Find#find
39
- def find(dir='.', pattern='*')
40
- glob(dir, '**', pattern)
37
+ def list_dirs(dir='.', pattern='*')
38
+ glob(dir, pattern, ->(path){FS.directory?(path)})
39
+ end
40
+
41
+ def list_files(dir='.', pattern='*')
42
+ glob(dir, pattern, ->(path){FS.file?(path)})
41
43
  end
42
44
 
43
45
  # TODO: find time to make this cool, not work only
@@ -93,8 +95,9 @@ module FS
93
95
  end
94
96
 
95
97
  # Dir#home
98
+ # the path is always expanded
96
99
  def home(user=nil)
97
- Dir.home(user)
100
+ File.expand_path(Dir.home(user))
98
101
  end
99
102
 
100
103
  # always returns '/'
@@ -168,8 +171,22 @@ module FS
168
171
  end
169
172
 
170
173
  # File.expand_path
171
- def expand_path(path)
172
- File.expand_path(path)
174
+ def expand_path(path, base=nil)
175
+ File.expand_path(path, base)
176
+ end
177
+
178
+ # chop base from the path
179
+ # if it's not a subdir the absolute path will be returned
180
+ def chop_path(path, base='.')
181
+ full_base = File.expand_path(base)
182
+ full_path = File.expand_path(path)
183
+ if full_path == full_base
184
+ '.'
185
+ elsif full_path.start_with?(full_base)
186
+ full_path[full_base.size+1..-1]
187
+ else
188
+ full_path
189
+ end
173
190
  end
174
191
 
175
192
  # checks for a slash at the beginning
@@ -209,13 +226,15 @@ module FS
209
226
  end
210
227
 
211
228
  # __FILE__ of the caller
229
+ # the path is always expanded
212
230
  def this_file
213
- caller_file(caller)
231
+ File.expand_path(caller_file(caller))
214
232
  end
215
233
 
216
234
  # File.dirname(__FILE__) of the caller
235
+ # the path is always expanded
217
236
  def this_dir
218
- File.dirname(caller_file(caller))
237
+ File.expand_path(File.dirname(caller_file(caller)))
219
238
  end
220
239
 
221
240
  private
@@ -224,12 +243,14 @@ module FS
224
243
  raise "not a directory: #{path}" unless File.directory?(path)
225
244
  end
226
245
 
227
- def glob(dir, *patterns)
246
+ def glob(dir, *patterns, condition)
228
247
  fulldir = File.expand_path(dir)
229
248
  regexp = /^#{Regexp.escape(fulldir)}\/?/
230
- Dir.glob(File.join(fulldir, patterns)).map do |path|
231
- path.gsub(regexp, '')
232
- end
249
+ Dir.
250
+ glob(File.join(fulldir, patterns)).
251
+ select {|path| condition.nil? || condition[path] }.
252
+ map {|path| path.gsub(regexp, '') }.
253
+ sort
233
254
  end
234
255
 
235
256
  def visit_tree(output, parent_path, indent, arm, tie, node)
@@ -259,7 +280,7 @@ module FS
259
280
  end
260
281
 
261
282
  # http://grosser.it/2009/07/01/getting-the-caller-method-in-ruby/
262
- # Stolen from ActionMailer, where this was used but was not made reusable
283
+ # Stolen from ActionMailer, where it wasn't reusable
263
284
  def parse_caller(at)
264
285
  if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
265
286
  file = Regexp.last_match[1]
data/lib/fs/find.rb ADDED
@@ -0,0 +1,42 @@
1
+ module FS
2
+ module Find
3
+
4
+ # Find::find
5
+ def find(dir, options={}, &block)
6
+ defaults = {
7
+ :current => false,
8
+ :absolute => false,
9
+ :condition => nil
10
+ }
11
+ options = defaults.merge(options)
12
+
13
+ result = []
14
+
15
+ full_dir = File.expand_path(dir)
16
+ ::Find.find(dir) do |full_path|
17
+ next if !options[:current] && full_path == full_dir
18
+ path = options[:absolute] ? full_path : FS.chop(full_path, full_dir)
19
+ next if options[:condition] && !options[:condition][path]
20
+
21
+ if block
22
+ block[path]
23
+ else
24
+ result << path
25
+ end
26
+ end
27
+
28
+ block ? nil : result
29
+ end
30
+
31
+ def find_dirs(dir, options={}, &block)
32
+ condition = ->(path){FileTest.directory?(path)}
33
+ find(dir, options.merge(:condition => condition), &block)
34
+ end
35
+
36
+ def find_files(dir, options={}, &block)
37
+ condition = ->(path){!FileTest.directory?(path)}
38
+ find(dir, options.merge(:condition => condition), &block)
39
+ end
40
+
41
+ end
42
+ end
data/lib/fs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module FS
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
data/spec/base_spec.rb CHANGED
@@ -137,18 +137,12 @@ describe FS::Base do
137
137
  FS.makedir('foo/dir.rb')
138
138
  FS.list('foo', '*.txt').should eql(['dir.txt', 'file.txt'])
139
139
  end
140
- end
141
-
142
- describe '::find' do
143
- it 'returns an empty list if there are no files' do
144
- FS.find('.').should be_empty
145
- end
146
140
 
147
- it 'finds files in all subdirs' do
141
+ it 'lists files in all subdirs' do
148
142
  FS.makedirs('one/two/three')
149
143
  FS.touch('one/file.one')
150
144
  FS.touch('one/two/three/file.three')
151
- FS.find.should eql([
145
+ FS.list('.', '**/*').should eql([
152
146
  'one',
153
147
  'one/file.one',
154
148
  'one/two',
@@ -161,13 +155,39 @@ describe FS::Base do
161
155
  FS.makedirs('one/two/three')
162
156
  FS.touch('one/file.one')
163
157
  FS.touch('one/two/three/file.three')
164
- FS.find('.', 'file.*').should eql([
158
+ FS.list('.', '**/file.*').should eql([
165
159
  'one/file.one',
166
160
  'one/two/three/file.three'
167
161
  ])
168
162
  end
169
163
  end
170
164
 
165
+ describe '::list_dirs' do
166
+ it 'lists dirs only' do
167
+ FS.touch('bar.file')
168
+ FS.makedir('bar.dir')
169
+ FS.touch('foo.file')
170
+ FS.makedir('foo.dir')
171
+ FS.list_dirs.should eql([
172
+ 'bar.dir',
173
+ 'foo.dir'
174
+ ])
175
+ end
176
+ end
177
+
178
+ describe '::list_files' do
179
+ it 'lists files only' do
180
+ FS.touch('bar.file')
181
+ FS.makedir('bar.dir')
182
+ FS.touch('foo.file')
183
+ FS.makedir('foo.dir')
184
+ FS.list_files.should eql([
185
+ 'bar.file',
186
+ 'foo.file'
187
+ ])
188
+ end
189
+ end
190
+
171
191
  describe '::move' do
172
192
  it 'renames a file' do
173
193
  FS.touch('foo.txt')
@@ -327,7 +347,7 @@ describe FS::Base do
327
347
  FS.touch('a.file')
328
348
  FS.makedir('baz')
329
349
  FS.touch('baz/b.file')
330
- FS.mkdir('baz/bar')
350
+ FS.makedir('baz/bar')
331
351
  FS.touch('baz/bar/c.file')
332
352
  FS.touch('baz/d.file')
333
353
  FS.makedir('foo')
@@ -406,8 +426,8 @@ TXT
406
426
  end
407
427
 
408
428
  it 'returns if a dir is empty' do
409
- FS.mkdir('empty.dir')
410
- FS.mkdir('content.dir')
429
+ FS.makedir('empty.dir')
430
+ FS.makedir('content.dir')
411
431
  FS.touch('content.dir/some.file')
412
432
  FS.empty?('empty.dir').should be_true
413
433
  FS.empty?('content.dir').should be_false
@@ -429,6 +449,46 @@ TXT
429
449
  FS.expand_path('foo').should eql(File.join(here, 'foo'))
430
450
  FS.expand_path('foo/bar').should eql(File.join(here, 'foo', 'bar'))
431
451
  end
452
+
453
+ it 'uses a base dir to expand the path' do
454
+ here = File.expand_path('.')
455
+ FS.expand_path('foo', nil).should eql(File.join(here, 'foo'))
456
+ FS.expand_path('foo', here).should eql(File.join(here, 'foo'))
457
+ FS.expand_path('foo', '/').should eql('/foo')
458
+ FS.expand_path('foo', '/bar').should eql('/bar/foo')
459
+ FS.expand_path('foo', '/bar/').should eql('/bar/foo')
460
+ end
461
+ end
462
+
463
+ describe '::chop_path' do
464
+ it 'does nothing for relative paths' do
465
+ FS.chop_path('.').should eql('.')
466
+ FS.chop_path('./foo').should eql('foo')
467
+ FS.chop_path('foo').should eql('foo')
468
+ FS.chop_path('foo/bar').should eql('foo/bar')
469
+ end
470
+
471
+ it 'does not chop for non subdirs' do
472
+ FS.chop_path('/').should eql('/')
473
+ FS.chop_path('..').should eql(File.expand_path('..'))
474
+ FS.chop_path('/foo', '/foo/bar').should eql('/foo')
475
+ end
476
+
477
+ it 'chop absolute the path' do
478
+ here = File.expand_path('.')
479
+ FS.chop_path(here).should eql('.')
480
+ FS.chop_path(File.join(here, '.')).should eql('.')
481
+ FS.chop_path(File.join(here, 'foo')).should eql('foo')
482
+ FS.chop_path(File.join(here, 'foo/bar')).should eql('foo/bar')
483
+ FS.chop_path('/foo/bar').should eql('/foo/bar')
484
+ end
485
+
486
+ it 'uses a base dir to chop the path' do
487
+ FS.chop_path('.', '.').should eql('.')
488
+ FS.chop_path('/', '/').should eql('.')
489
+ FS.chop_path('/foo', '/foo').should eql('.')
490
+ FS.chop_path('/foo/bar', '/foo').should eql('bar')
491
+ end
432
492
  end
433
493
 
434
494
  describe '::absolute?' do
@@ -520,7 +580,7 @@ TXT
520
580
  dir = FS.maketempdir
521
581
  File.exist?(dir).should be_true
522
582
  File.directory?(dir).should be_true
523
- Dir.entries(dir).should eql([".", ".."])
583
+ Dir.entries(dir).should =~ ['.', '..']
524
584
  Dir.entries(Dir.tmpdir).should include(File.basename(dir))
525
585
  end
526
586
 
@@ -529,7 +589,7 @@ TXT
529
589
  dir.should match(/\/my_dir/)
530
590
  File.exist?(dir).should be_true
531
591
  File.directory?(dir).should be_true
532
- Dir.entries(dir).should eql([".", ".."])
592
+ Dir.entries(dir).should =~ ['.', '..']
533
593
  Dir.entries(Dir.tmpdir).should include(File.basename(dir))
534
594
  end
535
595
 
@@ -538,7 +598,7 @@ TXT
538
598
  dir = FS.maketempdir(nil, parent_dir)
539
599
  File.exist?(dir).should be_true
540
600
  File.directory?(dir).should be_true
541
- Dir.entries(dir).should eql([".", ".."])
601
+ Dir.entries(dir).should =~ ['.', '..']
542
602
  Dir.entries(parent_dir).should include(File.basename(dir))
543
603
  end
544
604
  end
data/spec/find_spec.rb ADDED
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+
3
+ describe FS::Find do
4
+ before do
5
+ FS.touch 'a.txt'
6
+ FS.touch 'b.txt'
7
+ FS.makedirs 'bar'
8
+ FS.touch 'bar/c.txt'
9
+ FS.makedirs 'bar/foo'
10
+ FS.touch 'bar/foo/d.txt'
11
+ FS.makedirs 'baz'
12
+ FS.makedirs 'baz/lala'
13
+ FS.touch 'e.txt'
14
+ end
15
+
16
+ describe '::find' do
17
+ it 'returns the subdirs and files' do
18
+ FS.find(@test_dir).should == %w(
19
+ a.txt
20
+ b.txt
21
+ bar
22
+ bar/c.txt
23
+ bar/foo
24
+ bar/foo/d.txt
25
+ baz
26
+ baz/lala
27
+ e.txt
28
+ )
29
+ end
30
+
31
+ it 'returns current dir, subdirs and files' do
32
+ FS.find(@test_dir, :current => true).should == %w(
33
+ .
34
+ a.txt
35
+ b.txt
36
+ bar
37
+ bar/c.txt
38
+ bar/foo
39
+ bar/foo/d.txt
40
+ baz
41
+ baz/lala
42
+ e.txt
43
+ )
44
+ end
45
+
46
+ it 'returns the full path' do
47
+ FS.find(@test_dir, :absolute => true).should == [
48
+ FS[@test_dir, 'a.txt'],
49
+ FS[@test_dir, 'b.txt'],
50
+ FS[@test_dir, 'bar'],
51
+ FS[@test_dir, 'bar/c.txt'],
52
+ FS[@test_dir, 'bar/foo'],
53
+ FS[@test_dir, 'bar/foo/d.txt'],
54
+ FS[@test_dir, 'baz'],
55
+ FS[@test_dir, 'baz/lala'],
56
+ FS[@test_dir, 'e.txt']
57
+ ]
58
+ end
59
+
60
+ it 'yields the result' do
61
+ result = []
62
+
63
+ FS.find(@test_dir) do |path|
64
+ result << path
65
+ end
66
+
67
+ result.should == %w(
68
+ a.txt
69
+ b.txt
70
+ bar
71
+ bar/c.txt
72
+ bar/foo
73
+ bar/foo/d.txt
74
+ baz
75
+ baz/lala
76
+ e.txt
77
+ )
78
+ end
79
+ end
80
+
81
+ describe '::find_dirs' do
82
+ it 'returns dirs only' do
83
+ FS.find_dirs(@test_dir).should == %w(
84
+ bar
85
+ bar/foo
86
+ baz
87
+ baz/lala
88
+ )
89
+ end
90
+
91
+ it 'yields dirs only' do
92
+ result = []
93
+
94
+ FS.find_dirs(@test_dir) do |path|
95
+ result << path
96
+ end
97
+
98
+ result.should == %w(
99
+ bar
100
+ bar/foo
101
+ baz
102
+ baz/lala
103
+ )
104
+ end
105
+ end
106
+
107
+ describe '::find_files' do
108
+ it 'returns files only' do
109
+ FS.find_files(@test_dir).should == %w(
110
+ a.txt
111
+ b.txt
112
+ bar/c.txt
113
+ bar/foo/d.txt
114
+ e.txt
115
+ )
116
+ end
117
+
118
+ it 'yields files only' do
119
+ result = []
120
+
121
+ FS.find_files(@test_dir) do |path|
122
+ result << path
123
+ end
124
+
125
+ result.should == %w(
126
+ a.txt
127
+ b.txt
128
+ bar/c.txt
129
+ bar/foo/d.txt
130
+ e.txt
131
+ )
132
+ end
133
+ end
134
+
135
+ end
@@ -15,7 +15,7 @@ describe FS do
15
15
  end
16
16
 
17
17
  it 'is empty' do
18
- Dir.entries(@test_dir).should eql([".", ".."])
18
+ Dir.entries(@test_dir).should =~ ['.', '..']
19
19
  end
20
20
 
21
21
  it 'is the current dir' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
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: 2011-11-04 00:00:00.000000000Z
12
+ date: 2011-11-10 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &2157319500 !ruby/object:Gem::Requirement
16
+ requirement: &2158694320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.9.2.2
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2157319500
24
+ version_requirements: *2158694320
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2157319020 !ruby/object:Gem::Requirement
27
+ requirement: &2158693840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.7.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2157319020
35
+ version_requirements: *2158693840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: yard
38
- requirement: &2157318560 !ruby/object:Gem::Requirement
38
+ requirement: &2158693380 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - =
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.7.2
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2157318560
46
+ version_requirements: *2158693380
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bluecloth
49
- requirement: &2157318100 !ruby/object:Gem::Requirement
49
+ requirement: &2158692920 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: 2.2.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2157318100
57
+ version_requirements: *2158692920
58
58
  description: FS gathers the cluttered methods for working with files and dirs. Internally
59
59
  using the good old standard library, but providing simple methods in a single place.
60
60
  email:
@@ -65,6 +65,7 @@ extra_rdoc_files: []
65
65
  files:
66
66
  - .gitignore
67
67
  - .rspec
68
+ - .travis.yml
68
69
  - Gemfile
69
70
  - README.mdown
70
71
  - Rakefile
@@ -72,9 +73,11 @@ files:
72
73
  - lib/fs.rb
73
74
  - lib/fs/alias.rb
74
75
  - lib/fs/base.rb
76
+ - lib/fs/find.rb
75
77
  - lib/fs/version.rb
76
78
  - spec/alias_spec.rb
77
79
  - spec/base_spec.rb
80
+ - spec/find_spec.rb
78
81
  - spec/spec_helper.rb
79
82
  - spec/support/test_dir_support.rb
80
83
  - spec/test_dir_spec.rb
@@ -92,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
95
  version: '0'
93
96
  segments:
94
97
  - 0
95
- hash: 612170262386871478
98
+ hash: 2428767844622882813
96
99
  required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  none: false
98
101
  requirements:
@@ -101,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
104
  version: '0'
102
105
  segments:
103
106
  - 0
104
- hash: 612170262386871478
107
+ hash: 2428767844622882813
105
108
  requirements: []
106
109
  rubyforge_project:
107
110
  rubygems_version: 1.8.10
@@ -111,6 +114,7 @@ summary: Work with your filesystem!
111
114
  test_files:
112
115
  - spec/alias_spec.rb
113
116
  - spec/base_spec.rb
117
+ - spec/find_spec.rb
114
118
  - spec/spec_helper.rb
115
119
  - spec/support/test_dir_support.rb
116
120
  - spec/test_dir_spec.rb