Настройка bash prompt для Subversion, Git и Mercurial

Руководство
В последнее время количество доступных для использования систем контроля версий стало настолько большим (subversion, git, mercurial и т.д.), что уже не редкость, когда на одном и том же компьютере может одновременно находится множество проектов под управлением различных систем контроля версий. Становится очевидной необходимость при навигации в файловой системе в более быстром определении типа системы контроля версий и наличия изменений в ней.

Конечно, можно при заходе в директорию делать svn|hg|git info, но это все требует времени, а так же знания того, какая система контроля версий используется в текущей директории.

Одним из вариантов решения проблемы (при условии, что в системе используется bash) будет переопределение строки приглашения (bash prompt) таким образом, чтобы в ней выводились не только стандартные имя пользователя, название компьютера и текущий путь в файловой системе, но и тип системы контроля версий, а так же признак наличия изменений.

Изменение bash prompt
Для изменения вида строки приглашения bash достаточно изменить переменную окружения PS1. Для этого необходимо будет изменить файл ~/.bashrc:
$ vim ~/.bashrc

В файле необходимо найти место, где переменной PS1 присваивается значение. У некоторых это может выглядеть так:
PS1='${debian_chroot:+($debian_chroot)}\
\[\033[01;32m\]\u@\h\[\033[00m\]:\
\[\033[01;34m\]\w\[\033[00m\] \$ '

Подключение subversion
В том же файле (~/.bashrc), перед присвоением значения PS1 дописываем следующий код:
txtred='\033[1;31m' # Red bold 
txtpur='\033[1;35m' # Purple bold
txtrst='\033[0m'    # Text Reset

# вывод признака системы контроля версии и относительного
# пути в репозитории
svn_branch() {
    svn_url | sed -e 's#^'"$(svn_repository_root)"'##g' | \
        awk -v "clrp=$txtpur" -v "clrr=$txtrst" \
            '{ print clrp ":svn" $1 clrr}'
}

# вывод полного текущего пути в svn-репозитории
svn_url() {
    svn info 2>/dev/null | sed -ne 's#^URL: ##p'
}

# вывод базового пути svn-репозитория
svn_repository_root() {
    svn info 2>/dev/null | head -n3| tail -n1 | awk '{print $3}'
}

# вывод признака наличия изменений в директории
svn_dirty() {
    [ $(svn status 2> /dev/null | wc -l) != 0 ] && \
        echo -e "${txtred}*${txtrst}"
}

В этом блоке кода определяется несколько функций, которые позволяют определить относительный путь в Subversion репозитории, а так же определить наличие изменений в нем. Весь вывод функций подсвечивается пурпурным или красным цветом

Далее, дописываем определение переменной PS1 следующим образом:
PS1='${debian_chroot:+($debian_chroot)}\
\[\033[01;32m\]\u@\h\[\033[00m\]:\
\[\033[01;34m\]\w\[\033[00m\]\
$(svn_branch)$(svn_dirty) $ '

Теперь, при условии, что текущая директория находится под управлением Subversion, в строке приглашения появится признак типа системы и относительный путь в нем, окрашенные в пурпурный цвет. Кроме того, если в директории есть изменения, то после относительного пути появится красный астериск (знак звездочки).

Подключение Mercurial
Для Mercurial поступаем аналогичным образом. Перед присвоением переменной PS1 значения дописываем следующие функции:
# вывод признака системы контроля версии и относительного
# пути в репозитории
hg_branch() {
    hg branch 2> /dev/null | \
        awk -v "clrp=$txtpur" -v "clrr=$txtrst" \
            '{ print clrp ":hg/" $1 clrr}'
}

# вывод признака наличия изменений в репозитории
hg_dirty() {
    [ $(hg status 2> /dev/null | wc -l) != 0 ] && \
        echo -e "${txtred}*${txtrst}"
}

Далее, дописываем определение переменной PS1:
PS1='${debian_chroot:+($debian_chroot)}\
\[\033[01;32m\]\u@\h\[\033[00m\]:\
\[\033[01;34m\]\w\[\033[00m\]\
$(svn_branch)$(svn_dirty)\
$(hg_branch)$(hg_dirty) $ '

Теперь, при условии, что текущая директория находится под управлением Mercurial, в bash prompt будет выведен тип системы контроля версий, относительный путь в нем и признак наличия изменений (*, все тот же астериск), если они есть.

Подключение Git
Для Git пишем аналогичные функции:
# вывод признака системы контроля версии и относительного
# пути в репозитории
git_branch() {
    git branch --no-color 2> /dev/null | \
        awk -v "clrp=$txtpur" -v "clrr=$txtrst" \
            '{ print clrp ":git/" $2 clrr}'
}

# вывод признака наличия изменений в репозитории
git_dirty() {
    [ $(git status --short 2> /dev/null | wc -l) != 0 ] && \
        echo -e "${txtred}*${txtrst}"
}

И дописываем вызов новый функций в определение PS1:
PS1='${debian_chroot:+($debian_chroot)}\
\[\033[01;32m\]\u@\h\[\033[00m\]:\
\[\033[01;34m\]\w\[\033[00m\]\
$(svn_branch)$(svn_dirty)\
$(hg_branch)$(hg_dirty)\
$(git_branch)$(git_dirty) $ '

Готово. Теперь у вас перед глазами всегда будет информация о:
  • находится ли текущая директория под управлением какой-либо системы контроля версий
  • с какой именной системой контроля версий идет работа
  • ветка или относительный путь в репозитории
  • есть ли в локальной версии репозитория изменения

1 комментарий

avatar
Большое спасибо. Работает.

Скажите, а с использованием mercurial дополнения PromptExtension разве не должно получиться производительнее?

Уж больно притормаживает опрос hg после каждой команды консоли.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.