folio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ class Dir
2
+
3
+ # Like +glob+ but can take multiple patterns.
4
+ #
5
+ # Dir.multiglob( '*.rb', '*.py' )
6
+ #
7
+ # Rather then constants for options multiglob accepts a trailing options
8
+ # hash of symbol keys.
9
+ #
10
+ # :noescape File::FNM_NOESCAPE
11
+ # :casefold File::FNM_CASEFOLD
12
+ # :pathname File::FNM_PATHNAME
13
+ # :dotmatch File::FNM_DOTMATCH
14
+ # :strict File::FNM_PATHNAME && File::FNM_DOTMATCH
15
+ #
16
+ # It also has an option for recurse.
17
+ #
18
+ # :recurse Recurively include contents of directories.
19
+ #
20
+ # For example
21
+ #
22
+ # Dir.multiglob( '*', :recurse => true )
23
+ #
24
+ # would have the same result as
25
+ #
26
+ # Dir.multiglob('**/*')
27
+ #
28
+ #--
29
+ # DEPRECATED
30
+ #
31
+ # Multiglob also accepts '+' and '-' prefixes. Any entry that begins with a '-'
32
+ # is treated as an exclusion glob and will be removed from the final result.
33
+ # For example, to collect all files in the current directory, less ruby scripts:
34
+ #
35
+ # Dir.multiglob( '*', '-*.rb' )
36
+ #
37
+ # This is very useful in collecting files as specificed by a configuration
38
+ # parameter.
39
+ #++
40
+ def self.multiglob(*patterns)
41
+ options = (Hash === patterns.last ? patterns.pop : {})
42
+
43
+ if options.delete(:recurse)
44
+ #patterns += patterns.collect{ |f| File.join(f, '**', '**') }
45
+ multiglob_r(*patterns)
46
+ end
47
+
48
+ bitflags = 0
49
+ bitflags |= File::FNM_NOESCAPE if options[:noescape]
50
+ bitflags |= File::FNM_CASEFOLD if options[:casefold]
51
+ bitflags |= File::FNM_PATHNAME if options[:pathname] or options[:strict]
52
+ bitflags |= File::FNM_DOTMATCH if options[:dotmatch] or options[:strict]
53
+
54
+ patterns = [patterns].flatten.compact
55
+
56
+ if options[:recurse]
57
+ patterns += patterns.collect{ |f| File.join(f, '**', '**') }
58
+ end
59
+
60
+ files = []
61
+ files += patterns.collect{ |pattern| Dir.glob(pattern, bitflags) }.flatten.uniq
62
+
63
+ return files
64
+ end
65
+
66
+ # The same as +multiglob+, but recusively includes directories.
67
+ #
68
+ # Dir.multiglob_r( 'folder' )
69
+ #
70
+ # is equivalent to
71
+ #
72
+ # Dir.multiglob( 'folder', :recurse=>true )
73
+ #
74
+ # The effect of which is
75
+ #
76
+ # Dir.multiglob( 'folder', 'folder/**/**' )
77
+ #
78
+ def self.multiglob_r(*patterns)
79
+ options = (Hash === patterns.last ? patterns.pop : {})
80
+ matches = multiglob(*patterns)
81
+ directories = matches.select{ |m| File.directory?(m) }
82
+ matches += directories.collect{ |d| multiglob_r(File.join(d, '**'), options) }.flatten
83
+ matches.uniq
84
+ #options = (Hash === patterns.last ? patterns.pop : {})
85
+ #options[:recurse] = true
86
+ #patterns << options
87
+ #multiglob(*patterns)
88
+ end
89
+
90
+ end
91
+
@@ -0,0 +1,56 @@
1
+ #require 'pathname'
2
+
3
+ module Folio
4
+
5
+ class Path
6
+
7
+ def initialize(path)
8
+ if File.exist?(path)
9
+ @delegate = Pathname.new(path, self)
10
+ else
11
+ @delegate = FileObject[path]
12
+ end
13
+ end
14
+
15
+ def replace(file_object)
16
+ @delegate = file_object
17
+ end
18
+
19
+ def method_missing(s, *a, &b)
20
+ @delegate.__send__(s, *a, &b)
21
+ end
22
+ end
23
+
24
+
25
+ class Pathname
26
+
27
+ def initialize(path, delegator)
28
+
29
+ end
30
+
31
+ def cd
32
+ delegator.replace(Directory.new(to_s))
33
+ delegator.cd()
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+
41
+
42
+
43
+ #module Kernel
44
+ # def path(name)
45
+ # Folio::Path.new(name)
46
+ # end
47
+ #end
48
+
49
+ #$path = lambda{ |path| Folio::Path.new(path) }
50
+
51
+ #class String
52
+ # def to_path
53
+ # Folio::Path.new(self)
54
+ # end
55
+ #end
56
+
@@ -1,5 +1,9 @@
1
1
  module Folio
2
2
  require 'folio/xdg'
3
+ require 'folio/filetest'
4
+ require 'folio/fileutils'
5
+ require 'folio/ziputils'
6
+ require 'folio/multiglob'
3
7
 
4
8
  # = Prompt class
5
9
  #
@@ -21,7 +25,7 @@ module Folio
21
25
  raise FileNotFound, "#{path}" unless ::File.exist?(path)
22
26
  raise FileNotFound, "#{path}" unless ::File.directory?(path)
23
27
 
24
- @work = Directory.new(path)
28
+ @work = dir(path)
25
29
  end
26
30
 
27
31
  # Opertaton mode. This can be :noop, :verbose or :dryrun.
@@ -48,10 +52,10 @@ module Folio
48
52
  attr :work
49
53
 
50
54
  # Home location.
51
- def home ; file('~') ; end
55
+ def home ; dir('~') ; end
52
56
 
53
57
  # Root location.
54
- def root ; file('/') ; end
58
+ def root ; dir('/') ; end
55
59
 
56
60
  # Return a new prompt with the same location.
57
61
  # NOTE: Use #dup or #clone ?
@@ -62,17 +66,32 @@ module Folio
62
66
  # TODO: Should there be methods like this for each
63
67
  # type, and raise an error if not the right type?
64
68
  #
69
+ #
70
+ def [](name)
71
+ FileObject[name]
72
+ end
73
+
65
74
  def file(name)
66
75
  FileObject[name]
67
76
  end
68
77
 
69
- alias_method :[], :file
78
+ def pathname(name)
79
+ Pathname.new(name)
80
+ end
81
+
82
+ def doc(name)
83
+ Document.new(name)
84
+ end
85
+
86
+ def dir(name)
87
+ Directory.new(name)
88
+ end
70
89
 
71
90
  # Join paths.
72
91
  def +(fname)
73
92
  @work =+ fname
74
93
  end
75
- alias_method :/, :+
94
+ alias_method '/', '+'
76
95
 
77
96
  # Lists all entries.
78
97
  def entries
@@ -99,132 +118,331 @@ module Folio
99
118
  # Returns Enumerator of documents.
100
119
  def directories ; work.directories ; end
101
120
 
102
- # Glob pattern.
103
- def glob(*patterns)
121
+ # Glob pattern. Returns matches as strings.
122
+ def glob(*patterns, &block)
123
+ opts = (::Integer===patterns.last ? patterns.pop : 0)
124
+ patterns = localize(patterns)
125
+ matches = patterns.map{ |pattern| ::Dir.glob(pattern, opts) }.flatten
126
+ if block_given?
127
+ matches.each(&block)
128
+ end
129
+ end
130
+
131
+ # TODO: Ultimately merge #glob and #multiglob.
132
+ def multiglob(*a)
133
+ Dir.multiglob(*a)
134
+ end
135
+
136
+ def multiglob_r(*a)
137
+ Dir.multiglob_r(*a)
138
+ end
139
+
140
+ # Match pattern. Like #glob but returns file objects.
141
+ def match(*patterns, &block)
104
142
  opts = (::Integer===patterns.last ? patterns.pop : 0)
105
- pattern = localize(pattern)
106
- ::Dir.glob(pattern, opts).each{ |f| FileObject[f] }
143
+ patterns = localize(patterns)
144
+ matches = patterns.map{ |pattern| ::Dir.glob(pattern, opts) }.flatten
145
+ matches = matches.map{ |f| FileObject[f] }
146
+ if block_given?
147
+ matches.each(&block)
148
+ end
107
149
  end
108
150
 
109
151
  # Chage working directory.
110
152
  def cd(dir, &block)
111
- #dir = localize(dir)
112
153
  if block
113
- @work.cd(dir, &block)
154
+ Dir.chdir(localize(dir), &block)
114
155
  else
115
156
  @work += dir
116
157
  end
117
158
  end
159
+ alias_method :chdir, :cd
160
+
161
+ #############
162
+ # FileTest #
163
+ #############
164
+
165
+ #
166
+ def size(path) ; FileTest.size(localize(path)) ; end
167
+ def size?(path) ; FileTest.size(localize(path)) ; end
168
+ def directory?(path) ; FileTest.directory?(localize(path)) ; end
169
+ def symlink?(path) ; FileTest.symlink?(localize(path)) ; end
170
+ def readable?(path) ; FileTest.readable?(localize(path)) ; end
171
+ def size?(path) ; FileTest.size?(localize(path)) ; end
172
+ def chardev?(path) ; FileTest.chardev?(localize(path)) ; end
173
+ def exist?(path) ; FileTest.exist?(localize(path)) ; end
174
+ def exists?(path) ; FileTest.exists?(localize(path)) ; end
175
+ def zero?(path) ; FileTest.zero?(localize(path)) ; end
176
+ def pipe?(path) ; FileTest.pipe?(localize(path)) ; end
177
+ def file?(path) ; FileTest.file?(localize(path)) ; end
178
+ def sticky?(path) ; FileTest.sticky?(localize(path)) ; end
179
+ def blockdev?(path) ; FileTest.blockdev?(localize(path)) ; end
180
+ def grpowned?(path) ; FileTest.grpowned?(localize(path)) ; end
181
+ def setgid?(path) ; FileTest.setgid?(localize(path)) ; end
182
+ def setuid?(path) ; FileTest.setuid?(localize(path)) ; end
183
+ def socket?(path) ; FileTest.socket?(localize(path)) ; end
184
+ def directory?(path) ; FileTest.directory?(localize(path)) ; end
185
+ def owned?(path) ; FileTest.owned?(localize(path)) ; end
186
+ def identical?(path) ; FileTest.identical?(localize(path)) ; end
187
+ def writable?(path) ; FileTest.writable?(localize(path)) ; end
188
+ def executable?(path) ; FileTest.executable?(localize(path)) ; end
189
+
190
+ def writable_real?(path) ; FileTest.writable_real?(localize(path)) ; end
191
+ def executable_real?(path) ; FileTest.executable_real?(localize(path)) ; end
192
+ def readable_real?(path) ; FileTest.readable_real?(localize(path)) ; end
193
+
194
+ def safe?(path) ; FileTest.safe?(localize(path)) ; end
195
+
196
+ # TODO: Is #out_of_date? this the same as #uptodate?
197
+ def out_of_date?(path, *sources)
198
+ FileTest.out_of_date?(localize(path), *localize(sources))
199
+ end
200
+
201
+ def relative?(path) ; FileTest.relative?(path) ; end
202
+ def absolute?(path) ; FileTest.absolute?(path) ; end
203
+
118
204
 
119
205
  #############
120
206
  # FileUtils #
121
207
  #############
122
208
 
209
+ # Low-level Methods Omitted
210
+ # -------------------------
211
+ # getwd -> pwd
212
+ # compare_file -> cmp
213
+ # remove_file -> rm
214
+ # copy_file -> cp
215
+ # remove_dir -> rmdir
216
+ # safe_unlink -> rm_f
217
+ # makedirs -> mkdir_p
218
+ # rmtree -> rm_rf
219
+ # copy_stream
220
+ # remove_entry
221
+ # copy_entry
222
+ # remove_entry_secure
223
+ # compare_stream
224
+
225
+ # Present working directory.
226
+ def pwd
227
+ work.to_s
228
+ end
229
+
230
+ # Same as identical?
231
+ def cmp(a,b)
232
+ fileutils.cmp(a,b)
233
+ end
234
+
235
+ #
236
+ def uptodate?(new, old_list, options=nil)
237
+ new = localize(new)
238
+ old = localize(old_list)
239
+ fileutils.uptodate?(new, old, options)
240
+ end
241
+
123
242
  #
124
- def mkdir(dir, options)
243
+ def mkdir(dir, options={})
125
244
  dir = localize(dir)
126
245
  fileutils.mkdir(dir, options)
127
246
  end
128
247
 
129
- def mkdir_p(dir, options)
248
+ def mkdir_p(dir, options={})
130
249
  dir = localize(dir)
131
250
  fileutils.mkdir_p(dir, options)
132
251
  end
252
+ alias_method :mkpath, :mkdir_p
133
253
 
134
- def rmdir(dir, options)
254
+ def rmdir(dir, options={})
135
255
  dir = localize(dir)
136
256
  fileutils.rmdir(dir, options)
137
257
  end
138
258
 
139
- # ln(list, destdir, options)
140
- def ln(old, new, options)
259
+ # ln(list, destdir, options={})
260
+ def ln(old, new, options={})
141
261
  old = localize(old)
142
262
  new = localize(new)
143
263
  fileutils.ln(old, new, options)
144
264
  end
265
+ alias_method :link, :ln
145
266
 
146
- # ln_s(list, destdir, options)
147
- def ln_s(old, new, options)
267
+ # ln_s(list, destdir, options={})
268
+ def ln_s(old, new, options={})
148
269
  old = localize(old)
149
270
  new = localize(new)
150
271
  fileutils.ln_s(old, new, options)
151
272
  end
273
+ alias_method :symlink, :ln_s
152
274
 
153
- def ln_sf(old, new, options)
275
+ def ln_sf(old, new, options={})
154
276
  old = localize(old)
155
277
  new = localize(new)
156
278
  fileutils.ln_sf(old, new, options)
157
279
  end
158
280
 
159
- # cp(list, dir, options)
160
- def cp(src, dest, options)
281
+ # cp(list, dir, options={})
282
+ def cp(src, dest, options={})
161
283
  src = localize(src)
162
284
  dest = localize(dest)
163
285
  fileutils.cp(src, dest, options)
164
286
  end
287
+ alias_method :copy, :cp
165
288
 
166
- # cp_r(list, dir, options)
167
- def cp_r(src, dest, options)
289
+ # cp_r(list, dir, options={})
290
+ def cp_r(src, dest, options={})
168
291
  src = localize(src)
169
292
  dest = localize(dest)
170
293
  fileutils.cp_r(src, dest, options)
171
294
  end
172
295
 
173
- # mv(list, dir, options)
174
- def mv(src, dest, options)
296
+ # mv(list, dir, options={})
297
+ def mv(src, dest, options={})
175
298
  src = localize(src)
176
299
  dest = localize(dest)
177
300
  fileutils.mv(src, dest, options)
178
301
  end
302
+ alias_method :move, :mv
179
303
 
180
- def rm(list, options)
304
+ def rm(list, options={})
181
305
  list = localize(list)
182
306
  fileutils.rm(list, options)
183
307
  end
308
+ alias_method :remove, :rm
184
309
 
185
- def rm_r(list, options)
310
+ def rm_r(list, options={})
311
+ list = localize(list)
312
+ fileutils.rm_r(list, options)
313
+ end
314
+
315
+ def rm_f(list, options={})
186
316
  list = localize(list)
187
317
  fileutils.rm_f(list, options)
188
318
  end
189
319
 
190
- def rm_rf(list, options)
320
+ def rm_rf(list, options={})
191
321
  list = localize(list)
192
322
  fileutils.rm_rf(list, options)
193
323
  end
194
324
 
195
- def install(src, dest, mode, options)
325
+ def install(src, dest, mode, options={})
196
326
  src = localize(src)
197
327
  dest = localize(dest)
198
328
  fileutils.install(src, dest, mode, options)
199
329
  end
200
330
 
201
- def chmod(mode, list, options)
331
+ def chmod(mode, list, options={})
202
332
  list = localize(list)
203
333
  fileutils.chmod(mode, list, options)
204
334
  end
205
335
 
206
- def chmod_r(mode, list, options)
336
+ def chmod_r(mode, list, options={})
207
337
  list = localize(list)
208
338
  fileutils.chmod_r(mode, list, options)
209
339
  end
210
340
  #alias_method :chmod_R, :chmod_r
211
341
 
212
- def chown(user, group, list, options)
342
+ def chown(user, group, list, options={})
213
343
  list = localize(list)
214
344
  fileutils.chown(user, group, list, options)
215
345
  end
216
346
 
217
- def chown_r(user, group, list, options)
347
+ def chown_r(user, group, list, options={})
218
348
  list = localize(list)
219
349
  fileutils.chown_r(user, group, list, options)
220
350
  end
221
351
  #alias_method :chown_R, :chown_r
222
352
 
223
- def touch(list, options)
353
+ def touch(list, options={})
224
354
  list = localize(list)
225
355
  fileutils.touch(list, options)
226
356
  end
227
357
 
358
+ #
359
+ def stage(stage_directory, files)
360
+ dir = localize(stage_directory)
361
+ files = localize(files)
362
+ fileutils.stage(dir, files)
363
+ end
364
+
365
+ #############
366
+ # ZipUtils #
367
+ #############
368
+
369
+ # Compress directory to file. Format is determined
370
+ # by file extension.
371
+ def compress(folder, file, options={})
372
+ ziputils.compress(folder, file, options)
373
+ end
374
+
375
+ #
376
+ def gzip(file=nil, options={})
377
+ file = localize(file)
378
+ ziputils.gzip(file, options)
379
+ end
380
+
381
+ #
382
+ def bzip2(file=nil, options={})
383
+ file = localize(file)
384
+ ziputils.bzip2(file, options)
385
+ end
386
+
387
+ # Create a zip file of a directory.
388
+ def zip(folder, file=nil, options={})
389
+ folder = localize(folder)
390
+ file = localize(file)
391
+ ziputils.zip(folder, file, options)
392
+ end
393
+
394
+ #
395
+ def tar(folder, file=nil, options={})
396
+ folder = localize(folder)
397
+ file = localize(file)
398
+ ziputils.tar_gzip(folder, file, options)
399
+ end
400
+
401
+ # Create a tgz file of a directory.
402
+ def tar_gzip(folder, file=nil, options={})
403
+ folder = localize(folder)
404
+ file = localize(file)
405
+ ziputils.tar_gzip(folder, file, options)
406
+ end
407
+ alias_method :tgz, :tar_gzip
408
+
409
+ # Create a tar.bz2 file of a directory.
410
+ def tar_bzip2(folder, file=nil, options={})
411
+ folder = localize(folder)
412
+ file = localize(file)
413
+ ziputils.tar_bzip2(folder, file, options)
414
+ end
415
+
416
+ def ungzip(file, options)
417
+ file = localize(file)
418
+ ziputils.ungzip(file, options)
419
+ end
420
+
421
+ def unbzip2(file, options)
422
+ file = localize(file)
423
+ ziputils.unbzip2(file, options)
424
+ end
425
+
426
+ def unzip(file, options)
427
+ file = localize(file)
428
+ ziputils.unzip(file, options)
429
+ end
430
+
431
+ def untar(file, options)
432
+ file = localize(file)
433
+ ziputils.untar(file, options)
434
+ end
435
+
436
+ def untar_gzip(file, options)
437
+ file = localize(file)
438
+ ziputils.untar_gzip(file, options)
439
+ end
440
+
441
+ def untar_bzip2(file, options)
442
+ file = localize(file)
443
+ ziputils.untar_bzip2(file, options)
444
+ end
445
+
228
446
  #################
229
447
  # XDG locations #
230
448
  #################
@@ -246,52 +464,58 @@ module Folio
246
464
 
247
465
  # Return a enumertor of system config directories.
248
466
  def root_config() #_directories
249
- XDG.xdg_config_dirs.to_enum(:each){ |f| file(f) }
467
+ XDG.xdg_config_dirs.to_enum(:each){ |f| dir(f) }
250
468
  end
251
469
 
252
470
  # Return a enumertor of system data directories.
253
471
  def root_data() #_directories
254
- XDG.xdg_data_dirs.to_enum(:each){ |f| file(f) }
472
+ XDG.xdg_data_dirs.to_enum(:each){ |f| dir(f) }
255
473
  end
256
474
 
257
475
  # Return the home config directory.
258
476
  def home_config
259
- file(XDG.xdg_config_home)
477
+ dir(XDG.xdg_config_home)
260
478
  end
261
479
 
262
480
  # Return the home data directory.
263
481
  def home_data
264
- file(XDG.xdg_data_home)
482
+ dir(XDG.xdg_data_home)
265
483
  end
266
484
 
267
485
  # Return the home cache directory.
268
486
  def home_cache
269
- file(XDG.xdg_cache_home)
487
+ dir(XDG.xdg_cache_home)
270
488
  end
271
489
 
272
- # Return the home config directory.
490
+ # Return the work config directory.
273
491
  def work_config
274
- file(XDG.xdg_config_work)
275
- end
276
-
277
- # Return the home data directory.
278
- def work_data
279
- file(XDG.xdg_data_work)
492
+ dir(XDG.xdg_config_work)
280
493
  end
281
494
 
282
- # Return the home cache directory.
495
+ # Return the work cache directory.
283
496
  def work_cache
284
- file(XDG.xdg_cache_work)
497
+ dir(XDG.xdg_cache_work)
285
498
  end
286
499
 
287
500
  private
288
501
 
289
502
  def localize(local_path)
503
+ # some path arguments are optional
504
+ return local_path unless local_path
505
+ #
290
506
  case local_path
291
507
  when Array
292
- local_path.collect{ |lp| File.expand_path(File.join(path, lp)) }
508
+ local_path.collect do |lp|
509
+ if absolute?(lp)
510
+ lp
511
+ else
512
+ File.expand_path(File.join(work.to_s, lp))
513
+ end
514
+ end
293
515
  else
294
- File.expand_path(File.join(path, local_path))
516
+ # do not localize an absolute path
517
+ return local_path if absolute?(local_path)
518
+ File.expand_path(File.join(work.to_s, local_path))
295
519
  end
296
520
  end
297
521
 
@@ -310,6 +534,21 @@ module Folio
310
534
  end
311
535
  end
312
536
 
537
+ # Returns ZipUtils module based on mode.
538
+ def ziputils
539
+ return ::ZipUtils unless @mode
540
+ case @mode
541
+ when :dryrun
542
+ ::ZipUtils::DryRun
543
+ when :noop
544
+ ::ZipUtils::Noop
545
+ when :verbose
546
+ ::ZipUtils::Verbose
547
+ else
548
+ ::ZipUtils
549
+ end
550
+ end
551
+
313
552
  public#class
314
553
 
315
554
  def self.[](path)