class Ratch::Shell

Shell Prompt class

Ratch Shell object provides a limited file system shell in code. It is similar to having a shell prompt available to you in Ruby.

NOTE: We have used the term trace in place of verbose for command line options. Even though Ruby itself uses the term verbose with respect to FileUtils, the term is commonly used for command specific needs, so we want to leave it open for such cases.

Public Class Methods

new(*args) click to toggle source

New Shell object.

Shell.new(:noop=>true)
Shell.new('..', :quiet=>true)
# File lib/ratch/shell.rb, line 28
def initialize(*args)
  path, opts = parse_arguments(*args)

  opts.rekey!(&:to_sym)

  set_options(opts)

  if path.empty?
    path = Dir.pwd
  else
    path = File.join(*path)
  end

  raise FileNotFound, "#{path}" unless ::File.exist?(path)
  raise FileNotFound, "#{path}" unless ::File.directory?(path)

  @_work = Pathname.new(path).expand_path
end

Public Instance Methods

+(path)

Alias for #/.

Alias for: /
/(path) click to toggle source

Join paths. TODO: Should this return a new directory object? Or should it change directories?

# File lib/ratch/shell.rb, line 290
def /(path)
  #@_work += dir   # did not work, why?
  @_work = dir(localize(path))
  self
end
Also aliased as: +
==(other) click to toggle source

Two Shell’s are equal if they have the same working path.

# File lib/ratch/shell.rb, line 98
def ==(other)
  return false unless other.is_a?(self.class)
  return false unless work == other.work
  true
end
absolute?(path) click to toggle source
# File lib/ratch/shell.rb, line 414
def absolute?(path)   ; FileTest.absolute?(path)       ; end
amass(include_globs, exclude_globs=[], ignore_globs=[]) click to toggle source

An intergrated glob like method that takes a set of include globs, exclude globs and ignore globs to produce a collection of paths.

Ignore_globs differ from exclude_globs in that they match by the basename of the path rather than the whole pathname.

# File lib/ratch/shell.rb, line 615
def amass(include_globs, exclude_globs=[], ignore_globs=[])
  locally do
    fileutils.amass(include_globs, exclude_globs, ignore_globs)
  end
end
append(path, text) click to toggle source

Append to file.

# File lib/ratch/shell.rb, line 379
def append(path, text)
  $stderr.puts "append #{path}" if trace?
  File.open(localize(path), 'a'){ |f| f << text } unless noop?
end
apply_naming_policy(name, ext) click to toggle source
# File lib/ratch/shell.rb, line 735
def apply_naming_policy(name, ext)
  naming_policy.each do |policy|
    case policy.to_s
    when /^low/, /^down/
      name = name.downcase
    when /^up/
      name = name.upcase
    when /^cap/
      name = name.capitalize
    when /^ext/
      name = name + ".#{ext}"
    end
  end
  name
end
batch(*patterns) click to toggle source

Returns a Batch of file patterns.

# File lib/ratch/shell.rb, line 172
def batch(*patterns)
  Batch.new patterns.map{|pattern| localize(pattern)}
end
batch_all(*patterns) click to toggle source

Returns a Batch of file patterns, without any exclusions.

# File lib/ratch/shell.rb, line 177
def batch_all(*patterns)
  Batch.all patterns.map{|pattern| localize(pattern)}
end
blockdev?(path) click to toggle source
# File lib/ratch/shell.rb, line 402
def blockdev?(path)   ; FileTest.blockdev?(localize(path))  ; end
cd(path, &block) click to toggle source

Change working directory.

TODO: Make thread safe.

# File lib/ratch/shell.rb, line 339
def cd(path, &block)
  if block
    work_old = @_work
    begin
      @_work = dir(localize(path))
      locally(&block)
      #mutex.synchronize do
      #  Dir.chdir(@_work){ block.call }
      #end
    ensure
      @_work = work_old
    end
  else
    @_work = dir(localize(path))
  end
end
Also aliased as: chdir
chardev?(path) click to toggle source
# File lib/ratch/shell.rb, line 395
def chardev?(path)    ; FileTest.chardev?(localize(path))   ; end
chdir(path, &block)
Alias for: cd
chmod(mode, list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 570
def chmod(mode, list, options={})
  list = localize(list)
  fileutils.chmod(mode, list, options)
end
chmod_r(mode, list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 575
def chmod_r(mode, list, options={})
  list = localize(list)
  fileutils.chmod_r(mode, list, options)
end
chown(user, group, list, options={}) click to toggle source

alias_method :chmod_R, :chmod_r

# File lib/ratch/shell.rb, line 581
def chown(user, group, list, options={})
  list = localize(list)
  fileutils.chown(user, group, list, options)
end
chown_r(user, group, list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 586
def chown_r(user, group, list, options={})
  list = localize(list)
  fileutils.chown_r(user, group, list, options)
end
cmp(a,b) click to toggle source

Same as identical?

# File lib/ratch/shell.rb, line 475
def cmp(a,b)
  fileutils.compare_file(a,b)
end
compare_file(path, other)
Alias for: identical?
copy(src, dest, options={})
Alias for: cp
cp(src, dest, options={}) click to toggle source

cp(list, dir, options={})

# File lib/ratch/shell.rb, line 521
def cp(src, dest, options={})
  src  = localize(src)
  dest = localize(dest)
  fileutils.cp(src, dest, options)
end
Also aliased as: copy
cp_r(src, dest, options={}) click to toggle source

cp_r(list, dir, options={})

# File lib/ratch/shell.rb, line 529
def cp_r(src, dest, options={})
  src  = localize(src)
  dest = localize(dest)
  fileutils.cp_r(src, dest, options)
end
dir(path) click to toggle source
# File lib/ratch/shell.rb, line 200
def dir(path)
  #Directory.new(name)
  path = localize(path)
  raise FileNotFound unless File.directory?(path)
  Pathname.new(path)
end
dir_entries()
Alias for: directory_entries
directories() click to toggle source

Returns list of directories.

# File lib/ratch/shell.rb, line 233
def directories
  pathnames.select{ |f| f.directory? }
end
Also aliased as: dirs, folders
directory?(path) click to toggle source
# File lib/ratch/shell.rb, line 392
def directory?(path)  ; FileTest.directory?(localize(path)) ; end
directory_entries() click to toggle source

Lists directory entries.

# File lib/ratch/shell.rb, line 215
def directory_entries
  entries.select{ |d| d.directory? }
end
Also aliased as: dir_entries
dirs()
Alias for: directories
dryrun?() click to toggle source

def force? ; @_force ; end

# File lib/ratch/shell.rb, line 92
def dryrun?  ; noop? && trace? ; end
entries() click to toggle source

Lists all entries.

# File lib/ratch/shell.rb, line 208
def entries
  work.entries
end
eql?(other) click to toggle source

Same as == except that noop? must also be the same.

# File lib/ratch/shell.rb, line 105
def eql?(other)
  return false unless other.is_a?(self.class)
  return false unless work == other.work
  return false unless noop?  == other.noop?
  true
end
executable?(path) click to toggle source
# File lib/ratch/shell.rb, line 409
def executable?(path) ; FileTest.executable?(localize(path))  ; end
executable_real?(path) click to toggle source
# File lib/ratch/shell.rb, line 417
def executable_real?(path) ; FileTest.executable_real?(localize(path)) ; end
exist?(path) click to toggle source
# File lib/ratch/shell.rb, line 396
def exist?(path)      ; FileTest.exist?(localize(path))     ; end
exists?(path) click to toggle source
# File lib/ratch/shell.rb, line 397
def exists?(path)     ; FileTest.exists?(localize(path))    ; end
file(path) click to toggle source
# File lib/ratch/shell.rb, line 188
def file(path)
  #FileObject[name]
  path = localize(path)
  raise FileNotFound unless File.file?(path)
  Pathname.new(path)
end
file?(path) click to toggle source
# File lib/ratch/shell.rb, line 400
def file?(path)       ; FileTest.file?(localize(path))      ; end
file_entries() click to toggle source

Lists file entries.

# File lib/ratch/shell.rb, line 223
def file_entries
  entries.select{ |f| f.file? }
end
files() click to toggle source

Returns list of files.

# File lib/ratch/shell.rb, line 240
def files
  pathnames.select{ |f| f.file? }
end
folders()
Alias for: directories
glob(*patterns, &block) click to toggle source

Glob pattern. Returns matches as strings.

# File lib/ratch/shell.rb, line 245
def glob(*patterns, &block)
  opts = (::Integer===patterns.last ? patterns.pop : 0)
  matches = []
  locally do
    matches = patterns.map{ |pattern| ::Dir.glob(pattern, opts) }.flatten
  end
  if block_given?
    matches.each(&block)
  else
    matches
  end
end
grpowned?(path) click to toggle source
# File lib/ratch/shell.rb, line 403
def grpowned?(path)   ; FileTest.grpowned?(localize(path))  ; end
home(*args) click to toggle source

Current home path.

# File lib/ratch/shell.rb, line 143
def home(*args)
  dir(File.expand_path('~'), *args)
end
identical?(path, other) click to toggle source
# File lib/ratch/shell.rb, line 420
def identical?(path, other)
  FileTest.identical?(localize(path), localize(other))
end
Also aliased as: compare_file
install(src, dest, mode, options={}) click to toggle source
# File lib/ratch/shell.rb, line 564
def install(src, dest, mode, options={})
  src  = localize(src)
  dest = localize(dest)
  fileutils.install(src, dest, mode, options)
end
ln(old, new, options={}) click to toggle source

ln(list, destdir, options={})

# File lib/ratch/shell.rb, line 499
def ln(old, new, options={})
  old = localize(old)
  new = localize(new)
  fileutils.ln(old, new, options)
end
Also aliased as: link
ln_s(old, new, options={}) click to toggle source

ln_s(list, destdir, options={})

# File lib/ratch/shell.rb, line 507
def ln_s(old, new, options={})
  old = localize(old)
  new = localize(new)
  fileutils.ln_s(old, new, options)
end
Also aliased as: symlink
ln_sf(old, new, options={}) click to toggle source
# File lib/ratch/shell.rb, line 514
def ln_sf(old, new, options={})
  old = localize(old)
  new = localize(new)
  fileutils.ln_sf(old, new, options)
end
localize(local_path) click to toggle source

Returns a path local to the current working path.

# File lib/ratch/shell.rb, line 687
def localize(local_path)
  # some path arguments are optional
  return local_path unless local_path
  #
  case local_path
  when Array
    local_path.collect do |lp|
      if absolute?(lp)
        lp
      else
        File.expand_path(File.join(work.to_s, lp))
      end
    end
  else
    # do not localize an absolute path
    return local_path if absolute?(local_path)
    File.expand_path(File.join(work.to_s, local_path))
    #(work + local_path).expand_path.to_s
  end
end
locally(&block) click to toggle source

Change directory to the shell’s work directory, process the block and then return to user directory.

# File lib/ratch/shell.rb, line 710
def locally(&block)
  if work.to_s == Dir.pwd
    block.call
  else
    mutex.synchronize do
      #work.chdir(&block)
      Dir.chdir(work, &block)
    end
  end
end
mkdir(dir, options={}) click to toggle source
# File lib/ratch/shell.rb, line 480
def mkdir(dir, options={})
  dir = localize(dir)
  fileutils.mkdir(dir, options)
end
mkdir_p(dir, options={}) click to toggle source
# File lib/ratch/shell.rb, line 485
def mkdir_p(dir, options={})
  dir = localize(dir)
  unless File.directory?(dir)
    fileutils.mkdir_p(dir, options)
  end
end
Also aliased as: mkpath
mkpath(dir, options={})
Alias for: mkdir_p
move(src, dest, options={})
Alias for: mv
multiglob(*args, &blk) click to toggle source

TODO: Ultimately merge glob and multiglob.

# File lib/ratch/shell.rb, line 264
def multiglob(*args, &blk)
  Dir.multiglob(*args, &blk)
end
multiglob_r(*args, &blk) click to toggle source
# File lib/ratch/shell.rb, line 268
def multiglob_r(*args, &blk)
  Dir.multiglob_r(*args, &blk)
end
mv(src, dest, options={}) click to toggle source

mv(list, dir, options={})

# File lib/ratch/shell.rb, line 536
def mv(src, dest, options={})
  src  = localize(src)
  dest = localize(dest)
  fileutils.mv(src, dest, options)
end
Also aliased as: move
naming_policy(*policies) click to toggle source
# File lib/ratch/shell.rb, line 725
def naming_policy(*policies)
  if policies.empty?
    @naming_policy ||= ['down', 'ext']
  else
    @naming_policy = policies
  end
end
noop?() click to toggle source
# File lib/ratch/shell.rb, line 89
def noop?    ; @_noop  ; end
outofdate?(path, *sources) click to toggle source
# File lib/ratch/shell.rb, line 622
def outofdate?(path, *sources)
  #fileutils.outofdate?(localize(path), localize(sources))  # DIDN'T WORK, why?
  locally do
    fileutils.outofdate?(path, sources.flatten)
  end
end
owned?(path) click to toggle source
# File lib/ratch/shell.rb, line 407
def owned?(path)      ; FileTest.owned?(localize(path))     ; end
parent() click to toggle source
Return a new prompt with the same location.
NOTE: Use #dup or #clone ?

def new ; Shell.new(work) ; end

# File lib/ratch/shell.rb, line 160
def parent
  dir('..')
end
path(path) click to toggle source
# File lib/ratch/shell.rb, line 182
def path(path)
  Pathname.new(localize(path))
end
Also aliased as: pathname
pathname(path)
Alias for: path
pathnames() click to toggle source

Likes entries but omits ‘.’ and ‘..’ paths.

# File lib/ratch/shell.rb, line 228
def pathnames
  work.entries - %w{. ..}.map{|f|Pathname.new(f)}
end
pipe?(path) click to toggle source
# File lib/ratch/shell.rb, line 399
def pipe?(path)       ; FileTest.pipe?(localize(path))      ; end
pwd() click to toggle source

Present working directory.

# File lib/ratch/shell.rb, line 470
def pwd
  work.to_s
end
quiet?() click to toggle source
Opertaton mode. This can be :noop, :verbose or :dryrun.
The later is the same as the first two combined.

def mode(opts=nil)

return @mode unless opts
opts.each do |key, val|
  next unless val
  case key
  when :noop
    @mode = (@mode == :verbose ? :dryrun : :noop)
  when :verbose
    @mode = (@mode == :noop ? :dryrun : :verbose)
  when :dryrun
    @mode = :dryrun
  end
end

end

# File lib/ratch/shell.rb, line 87
def quiet?   ; @_quiet ; end
read(path) click to toggle source

Read file.

# File lib/ratch/shell.rb, line 368
def read(path)
  File.read(localize(path))
end
readable?(path) click to toggle source
# File lib/ratch/shell.rb, line 394
def readable?(path)   ; FileTest.readable?(localize(path))  ; end
readable_real?(path) click to toggle source
# File lib/ratch/shell.rb, line 418
def readable_real?(path)   ; FileTest.readable_real?(localize(path))   ; end
relative?(path) click to toggle source
# File lib/ratch/shell.rb, line 413
def relative?(path)   ; FileTest.relative?(path)       ; end
remove(list, options={})
Alias for: rm
rm(list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 543
def rm(list, options={})
  list = localize(list)
  fileutils.rm(list, options)
end
Also aliased as: remove
rm_f(list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 554
def rm_f(list, options={})
  list = localize(list)
  fileutils.rm_f(list, options)
end
rm_r(list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 549
def rm_r(list, options={})
  list = localize(list)
  fileutils.rm_r(list, options)
end
rm_rf(list, options={}) click to toggle source
# File lib/ratch/shell.rb, line 559
def rm_rf(list, options={})
  list = localize(list)
  fileutils.rm_rf(list, options)
end
rmdir(dir, options={}) click to toggle source
# File lib/ratch/shell.rb, line 493
def rmdir(dir, options={})
  dir = localize(dir)
  fileutils.rmdir(dir, options)
end
root(*args) click to toggle source

Root location.

# File lib/ratch/shell.rb, line 138
def root(*args)
  dir('/', *args)
end
safe?(path) click to toggle source
# File lib/ratch/shell.rb, line 411
def safe?(path)       ; FileTest.safe?(localize(path)) ; end
setgid?(path) click to toggle source
# File lib/ratch/shell.rb, line 404
def setgid?(path)     ; FileTest.setgid?(localize(path))    ; end
setuid?(path) click to toggle source
# File lib/ratch/shell.rb, line 405
def setuid?(path)     ; FileTest.setuid?(localize(path))    ; end
sh(cmd) click to toggle source

Shell runner.

# File lib/ratch/shell.rb, line 307
def sh(cmd)
  #puts "--> system call: #{cmd}" if trace?
  puts cmd if trace?
  return true if noop?
  #locally do
    if quiet?
      silently{ system(cmd) }
    else
      system(cmd)
    end
  #end
end
size(path) click to toggle source
# File lib/ratch/shell.rb, line 390
def size(path)        ; FileTest.size(localize(path))       ; end
size?(path) click to toggle source
# File lib/ratch/shell.rb, line 391
def size?(path)       ; FileTest.size?(localize(path))      ; end
socket?(path) click to toggle source
# File lib/ratch/shell.rb, line 406
def socket?(path)     ; FileTest.socket?(localize(path))    ; end
stage(stage_dir, files) click to toggle source

TODO: should this have SOURCE diectory?

stage(directory, source_dir, files)
# File lib/ratch/shell.rb, line 601
def stage(stage_dir, files)
  #dir   = localize(directory)
  #files = localize(files)
  locally do
    fileutils.stage(stage_dir, work, files)
  end
end
sticky?(path) click to toggle source
# File lib/ratch/shell.rb, line 401
def sticky?(path)     ; FileTest.sticky?(localize(path))    ; end
system(cmd) click to toggle source

TODO: Tie this into the System class.

Calls superclass method
# File lib/ratch/shell.rb, line 300
def system(cmd)
  locally do
    super(cmd)
  end
end
to_s() click to toggle source

String representation is work directory path.

# File lib/ratch/shell.rb, line 95
def to_s ; work.to_s ; end
touch(list, options={}) click to toggle source

alias_method :chown_R, :chown_r

# File lib/ratch/shell.rb, line 592
def touch(list, options={})
  list = localize(list)
  fileutils.touch(list, options)
end
trace?() click to toggle source
# File lib/ratch/shell.rb, line 88
def trace?   ; @_trace ; end
uptodate?(path, *sources) click to toggle source
# File lib/ratch/shell.rb, line 647
def uptodate?(path, *sources)
  locally do
    fileutils.uptodate?(path, sources.flatten)
  end
end
work(*args) click to toggle source

Current working path.

# File lib/ratch/shell.rb, line 148
def work(*args)
  return @_work if args.empty?
  return dir(@_work, *args)
end
writable?(path) click to toggle source
# File lib/ratch/shell.rb, line 408
def writable?(path)   ; FileTest.writable?(localize(path))  ; end
writable_real?(path) click to toggle source
# File lib/ratch/shell.rb, line 416
def writable_real?(path)   ; FileTest.writable_real?(localize(path))   ; end
write(path, text) click to toggle source

Write file.

# File lib/ratch/shell.rb, line 373
def write(path, text)
  $stderr.puts "write #{path}" if trace?
  File.open(localize(path), 'w'){ |f| f << text } unless noop?
end
zero?(path) click to toggle source
# File lib/ratch/shell.rb, line 398
def zero?(path)       ; FileTest.zero?(localize(path))      ; end

Private Instance Methods

fileutils() click to toggle source

Returns FileUtils module based on mode.

# File lib/ratch/shell.rb, line 754
def fileutils
  if dryrun?
    ::FileUtils::DryRun
  elsif noop?
    ::FileUtils::Noop
  elsif trace?
    ::FileUtils::Verbose
  else
    ::FileUtils
  end
end
mutex() click to toggle source
# File lib/ratch/shell.rb, line 64
def mutex
  @mutex ||= Mutex.new
end
parse_arguments(*args) click to toggle source
# File lib/ratch/shell.rb, line 50
def parse_arguments(*args)
  opts = (Hash===args.last ? args.pop : {})
  return args, opts
end
set_options(opts) click to toggle source
# File lib/ratch/shell.rb, line 56
def set_options(opts)
  @_quiet = opts[:quiet]
  @_noop  = opts[:noop]  || opts[:dryrun]
  @_trace = opts[:trace] || opts[:dryrun]
  #@_force = opts[:force]
end
util_options(options) click to toggle source

This may be used by script commands to allow for per command noop and trace options. Global options have precedence.

# File lib/ratch/shell.rb, line 768
def util_options(options)
  noop  = noop?  || options[:noop]  || options[:dryrun]
  trace = trace? || options[:trace] || options[:dryrun]
  return noop, trace
end