1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyでうっかり行末に;をつけたままgit commitしたくない

Posted at

Rubyを書いているのに行末にセミコロンを打ってしまうことが時々あります。
JavaScriptとかJavaとかC言語とか、セミコロンを書かないといけない(or 書いたほうが良い)言語を書いたあとにRubyに戻ってくると特に顕著に発生します。

そういうことがあるたびに、「あ、Rubyってセミコロン要らないんだ」 と初学者の頃の新鮮な気持ちに立ち帰る事が出来るわけですが、うっかり気づかすにリポジトリにpushしてしまいレビューアーに「; m9(^Д^)」というコメントを付けられるのは業腹です。(実際は優しく指摘されます)

そこで、Gitフックを使ってRubyコードの行末に ; があったらcommitできなくしてみました。

前提

  • 毎回RuboCopを回したいわけではない。
  • addしたファイルの変更行だけをチェックしたい。

やってみた

リポジトリの .git/hooks/pre-commit に以下を書きます。忘れずに実行権限もつけておきましょう。

#!/usr/bin/env ruby

def check_ruby_file(adds)
  adds.select {|add|
    /;\z/.match? add
  }.instance_eval {
    any? ? "Find ';' in Ruby file's line end." : 'ok'
  }
end

def check_adds(filename, adds)
  results = []

  results << check_ruby_file(adds) if /\.rb\z/.match? filename

  results.all? {|result| result == 'ok' } ? 'ok' : results.join("\n")
end

changed_files = `git diff --cached --name-only HEAD`
exit_code = changed_files.split(/\R/).map {|filename|
    [filename, `git diff --cached -U0 HEAD -- "#{filename}"`]
  }.map {|(filename, diffs)|
    [
      filename,
      diffs.split(/\R/).select {|diff| /\A\+[^\+]/.match?(diff) }
    ]
  }.reject {|(_, adds)|
    adds.empty?
  }.map {|(filename, adds)|
    [filename, adds, check_adds(filename, adds)]
  }.reject {|(_, _, result)|
    result == 'ok'
  }.tap {|elements|
    puts 'Invalid adds detected.'
    elements.each do |(filename, adds, result)|
      puts filename
      puts "  \e[31m#{adds.join("\n  ")}\e[0m"
      puts "    #{result}"
    end
  }.any? ? 1 : 0

exit exit_code
スクリーンショット 2018-05-24 14.09.31.png

なかなか雑なコードですが、これでも実用上困らない程度には動いています。
行末セミコロン以外もチェックしたければcheck_ruby_fileメソッドを変更、.rbファイル以外も見たければcheck_addsメソッドを変更すれば拡張できます。

正規表現で引っ掛けているだけなので、コメント行の末尾にセミコロンがあったり、ヒアドキュメントの中にJavaScriptのコードがあったりすると誤検出します。が、うっかりcommit -> pushしてしまうのを事前に防ぎたいだけですので、内容を見て問題なければ --no-verify オプションをつけてcommitしてしまっています。

まとめ

今回はGitフックを書いてみる練習を兼ねて作成してみました。
複雑なチェックをしたければRuboCopなどLintツールを使うべきでしょうが、簡単なチェックくらいは手慣れた言語で簡単に作成できます。

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?