#!/usr/bin/env zsh # # Copyright © 2008-2011 Nick Bowler # # License WTFPL2: Do What The Fuck You Want To Public License, version 2. # This is free software: you are free to do what the fuck you want to. # There is NO WARRANTY, to the extent permitted by law. # List all commits that have not yet been committed to CVS. (run this command # from the root of the CVS repository) git-cvs-commitlist() { if [[ -z "$1" ]]; then echo "usage: git-cvs-commitlist [origin]" 1>&2 return 1 fi [[ -z "$2" ]] && 2="remotes/CVS/master" [[ -d "$1/.git" ]] && 1="$1/.git" GIT_DIR="$1" git cherry -v "$2" } # Commit a specified commit to CVS (run this command from the root of the CVS # repository). git-cvs-commit() { if [[ -z "$1" || -z "$2" ]]; then echo "usage: git-cvs-commit " 1>&2 return 1 fi [[ -d "$1/.git" ]] && 1="$1/.git" GIT_DIR="$1" git cvsexportcommit -cvp "$2" } # Commit all commits that are not yet in CVS to CVS. # (run this command from the root of the CVS repository). git-cvs-commit-all() { if [[ -z "$1" ]]; then echo "usage: git-cvs-commit-all " 1>&2 return 1 fi git-cvs-commitlist $1 | while read i; do local commit=$(echo $i | cut -d ' ' -f 2) git-cvs-commit $1 $commit || return $? done } # Import the latest and greatest changes into a git repository (will create # a new repository if run outside of any git repo). # # The details used to fetch from CVS are recorded so that running # git-cvs-fetch with no arguments will repeat the same fetch as last time. # Currently, some arguments which don't make sense to record are recorded # anyway, so you may need to manually edit .git/config afterwards... git-cvs-fetch() { local tmp cvsroot cvsmod cvsopts cvsroot=${$(git config cvs.root):-$CVSROOT} cvsopts=${$(git config cvs.opts):-'$@'} eval "cvsopts=($cvsopts)" # Extract a CVS root from opts, if any. while [[ $((tmp=${cvsopts[(i)-d*]})) -le $#cvsopts ]]; do cvsroot=${cvsopts[$tmp]#-d} cvsopts=($cvsopts[1,$tmp-1] $cvsopts[$tmp+1,-1]) if [[ -z $cvsroot ]]; then cvsroot=${cvsopts[$tmp]} cvsopts=($cvsopts[1,$tmp-1] $cvsopts[$tmp+1,-1]) fi done if ! cvsmod=$(git config cvs.module); then cvsmod=$cvsopts[-1] cvsopts=($cvsopts[1,-2]) fi # By this point, we must have a CVS root and module. if [[ -z $cvsroot ]]; then printf '%s: no CVS root set.\n' $0 1>&2 return 1 fi if [[ -z $cvsmod ]]; then printf '%s: no CVS module set.\n' $0 1>&2 return 1 fi GIT_DIR=`git rev-parse --git-dir 2>/dev/null` git cvsimport \ -air CVS -d $cvsroot $cvsopts $cvsmod || return 1 # Store the settings for this run. git config cvs.root $cvsroot git config cvs.module $cvsmod [[ $#cvsopts -gt 0 ]] && git config cvs.opts ${(j: :)${(qq)cvsopts}} : } # Generate an excludes file, suitable for writing to .git/info/exclude, based # on .cvsignore files found in the repository. Run this command from the git # repository. git-cvs-genexclude() { local dir i j cvsdefaults work work=`git rev-parse --show-toplevel` || return 1 if test -z $work; then printf '%s: must be run from the work tree\n' $0 1>&2 return 1 fi printf '#\n# Automatically generated by %s\n#\n' "$0 $*" # CVS ignores a number of patterns by default. cvsdefaults=( 'RCS' 'SCCS' 'CVS' 'CVS.adm' 'RCSLOG' 'cvslog.*' 'tags' 'TAGS' '.make.state' '.nse_depinfo' '*~' '#*' '.#*' ',*' '_$*' '*$' '*.old' '*.bak' '*.BAK' '*.orig' '*.rej' '.del-*' '*.a' '*.olb' '*.o' '*.obj' '*.so' '*.exe' '*.Z' '*.elc' '*.ln' 'core' ) printf '%s\n' $cvsdefaults find $work -name .cvsignore | while read i; do dir=${$(dirname $i)#$work} < $i while read j; do printf '%s/%s\n' $dir $j done done } # For executable-like invocation... # It would be nice if we could detect whether we are invoked as an executable # and print a usage message if not given any arguments. I have yet to find # a clean way to do this, however. if [ $# -gt 0 ]; then func="git-cvs-${1#git-cvs-}" shift "$func" $@ fi