def native(cmd, options = {}, *args, &block)
      args     = args.first if args.size == 1 && args[0].is_a?(Array)
      args.map!    { |a| a.to_s }
      args.reject! { |a| a.empty? }

      # special option arguments
      env = options.delete(:env) || {}
      raise_errors = options.delete(:raise)
      process_info = options.delete(:process_info)

      # fall back to using a shell when the last argument looks like it wants to
      # start a pipeline for compatibility with previous versions of grit.
      return run(prefix, cmd, '', options, args) if args[-1].to_s[0] == ?|

      # more options
      input    = options.delete(:input)
      timeout  = options.delete(:timeout); timeout = true if timeout.nil?
      base     = options.delete(:base);    base    = true if base.nil?
      chdir    = options.delete(:chdir)

      # build up the git process argv
      argv = []
      argv << Git.git_binary
      argv << "--git-dir=#{git_dir}" if base
      argv << cmd.to_s.tr('_', '-')
      argv.concat(options_to_argv(options))
      argv.concat(args)

      # run it and deal with fallout
      Grit.log(argv.join(' ')) if Grit.debug

      process =
        Child.new(env, *(argv + [{
          :input   => input,
          :chdir   => chdir,
          :timeout => (Grit::Git.git_timeout if timeout == true),
          :max     => (Grit::Git.git_max_size if timeout == true)
        }]))
      Grit.log(process.out) if Grit.debug
      Grit.log(process.err) if Grit.debug

      status = process.status
      if raise_errors && !status.success?
        raise CommandFailed.new(argv.join(' '), status.exitstatus, process.err)
      elsif process_info
        [status.exitstatus, process.out, process.err]
      else
        process.out
      end
    rescue TimeoutExceeded, MaximumOutputExceeded
      raise GitTimeout, argv.join(' ')
    end
def native(cmd, options = {}, *args, &block)
      args     = args.first if args.size == 1 && args[0].is_a?(Array)
      args.map!    { |a| a.to_s }
      args.reject! { |a| a.empty? }

      # special option arguments
      env = options.delete(:env) || {}
      raise_errors = options.delete(:raise)
      process_info = options.delete(:process_info)

      # fall back to using a shell when the last argument looks like it wants to
      # start a pipeline for compatibility with previous versions of grit.
      return run(prefix, cmd, '', options, args) if args[-1].to_s[0] == ?|

      # more options
      input    = options.delete(:input)
      timeout  = options.delete(:timeout); timeout = true if timeout.nil?
      base     = options.delete(:base);    base    = true if base.nil?
      chdir    = options.delete(:chdir)

      # build up the git process argv
      argv = []
      argv << Git.git_binary
      argv << "--git-dir=#{git_dir}" if base
      argv << cmd.to_s.tr('_', '-')
      argv.concat(options_to_argv(options))
      argv.concat(args)

      # run it and deal with fallout
      Grit.log(argv.join(' ')) if Grit.debug

      process =
        Child.new(env, *(argv + [{
          :input   => input,
          :chdir   => chdir,
          :timeout => (Grit::Git.git_timeout if timeout == true),
          :max     => (Grit::Git.git_max_size if timeout == true)
        }]))
      Grit.log(process.out) if Grit.debug
      Grit.log(process.err) if Grit.debug

      status = process.status
      if raise_errors && !status.success?
        raise CommandFailed.new(argv.join(' '), status.exitstatus, process.err)
      elsif process_info
        [status.exitstatus, process.out, process.err]
      else
        process.out
      end
    rescue TimeoutExceeded, MaximumOutputExceeded
      raise GitTimeout, argv.join(' ')
    end
Execute a git command, bypassing any library implementation.

 cmd - The name of the git command as a Symbol. Underscores are
   converted to dashes as in :rev_parse => 'rev-parse'.
 options - Command line option arguments passed to the git command.
   Single char keys are converted to short options (:a => -a).
   Multi-char keys are converted to long options (:arg => '--arg').
   Underscores in keys are converted to dashes. These special options
   are used to control command execution and are not passed in command
   invocation:
     :timeout - Maximum amount of time the command can run for before
       being aborted. When true, use Grit::Git.git_timeout; when numeric,
       use that number of seconds; when false or 0, disable timeout.
     :base - Set false to avoid passing the --git-dir argument when
       invoking the git command.
     :env - Hash of environment variable key/values that are set on the
       child process.
     :raise - When set true, commands that exit with a non-zero status
       raise a CommandFailed exception. This option is available only on
       platforms that support fork(2).
     :process_info - By default, a single string with output written to
       the process's stdout is returned. Setting this option to true
       results in a [exitstatus, out, err] tuple being returned instead.
 args - Non-option arguments passed on the command line.

 Optionally yields to the block an IO object attached to the child
 process's STDIN.

 Examples
   git.native(:rev_list, {:max_count => 10, :header => true}, "master")

 Returns a String with all output written to the child process's stdout
   when the :process_info option is not set.
 Returns a [exitstatus, out, err] tuple when the :process_info option is
   set. The exitstatus is an small integer that was the process's exit
   status. The out and err elements are the data written to stdout and
   stderr as Strings.
 Raises Grit::Git::GitTimeout when the timeout is exceeded or when more
   than Grit::Git.git_max_size bytes are output.
 Raises Grit::Git::CommandFailed when the :raise option is set true and the
   git command exits with a non-zero exit status. The CommandFailed's #command,
   #exitstatus, and #err attributes can be used to retrieve additional
   detail about the error.