bowline 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.4
1
+ 0.5.5
data/bowline.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bowline}
8
- s.version = "0.5.4"
8
+ s.version = "0.5.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alex MacCaw"]
12
- s.date = %q{2009-12-22}
12
+ s.date = %q{2009-12-23}
13
13
  s.default_executable = %q{bowline-gen}
14
14
  s.description = %q{Ruby/JS GUI framework}
15
15
  s.email = %q{alex@leadthinking.com}
@@ -116,7 +116,6 @@ Gem::Specification.new do |s|
116
116
  "templates/script/init",
117
117
  "templates/script/run",
118
118
  "templates/window.rb",
119
- "vendor/pathname.rb",
120
119
  "vendor/progressbar.rb"
121
120
  ]
122
121
  s.homepage = %q{http://github.com/maccman/bowline}
@@ -60,34 +60,6 @@ module Bowline
60
60
  @configuration = configuration
61
61
  @loaded_plugins = []
62
62
  end
63
-
64
- # Add all of Ruby's stdlib to the load path
65
- def initialize_ruby
66
- return unless Bowline::Desktop.enabled?
67
- ruby_path = Bowline::Library.local_rubylib_path
68
- unless File.directory?(ruby_path)
69
- ruby_path = Bowline::Library.rubylib_path
70
- return unless File.directory?(ruby_path)
71
- end
72
- # Remove old stdlib load paths
73
- $:.delete_if {|path| path =~ /^\/usr\// }
74
-
75
- # Add new stdlib load paths
76
- version = Library::RUBY_LIB_VERSION
77
- platform = Library::RUBY_ARCHLIB_PLATFORM
78
- $: << File.join(ruby_path, version) # RUBY_LIB
79
- $: << File.join(ruby_path, version, platform) # RUBY_ARCHLIB
80
- $: << File.join(ruby_path, "site_path") # RUBY_SITE_LIB
81
- $: << File.join(ruby_path, "site_path", version) # RUBY_SITE_LIB2
82
- $: << File.join(ruby_path, "site_ruby", version, platform) # RUBY_SITE_ARCHLIB
83
- $: << File.join(ruby_path, "vendor_ruby") # RUBY_VENDOR_LIB
84
- $: << File.join(ruby_path, "vendor_ruby", version) # RUBY_VENDOR_LIB2
85
- $: << File.join(ruby_path, "vendor_ruby", version, platform) # RUBY_VENDOR_ARCHLIB
86
-
87
- # These two need to be required to fully setup internationalization
88
- require File.join(*%w[enc encdb])
89
- require File.join(*%w[enc trans transdb])
90
- end
91
63
 
92
64
  def require_frameworks
93
65
  configuration.frameworks.each { |framework| require(framework.to_s) }
@@ -203,6 +175,7 @@ module Bowline
203
175
  end
204
176
 
205
177
  def initialize_gems
178
+ require "rubygems"
206
179
  Gem.clear_paths
207
180
  Gem.path.unshift(configuration.gem_path)
208
181
  end
@@ -307,7 +280,6 @@ module Bowline
307
280
  def process
308
281
  Bowline.configuration = configuration
309
282
 
310
- initialize_ruby
311
283
  set_load_path
312
284
  initialize_gems
313
285
  load_gems
@@ -1,8 +1,6 @@
1
1
  module Bowline
2
2
  # Provides paths to Bowline's required libraries.
3
3
  module Library
4
- RUBY_LIB_VERSION = "1.9.1"
5
- RUBY_ARCHLIB_PLATFORM = "i386-darwin9.8.0"
6
4
  PROJECT_URL = "http://bowline.s3.amazonaws.com/#{Platform.type}"
7
5
  DESKTOP_URL = "#{PROJECT_URL}/bowline-desktop"
8
6
  RUBYLIB_URL = "#{PROJECT_URL}/rubylib.zip"
@@ -33,27 +33,33 @@ def unzip(fpath, tpath)
33
33
  }
34
34
  end
35
35
 
36
+ def sym_or_copy(from, to)
37
+ begin
38
+ FileUtils.ln_s(from, to)
39
+ rescue NotImplementedError
40
+ FileUtils.cp_r(from, to)
41
+ end
42
+ end
43
+
36
44
  namespace :libs do
37
- # Lots of people are using Ruby 1.8 with Bowline.
38
- # When bowline-desktop loads, it doesn't know where the
39
- # Bowline gem is if it's an 1.8 gem dir. So, we just symlink
40
- # it to vendor/bowline. One caveat though, is that you have to
41
- # re-run this task when you update the gem.
42
45
  task :unpack => :environment do
43
- local_path = Bowline::Library.local_bowline_path
44
- unless File.directory?(local_path)
45
- begin
46
- FileUtils.ln_s(
47
- Bowline.lib_path,
48
- local_path
49
- )
50
- rescue NotImplementedError
51
- FileUtils.cp_r(
52
- Bowline.lib_path,
53
- local_path
54
- )
55
- end
56
- end
46
+ # Lots of people are using Ruby 1.8 with Bowline.
47
+ # When bowline-desktop loads, it doesn't know where the
48
+ # Bowline gem is if it's an 1.8 gem dir. So, we just symlink
49
+ # it to vendor/bowline. One caveat though, is that you have to
50
+ # re-run this task when you update the gem.
51
+ local_bowline_path = Bowline::Library.local_bowline_path
52
+ sym_or_copy(
53
+ Bowline.lib_path,
54
+ local_bowline_path
55
+ ) unless File.directory?(local_bowline_path)
56
+
57
+ local_rubylib_path = Bowline::Library.local_rubylib_path
58
+ raise "Run libs:download task first" unless File.directory?(Bowline::Library.rubylib_path)
59
+ sym_or_copy(
60
+ Bowline::Library.rubylib_path,
61
+ local_rubylib_path
62
+ ) unless File.directory?(local_rubylib_path)
57
63
  end
58
64
 
59
65
  desc "Download Bowline's binary and pre-compiled libs"
@@ -77,7 +83,7 @@ namespace :libs do
77
83
  end
78
84
  end
79
85
 
80
- task :setup => [:environment, "gems:sync", "libs:unpack", "libs:download"]
86
+ task :setup => [:environment, "gems:sync", "libs:download", "libs:unpack"]
81
87
 
82
88
  desc "Update Bowline's binary and pre-compiled libs"
83
89
  task :update => :environment do
@@ -2,7 +2,7 @@ module Bowline
2
2
  module Version #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 5
5
- TINY = 4
5
+ TINY = 5
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bowline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex MacCaw
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-22 00:00:00 +00:00
12
+ date: 2009-12-23 00:00:00 +00:00
13
13
  default_executable: bowline-gen
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -149,7 +149,6 @@ files:
149
149
  - templates/script/init
150
150
  - templates/script/run
151
151
  - templates/window.rb
152
- - vendor/pathname.rb
153
152
  - vendor/progressbar.rb
154
153
  has_rdoc: true
155
154
  homepage: http://github.com/maccman/bowline
data/vendor/pathname.rb DELETED
@@ -1,1095 +0,0 @@
1
- #
2
- # = pathname.rb
3
- #
4
- # Object-Oriented Pathname Class
5
- #
6
- # Author:: Tanaka Akira <akr@m17n.org>
7
- # Documentation:: Author and Gavin Sinclair
8
- #
9
- # For documentation, see class Pathname.
10
- #
11
- # <tt>pathname.rb</tt> is distributed with Ruby since 1.8.0.
12
- #
13
-
14
- #
15
- # == Pathname
16
- #
17
- # Pathname represents a pathname which locates a file in a filesystem.
18
- # The pathname depends on OS: Unix, Windows, etc.
19
- # Pathname library works with pathnames of local OS.
20
- # However non-Unix pathnames are supported experimentally.
21
- #
22
- # It does not represent the file itself.
23
- # A Pathname can be relative or absolute. It's not until you try to
24
- # reference the file that it even matters whether the file exists or not.
25
- #
26
- # Pathname is immutable. It has no method for destructive update.
27
- #
28
- # The value of this class is to manipulate file path information in a neater
29
- # way than standard Ruby provides. The examples below demonstrate the
30
- # difference. *All* functionality from File, FileTest, and some from Dir and
31
- # FileUtils is included, in an unsurprising way. It is essentially a facade for
32
- # all of these, and more.
33
- #
34
- # == Examples
35
- #
36
- # === Example 1: Using Pathname
37
- #
38
- # require 'pathname'
39
- # p = Pathname.new("/usr/bin/ruby")
40
- # size = p.size # 27662
41
- # isdir = p.directory? # false
42
- # dir = p.dirname # Pathname:/usr/bin
43
- # base = p.basename # Pathname:ruby
44
- # dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby]
45
- # data = p.read
46
- # p.open { |f| _ }
47
- # p.each_line { |line| _ }
48
- #
49
- # === Example 2: Using standard Ruby
50
- #
51
- # p = "/usr/bin/ruby"
52
- # size = File.size(p) # 27662
53
- # isdir = File.directory?(p) # false
54
- # dir = File.dirname(p) # "/usr/bin"
55
- # base = File.basename(p) # "ruby"
56
- # dir, base = File.split(p) # ["/usr/bin", "ruby"]
57
- # data = File.read(p)
58
- # File.open(p) { |f| _ }
59
- # File.foreach(p) { |line| _ }
60
- #
61
- # === Example 3: Special features
62
- #
63
- # p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
64
- # p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
65
- # p3 = p1.parent # Pathname:/usr
66
- # p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
67
- # pwd = Pathname.pwd # Pathname:/home/gavin
68
- # pwd.absolute? # true
69
- # p5 = Pathname.new "." # Pathname:.
70
- # p5 = p5 + "music/../articles" # Pathname:music/../articles
71
- # p5.cleanpath # Pathname:articles
72
- # p5.realpath # Pathname:/home/gavin/articles
73
- # p5.children # [Pathname:/home/gavin/articles/linux, ...]
74
- #
75
- # == Breakdown of functionality
76
- #
77
- # === Core methods
78
- #
79
- # These methods are effectively manipulating a String, because that's all a path
80
- # is. Except for #mountpoint?, #children, and #realpath, they don't access the
81
- # filesystem.
82
- #
83
- # - +
84
- # - #join
85
- # - #parent
86
- # - #root?
87
- # - #absolute?
88
- # - #relative?
89
- # - #relative_path_from
90
- # - #each_filename
91
- # - #cleanpath
92
- # - #realpath
93
- # - #children
94
- # - #mountpoint?
95
- #
96
- # === File status predicate methods
97
- #
98
- # These methods are a facade for FileTest:
99
- # - #blockdev?
100
- # - #chardev?
101
- # - #directory?
102
- # - #executable?
103
- # - #executable_real?
104
- # - #exist?
105
- # - #file?
106
- # - #grpowned?
107
- # - #owned?
108
- # - #pipe?
109
- # - #readable?
110
- # - #world_readable?
111
- # - #readable_real?
112
- # - #setgid?
113
- # - #setuid?
114
- # - #size
115
- # - #size?
116
- # - #socket?
117
- # - #sticky?
118
- # - #symlink?
119
- # - #writable?
120
- # - #world_writable?
121
- # - #writable_real?
122
- # - #zero?
123
- #
124
- # === File property and manipulation methods
125
- #
126
- # These methods are a facade for File:
127
- # - #atime
128
- # - #ctime
129
- # - #mtime
130
- # - #chmod(mode)
131
- # - #lchmod(mode)
132
- # - #chown(owner, group)
133
- # - #lchown(owner, group)
134
- # - #fnmatch(pattern, *args)
135
- # - #fnmatch?(pattern, *args)
136
- # - #ftype
137
- # - #make_link(old)
138
- # - #open(*args, &block)
139
- # - #readlink
140
- # - #rename(to)
141
- # - #stat
142
- # - #lstat
143
- # - #make_symlink(old)
144
- # - #truncate(length)
145
- # - #utime(atime, mtime)
146
- # - #basename(*args)
147
- # - #dirname
148
- # - #extname
149
- # - #expand_path(*args)
150
- # - #split
151
- #
152
- # === Directory methods
153
- #
154
- # These methods are a facade for Dir:
155
- # - Pathname.glob(*args)
156
- # - Pathname.getwd / Pathname.pwd
157
- # - #rmdir
158
- # - #entries
159
- # - #each_entry(&block)
160
- # - #mkdir(*args)
161
- # - #opendir(*args)
162
- #
163
- # === IO
164
- #
165
- # These methods are a facade for IO:
166
- # - #each_line(*args, &block)
167
- # - #read(*args)
168
- # - #readlines(*args)
169
- # - #sysopen(*args)
170
- #
171
- # === Utilities
172
- #
173
- # These methods are a mixture of Find, FileUtils, and others:
174
- # - #find(&block)
175
- # - #mkpath
176
- # - #rmtree
177
- # - #unlink / #delete
178
- #
179
- #
180
- # == Method documentation
181
- #
182
- # As the above section shows, most of the methods in Pathname are facades. The
183
- # documentation for these methods generally just says, for instance, "See
184
- # FileTest.writable?", as you should be familiar with the original method
185
- # anyway, and its documentation (e.g. through +ri+) will contain more
186
- # information. In some cases, a brief description will follow.
187
- #
188
- class Pathname
189
-
190
- # :stopdoc:
191
- if RUBY_VERSION < "1.9"
192
- TO_PATH = :to_str
193
- else
194
- # to_path is implemented so Pathname objects are usable with File.open, etc.
195
- TO_PATH = :to_path
196
- end
197
-
198
- SAME_PATHS = if File::FNM_SYSCASE
199
- proc {|a, b| a.casecmp(b).zero?}
200
- else
201
- proc {|a, b| a == b}
202
- end
203
-
204
- # :startdoc:
205
-
206
- #
207
- # Create a Pathname object from the given String (or String-like object).
208
- # If +path+ contains a NUL character (<tt>\0</tt>), an ArgumentError is raised.
209
- #
210
- def initialize(path)
211
- path = path.__send__(TO_PATH) if path.respond_to? TO_PATH
212
- @path = path.dup
213
-
214
- if /\0/ =~ @path
215
- raise ArgumentError, "pathname contains \\0: #{@path.inspect}"
216
- end
217
-
218
- self.taint if @path.tainted?
219
- end
220
-
221
- def freeze() super; @path.freeze; self end
222
- def taint() super; @path.taint; self end
223
- def untaint() super; @path.untaint; self end
224
-
225
- #
226
- # Compare this pathname with +other+. The comparison is string-based.
227
- # Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
228
- # can refer to the same file.
229
- #
230
- def ==(other)
231
- return false unless Pathname === other
232
- other.to_s == @path
233
- end
234
- alias === ==
235
- alias eql? ==
236
-
237
- # Provides for comparing pathnames, case-sensitively.
238
- def <=>(other)
239
- return nil unless Pathname === other
240
- @path.tr('/', "\0") <=> other.to_s.tr('/', "\0")
241
- end
242
-
243
- def hash # :nodoc:
244
- @path.hash
245
- end
246
-
247
- # Return the path as a String.
248
- def to_s
249
- @path.dup
250
- end
251
-
252
- # to_path is implemented so Pathname objects are usable with File.open, etc.
253
- alias_method TO_PATH, :to_s
254
-
255
- def inspect # :nodoc:
256
- "#<#{self.class}:#{@path}>"
257
- end
258
-
259
- # Return a pathname which is substituted by String#sub.
260
- def sub(pattern, *rest, &block)
261
- if block
262
- path = @path.sub(pattern, *rest) {|*args|
263
- begin
264
- old = Thread.current[:pathname_sub_matchdata]
265
- Thread.current[:pathname_sub_matchdata] = $~
266
- eval("$~ = Thread.current[:pathname_sub_matchdata]", block.binding)
267
- ensure
268
- Thread.current[:pathname_sub_matchdata] = old
269
- end
270
- yield *args
271
- }
272
- else
273
- path = @path.sub(pattern, *rest)
274
- end
275
- self.class.new(path)
276
- end
277
-
278
- if File::ALT_SEPARATOR
279
- SEPARATOR_LIST = "#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}"
280
- SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/
281
- else
282
- SEPARATOR_LIST = "#{Regexp.quote File::SEPARATOR}"
283
- SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/
284
- end
285
-
286
- # Return a pathname which the extension of the basename is substituted by
287
- # <i>repl</i>.
288
- #
289
- # If self has no extension part, <i>repl</i> is appended.
290
- def sub_ext(repl)
291
- ext = File.extname(@path)
292
- self.class.new(@path.chomp(ext) + repl)
293
- end
294
-
295
- # chop_basename(path) -> [pre-basename, basename] or nil
296
- def chop_basename(path)
297
- base = File.basename(path)
298
- if /\A#{SEPARATOR_PAT}?\z/ =~ base
299
- return nil
300
- else
301
- return path[0, path.rindex(base)], base
302
- end
303
- end
304
- private :chop_basename
305
-
306
- # split_names(path) -> prefix, [name, ...]
307
- def split_names(path)
308
- names = []
309
- while r = chop_basename(path)
310
- path, basename = r
311
- names.unshift basename
312
- end
313
- return path, names
314
- end
315
- private :split_names
316
-
317
- def prepend_prefix(prefix, relpath)
318
- if relpath.empty?
319
- File.dirname(prefix)
320
- elsif /#{SEPARATOR_PAT}/ =~ prefix
321
- prefix = File.dirname(prefix)
322
- prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
323
- prefix + relpath
324
- else
325
- prefix + relpath
326
- end
327
- end
328
- private :prepend_prefix
329
-
330
- # Returns clean pathname of +self+ with consecutive slashes and useless dots
331
- # removed. The filesystem is not accessed.
332
- #
333
- # If +consider_symlink+ is +true+, then a more conservative algorithm is used
334
- # to avoid breaking symbolic linkages. This may retain more <tt>..</tt>
335
- # entries than absolutely necessary, but without accessing the filesystem,
336
- # this can't be avoided. See #realpath.
337
- #
338
- def cleanpath(consider_symlink=false)
339
- if consider_symlink
340
- cleanpath_conservative
341
- else
342
- cleanpath_aggressive
343
- end
344
- end
345
-
346
- #
347
- # Clean the path simply by resolving and removing excess "." and ".." entries.
348
- # Nothing more, nothing less.
349
- #
350
- def cleanpath_aggressive
351
- path = @path
352
- names = []
353
- pre = path
354
- while r = chop_basename(pre)
355
- pre, base = r
356
- case base
357
- when '.'
358
- when '..'
359
- names.unshift base
360
- else
361
- if names[0] == '..'
362
- names.shift
363
- else
364
- names.unshift base
365
- end
366
- end
367
- end
368
- if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
369
- names.shift while names[0] == '..'
370
- end
371
- self.class.new(prepend_prefix(pre, File.join(*names)))
372
- end
373
- private :cleanpath_aggressive
374
-
375
- # has_trailing_separator?(path) -> bool
376
- def has_trailing_separator?(path)
377
- if r = chop_basename(path)
378
- pre, basename = r
379
- pre.length + basename.length < path.length
380
- else
381
- false
382
- end
383
- end
384
- private :has_trailing_separator?
385
-
386
- # add_trailing_separator(path) -> path
387
- def add_trailing_separator(path)
388
- if File.basename(path + 'a') == 'a'
389
- path
390
- else
391
- File.join(path, "") # xxx: Is File.join is appropriate to add separator?
392
- end
393
- end
394
- private :add_trailing_separator
395
-
396
- def del_trailing_separator(path)
397
- if r = chop_basename(path)
398
- pre, basename = r
399
- pre + basename
400
- elsif /#{SEPARATOR_PAT}+\z/o =~ path
401
- $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
402
- else
403
- path
404
- end
405
- end
406
- private :del_trailing_separator
407
-
408
- def cleanpath_conservative
409
- path = @path
410
- names = []
411
- pre = path
412
- while r = chop_basename(pre)
413
- pre, base = r
414
- names.unshift base if base != '.'
415
- end
416
- if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
417
- names.shift while names[0] == '..'
418
- end
419
- if names.empty?
420
- self.class.new(File.dirname(pre))
421
- else
422
- if names.last != '..' && File.basename(path) == '.'
423
- names << '.'
424
- end
425
- result = prepend_prefix(pre, File.join(*names))
426
- if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
427
- self.class.new(add_trailing_separator(result))
428
- else
429
- self.class.new(result)
430
- end
431
- end
432
- end
433
- private :cleanpath_conservative
434
-
435
- def realpath_rec(prefix, unresolved, h)
436
- resolved = []
437
- until unresolved.empty?
438
- n = unresolved.shift
439
- if n == '.'
440
- next
441
- elsif n == '..'
442
- resolved.pop
443
- else
444
- path = prepend_prefix(prefix, File.join(*(resolved + [n])))
445
- if h.include? path
446
- if h[path] == :resolving
447
- raise Errno::ELOOP.new(path)
448
- else
449
- prefix, *resolved = h[path]
450
- end
451
- else
452
- s = File.lstat(path)
453
- if s.symlink?
454
- h[path] = :resolving
455
- link_prefix, link_names = split_names(File.readlink(path))
456
- if link_prefix == ''
457
- prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h)
458
- else
459
- prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h)
460
- end
461
- else
462
- resolved << n
463
- h[path] = [prefix, *resolved]
464
- end
465
- end
466
- end
467
- end
468
- return prefix, *resolved
469
- end
470
- private :realpath_rec
471
-
472
- #
473
- # Returns a real (absolute) pathname of +self+ in the actual filesystem.
474
- # The real pathname doesn't contain symlinks or useless dots.
475
- #
476
- # No arguments should be given; the old behaviour is *obsoleted*.
477
- #
478
- def realpath
479
- path = @path
480
- prefix, names = split_names(path)
481
- if prefix == ''
482
- prefix, names2 = split_names(Dir.pwd)
483
- names = names2 + names
484
- end
485
- prefix, *names = realpath_rec(prefix, names, {})
486
- self.class.new(prepend_prefix(prefix, File.join(*names)))
487
- end
488
-
489
- # #parent returns the parent directory.
490
- #
491
- # This is same as <tt>self + '..'</tt>.
492
- def parent
493
- self + '..'
494
- end
495
-
496
- # #mountpoint? returns +true+ if <tt>self</tt> points to a mountpoint.
497
- def mountpoint?
498
- begin
499
- stat1 = self.lstat
500
- stat2 = self.parent.lstat
501
- stat1.dev == stat2.dev && stat1.ino == stat2.ino ||
502
- stat1.dev != stat2.dev
503
- rescue Errno::ENOENT
504
- false
505
- end
506
- end
507
-
508
- #
509
- # #root? is a predicate for root directories. I.e. it returns +true+ if the
510
- # pathname consists of consecutive slashes.
511
- #
512
- # It doesn't access actual filesystem. So it may return +false+ for some
513
- # pathnames which points to roots such as <tt>/usr/..</tt>.
514
- #
515
- def root?
516
- !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path)
517
- end
518
-
519
- # Predicate method for testing whether a path is absolute.
520
- # It returns +true+ if the pathname begins with a slash.
521
- def absolute?
522
- !relative?
523
- end
524
-
525
- # The opposite of #absolute?
526
- def relative?
527
- path = @path
528
- while r = chop_basename(path)
529
- path, basename = r
530
- end
531
- path == ''
532
- end
533
-
534
- #
535
- # Iterates over each component of the path.
536
- #
537
- # Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
538
- # # yields "usr", "bin", and "ruby".
539
- #
540
- def each_filename # :yield: filename
541
- return to_enum(__method__) unless block_given?
542
- prefix, names = split_names(@path)
543
- names.each {|filename| yield filename }
544
- nil
545
- end
546
-
547
- # Iterates over and yields a new Pathname object
548
- # for each element in the given path in descending order.
549
- #
550
- # Pathname.new('/path/to/some/file.rb').descend {|v| p v}
551
- # #<Pathname:/>
552
- # #<Pathname:/path>
553
- # #<Pathname:/path/to>
554
- # #<Pathname:/path/to/some>
555
- # #<Pathname:/path/to/some/file.rb>
556
- #
557
- # Pathname.new('path/to/some/file.rb').descend {|v| p v}
558
- # #<Pathname:path>
559
- # #<Pathname:path/to>
560
- # #<Pathname:path/to/some>
561
- # #<Pathname:path/to/some/file.rb>
562
- #
563
- # It doesn't access actual filesystem.
564
- #
565
- # This method is available since 1.8.5.
566
- #
567
- def descend
568
- vs = []
569
- ascend {|v| vs << v }
570
- vs.reverse_each {|v| yield v }
571
- nil
572
- end
573
-
574
- # Iterates over and yields a new Pathname object
575
- # for each element in the given path in ascending order.
576
- #
577
- # Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
578
- # #<Pathname:/path/to/some/file.rb>
579
- # #<Pathname:/path/to/some>
580
- # #<Pathname:/path/to>
581
- # #<Pathname:/path>
582
- # #<Pathname:/>
583
- #
584
- # Pathname.new('path/to/some/file.rb').ascend {|v| p v}
585
- # #<Pathname:path/to/some/file.rb>
586
- # #<Pathname:path/to/some>
587
- # #<Pathname:path/to>
588
- # #<Pathname:path>
589
- #
590
- # It doesn't access actual filesystem.
591
- #
592
- # This method is available since 1.8.5.
593
- #
594
- def ascend
595
- path = @path
596
- yield self
597
- while r = chop_basename(path)
598
- path, name = r
599
- break if path.empty?
600
- yield self.class.new(del_trailing_separator(path))
601
- end
602
- end
603
-
604
- #
605
- # Pathname#+ appends a pathname fragment to this one to produce a new Pathname
606
- # object.
607
- #
608
- # p1 = Pathname.new("/usr") # Pathname:/usr
609
- # p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
610
- # p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
611
- #
612
- # This method doesn't access the file system; it is pure string manipulation.
613
- #
614
- def +(other)
615
- other = Pathname.new(other) unless Pathname === other
616
- Pathname.new(plus(@path, other.to_s))
617
- end
618
-
619
- def plus(path1, path2) # -> path
620
- prefix2 = path2
621
- index_list2 = []
622
- basename_list2 = []
623
- while r2 = chop_basename(prefix2)
624
- prefix2, basename2 = r2
625
- index_list2.unshift prefix2.length
626
- basename_list2.unshift basename2
627
- end
628
- return path2 if prefix2 != ''
629
- prefix1 = path1
630
- while true
631
- while !basename_list2.empty? && basename_list2.first == '.'
632
- index_list2.shift
633
- basename_list2.shift
634
- end
635
- break unless r1 = chop_basename(prefix1)
636
- prefix1, basename1 = r1
637
- next if basename1 == '.'
638
- if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
639
- prefix1 = prefix1 + basename1
640
- break
641
- end
642
- index_list2.shift
643
- basename_list2.shift
644
- end
645
- r1 = chop_basename(prefix1)
646
- if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1)
647
- while !basename_list2.empty? && basename_list2.first == '..'
648
- index_list2.shift
649
- basename_list2.shift
650
- end
651
- end
652
- if !basename_list2.empty?
653
- suffix2 = path2[index_list2.first..-1]
654
- r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
655
- else
656
- r1 ? prefix1 : File.dirname(prefix1)
657
- end
658
- end
659
- private :plus
660
-
661
- #
662
- # Pathname#join joins pathnames.
663
- #
664
- # <tt>path0.join(path1, ..., pathN)</tt> is the same as
665
- # <tt>path0 + path1 + ... + pathN</tt>.
666
- #
667
- def join(*args)
668
- args.unshift self
669
- result = args.pop
670
- result = Pathname.new(result) unless Pathname === result
671
- return result if result.absolute?
672
- args.reverse_each {|arg|
673
- arg = Pathname.new(arg) unless Pathname === arg
674
- result = arg + result
675
- return result if result.absolute?
676
- }
677
- result
678
- end
679
-
680
- #
681
- # Returns the children of the directory (files and subdirectories, not
682
- # recursive) as an array of Pathname objects. By default, the returned
683
- # pathnames will have enough information to access the files. If you set
684
- # +with_directory+ to +false+, then the returned pathnames will contain the
685
- # filename only.
686
- #
687
- # For example:
688
- # p = Pathname("/usr/lib/ruby/1.8")
689
- # p.children
690
- # # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
691
- # Pathname:/usr/lib/ruby/1.8/Env.rb,
692
- # Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
693
- # p.children(false)
694
- # # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
695
- #
696
- # Note that the result never contain the entries <tt>.</tt> and <tt>..</tt> in
697
- # the directory because they are not children.
698
- #
699
- # This method has existed since 1.8.1.
700
- #
701
- def children(with_directory=true)
702
- with_directory = false if @path == '.'
703
- result = []
704
- Dir.foreach(@path) {|e|
705
- next if e == '.' || e == '..'
706
- if with_directory
707
- result << self.class.new(File.join(@path, e))
708
- else
709
- result << self.class.new(e)
710
- end
711
- }
712
- result
713
- end
714
-
715
- #
716
- # #relative_path_from returns a relative path from the argument to the
717
- # receiver. If +self+ is absolute, the argument must be absolute too. If
718
- # +self+ is relative, the argument must be relative too.
719
- #
720
- # #relative_path_from doesn't access the filesystem. It assumes no symlinks.
721
- #
722
- # ArgumentError is raised when it cannot find a relative path.
723
- #
724
- # This method has existed since 1.8.1.
725
- #
726
- def relative_path_from(base_directory)
727
- dest_directory = self.cleanpath.to_s
728
- base_directory = base_directory.cleanpath.to_s
729
- dest_prefix = dest_directory
730
- dest_names = []
731
- while r = chop_basename(dest_prefix)
732
- dest_prefix, basename = r
733
- dest_names.unshift basename if basename != '.'
734
- end
735
- base_prefix = base_directory
736
- base_names = []
737
- while r = chop_basename(base_prefix)
738
- base_prefix, basename = r
739
- base_names.unshift basename if basename != '.'
740
- end
741
- unless SAME_PATHS[dest_prefix, base_prefix]
742
- raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
743
- end
744
- while !dest_names.empty? &&
745
- !base_names.empty? &&
746
- SAME_PATHS[dest_names.first, base_names.first]
747
- dest_names.shift
748
- base_names.shift
749
- end
750
- if base_names.include? '..'
751
- raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
752
- end
753
- base_names.fill('..')
754
- relpath_names = base_names + dest_names
755
- if relpath_names.empty?
756
- Pathname.new('.')
757
- else
758
- Pathname.new(File.join(*relpath_names))
759
- end
760
- end
761
- end
762
-
763
- class Pathname # * IO *
764
- #
765
- # #each_line iterates over the line in the file. It yields a String object
766
- # for each line.
767
- #
768
- # This method has existed since 1.8.1.
769
- #
770
- def each_line(*args, &block) # :yield: line
771
- IO.foreach(@path, *args, &block)
772
- end
773
-
774
- # Pathname#foreachline is *obsoleted* at 1.8.1. Use #each_line.
775
- def foreachline(*args, &block)
776
- warn "Pathname#foreachline is obsoleted. Use Pathname#each_line."
777
- each_line(*args, &block)
778
- end
779
-
780
- # See <tt>IO.read</tt>. Returns all the bytes from the file, or the first +N+
781
- # if specified.
782
- def read(*args) IO.read(@path, *args) end
783
-
784
- # See <tt>IO.readlines</tt>. Returns all the lines from the file.
785
- def readlines(*args) IO.readlines(@path, *args) end
786
-
787
- # See <tt>IO.sysopen</tt>.
788
- def sysopen(*args) IO.sysopen(@path, *args) end
789
- end
790
-
791
-
792
- class Pathname # * File *
793
-
794
- # See <tt>File.atime</tt>. Returns last access time.
795
- def atime() File.atime(@path) end
796
-
797
- # See <tt>File.ctime</tt>. Returns last (directory entry, not file) change time.
798
- def ctime() File.ctime(@path) end
799
-
800
- # See <tt>File.mtime</tt>. Returns last modification time.
801
- def mtime() File.mtime(@path) end
802
-
803
- # See <tt>File.chmod</tt>. Changes permissions.
804
- def chmod(mode) File.chmod(mode, @path) end
805
-
806
- # See <tt>File.lchmod</tt>.
807
- def lchmod(mode) File.lchmod(mode, @path) end
808
-
809
- # See <tt>File.chown</tt>. Change owner and group of file.
810
- def chown(owner, group) File.chown(owner, group, @path) end
811
-
812
- # See <tt>File.lchown</tt>.
813
- def lchown(owner, group) File.lchown(owner, group, @path) end
814
-
815
- # See <tt>File.fnmatch</tt>. Return +true+ if the receiver matches the given
816
- # pattern.
817
- def fnmatch(pattern, *args) File.fnmatch(pattern, @path, *args) end
818
-
819
- # See <tt>File.fnmatch?</tt> (same as #fnmatch).
820
- def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end
821
-
822
- # See <tt>File.ftype</tt>. Returns "type" of file ("file", "directory",
823
- # etc).
824
- def ftype() File.ftype(@path) end
825
-
826
- # See <tt>File.link</tt>. Creates a hard link.
827
- def make_link(old) File.link(old, @path) end
828
-
829
- # See <tt>File.open</tt>. Opens the file for reading or writing.
830
- def open(*args, &block) # :yield: file
831
- File.open(@path, *args, &block)
832
- end
833
-
834
- # See <tt>File.readlink</tt>. Read symbolic link.
835
- def readlink() self.class.new(File.readlink(@path)) end
836
-
837
- # See <tt>File.rename</tt>. Rename the file.
838
- def rename(to) File.rename(@path, to) end
839
-
840
- # See <tt>File.stat</tt>. Returns a <tt>File::Stat</tt> object.
841
- def stat() File.stat(@path) end
842
-
843
- # See <tt>File.lstat</tt>.
844
- def lstat() File.lstat(@path) end
845
-
846
- # See <tt>File.symlink</tt>. Creates a symbolic link.
847
- def make_symlink(old) File.symlink(old, @path) end
848
-
849
- # See <tt>File.truncate</tt>. Truncate the file to +length+ bytes.
850
- def truncate(length) File.truncate(@path, length) end
851
-
852
- # See <tt>File.utime</tt>. Update the access and modification times.
853
- def utime(atime, mtime) File.utime(atime, mtime, @path) end
854
-
855
- # See <tt>File.basename</tt>. Returns the last component of the path.
856
- def basename(*args) self.class.new(File.basename(@path, *args)) end
857
-
858
- # See <tt>File.dirname</tt>. Returns all but the last component of the path.
859
- def dirname() self.class.new(File.dirname(@path)) end
860
-
861
- # See <tt>File.extname</tt>. Returns the file's extension.
862
- def extname() File.extname(@path) end
863
-
864
- # See <tt>File.expand_path</tt>.
865
- def expand_path(*args) self.class.new(File.expand_path(@path, *args)) end
866
-
867
- # See <tt>File.split</tt>. Returns the #dirname and the #basename in an
868
- # Array.
869
- def split() File.split(@path).map {|f| self.class.new(f) } end
870
-
871
- # Pathname#link is confusing and *obsoleted* because the receiver/argument
872
- # order is inverted to corresponding system call.
873
- def link(old)
874
- warn 'Pathname#link is obsoleted. Use Pathname#make_link.'
875
- File.link(old, @path)
876
- end
877
-
878
- # Pathname#symlink is confusing and *obsoleted* because the receiver/argument
879
- # order is inverted to corresponding system call.
880
- def symlink(old)
881
- warn 'Pathname#symlink is obsoleted. Use Pathname#make_symlink.'
882
- File.symlink(old, @path)
883
- end
884
- end
885
-
886
-
887
- class Pathname # * FileTest *
888
-
889
- # See <tt>FileTest.blockdev?</tt>.
890
- def blockdev?() FileTest.blockdev?(@path) end
891
-
892
- # See <tt>FileTest.chardev?</tt>.
893
- def chardev?() FileTest.chardev?(@path) end
894
-
895
- # See <tt>FileTest.executable?</tt>.
896
- def executable?() FileTest.executable?(@path) end
897
-
898
- # See <tt>FileTest.executable_real?</tt>.
899
- def executable_real?() FileTest.executable_real?(@path) end
900
-
901
- # See <tt>FileTest.exist?</tt>.
902
- def exist?() FileTest.exist?(@path) end
903
-
904
- # See <tt>FileTest.grpowned?</tt>.
905
- def grpowned?() FileTest.grpowned?(@path) end
906
-
907
- # See <tt>FileTest.directory?</tt>.
908
- def directory?() FileTest.directory?(@path) end
909
-
910
- # See <tt>FileTest.file?</tt>.
911
- def file?() FileTest.file?(@path) end
912
-
913
- # See <tt>FileTest.pipe?</tt>.
914
- def pipe?() FileTest.pipe?(@path) end
915
-
916
- # See <tt>FileTest.socket?</tt>.
917
- def socket?() FileTest.socket?(@path) end
918
-
919
- # See <tt>FileTest.owned?</tt>.
920
- def owned?() FileTest.owned?(@path) end
921
-
922
- # See <tt>FileTest.readable?</tt>.
923
- def readable?() FileTest.readable?(@path) end
924
-
925
- # See <tt>FileTest.world_readable?</tt>.
926
- def world_readable?() FileTest.world_readable?(@path) end
927
-
928
- # See <tt>FileTest.readable_real?</tt>.
929
- def readable_real?() FileTest.readable_real?(@path) end
930
-
931
- # See <tt>FileTest.setuid?</tt>.
932
- def setuid?() FileTest.setuid?(@path) end
933
-
934
- # See <tt>FileTest.setgid?</tt>.
935
- def setgid?() FileTest.setgid?(@path) end
936
-
937
- # See <tt>FileTest.size</tt>.
938
- def size() FileTest.size(@path) end
939
-
940
- # See <tt>FileTest.size?</tt>.
941
- def size?() FileTest.size?(@path) end
942
-
943
- # See <tt>FileTest.sticky?</tt>.
944
- def sticky?() FileTest.sticky?(@path) end
945
-
946
- # See <tt>FileTest.symlink?</tt>.
947
- def symlink?() FileTest.symlink?(@path) end
948
-
949
- # See <tt>FileTest.writable?</tt>.
950
- def writable?() FileTest.writable?(@path) end
951
-
952
- # See <tt>FileTest.world_writable?</tt>.
953
- def world_writable?() FileTest.world_writable?(@path) end
954
-
955
- # See <tt>FileTest.writable_real?</tt>.
956
- def writable_real?() FileTest.writable_real?(@path) end
957
-
958
- # See <tt>FileTest.zero?</tt>.
959
- def zero?() FileTest.zero?(@path) end
960
- end
961
-
962
-
963
- class Pathname # * Dir *
964
- # See <tt>Dir.glob</tt>. Returns or yields Pathname objects.
965
- def Pathname.glob(*args) # :yield: p
966
- if block_given?
967
- Dir.glob(*args) {|f| yield self.new(f) }
968
- else
969
- Dir.glob(*args).map {|f| self.new(f) }
970
- end
971
- end
972
-
973
- # See <tt>Dir.getwd</tt>. Returns the current working directory as a Pathname.
974
- def Pathname.getwd() self.new(Dir.getwd) end
975
- class << self; alias pwd getwd end
976
-
977
- # Pathname#chdir is *obsoleted* at 1.8.1.
978
- def chdir(&block)
979
- warn "Pathname#chdir is obsoleted. Use Dir.chdir."
980
- Dir.chdir(@path, &block)
981
- end
982
-
983
- # Pathname#chroot is *obsoleted* at 1.8.1.
984
- def chroot
985
- warn "Pathname#chroot is obsoleted. Use Dir.chroot."
986
- Dir.chroot(@path)
987
- end
988
-
989
- # Return the entries (files and subdirectories) in the directory, each as a
990
- # Pathname object.
991
- def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
992
-
993
- # Iterates over the entries (files and subdirectories) in the directory. It
994
- # yields a Pathname object for each entry.
995
- #
996
- # This method has existed since 1.8.1.
997
- def each_entry(&block) # :yield: p
998
- Dir.foreach(@path) {|f| yield self.class.new(f) }
999
- end
1000
-
1001
- # Pathname#dir_foreach is *obsoleted* at 1.8.1.
1002
- def dir_foreach(*args, &block)
1003
- warn "Pathname#dir_foreach is obsoleted. Use Pathname#each_entry."
1004
- each_entry(*args, &block)
1005
- end
1006
-
1007
- # See <tt>Dir.mkdir</tt>. Create the referenced directory.
1008
- def mkdir(*args) Dir.mkdir(@path, *args) end
1009
-
1010
- # See <tt>Dir.rmdir</tt>. Remove the referenced directory.
1011
- def rmdir() Dir.rmdir(@path) end
1012
-
1013
- # See <tt>Dir.open</tt>.
1014
- def opendir(&block) # :yield: dir
1015
- Dir.open(@path, &block)
1016
- end
1017
- end
1018
-
1019
-
1020
- class Pathname # * Find *
1021
- #
1022
- # Pathname#find is an iterator to traverse a directory tree in a depth first
1023
- # manner. It yields a Pathname for each file under "this" directory.
1024
- #
1025
- # Since it is implemented by <tt>find.rb</tt>, <tt>Find.prune</tt> can be used
1026
- # to control the traverse.
1027
- #
1028
- # If +self+ is <tt>.</tt>, yielded pathnames begin with a filename in the
1029
- # current directory, not <tt>./</tt>.
1030
- #
1031
- def find(&block) # :yield: p
1032
- require 'find'
1033
- if @path == '.'
1034
- Find.find(@path) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
1035
- else
1036
- Find.find(@path) {|f| yield self.class.new(f) }
1037
- end
1038
- end
1039
- end
1040
-
1041
-
1042
- class Pathname # * FileUtils *
1043
- # See <tt>FileUtils.mkpath</tt>. Creates a full path, including any
1044
- # intermediate directories that don't yet exist.
1045
- def mkpath
1046
- require 'fileutils'
1047
- FileUtils.mkpath(@path)
1048
- nil
1049
- end
1050
-
1051
- # See <tt>FileUtils.rm_r</tt>. Deletes a directory and all beneath it.
1052
- def rmtree
1053
- # The name "rmtree" is borrowed from File::Path of Perl.
1054
- # File::Path provides "mkpath" and "rmtree".
1055
- require 'fileutils'
1056
- FileUtils.rm_r(@path)
1057
- nil
1058
- end
1059
- end
1060
-
1061
-
1062
- class Pathname # * mixed *
1063
- # Removes a file or directory, using <tt>File.unlink</tt> or
1064
- # <tt>Dir.unlink</tt> as necessary.
1065
- def unlink()
1066
- begin
1067
- Dir.unlink @path
1068
- rescue Errno::ENOTDIR
1069
- File.unlink @path
1070
- end
1071
- end
1072
- alias delete unlink
1073
-
1074
- # This method is *obsoleted* at 1.8.1. Use #each_line or #each_entry.
1075
- def foreach(*args, &block)
1076
- warn "Pathname#foreach is obsoleted. Use each_line or each_entry."
1077
- if FileTest.directory? @path
1078
- # For polymorphism between Dir.foreach and IO.foreach,
1079
- # Pathname#foreach doesn't yield Pathname object.
1080
- Dir.foreach(@path, *args, &block)
1081
- else
1082
- IO.foreach(@path, *args, &block)
1083
- end
1084
- end
1085
- end
1086
-
1087
- module Kernel
1088
- # create a pathname object.
1089
- #
1090
- # This method is available since 1.8.5.
1091
- def Pathname(path) # :doc:
1092
- Pathname.new(path)
1093
- end
1094
- private :Pathname
1095
- end