#!/usr/bin/env ruby

require "open3"
require "nkf"

TargetCode = "UTF-8"
NoCheckCodes = ["BINARY", "ASCII", "US-ASCII"]
PermittedUsers = ["yot"]

# enforced custom commit message code
# reference url:
#   http://git-scm.com/book/ja/v1/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E5%AE%9F%E6%96%BD%E4%BE%8B
#
def check_commit_log_code( oldrev, newrev )
  missed_revs = `git rev-list #{oldrev}..#{newrev}`.split("\n")
  missed_revs.each do |rev|
    message = `git cat-file commit #{rev} | sed '1,/^$/d'`
    o, e, s = NKF.guess( message )
    mojicode = o.to_s
    if checkcode( mojicode, TargetCode ) != 0 then
      puts "[POLICY] Commit message is not written in #{TargetCode}, but in #{mojicode}."
      exit 1
    else
    end
  end
end

def checkcode( mojicode, code )
  istatus = 1
  NoCheckCodes.each do |compcode|
    if mojicode == compcode then
      istatus = 0
    end
  end
  if mojicode == code then
    istatus = 0
  end
  return istatus
end

# enforced custom commit file code
#
def check_pushed_file_code( oldrev, newrev )
  missed_revs = `git rev-list #{oldrev}..#{newrev}`.split("\n")
  missed_revs.each do |rev|
    fns = `git log --name-only --pretty=format:"" #{rev} | grep -v '^\s*$'`.split("\n")
    fns.each do |fn|
      o, e, s = Open3.capture3( "git show #{rev}:#{fn} | nkf -g" )
      mojicode = o.to_s.chomp
      istatus = checkcode( mojicode, TargetCode )
      if istatus != 0 then
        puts "[POLICY] A file, #{fn}, is not written in #{TargetCode}, but in #{mojicode}."
        exit 1
      end

#    system( "git log -p #{rev}" )
#    lines = `git log -p #{rev}`.split("\n")
#    lines = `git log -p #{rev}`
#
#    p lines
#    o, e, s = NKF.guess( lines )
#    mojicode = o.to_s
#    p mojicode
#    if checkcode( message, TargetCode ) != 0 then
#      puts "[POLICY] Your message is not written in #{TargetCode}."
#      exit 1
#    else
#      exit 0

    end
  end
end

# check users who can push to master branch
#
def check_user_pushing_on_master( refname, pushing_user )
  # Check a branch which pushing_user pushes.
  if refname.split("/")[-1] != "master" then
    istatus = 0
  else
    istatus = 1
    PermittedUsers.each do |user|
      if pushing_user == user then
        istatus = 0
      end
    end
  end
  if istatus == 1 then
    puts "[POLICY] User, #{pushing_user}, cannot push on master."
    exit 1
  end
end

refname = ARGV[0]
oldrev  = ARGV[1]
newrev  = ARGV[2]
user    = ENV['USER']

puts "Enforcing Policies... \n(#{refname}) (#{oldrev[0,6]}) (#{newrev[0,6]})"

check_commit_log_code( oldrev, newrev )

check_pushed_file_code( oldrev, newrev )

check_user_pushing_on_master( refname, user )
