Skip to content

Instantly share code, notes, and snippets.

@yoshitsugu
Created January 7, 2014 01:42
Show Gist options
  • Save yoshitsugu/8293376 to your computer and use it in GitHub Desktop.
Save yoshitsugu/8293376 to your computer and use it in GitHub Desktop.
grit git native

grit/lib/grit/git.rb

source

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

知見

  • cmdでgitコマンド、optionsでoptionを渡す
  • optionはシンボルをキーとしたハッシュ形式
    • 一文字でもそれ以上でもいける。(:a -> -a , :arg -> –arg)
  • エラーは2種類
    • Grit::Git::GitTimeout タイムアウト時
    • Grit::Git::CommandFailed 返り値が0じゃなかったとき
  • 子プロセスとしてgitコマンドをたたく
    • chdirとかも設定できる

ここがよい

  • コメントがしっかりかかれている。
  • オプション指定の柔軟さ
  • 三項演算子つかわないかきかた
    # 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)
        
    • vs
    # more options
    input    = options.delete(:input)
    timeout  = timeout.nil? ? timeout = true : options.delete(:timeout)
    base     = base.nil? ? base = true : options.delete(:base)
    chdir    = options.delete(:chdir)
        

ここがだめ

  • process_infoを指定しないと標準エラー出力がみれない?
    • コマンドがエラーはいたときはCommandFailed例外で内容を表示しているっぽいからへいき
  • 本当に網羅できているのかは自分のgitの知識じゃピントこない
  • メソッドが長いきがするが、これはこんなもん?
    • どうしても汚くなるからきれいなほうかも
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment