# Source this file in your .zshrc to setup a chpwd function that will # maintain some helpful repo-related aliases for you. These aliases # change based on what kind of repo you've cd'ed into. # # The aliases default to the following 2-letter commands (though you # can configure them down in the repo_chpwd function): # # ad Repo's "add" command. # # ci Does a checkin, defaulting to the committing of all changed # files unless an arg beyond "-m msg" is specified (e.g. one or # more filenames). For git, you can also specify a trailing -i # if you want to turn off the -a option without specifying any # files (and thus just commit things that have been explicitly # added). # # co Does a checkout, for things like changing branches or updating # files to different versions. # # di Repo's "diff" command. Auto-pages. # # lo Repo's "log" command. Auto-pages. The -v option can be used # to request that file names be included in the commit output, # even in git. The -s option can be used in a git-svn repo to # ask for the "git svn log" output. # # st Repo's "status" command. For cvs, this uses a helper script # (cvs-status) to output status ala svn, with the default being # local-only output, and remote-status added in via -u (though # local cvs status does not include info on unknown files). For # git, this hides a non-zero exit status (not needed for 1.7). # # pu Push the currently-checked-in changes. This has no effect in # svn or cvs. For git, it will do the right thing in a git-svn # checkout, as well as a custom cvs-modifying git checkout (see # the helper-script git-cvs-push). # # up Update from the saved remote repo location. For git, this # defaults to doing a "git pull --rebase" for a normal repo, or # a "git svn rebase" for a git-svn repo. # # The commands that "auto-page" pipe their output through "less -F" so # that you get a pager if the output is long, and normal output if it is # not. It helps to have a modern version of less to avoid jumping down # to the bottom of the screen when that is not needed. Note that git # auto-pages by default, so we leave it alone (which ensures auto-color # is unaffected). # # The aliases that use helper functions get a compdef setting that makes # them share their repo's command-line completion. # # See: http://opencoder.net/repos/ for more info and the helper scripts. # Written by: Wayne Davison # Freely redistributable. function paged_cvs { cvs "${@}" | less -F } compdef _cvs paged_cvs=cvs function paged_svn { svn "${@}" | less -F } compdef _subversion paged_svn=svn function paged_bzr { bzr "${@}" | less -F } compdef _bzr paged_bzr=bzr function paged_hg { hg "${@}" | less -F } compdef _mercurial paged_hg=hg # This changes the default behavior of a git commit to assume the --all # option unless it is overridden by explicit filenames or other options. # To override this (committing just queued changes), this supports a trailing # -i option (-i normally takes an arg, but has the new meaning if last). function git4commit { local arg args args=( commit ) shift # discard "commit" arg # This makes -a the default with no args or just a -m arg. if [[ $# == 0 || ($# == 2 && x$1 == x-m) ]]; then args+=-a fi args+=( "${@}" ) # This removes a trailing -i option (used to override the default -a # behavior and just commit what has been manually added). if [[ x$args[-1] == x-i ]]; then args[-1]=( ) fi git $args } compdef _git git4commit=git # This adds 2 new log options for git repos: # -v -> --name-stats # -s -> run "git svn log" instead of "git log". function git4log { local arg args args=( log ) shift # discard "log" arg for arg in "${@}"; do if [[ x$arg == x-s && $REPOS_ZSH_TYPE == git-svn ]]; then args=(svn $args) continue fi if [[ x$arg == x-v && $args[1] == log ]]; then arg=--name-status fi args+=$arg done git $args } compdef _git git4log=git # This just forces the return code from "git status" to always be 0. Since # git 1.7 no longer has this issue, this will go away at some point. function git4status { git "${@}" return 0 } compdef _git git4status=git # This ensures that if something like "git init" is run on the current # directory, we don't need a chdir event to figure out that we're now # in an scm dir. function recheck_scm_dir { local x=$1 shift repo_chpwd case $aliases[$x] in *recheck_scm_dir*) echo "You are not in an scm dir." ;; *) $=aliases[$x] "${@}" ;; esac } # This is the main function -- it is run after each chdir and a couple other times. function repo_chpwd { # This section defines the alias names that will be created. If you # want to use a different set of alias than the default 2-letter ones # Wayne created, change the name after the equal (e.g. "local ad=add"). local ad=ad local ci=ci local co=co local di=di local lo=lo local st=st local pu=pu local up=up # You can also tweak the aliases below to have the options you like best. # Finally, you may wish to tweak things like my change to make "ci" default # to committing with --all. To do that, either stop using git4commit (change # that reference to just "git") or tweak the git4commit function (above). local inode prior_inode check_dir=. while : ; do inode=`/usr/bin/stat -c %i $check_dir` if [[ $inode == $prior_inode ]]; then alias $ad="recheck_scm_dir $ad" alias $ci="recheck_scm_dir $ci" alias $co="recheck_scm_dir $co" alias $di="recheck_scm_dir $di" alias $lo="recheck_scm_dir $lo" alias $st="recheck_scm_dir $st" alias $pu="recheck_scm_dir $pu" alias $up="recheck_scm_dir $up" REPOS_ZSH_TYPE=none break fi if [[ -d $check_dir/.git ]]; then alias $ad='git add' alias $ci='git4commit commit' alias $co='git checkout' alias $di='git diff --patience' alias $lo='git4log log --patience --cc' alias $st='git4status status' if [[ -d $check_dir/.git/svn ]]; then alias $pu='git svn dcommit --rmdir' alias $up='git svn rebase' export REPOS_ZSH_TYPE=git-svn elif [[ -d $check_dir/.git/cvs ]]; then alias $pu="git-cvs-push '$check_dir'" alias $up='git pull --rebase --stat' export REPOS_ZSH_TYPE=git-cvs else alias $pu='git push' alias $up='git pull --rebase --stat' export REPOS_ZSH_TYPE=git fi break fi if [[ -d $check_dir/.bzr ]]; then alias $ad='bzr add' alias $ci='bzr commit' alias $co='bzr checkout' alias $di='paged_bzr diff' alias $lo='paged_bzr log' alias $pu='bzr push' alias $st='bzr st' alias $up='bzr pull' REPOS_ZSH_TYPE=bzr break fi if [[ -d $check_dir/.hg ]]; then alias $ad='hg add' alias $ci='hg ci' alias $co='hg update' alias $di='paged_hg diff' alias $lo='paged_hg log' alias $pu='hg push' alias $st='hg st' alias $up='hg pull -u' REPOS_ZSH_TYPE=hg break fi if [[ -d $check_dir/.svn ]]; then alias $ad='svn add' alias $ci='svn ci' alias $co='svn update' alias $di='paged_svn diff --no-diff-deleted' alias $lo='paged_svn log' alias $pu='echo "This is an svn repository!"' alias $st='svn st' alias $up='svn up' REPOS_ZSH_TYPE=svn break fi if [[ -z $prior_inode ]]; then # Only check for CVS in the current dir. if [[ -d $check_dir/CVS ]]; then alias $ad='cvs add' alias $ci='cvs ci' alias $co='cvs update' alias $di='paged_cvs -q diff -up' alias $lo='paged_cvs log' alias $pu='echo "This is a cvs repository!"' alias $st='cvs-status' alias $up='cvs -q up -d -P' REPOS_ZSH_TYPE=cvs break fi fi prior_inode=$inode check_dir=../$check_dir done } # If repo_chpwd isn't in the chpwd list of functions yet, add it. case "$functions[chpwd]" in *repo_chpwd*) ;; *) functions[chpwd]+=' repo_chpwd' ;; esac # Initialize things by running the function once. repo_chpwd # vim: sw=4 ts=8 noet ft=zsh