2012年10月31日水曜日

[git] コミットした時、コミットメッセージにブランチ名つけた方がいいんじゃない?

背景


コミットメッセージにブランチ名をつけてくれるといいかなって思った。

prepare-commit-msg


コミットを実行するとき、呼ばれるhook スクリプト。
引数として、「コミットログメッセージを保存したファイル名」、「ログメッセージの出処」、
「コミットログメッセージを再利用している元のコミットオブジェクト名」の3つが渡される。


ログメッセージの出処には、5つの種類がある。

1,message
git commit コマンドに -m や -Fオプションでメッセージを与えた場合

2,template
git commit コマンドに -t でメッセージを与えた場合

3,merge
git merge コマンドでメッセージを与えた場合

4,squash
git merge --squash コマンドでメッセージを与えた場合

5,commit
git commit コマンドに -c や -Cオプションでメッセージを与えた場合

また、このフックがゼロ以外で終了すると、コミットを作らず終了してしまう。

なんかようわからんから、とりあえず、messageの時だけ、頭にブランチ名付けることにした



ソース


以下を、.git/hooks/したに、prepare-commit-msgという名前で保存しておくと、
コミットメッセージの頭に現在のブランチ名をつけてくれる。

#!/usr/bin/python
# coding: utf-8

import sys
import subprocess

def get_now_branch():

    # コマンドを実行
    proc = subprocess.Popen(['git', 'symbolic-ref', 'HEAD'],
                            #shell=True,
                            #cwd='/',
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            close_fds=True)

    # 結果を読む
    line = proc.stdout.readline()
    gitlist = line.rstrip("\n").split('/')
    branch  = gitlist[len(gitlist)-1]

    return branch


def get_commit_msg(file):
    for line in open(file, 'r'):
        return line.rstrip('\n')

def set_commit_msg(file, msg):
    f = open(file, 'w')
    f.write(msg)
    f.close()
    return

def main():


    # 引数取得
    argvs = sys.argv  # コマンドライン引数を格納したリストの取得

    # branch取得
    branch = get_now_branch()
    if branch.find('fatal')>=0:
        return

    # edit fileのパスを取得
    git_commit_editmsg=argvs[1]

    # commit msgにブランチを設定
    if len(argvs) >=3:
        if argvs[2] == 'message':

            # commit msgにブランチを設定
            cm = get_commit_msg(git_commit_editmsg)
            commit_msg =  "["+branch+"] " + cm

            # commmit messageを保存
            set_commit_msg(git_commit_editmsg, commit_msg)

if __name__ == '__main__':
    main()

2012年10月29日月曜日

[git] とりあえず、pre-commit hookは必要でしょ

背景


コミットする時、PHP errorチェックをするいつものやつ。

pre-commit フック


git commitでコミットする時に実行サれるフック。
このスクリプトが0以外で終了すると、コミットが止められる。
引数は特にない・・・?

ソース


こんな感じ。
gitの場合、パスが通っているところにgit-*って名前で保存されて、
実行権限があればgitのhookスクリプトとして認識してくれるみたいなので言語はなんでもいい。

これは、pythonで書いてみた。

地味に長くなったな・・・。


これを、.git/hooks/下に、pre-commitという名前で保存しておけば、
コミットする時エラーチェックをやってくれる。

#!/usr/bin/python
# coding: utf-8

import sys
import os
import subprocess

def get_index_files():

    # コマンドを実行
    proc = subprocess.Popen(['git', 'status', '--porcelain'],
                            #shell=True,
                            #cwd='/',
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            close_fds=True)

    # 結果を読む
    files = []
    while True:
        line = proc.stdout.readline()
        if not line:
            break

        # status, fileを分割
        status, file_path =line[:2], line[3:].rstrip('\n')
        if status[:1]=='A' or status[:1]=='M':
            root, ext = os.path.splitext(file_path)

            # not php file
            if ext == ".php":
                files.append( file_path )
                continue

    return files

def chk_php_error(file):

    # php -l
    proc = subprocess.Popen(['php', '-l', file],
                            #shell=True,
                            #cwd='/',
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            close_fds=True)

    # 結果を読む
    line = proc.stdout.readline()
    if line.find('No syntax errors') >= 0:
        return ""

    return  line.rstrip('\n')


def main():

    result=0

    # ファイルを取得
    files = get_index_files()

    # php -l 実行
    for f in files:
        error_str = chk_php_error(f)
        if error_str != "":
            print error_str
            result = 1

    # exit
    if result == 1:
        print '!!! git commit Failed !!!'

    sys.exit(result)


if __name__ == '__main__':
    main()





2012年10月28日日曜日

[vim] 末尾の空白を除去する

背景


virtualeditを設定しておくと、文字がないところにもカーソルが移動できるようになる。
好みの問題だけど、僕は移動できたほうが好き。
でもこれをやると、行末に空白がついたコードが増えちゃうとの指摘を受けたので、
保存する時、保存するとき空白を除去する設定をした。
ついでにtabも変えるようにした。


ソース


こんな感じ
最初は、 '%s/ \+$//e' だけだったけど、
それだと、保存するたびにカーソル移動してうざかったので、
カーソル保存して、最後に元の位置に移動してる
なんかあれな感じだけど
autocmd BufWritePost *.vim call DeleteLastSpace()                                                                     
autocmd BufWritePost *.php call DeleteLastSpace()                                                                     
autocmd BufWritePost *.py call DeleteLastSpace()                                                                                                                                   
                                                                                                                      
function! DeleteLastSpace()
    let save_cursor = getpos('.')                                                                                     
    silent exec 'retab'
    silent exec '%s/ \+$//e'                                                                                          
    call setpos(".", save_cursor)                                                                                     
endfunction


書いた後調べてみると、全く同じコトしてる人いた。
ちゃんと調べてから書こう。。
vimを使って保存時に楽をする

[git] gitの便利な設定をチームで共有するためには。

背景


最近、会社で使うバージョン管理ツールをbzrからgitに変えてみた。

慣れてしまうとすごくいろんな事できて楽しい。
ただ、慣れるまではたいへんだから、新しいメンバが入ってきたときは、すごくたいへんそう。
少なくとも、便利なコマンドとかは、チーム内で共有できるようにしておきたい。

 「gitコマンド」、「alias」、「hook script」の3点は必須。
かつ、後々変更があった時も、簡単に取り込めるようにしたい。

git コマンド


git コマンドは簡単に共有できるようにしておきたい。

経験的に、何か作っても、「これインストールすれば使えます」じゃ、誰も使わない。
「このコマンド叩いてください」ってレベルにしておかないと。

git は、パスの通ったところにgit-*って名前で保存しておけば、
勝手にgitのコマンドとして認識してくれるようなので、
作成されたコマンドをプロジェクトのレポジトリに混ぜることにした。

 新しいプロジェクトメンバーが入ってきたら、
.bashrcに、そのディレクトリへのパスを通してもらえれば、
後々、あたらしくコマンドが追加されてもpullすればOK。

共有用ディレクトリには、作ったgitコマンドを入れておく。
$ ls -l (共有用ディレクトリへのパス)
git-scp 
git-test
git-getbranch

.bashrcに以下を書く。
export PATH=$PATH:(共有用ディレクトリへのパス)

alias


aliasも共有にしたい。

 logの表示形式とか、diffをvimdiffで開くとか。

でも、なかなかうまい方法がなかった。

① .git/configを共有
cloneではここ共有されないらしい。
そして、pullしても共有されない。

② ~/.gitconfigを共有にする。
全部共有にすると、こみったーが全員一緒に・・・。

③ [include]を使う
1.7.10から、別のファイルを読み込めるようになったらしい。
これが使えれば、gitコマンドのときみたいに、
共有にしたい設定だけレポジトリの中入れといて、 新しいプロジェクトメンバーが入ってきたら、 .gitconfigに、名前の設定とincludeを書いてもらえればOK。 

やっぱりこの方法が一番スマートだと思う。
.gitconfigを別ファイルで読み込む gitインストール

が、みんなが入れてるgitのversion古くて使えない。。


④ setupコマンドを準備

結局、setupというコマンドを準備して、やってもらいたいalias全部書き込んでおくことにした。
何か変更があったら、pullして、setupを実行してもらう。
まぁまぁこれくらいならやってくれるだろう。 
以下を、(共有用ディレクトリへのパス)に、git-setupというん名前で、
実行権限つけて保存しておいた。


#!/bin/sh

# git rootの取得
gitroot=$(git rev-parse --show-toplevel)

# alias の設定
echo "+ setting alias"
git config --global diff.external git_diff_wrapper
git config --global pager.diff ""
git config --global diff.tool vimdiff
git config --global difftool.prompt false

git config --global alias.files "diff --name-only"
git config --global alias.hist "log --pretty=format:\"%h %C(yellow)%ad%C(reset) | %s%C(red)%d%C(reset) %C(blue)[%an]%C(reset)\" --graph --date=iso"

git config --global alias.ch checkout
git config --global alias.co commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.pull "pull --rebase"
git config --global alias.sb "show-branch --color"
git config --global core.pager less


# hookの設定
echo "+ setting hooks"
ln -sf ${gitroot}/data/gittool/pre-commit ${gitroot}/.git/hooks/pre-commit
ln -sf ${gitroot}/data/gittool/prepare-commit-msg ${gitroot}/.git/hooks/prepare-commit-msg

hook script


hookスクリプトも共有にしたい。

commitのときエラーチェック入れるとか、
commitメッセージを決めるとか、
master push するときIRCに投げるとか。 

1,2と同じディレクトリにスクリプト置いといて、 2のsetupコマンドに書いておいた。

2012年10月27日土曜日

[vim] PHPのエラー箇所をハイライトする

背景


前に、PHPのエラーをステータスラインに表示する設定をした。
[vim] phpファイルを保存するとき、エラーチェックして、エラーがあったらステータスラインを赤にする設定

 この状態で使ってて思った。
 ステータスラインに表示されても気づかない。。 

修正して、動かして見たらPHP Fatal Errorはかれてて、
ソースに戻って見たら、ステータスライン赤くなってる・・・。

無意味。

やっぱり、画面の下じゃなくて、画面の真ん中あたらを赤くしてくれないと気が付かない。
なんとかしなきゃ。


対処方法


① エラー時にsyntaxをoffにする。
やってみたけど、そんなにインパクトなかった。

② エラー箇所をハイライトする。
まぁ、こっちでしょう。 
errormarker.vimってのでもできるらしいが、 そんなに長く無いし、自分で書く。

phpでもerrormarker.vimをつかってflymakeしたい!

ソース


機能としては以下2点。
① エラー箇所をハイライト

ハイライトする。

② エラー箇所にジャンプ
spaceキーおしたら、そのエラー箇所にジャンプするようにしみてた。

またこれに伴って、エラー時のステータスラインに
ファイル名とか行番号とか表示指定してたのを外して、
エラーの内容のみを表示させるようにした。
縦分割するとき長すぎて全部入っていなかったので。




"----------------------------------------------------------+
" エラー行の背景色変更
"----------------------------------------------------------+

" キーバインドとautocmd設定
nnoremap  :call JumpToPHPError()
autocmd BufEnter,BufWritePost *.php call CheckErrorLine()

" エラー箇所にジャンプ
function! JumpToPHPError()
  silent! exe 'sign jump 99999 buffer='.winbufnr(0)
endfunction

" エラー箇所をハイライト
function! CheckErrorLine()

  " とりあえず消す.
  silent! exe 'sign unplace 99999 buffer=' . winbufnr(0)

  " チェックを実行(PHP)
  let l:tmp = system("php -l ".bufname(""))

  " エラーがあった場合
  if ! (l:tmp =~ "No syntax errors" )
      let s:line = matchstr(l:tmp,'on line \d\+')
      let l:line = split(s:line, 'line ')

     silent exe 'sign define PHPERROR text=>> linehl=ECOLOR texthl=ECOLOR'
     silent exe 'sign place 99999 line=' . l:line[1] . ' name=PHPERROR buffer=' . winbufnr(0)
     silent exe 'hi ECOLOR ctermfg=Yellow ctermbg=Red cterm=none'

     return
  endif

  return