Class: CSD::Commands
Overview
This class contains wrapper methods for standard file system operations. They are meant to be a little bit more robust (e.g. raising no exceptions) and return elaborate feedback on their operation. All of these methods, except for the run method, are platform independent.
Defined Under Namespace
Classes: Replacer
Instance Method Summary collapse
-
#cd(target, params = {}) ⇒ Object
Changes the current directory.
-
#copy(src, dest, params = {}) ⇒ Object
Copies one or several files to the destination.
-
#download(url, destination) ⇒ Object
This downloads a file.
-
#git_clone(name, repository, destination) ⇒ Object
Clones the master branch of a repository using
git. -
#mkdir(target, params = {}) ⇒ Object
Creates a directory recursively.
-
#move(src, dest, params = {}) ⇒ Object
Moves one or several files to the destination.
-
#pwd ⇒ Object
This returns the current pwd.
-
#replace(filepath, pattern = '', substitution = '', params = {}, &block) ⇒ Object
Replaces all occurences of a pattern in a file.
-
#run(cmd, params = {}) ⇒ Object
Runs a command on the system.
-
#touch_and_replace_content(target, content = '', params = {}) ⇒ Object
Creates a new file and writes content to it.
Instance Method Details
#cd(target, params = {}) ⇒ Object
Changes the current directory.
Returns
This method returns a CommandResult object with the following values:
success?-
trueif pwd is where it was requested to be after the operation,nilif not.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/csd/commands.rb', line 68 def cd(target, params={}) default_params = { :die_on_failure => true, :internal => false } params = default_params.merge(params) target = target.pathnamify result = CommandResult.new UI.info "cd #{target}".yellow unless params[:internal] if Options.reveal # We need to fake changing the directory in reveal mode. @pwd = target.to_s result.success = true else begin Dir.chdir(target) result.success = target.current_path? rescue Exception => e result.reason = "Cannot change to directory `#{target}´. Reason: #{e.}" params[:die_on_failure] ? raise(CSD::Error::Command::CdFailed, result.reason) : UI.error(result.reason) end end result end |
#copy(src, dest, params = {}) ⇒ Object
Copies one or several files to the destination
117 118 119 |
# File 'lib/csd/commands.rb', line 117 def copy(src, dest, params={}) transfer(:copy, src, dest, params) end |
#download(url, destination) ⇒ Object
This downloads a file. It could be replaced by Ruby internals in the future to make it work in Windows. The CommandResult of Cmd.run is returned, so result.success? will indicate whether the download was successful or not.
302 303 304 305 306 307 308 309 310 |
# File 'lib/csd/commands.rb', line 302 def download(url, destination) if Cmd.run('curl -h', :internal => true, :die_on_failure => false).success? # Darwin Cmd.run "curl #{url} --location -o #{destination}", :die_on_failure => false, :announce_pwd => false elsif Cmd.run('wget -h', :internal => true, :die_on_failure => false).success? # Linux Cmd.run "wget #{url} -O #{destination}", :die_on_failure => false, :announce_pwd => false end end |
#git_clone(name, repository, destination) ⇒ Object
Clones the master branch of a repository using git. name is a String used for UI outputs, repository is the URL/path to the repository, destination is an absolute or relative path to where the repository should be downloaded to.
This command will not do anything if the destination already exists.
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/csd/commands.rb', line 264 def git_clone(name, repository, destination) result = CommandResult.new destination = destination.pathnamify if destination.directory? and !Options.reveal UI.warn "Skipping #{name} download, because the directory already exists: #{destination.enquote}" result.already_exists = true return result end unless destination.parent.writable? or Options.reveal UI.error "Could not download #{name} (no permission): #{destination.enquote}" result. = true return result end UI.info "Downloading #{name} to #{destination.enquote}".green.bold if Options.github_tar and repository =~ /github.com/ Cmd.mkdir destination Cmd.cd destination repository = repository.gsub('.git', '/tarball/master') Cmd.run "wget #{repository}", :announce_pwd => false if tar_file = Dir[File.join(destination, '*.tar*')].first or Options.reveal Cmd.run "tar -xzf #{tar_file || '[NAME OF THE TARFILE]'}" Cmd.run "rm #{tar_file || '[NAME OF THE TARFILE]'}" end if extracted_directory = Dir[File.join(destination, '*')].first or Options.reveal content = Options.reveal ? File.join('[EXTRACTED DIRECTORY]', '*') : File.join(extracted_directory, '*') Cmd.run "mv #{content} #{destination}", :announce_pwd => false Cmd.run "rm -r #{extracted_directory || '[EXTRACTED DIRECTORY]'}" end else # We will simply return the CommandResult of the run-method. Cmd.run("git clone #{repository} #{destination}", :announce_pwd => false) end end |
#mkdir(target, params = {}) ⇒ Object
Creates a directory recursively.
Returns
This method returns a CommandResult object with the following values:
success?-
trueif the directory exists after the operation,nilif not. already_existed?-
trueif the directory existed before the operation,nilif not. writable?-
trueif the directory is writable,falseif not,nilif the directory doesn’t exist.
Examples
result = mkdir('foo') # => #<CommandResult...>
result.success? # => true
result.already_existed? # => false
puts "I created a directory" if mkdir('bar').success?
mkdir('i/can/create/directories/recursively')
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/csd/commands.rb', line 37 def mkdir(target, params={}) default_params = { :die_on_failure => true, :internal => false } params = default_params.merge(params) target = target.pathnamify result = CommandResult.new if target.directory? # Don't do anything if the directory already exists result.already_existed = true else begin UI.info "Creating directory: #{target}".cyan unless params[:internal] # Try to create the directory target.mkpath unless Options.reveal rescue Errno::EACCES => e result.reason = "Cannot create directory (no permission): #{target}" params[:die_on_failure] ? raise(CSD::Error::Command::MkdirFailed, result.reason) : UI.error(result.reason) end end result.success = (target.directory? or Options.reveal) result.writable = (target.writable? or Options.reveal) result end |
#move(src, dest, params = {}) ⇒ Object
Moves one or several files to the destination
123 124 125 |
# File 'lib/csd/commands.rb', line 123 def move(src, dest, params={}) transfer(:move, src, dest, params) end |
#pwd ⇒ Object
This returns the current pwd. However, it will return a fake result if we are in reveal-commands-mode.
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/csd/commands.rb', line 129 def pwd begin if Options.reveal @pwd ||= Dir.pwd else Dir.pwd end rescue Errno::ENOENT => e UI.debug "The current pwd could not be located. Was the directory removed?" nil end end |
#replace(filepath, pattern = '', substitution = '', params = {}, &block) ⇒ Object
Replaces all occurences of a pattern in a file. In a block, it yields the Replacer class. Otherwise it calls the replace function in the Replacer class.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/csd/commands.rb', line 146 def replace(filepath, pattern='', substitution='', params={}, &block) # In case of a block, the second argument might be the params params = pattern if pattern.is_a?(Hash) # Setting default parameters default_params = { :die_on_failure => true } params = default_params.merge(params) UI.info "Modifying contents of `#{filepath}´ as follows:".cyan Replacer.filepath = filepath if block_given? yield Replacer else Replacer.replace(pattern, substitution, params) end end |
#run(cmd, params = {}) ⇒ Object
Runs a command on the system.
Options
The following options can be passed as a hash.
:die_on_failure-
If the status code of the command was not 0, raise an Command::RunFailed exception (default:
true). :announce_pwd-
Before running the command, announce in which path the command will be executed (default:
true). :verbose-
Instead of printing just one ‘.´ per command output line, print the full command output lines (default:
false). :internal-
If this parameter is
true, there will be no output what-so-ever for running this command. (default:false). :force_in_reveal-
If this parameter is
true, the command will be executed, even in--revealmode (default:false).
Returns
This method returns a CommandResult object with the following values:
output-
The command’s output as a
String(with newline delimiters). Note that the status code can be accessed via the global variable$?. status?-
Contains
$?and all the methods Ruby provides for it. success?-
trueif the command was successful,nilif not (internally$?.success?is called).
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/csd/commands.rb', line 226 def run(cmd, params={}) default_params = { :die_on_failure => true, :announce_pwd => true, :verbose => Options.verbose, :internal => false, :force_in_reveal => false } params = default_params.merge(params) result = CommandResult.new cmd = cmd.to_s UI.info "Running command in #{pwd}".yellow if params[:announce_pwd] and !params[:internal] UI.info cmd.cyan unless params[:internal] if Options.reveal and !params[:force_in_reveal] result.success = true return result end result.output = '' STDOUT.sync = true # Because we redirect stderr into stdout to get the output and it needs to be flushing automatically IO.popen("#{cmd} 2>&1") do |pipe| # IO redirection is performed using operators pipe.sync = true while line = pipe.gets unless params[:internal] # No output needed for the unit-tests and AI-internal use params[:verbose] ? UI.info(" #{line}") : UI.indicate_activity end result.output << line end end UI.separator unless params[:verbose] or params[:internal] # i.e. if dots are concatenated in the same line, we should create a new line after them result.status = $? result.success = $?.success? if params[:die_on_failure] and !result.success UI.info result.output unless params[:verbose] # In verbose mode, we don't need to repeat the unsuccessful command's output raise CSD::Error::Command::RunFailed, "The last command was unsuccessful." end result end |
#touch_and_replace_content(target, content = '', params = {}) ⇒ Object
Creates a new file and writes content to it. Truncates the file if it already had content.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/csd/commands.rb', line 92 def touch_and_replace_content(target, content='', params={}) default_params = { :die_on_failure => true, :internal => false } params = default_params.merge(params) target = target.pathnamify result = CommandResult.new unless params[:internal] UI.info "Writing content into file #{target} as follows:".cyan UI.info "#{content}" end if Options.reveal result.success = true else begin File.open(target, 'w') { |f| f << content } result.success = target.file? # TODO: Maybe check for the actual content of the created file here rescue Exception => e result.reason = "Cannot write to file `#{target}´. Reason: #{e.}" params[:die_on_failure] ? raise(CSD::Error::Command::TouchAndReplaceContentFailed, result.reason) : UI.error(result.reason) end end result end |