/ #ruby #git 

濁点の合成文字がソースコードに入っちまった💢 -> gitのpre-commit hookで打ち勝った

濁点文字をソースコードに入れてしまって不具合を起こしてしまうということがありました。

なんという不覚。。

githubで見ても手元のvimで見ても見た目上は全く違いがわからんという状態。

いや、見た目でわかると思ったんですけどね

ちょっと以下3つの「バ」を見てください。

濁点アリの1文字「バ」

これが普通のバ。

2文字「ハ」+「゛」

ハ゛

👆くっつきかたが、ちょっと不自然だね!?不自然だね!?

IMEで「てんてん」と打って変換されるやつがこれ。

2文字「ハ」+「゙」

バ

👆くっつきかたが、、、え、、、自然だね!? これ最初のやつと見分けつかんね!?

今回はこいつにやられました。。

そもそも濁点は2種類あった!

「船は「2隻」あったッ!」って感じなんですが(ジョジョ5部アニメ楽しみですね)

濁点は2つあるのか、、

COMBINING のほうは、合成されるやつなんですね。 http://bardiel-of-may.blogspot.com/2013/05/blog-post.html こんな感じで。

どう防ぐか 🤔

見た目上は区別つかないし、vimの設定やるのもダルいので、

gitのpre-commit hookで防ぐことを思いつきました!

もともと私のpre-commit hookは、「AWSのシークレットキーっぽい文字列が入ったらfailすること」を書いていました。

以下のようにシェルスクリプトで書いていました。

#!/bin/sh
GREP_RESULT=`git diff --cached | grep AKIA`
if [[ -n "${GREP_RESULT}" ]]; then
  echo "\033[31m\]AWS_ACCESS_KEY might be in this index. Please check with git diff --cached"
  echo ${GREP_RESULT}
  exit 1
fi

これを、さらに 合成文字の濁点・半濁点が入ったらfailするようにすれば良さそう です。

最終的には、以下のようにしました。

#!/usr/bin/ruby
# frozen_string_literal: true

diff = `git diff --cached`

diff.each_line.grep(/^\+[^\+]/).each do |d|
  if /\bAKIA/ =~ d
    puts 'AWS_ACCESS_KEY might be in this index. Please check with git diff --cached'
    puts d
    exit 1
  end

  # see https://codepoints.net/U+3099
  # see https://codepoints.net/U+309A
  #
  dakuten_handakuten = /[\u{3099}\u{309A}]/

  next unless dakuten_handakuten =~ d
  puts 'dakuten or handakuten might be in this index. Please check with git diff --cached'
  puts d
  exit 1
end

えへへ。rubyで書き直しました。もともとmacでしかgit commitしないし、これで十分っぽい気がします。

✎まとめ

合成文字の濁点問題に対し、gitのpre-commit hookを使うことにより、現実的でラクな対応をしました。

Author

hoshinotsuyoshi

星野剛志(ほしのつよし) web application engineer. ruby/rails/docker