pa 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/pa.rb ADDED
@@ -0,0 +1,175 @@
1
+ require_relative "pa/core"
2
+
3
+ require "bundler/setup"
4
+ Bundler.require
5
+
6
+ =begin rdoc
7
+ Pa(Path) is similary to Pathname, but more powerful.
8
+ it combines fileutils, tmpdir, find, tempfile, File, Dir, Pathname
9
+
10
+ all class methods support Pa as parameter.
11
+
12
+ Examples:
13
+ ---------
14
+ pa = Pa('/home/a.vim')
15
+ pa.dir #=> '/home'
16
+ pa.base #=> 'a.vim'
17
+ pa.name #=> 'a'
18
+ pa.ext #=> 'vim'
19
+ pa.fext #=> '.vim'
20
+
21
+ Filename parts:
22
+ ---------
23
+ /home/guten.ogg
24
+ base: guten.ogg
25
+ dir: /home
26
+ ext: ogg
27
+ name: guten
28
+
29
+ Additional method list
30
+ ---------------------
31
+ * Pa.absolute _alias from `File.absolute_path`_
32
+ * Pa.expand _aliss from `File.expand_path`_
33
+
34
+ === create, modify path
35
+ Example1:
36
+ pa = Pa('/home/foo')
37
+ pa.join('a.txt') #=> new Pa('/home/foo/a.txt')
38
+
39
+ Example2:
40
+ pa1 = Pa('/home/foo/a.txt')
41
+ pa2 = Pa('/home/bar/b.txt')
42
+ pa1+'~' #=> new Pa('/home/foo/a.txt~')
43
+ Pa.join(pa1.dir, pa2.base) #=> '/home/foo/b.txt'
44
+
45
+ Example3:
46
+ pa1 = Pa('/home/foo/a.txt')
47
+ pa2 = Pa('/home/bar')
48
+ pa2.join(pa1.base) #=> new Pa('/home/bar/a.txt')
49
+
50
+ **Attributes**
51
+
52
+ name abbr description
53
+
54
+ path p
55
+ absolute a absolute path
56
+ dir d dirname of a path
57
+ base b basename of a path
58
+ fname fn alias of base
59
+ name n filename of a path
60
+ ext e extname of a path, return "" or "ogg"
61
+ fext fe return "" or ".ogg"
62
+
63
+ == used with rspec
64
+
65
+ File.exists?(path).should be_true
66
+ Pa(path).should be_exists
67
+
68
+ =end
69
+ class Pa
70
+ Error = Class.new Exception
71
+ EUnkonwType = Class.new Error
72
+
73
+ attr_reader :path
74
+
75
+ # @param [String,#path] path
76
+ def initialize path
77
+ @path = path.respond_to?(:path) ? path.path : path
78
+ initialize_variables
79
+ end
80
+
81
+ def ok
82
+ initialize_variables
83
+ end
84
+
85
+ chainable = Module.new do
86
+ def initialize_variables; end
87
+ end
88
+ include chainable
89
+
90
+ alias p path
91
+
92
+ # @param [String,#path]
93
+ # @return [Pa] the same Pa object
94
+ def replace path
95
+ @path = path.respond_to?(:path) ? path.path : path
96
+ initialize_variables
97
+ end
98
+
99
+ # return '#<Pa @path="foo", @absolute="/home/foo">'
100
+ #
101
+ # @return [String]
102
+ def inspect
103
+ ret="#<" + self.class.to_s + " "
104
+ ret += "@path=\"#{path}\", @absolute=\"#{absolute}\""
105
+ ret += " >"
106
+ ret
107
+ end
108
+
109
+ # return '/home/foo'
110
+ #
111
+ # @return [String] path
112
+ def to_s
113
+ @path
114
+ end
115
+
116
+ # missing method goes to Pa.class-method
117
+ def method_missing(name, *args, &blk)
118
+ ret = self.class.__send__(name, path, *args, &blk)
119
+
120
+ case ret
121
+
122
+ # e.g. readlink ..
123
+ when String
124
+ Pa(ret)
125
+
126
+ # e.g. directory?
127
+ else
128
+ ret
129
+ end
130
+
131
+ end
132
+
133
+
134
+ end
135
+
136
+ class Pa
137
+ module ClassMethods
138
+ UNDEFS = [:open, :fstat]
139
+
140
+ # missing method goes to File class method
141
+ def method_missing name, *args, &blk
142
+ raise NoMethodError, name.inspect if UNDEFS.include?(name)
143
+ return if args.size>1
144
+ File.__send__ name, get(args[0]), &blk
145
+ end
146
+ end
147
+ end
148
+
149
+ require_relative "pa/path"
150
+ require_relative "pa/cmd"
151
+ require_relative "pa/dir"
152
+ require_relative "pa/state"
153
+ class Pa
154
+ extend ClassMethods
155
+ extend ClassMethods::Path
156
+ extend ClassMethods::Dir
157
+ extend ClassMethods::State
158
+ extend ClassMethods::Cmd
159
+
160
+ include Path
161
+ include State
162
+ end
163
+
164
+ module Kernel
165
+ private
166
+ # a very convient function.
167
+ #
168
+ # @example
169
+ # Pa('/home').exists?
170
+ def Pa(path)
171
+ return path if Pa===path
172
+ Pa.new path
173
+ end
174
+ end
175
+
data/pa.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ $: << "."
2
+ require "version"
3
+ require "bundler"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pa"
7
+ s.version = Pa::VERSION::IS
8
+ s.summary = "a good lib"
9
+ s.description = <<-EOF
10
+ a good lib
11
+ EOF
12
+
13
+ s.author = "Guten"
14
+ s.email = "ywzhaifei@Gmail.com"
15
+ s.homepage = "http://github.com/GutenLinux/pa"
16
+ s.rubyforge_project = "xx"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+
20
+ s.add_bundler_dependencies
21
+ #s.add_dependency "x"
22
+ end
data/pa.watchr ADDED
@@ -0,0 +1,22 @@
1
+ # lib/**/*.rb
2
+ watch %r~lib/(.*)\.rb~ do |m|
3
+ test "spec/#{m[1]}_spec.rb"
4
+ end
5
+
6
+ # spec/**/*_spec.rb
7
+ watch %r~spec/.*_spec\.rb~ do |m|
8
+ test m[0]
9
+ end
10
+
11
+ # Ctrl-\
12
+ Signal.trap('QUIT') do
13
+ puts "--- Running all tests ---\n\n"
14
+ test "spec"
15
+ end
16
+
17
+ def test path
18
+ cmd = "rspec #{path}"
19
+ puts cmd
20
+ system cmd
21
+ end
22
+
@@ -0,0 +1,278 @@
1
+ require "spec_helper"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+
5
+ describe Pa do
6
+ it "a" do
7
+ Pa._copy 'a','b'
8
+ end
9
+ end
10
+
11
+
12
+ =begin
13
+ describe Pa do
14
+ before :all do
15
+ @curdir = Dir.pwd
16
+ @tmpdir = Dir.mktmpdir
17
+ Dir.chdir(@tmpdir)
18
+ end
19
+
20
+ after(:all) do
21
+ Dir.chdir(@curdir)
22
+ FileUtils.rm_r @tmpdir
23
+ end
24
+
25
+ describe "#_rmdir" do
26
+ # dir/
27
+ # a
28
+ # dira/
29
+ # aa
30
+ before(:all) do
31
+ @_rmdir = Pa.method(:_rmdir)
32
+ FileUtils.mkdir_p(%w(dir/dira))
33
+ FileUtils.touch(%w(dir/a dir/dira/aa))
34
+ end
35
+
36
+ it "remove directory" do
37
+ @_rmdir.call Pa("dir")
38
+ File.exists?("dir").should be_false
39
+ end
40
+ end
41
+
42
+ # rm family
43
+ describe "" do
44
+ # a
45
+ # dir/
46
+ # dira/
47
+ # a
48
+ before :each do
49
+ FileUtils.mkdir_p(%w(dir/dira))
50
+ FileUtils.touch(%w(a dir/a))
51
+ end
52
+
53
+ describe "#rm" do
54
+ it "remove file" do
55
+ Pa.rm "a"
56
+ File.exists?("a").should be_false
57
+ lambda{Pa.rm("dir")}.should raise_error(Errno::EISDIR)
58
+ end
59
+ end
60
+
61
+ describe "#rm_f" do
62
+ it "remove file force" do
63
+ lambda{Pa.rm_f("dir")}.should_not raise_error(Errno::EISDIR)
64
+ end
65
+ end
66
+
67
+ describe "#rmdir" do
68
+ it "remove directory" do
69
+ Pa.rmdir "dir"
70
+ File.exists?("dir").should be_false
71
+ lambda{Pa.rmdir("a")}.should raise_error(Errno::ENOTDIR)
72
+ end
73
+ end
74
+
75
+ describe "#rmdir_f" do
76
+ it "remove directory force" do
77
+ lambda{Pa.rmdir_r("a")}.should_not raise_error(Errno::ENOTDIR)
78
+ end
79
+ end
80
+
81
+ describe "#rm_r" do
82
+ it "remove both file and directory" do
83
+ Pa.rm "a"
84
+ File.exists?("a").should be_false
85
+ Pa.rm_r "dir"
86
+ File.exists?("dir").should be_false
87
+ end
88
+ end
89
+
90
+
91
+
92
+ describe "#rm_if" do
93
+ it "remove if condition" do
94
+ Pa.rm_if "." do |pa|
95
+ next if pa.p=="a"
96
+ yield if pa.b=="a"
97
+ end
98
+
99
+ File.exists?("a").should be_true
100
+ File.exists?("dir/dira/a").should be_false
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ describe "#mkdir" do
107
+ after :each do
108
+ FileUtils.rm_r Dir["*"]-%w(. ..)
109
+ end
110
+
111
+ it "mkdir" do
112
+ Pa.mkdir("guten/tag")
113
+ File.exists?("guten/tag").should be_true
114
+ end
115
+ end
116
+
117
+ describe "#_copy" do
118
+ # a symfile
119
+ # ab
120
+ # ac
121
+ # dir/
122
+ # b # guten
123
+ # dira/
124
+ # c
125
+ # destdir/
126
+ # b # tag
127
+ # dir/
128
+ before :all do
129
+ FileUtils.mkdir_p(%w(dir/dira destdir/dir))
130
+ FileUtils.touch(%w(a ab ac dir/b dir/dira/c destdir/dir/b))
131
+ File.symlink("a", "symfile")
132
+ open("dir/b", "w"){|f|f.write "guten"}
133
+ open("destdir/dir/b", "w"){|f|f.write "tag"}
134
+ end
135
+
136
+ it "_copy file" do
137
+ Pa._copy 'a', 'b', verbose: true
138
+ File.exists?('b').should be_true
139
+ end
140
+
141
+ it "_copy directory" do
142
+ Pa._copy 'dir', 'dirc'
143
+ Dir.entries('dirc').should == Dir.entries('dir')
144
+ end
145
+
146
+ context "with :symlink" do
147
+
148
+ it "_copy" do
149
+ Pa._copy 'symfile', 'symfilea'
150
+ File.symlink?('symfilea').should be_true
151
+ end
152
+
153
+ it "_copy with :folsymlink" do
154
+ Pa._copy 'symfile', 'folsymlink', folsymlink:true
155
+ File.symlink?('folsymlink').should be_false
156
+ File.file?('folsymlink').should be_true
157
+ end
158
+
159
+ end
160
+
161
+ context "with :mkdir" do
162
+ it "_copy" do
163
+ lambda{Pa.cp "a", "destdir/mkdir/dir"}.should raise_error(Errno::ENOENT)
164
+ end
165
+
166
+ it "_copy with :mkdir" do
167
+ lambda{Pa.cp "a", "destdir/mkdir/dir", mkdir:true}.should_not raise_error(Errno::ENOENT)
168
+ File.exists?("destdir/mkdir/dir/a").should be_true
169
+ end
170
+
171
+ it "_copy with :mkdir" do
172
+ lambda{Pa.cp "a", "destdir/mkdira", mkdir:true}.should_not raise_error(Errno::ENOENT)
173
+ File.exists?("destdir/mkdira/a").should be_true
174
+ end
175
+ end
176
+
177
+ context "with :force" do
178
+ it "_copy" do
179
+ File.open("destdir/overwrite","w"){|f|f.write("")}
180
+ lambda{Pa.cp "a", "destdir/overwrite"}.should raise_error(Errno::EEXIST)
181
+ end
182
+
183
+ it "_copy with :force" do
184
+ lambda{Pa.cp "a", "destdir/overwrite", force:true}.should_not raise_error(Errno::EEXIST)
185
+ end
186
+ end
187
+
188
+ it "_copy with :normal" do
189
+ Pa._copy 'dir', 'dir_normal', special: true
190
+ Dir.empty?('dir_normal').should be_true
191
+ end
192
+
193
+ end
194
+
195
+ describe "#cp" do
196
+ it "cp file destdir/file" do
197
+ Pa.cp "a", "destdir/aa"
198
+ File.exists?("destdir/aa").should be_true
199
+ end
200
+
201
+ it "cp file destdir/" do
202
+ Pa.cp "a", "destdir"
203
+ File.exists?("destdir/a").should be_true
204
+ end
205
+
206
+ it "cp file1 file2 .. dest_file" do
207
+ lambda{Pa.cp(%w(a ab), "ac")}.should raise_error(Errno::ENOTDIR)
208
+ end
209
+
210
+ it "cp file1 file2 .. dird/" do
211
+ Dir.mkdir 'dird'
212
+ Pa.cp %w(a ab), "dird"
213
+ File.exists?("dird/a").should be_true
214
+ File.exists?("dird/ab").should be_true
215
+ end
216
+ end
217
+
218
+ describe "#_move" do
219
+ # a
220
+ # dir/ b
221
+ before :each do
222
+ FileUtils.mkdir_p(%w(dir))
223
+ FileUtils.touch(%w(a dir/b))
224
+ end
225
+ after :each do
226
+ FileUtils.rm_r Dir["*"]-%w(. ..)
227
+ end
228
+
229
+ it "mv a dir/a" do
230
+ ino = File.stat('a').ino
231
+ Pa._move "a", "dir/a", {}
232
+ File.stat('dir/a').ino.should == ino
233
+ File.exists?("a").should be_false
234
+ end
235
+
236
+ context "with :force" do
237
+ it "mv a dir/b" do
238
+ lambda{Pa._move "a", "dir/b", {}}.should raise_error Errno::EEXIST
239
+ end
240
+
241
+ it "mv a dir/b :force" do
242
+ ino = File.stat('a').ino
243
+ Pa._move "a", "dir/b", force:true
244
+ File.stat("dir/b").ino.should == ino
245
+ end
246
+ end
247
+
248
+ end
249
+
250
+ describe "#mv" do
251
+ # a b c
252
+ # dir/ aa
253
+ before :each do
254
+ FileUtils.mkdir_p(%w(dir))
255
+ FileUtils.touch(%w(a b c dir/aa))
256
+ end
257
+ after :each do
258
+ FileUtils.rm_r Dir["*"]-%w(. ..)
259
+ end
260
+
261
+ it "mv a dir/" do
262
+ Pa.mv "a", "dir"
263
+ File.exists?("dir/a").should be_true
264
+ end
265
+
266
+ it "mv a b .. file" do
267
+ lambda{Pa.mv(%w(a b), "c")}.should raise_error(Errno::ENOTDIR)
268
+ end
269
+
270
+ it "mv file1 file2 .. dir/" do
271
+ Pa.mv %w(a b), "dir"
272
+ File.exists?("dir/a").should be_true
273
+ File.exists?("dir/b").should be_true
274
+ end
275
+ end
276
+
277
+ end
278
+ =end
@@ -0,0 +1,137 @@
1
+ require "spec_helper"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+
5
+ class Pa
6
+ class << self
7
+ public :_copy, :_move, :_rmdir, :_mktmpname, :_mkdir, :_touch
8
+ end
9
+ end
10
+
11
+ describe Pa do
12
+ before :all do
13
+ @curdir = Dir.pwd
14
+ @tmpdir = Dir.mktmpdir
15
+ Dir.chdir(@tmpdir)
16
+ end
17
+
18
+ after(:all) do
19
+ Dir.chdir(@curdir)
20
+ FileUtils.rm_r @tmpdir
21
+ end
22
+
23
+ describe "#glob" do
24
+ before(:each) do
25
+ @files = %w(fa .fa)
26
+ FileUtils.touch(@files)
27
+ end
28
+ after(:each) do
29
+ FileUtils.rm @files
30
+ end
31
+
32
+ context "call without any option" do
33
+ it "returns 1 items" do
34
+ Pa.glob("*").should have(1).items
35
+ end
36
+ end
37
+
38
+ context "call with :dotmatch option" do
39
+ it "returns 2 items" do
40
+ Pa.glob("*", dotmatch: true).should have(2).items
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#each" do
46
+ # fa .fa fa~
47
+ # dira/
48
+ # dirb/
49
+ # b
50
+ before(:each) do
51
+ @dirs = %w(dira/dirb)
52
+ @files = %w(fa .fa fa~ dira/dirb/b)
53
+ FileUtils.mkdir_p(@dirs)
54
+ FileUtils.touch(@files)
55
+ end
56
+ after(:each) do
57
+ FileUtils.rm @files
58
+ FileUtils.rm_r @dirs
59
+ end
60
+
61
+ it "runs on" do
62
+ ret = []
63
+ Pa.each{|pa| ret << pa.fname}
64
+ ret.sort.should == %w(.fa dira fa fa~)
65
+ end
66
+
67
+ it "return a Enumerator when call without block" do
68
+ Pa.each.should be_an_instance_of Enumerator
69
+ end
70
+
71
+ it "raise Errno::ENOENT if path doesn't exists" do
72
+ lambda { Pa.each("path_doesn't_exits"){} }.should raise_error(Errno::ENOENT)
73
+ end
74
+
75
+ it "raise Errno::ENOTDIDR if path isn't a directory" do
76
+ lambda { Pa.each("fa"){} }.should raise_error(Errno::ENOTDIR)
77
+ end
78
+
79
+ it "each(.) return 'foo' not '.foo'" do
80
+ Pa.each.with_object([]){|pa,m| m<<pa.p}.sort.should == %w(.fa dira fa fa~)
81
+ end
82
+
83
+ it "each(nodot: true) -> list all files except dot file" do
84
+ Pa.each(nodot: true).with_object([]){|pa,m|m<<pa.b}.sort.should == %w(dira fa fa~)
85
+ end
86
+
87
+ end
88
+
89
+ describe "#each_r" do
90
+ # fa .fa fa~
91
+ # dira/
92
+ # dirb/
93
+ # b
94
+ before(:each) do
95
+ @dirs = %w(dira/dirb)
96
+ @files = %w(fa .fa fa~ dira/dirb/b)
97
+ FileUtils.mkdir_p(@dirs)
98
+ FileUtils.touch(@files)
99
+ end
100
+ after(:each) do
101
+ FileUtils.rm @files
102
+ FileUtils.rm_r @dirs
103
+ end
104
+
105
+ it "each_r -> Enumerator" do
106
+ Pa.each_r.should be_an_instance_of Enumerator
107
+ Pa.each_r.with_object([]){|(pa,r),m|m<<r}.sort.should == %w(.fa dira dira/dirb dira/dirb/b fa fa~)
108
+ end
109
+ end
110
+
111
+
112
+ describe "#ls" do
113
+ # filea
114
+ # dira/
115
+ # fileb
116
+ before(:each) do
117
+ @dirs = %w(dira)
118
+ @files = %w(filea dira/fileb)
119
+ FileUtils.mkdir_p(@dirs)
120
+ FileUtils.touch(@files)
121
+ end
122
+ after(:each) do
123
+ FileUtils.rm @files
124
+ FileUtils.rm_r @dirs
125
+ end
126
+
127
+ it "runs ok -> Array" do
128
+ Pa.ls.should == ["filea", "dira"]
129
+ end
130
+
131
+ it "call a block" do
132
+ Pa.ls { |pa, fname| pa.directory? }.should == ["dira"]
133
+ end
134
+ end
135
+
136
+
137
+ end