require 'rprogram/rprogram' require 'rprogram/system' require 'rprogram/task' require 'rprogram/sudo_task' require 'rprogram/exceptions/program_not_found' module RProgram class Program # Path to the program attr_reader :path # Name of the program attr_reader :name # # Creates a new Program object. # # @param [String] path # The full-path of the program. # # @yield [prog] # If a block is given, it will be passed the newly created Program # object. # # @yieldparam [Program] prog # The newly created program object. # # @raise [ProgramNotFound] # Specifies the given path was not a valid file. # # @example # Program.new('/usr/bin/ls') # def initialize(path,&block) path = File.expand_path(path) unless File.file?(path) raise(ProgramNotFound,"program #{path.dump} does not exist",caller) end @path = path @name = File.basename(path) block.call(self) if block end # # @return [String] # The name of the program. # def self.program_name @program_name ||= nil end # # @return [Array] # The program's aliases. # def self.program_aliases @program_aliases ||= [] end # # Combines program_name with program_aliases. # # @return [Array] # Names the program is known by. # def self.program_names ([program_name] + program_aliases).compact end # # Sets the program name for the class. # # @param [String, Symbol] name # The new program name. # # @example # name_program 'ls' # def self.name_program(name) @program_name = name.to_s end # # Sets the program aliases for the class. # # @param [Array] aliases # The new program aliases. # # @example # alias_program 'vim', 'vi' # def self.alias_program(*aliases) @program_aliases = aliases.map { |name| name.to_s } end # # The default path of the program. # # @return [String, nil] # The path to the program. # # @since 0.2.0 # def self.path @program_path end # # Sets the default path to the program. # # @param [String] new_path # The new path to the program. # # @return [String, nil] # The path to the program. # # @since 0.2.0 # def self.path=(new_path) @program_path = if new_path File.expand_path(new_path) end end # # Creates a new program object. # # @param [String] path # The full-path of the program. # # @param [Array] arguments # Additional arguments to initialize the program with. # # @yield [prog] # If a block is given, it will be passed the newly created Program # object. # # @yieldparam [Program] prog # The newly created program object. # # @return [Program, nil] # Returns the newly created Program object. If the given path was # not a valid file, `nil` will be returned. # # @example # Program.find_with_path('/bin/cd') # # => Program # # @example # Program.find_with_path('/obviously/fake') # # => nil # def self.find_with_path(path,*arguments,&block) self.new(path,*arguments,&block) if File.file?(path) end # # Creates a new program object with the specified _paths_, # if a path within _paths_ is a valid file. Any given _arguments_ or # a given _block_ will be used in creating the new program. # # @param [Array] paths # The Array of paths to search for the program. # # @param [Array] arguments # Additional arguments to initialize the program with. # # @yield [prog] # If a block is given, it will be passed the newly created Program # object. # # @yieldparam [Program] prog # The newly created program object. # # @return [Program, nil] # Returns the newly created Program object. If none of the given # paths were valid files, `nil` will be returned. # # @example # Program.find_with_paths(['/bin/cd','/usr/bin/cd']) # # => Program # # @example # Program.find_with_paths(['/obviously/fake','/bla']) # # => nil # def self.find_with_paths(paths,*arguments,&block) paths.each do |path| if File.file?(path) return self.new(path,*arguments,&block) end end end # # Finds and creates the program using it's `program_names`. # # @param [Array] arguments # Additional arguments to initialize the program object with. # # @yield [prog] # If a block is given, it will be passed the newly created Program # object. # # @yieldparam [Program] prog # The newly created program object. # # @return [Program] # The newly created program object. # # @raise [ProgramNotFound] # Non of the `program_names` represented valid programs on the system. # # @example # Program.find # # => Program # # @example # MyProgram.find('stuff','here') do |prog| # # ... # end # def self.find(*arguments,&block) path = self.path path ||= System.find_program_by_names(*self.program_names) unless path names = self.program_names.map { |name| name.dump }.join(', ') raise(ProgramNotFound,"programs #{names} were not found",caller) end return self.new(path,*arguments,&block) end # # @return [String] # The program name of the class. # def program_name self.class.program_name end # # @return [Array] # The program aliases of the class. # def program_aliases self.class.program_aliases end # # @return [Array] # The program names of the class. # def program_names self.class.program_names end # # Runs the program. # # @overload run(*arguments) # Run the program with the given arguments. # # @param [Array] arguments # Additional arguments to run the program with. # # @overload run(*arguments,options) # Run the program with the given arguments and options. # # @param [Array] arguments # Additional arguments to run the program with. # # @param [Hash] options # Additional options to execute the program with. # # @option options [Hash{String => String}] :env # Environment variables to execute the program with. # # @option options [String] :popen # Specifies to run the program using `IO.popen` with the given # IO mode. # # @return [true, false] # Specifies the exit status of the program. # # @example # echo = Program.find_by_name('echo') # echo.run('hello') # # hello # # => true # # @see http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method # For acceptable options. # def run(*arguments) System.run(@path,*arguments) end # # Runs the program under sudo. # # @overload sudo(*arguments) # Run the program under `sudo` with the given arguments. # # @param [Array] arguments # Additional arguments to run the program with. # # @overload sudo(*arguments,options) # Run the program under `sudo` with the given arguments # and options. # # @param [Array] arguments # Additional arguments to run the program with. # # @param [Hash] options # Additional options to execute the program with. # # @option options [Hash{Symbol => Object}] :sudo # Additional `sudo` options. # # @return [Boolean] # Specifies whether the program exited successfully. # # @raise [ProgramNotFound] # Indicates that the `sudo` program could not be located. # # @since 0.1.8 # # @see http://rubydoc.info/stdlib/core/1.9.2/Kernel#spawn-instance_method # For acceptable options. # # @see SudoTask # For valid `:sudo` options. # def sudo(*arguments) options = if arguments.last.kind_of?(Hash) arguments.pop else {} end task = SudoTask.new(options.delete(:sudo) || {}) task.command = [@path] + arguments arguments = task.arguments arguments << options unless options.empty? return System.sudo(*arguments) end # # Runs the program with the arguments from the given task. # # @param [Task, #to_a] task # The task who's arguments will be used to run the program. # # @param [Hash] options # Additional options to execute the program with. # # @return [true, false] # Specifies the exit status of the program. # # @see #run # def run_task(task,options={}) arguments = task.arguments arguments << options unless options.empty? return run(*arguments) end # # Runs the program under `sudo` with the arguments from the given task. # # @param [Task, #to_a] task # The task who's arguments will be used to run the program. # # @param [Hash] options # Spawn options for the program to be ran. # # @yield [sudo] # If a block is given, it will be passed the sudo task. # # @yieldparam [SudoTask] sudo # The sudo tasks. # # @return [true, false] # Specifies the exit status of the program. # # @see #sudo # # @since 0.3.0 # def sudo_task(task,options={},&block) arguments = task.arguments arguments << options unless options.empty? return sudo(*arguments,&block) end # # Converts the program to a String. # # @return [String] # The path of the program. # # @example # Program.find_by_name('echo').to_s # # => "/usr/bin/echo" # def to_s @path.to_s end end end