# == ShellManager
#
# The ShellManager provides Unix-like shell commands for manipulating files and
# executing commands.
#
# *WARNING*: Previewing code can be dangerous. Read
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
# write code that can be safely previewed.
class AutomateIt::ShellManager < AutomateIt::Plugin::Manager
alias_methods :sh, :which, :which!, :mktemp, :mktempdir, :mktempdircd, :chperm, :umask
alias_methods :cd, :pwd, :mkdir, :mkdir_p, :rmdir, :ln, :ln_s, :ln_sf, :cp, :cp_r, :cp_R, :mv, :rm, :rm_r, :rm_rf, :install, :chmod, :chmod_R, :chown, :chown_R, :touch
#...[ Detection commands ]..............................................
# See ShellManager#provides_mode?
def provides_mode?() dispatch_safely end
# See ShellManager#provides_mode?
def provides_ownership?() dispatch_safely end
# See ShellManager#provides_mode?
def provides_symlink?() dispatch_safely end
# See ShellManager#provides_mode?
def provides_link?() dispatch_safely end
#...[ Custom commands ].................................................
# Execute a shell command.
def sh(*commands) dispatch(*commands) end
# What is the path for this command? Returns +nil+ if command isn't found.
#
# Example:
# which("ls") # => "/bin/ls"
def which(command) dispatch(command) end
# Same as #which but throws an ArgumentError if command isn't found.
def which!(command) dispatch(command) end
# Creates a temporary file. Optionally takes a +name+ argument which is
# purely cosmetic, e.g., if the +name+ is "foo", the routine may create a
# temporary file named /tmp/foo_qeKo7nJk1s.
#
# When called with a block, invokes the block with the path of the temporary
# file and deletes the file at the end of the block.
#
# Without a block, returns the path of the temporary file and you're
# responsible for removing it when done.
def mktemp(name=nil, &block) # :yields: path
dispatch(name, &block)
end
# Creates a temporary directory. See #mktemp for details on the +name+
# argument.
#
# When called with a block, invokes the block with the path of the
# temporary directory and recursively deletes the directory and its
# contents at the end of the block.
#
# Without a block, returns the path of the temporary directory and you're
# responsible for removing it when done.
#
# CAUTION: Read notes at the top of ShellManager for potentially
# problematic situations that may be encountered if using this command in
# preview mode!
def mktempdir(name=nil, &block) # :yields: path
dispatch(name, &block)
end
# Same as #mktempdir but performs a #cd into the directory for the duration
# of the block.
#
# Example:
#
# puts pwd # => "/home/bubba"
# mktempdircd do |path|
# puts path # => "/tmp/tempster_qeKo7nJk1s"
# puts pwd # => "/tmp/tempster_qeKo7nJk1s"
# end
# puts File.exists?("/tmp/tempster_qeKo7nJk1s") # => false
def mktempdircd(name=nil, &block) # :yields: path
dispatch(name, &block)
end
# Change the permissions of the +targets+. This command is like the #chmod
# and #chown in a single command.
#
# Options:
# * :recursive -- Change files and directories recursively. Defaults to false.
# * :user -- User name to change ownership to.
# * :group -- Group name to change ownership to.
# * :mode -- Mode to use as octal, e.g., 0400 to make a file
# readable only to its owner.
# * :details -- Reports the files modified, rather than the arguments
# modified. An argument might be a single directory, but this may result in
# modifications to many files within that directory. Use :details for
# situations when there's a need to see all files actually changed. The
# reason :details is off by default is that it will flood the screen with a
# list of all files modified in a large directory, which is overwhelming
# and probably unnecessary unless you actually need to see these details.
# Defaults to false.
def chperm(targets, opts={}) dispatch(targets, opts) end
# Set the umask to +mode+. If given a block, changes the umask only for the
# duration of the block and changes it back to its previous setting at the
# end.
def umask(mode=nil, &block) dispatch(mode, &block) end
#...[ FileUtils wrappers ]...............................................
# Changes the directory into the specified +dir+. If called with a block,
# changes to the directory for the duration of the block, and then changes
# back to the previous directory at the end.
#
# *WARNING*: Previewing code can be dangerous. Read
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
# write code that can be safely previewed.
def cd(dir, opts={}, &block) dispatch(dir, opts, &block) end
# Returns the current directory.
def pwd() dispatch() end
# Create a directory or directories. Returns an array of directories
# created or +false+ if all directories are already present.
#
# Options:
# * :parents -- Create parents, like "mkdir -p". Boolean.
# * :mode, :user, :group -- See #chperm
#
# *WARNING*: Previewing code can be dangerous. Read
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
# write code that can be safely previewed.
def mkdir(dirs, opts={}, &block) dispatch(dirs, &block) end
# Create a directory or directories with their parents. Returns an array of
# directories created or +false+ if all directories are already present.
#
# Options same as #mkdir.
#
# Example:
# File.exists?("/tmp/foo") # => false
# mkdir_p("/tmp/foo/bar")
# File.exists?("/tmp/foo") # => true
# File.exists?("/tmp/foo/bar") # => true
#
# *WARNING*: Previewing code can be dangerous. Read
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
# write code that can be safely previewed.
def mkdir_p(dirs, opts={}, &block) dispatch(dirs, &block) end
# Remove a directory or directories. The directories must be empty or an
# exception is thrown. Returns the directories removed or +false+ if none
# of the directories exist.
def rmdir(dirs) dispatch(dirs) end
# Create a hard link between the +source+ and +target+. Your platform must
# support hard links to use this. Returns the target created or +false+ if
# the link is already present.
def ln(source, target, opts={}) dispatch(source, target, opts) end
# Create a symbolic link between the +sources+ and +target+. Your platform
# must support symbolic links to use this. Returns an array of sources
# linked or +false+ if all are already present.
def ln_s(sources, target, opts={}) dispatch(sources, target, opts) end
# Create a symbolic link between the +sources+ and +target+. If the
# +target+ already exists, will remove it and recreate it. Your platform
# must support symbolic links to use this. Returns an array of sources
# linked or +false+ if all are already present.
def ln_sf(sources, target, opts={}) dispatch(sources, target, opts) end
# Copy the +sources+ to the +target+. Returns an array of sources copied or
# +false+ if all are present.
#
# Options:
# * :preserve -- preserve file modification time and ownership, boolean.
# * :recursive -- copy files and directories recursively, boolean.
def cp(sources, target, opts={}) dispatch(sources, target, opts) end
# Copy the +sources+ to the +target+ recursively. Returns an array of
# sources copied or +false+ if all are present.
def cp_r(sources, target, opts={}) dispatch(sources, target, opts) end
# Copy the +sources+ to the +target+ recursively. Returns an array of
# sources copied or +false+ if all are present.
def cp_R(sources, target, opts={}) dispatch(sources, target, opts) end
# Move the +sources+ to the +target+. Returns an array of sources copied or
# +false+ if none of the sources exist.
def mv(sources, target) dispatch(sources, target) end
# Remove the +targets+. Returns a list of targets removed or +false+ if
# none of them exist.
def rm(targets, opts={}) dispatch(targets, opts) end
# Remove the +targets+ recursively. Returns a list of targets removed or
# +false+ if none of them exist.
def rm_r(targets, opts={}) dispatch(targets, opts) end
# Remove the +targets+ recursively and forcefully. Returns a list of
# targets removed or +false+ if none of them exist.
def rm_rf(targets, opts={}) dispatch(targets, opts) end
# Copy the +source+ to the +target+ and set its +mode+. Returns true if the
# file was installed or +false+ if already present.
def install(source, target, mode) dispatch(source, target, mode) end
# Change the permission +mode+ of the +targets+. Returns an array of
# targets modified or +false+ if all have the desired mode.
def chmod(mode, targets, opts={}) dispatch(mode, targets, opts) end
# Change the permission +mode+ of the +targets+ recursively. Returns an
# array of targets modified or +false+ if all have the desired mode.
def chmod_R(mode, targets, opts={}) dispatch(mode, targets, opts) end
# Change the +user+ and +group+ ownership of the +targets+. You can leave
# either the user or group as nil if you don't want to change it. Returns
# an array of targets modified or +false+ if all have the desired
# ownership.
def chown(user, group, targets, opts={}) dispatch(user, group, targets, opts) end
# Change the +user+ and +group+ ownership of the +targets+ recursively. You
# can leave either the user or group as nil if you don't want to change it.
# Returns an array of targets modified or +false+ if all have the desired
# ownership.
def chown_R(user, group, targets, opts={}) dispatch(user, group, targets, opts) end
# Create the +targets+ as files if needed and update their modification
# time. Unlike most other commands provided by ShellManager, this one will
# always modify the targets. Returns an array of targets modified.
def touch(targets) dispatch(targets) end
end
# == ShellManager::BaseDriver
#
# Base class for all ShellManager drivers.
class AutomateIt::ShellManager::BaseDriver < AutomateIt::Plugin::Driver
def _replace_owner_with_user(opts)
value = opts.delete(:owner)
opts[:user] = value if value and not opts[:user]
return opts
end
protected :_replace_owner_with_user
# Returns hash of verbosity and preview settings for FileUtils commands.
def _fileutils_opts
opts = {}
opts[:verbose] = false # Generate our own log messages
opts[:noop] = true if preview?
return opts
end
private :_fileutils_opts
end
# Drivers
require 'automateit/shell_manager/portable'
require 'automateit/shell_manager/which'
require 'automateit/shell_manager/base_link'
require 'automateit/shell_manager/symlink'
require 'automateit/shell_manager/link'