[研究開発] zsh用、hg/gitの未push検出スクリプト

まえおき:

  • zshのhg/gitのサブコマンド補完は便利だ
    • そんなのないという人は要zshバージョンアップ
  • zshは更に、hg/gitのブランチ名表示機能(と、おまけで現在のステータス表示機能)も標準でついてる
    • 詳しいやりかたはぐぐる事。自分は標準でついてるのを知らずに自前で書いてしまったが
    • これで、hg/gitでブランチ別管理をやった人なら一度や二度となく引っかかったであろう、うっかり違うブランチをいじってしまうトラブルをほぼなくせる
  • しかし、zshにもhg/gitにも、「未push検出機能」がない
    • 手元でいじってるリポジトリはほぼ間違いなく、別サーバにある大元リポジトリのコピーであり、コミット後はpushが必要になる
      • そして、大元リポジトリによっては、作っているシステムが動作しなくなる変更をpushしようとすると拒否するような設定にできたりする(し、そもそもそんな変更をpushすると他の人に迷惑がかかる)ので、コミットした内容をすぐにpushせずに手元にためておくようなケースは結構多い
    • にも関わらず、未push状態の表示機能がない為に「せっかく新機能を実装/不具合を修正したのに、push忘れてて、リリースに含まれなかった」というミスをやった人は多いと思う。某社でも多発
    • でも標準ではこれを通知してくれる機能はzshにもhgにもgitにも、ない
    • なので、自作した


zsh内(hg/git共通)。以下を .zshrc 内で定義し、「$(print_directory_info $(pwd))」の実行結果を$PROMPT辺りに追加すればok

function print_directory_info() {
    local absdir=$1

    if [[ -d $absdir/.git ]] then
        # Git
        if [[ -e $absdir/.git/unpushed ]] then
            echo -n '*UNPUSHED* '
        fi
        git branch --no-color 2>/dev/null \
            | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'

    elif [[ -d $absdir/.hg ]] then
        # Hg
        if [[ -e $absdir/.hg/unpushed ]] then
            echo -n '*UNPUSHED* '
        fi
        cat $absdir/.hg/branch

    elif [[ -d $absdir/_darcs ]] then
        # Darcs
        basename $absdir

    elif [[ -r $absdir/CVS/Repository ]] then
        # CVS
        cat $absdir/CVS/Repository \
            | sed -e 's!\([^/]*\).*!\1!'

    else
        # Unknown.
        if [[ $absdir = "/" ]] then
            # This is the root directory so exit from the recursion.
            echo
        else
            # Recurse to the parent dir.
            print_directory_info $(dirname $absdir)
        fi
    fi
}


hg用。以下を ~/.hgrc に追加するだけでいい。単純

[hooks]
commit    = touch `hg root`/.hg/unpushed
post-push = rm -f `hg root`/.hg/unpushed


gitもhgみたくhookでできるかと思いきや、hookは大元サーバでの用途のものしかなく、commit/push時に手元のリポジトリを操作する為のhookはなかったので、自前でラッパーを書く羽目に

#!/bin/sh
# $Id$
if [ $# -lt 1 ]; then
  git
elif [ $1 = "commit" ]; then
  git "$@" && touch `git rev-parse --git-dir`/unpushed
elif [ $1 = "push" ]; then
  git "$@" && rm -f `git rev-parse --git-dir`/unpushed
else
  git "$@"
fi
# vim:set ft=sh sw=2 ts=2 et:
  • 上のスクリプトを、実行権限をつけて$PATHの通った場所に設置
  • .zshrc 内に以下を記述。以下のsetoptをしておかないと、コマンド名が違う為に、gitのサブコマンド補完が動かなくなってしまう
setopt complete_aliases # 補完時にalias展開を行わない
alias git=gitwrap


ていうか、zsh/hg/gitはこの未push検出機能を標準で備えるべき。
他の人は困ってないの?