Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@t-kunou

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

More than 1 year has passed since last update.

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ツールを使うべきでしょうが、簡単なチェックくらいは手慣れた言語で簡単に作成できます。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
esm
ソフトウェアで未来をつくる、人のチカラで未来をつくる。福井、東京、沖縄で活動するエンジニア集団。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?