folio 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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)