2008/12/9 Johannes Sixt <j.sixt@xxxxxxxxxxxxx>: > Santi Béjar schrieb: >> 2008/12/9 Johannes Schindelin <Johannes.Schindelin@xxxxxx>: >>> On Tue, 9 Dec 2008, Santi Béjar wrote: >>>> while [ $# != 0 ] ; do >>>> refs="$refs$LF$1" && shift >>>> done >>> That is equivalent to refs="$*", no? >> >> Almost, IFS is set to line-feed so I needed to put $LF instead of spaces. > > But "$*" inserts the first character of IFS (not necessarily spaces), and > since your IFS *is* $LF, "$*" should do what you want. > Oh, you are right. > Anyway, I found reading your shell script quite hard, because of excessive > use of brackets and single line && chains (which lack proper error > handling, BTW). I've changed the script to follow the Git's conventions (at least I've tried), a few more error handling and some simplification. BTW, what do you find hard with single line && chains? I do not sent a diff because it is almost as big as the script itself. #!/bin/sh OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ git bpush [options] [<remote> [<refs>...]] -- f,force force updates full create a full bundle v be verbose " SUBDIRECTORY_OK=Yes . git-sh-setup . git-parse-remote cd_to_toplevel LF=' ' IFS="$LF" bases= bbases= changed= force= nonff= remote= refs= while : do case "$1" in -v) verbose=t ;; --full) full=t ;; -f|--force) force=t ;; --) shift break ;; *) usage ;; esac shift done test -n "$1" && remote=$1 && shift refs="$*" test -z "$remote" && remote=$(get_default_remote) remoteurl=$(git config remote.${remote}.url) test -z "$remoteurl" && remoteurl=$remote test -d "$remoteurl" && die "$remoteurl is a directory" # Default bases in bundle.base # Default {refs,base} can be specified in remote.<remote>.{push,bundlebase} if test "$remote" != "$remoteurl" then test -z "$refs" && refs=$(git config --get-all remote.${remote}.push) bases=$(git config --get-all remote.${remote}.bundlebase || git config --get-all bundle.base) else bases=$(git config --get-all bundle.base) fi # git rev-parse --symbolic-full-name resolves symlinks # Keep at least HEAD head= for ref in $refs ; do test "$ref" = HEAD && head=t && break done test -n "$bases" && bases=$(git rev-parse --revs-only $bases | sort -u) # Full symbolic refs need to be uniq test -n "$refs" && refs=$(git-rev-parse --symbolic-full-name --revs-only $refs | sort -u) test -n "$head" && refs="HEAD$LF$refs" if test -e "$remoteurl" then blines=$(git bundle verify "$remoteurl" 2>/dev/null) || die "Verification of \"$remoteurl\" failed" # Find the bundle's bases refs="$refs$LF$(git bundle list-heads $remoteurl | cut -d " " -f 2)" requires= for line in $blines do case "$requires,$line" in ",The bundle requires"*) requires=t ;; t,) ;; t,*) bbase=$(echo $line | cut -d " " -f 1) bbases="$bbases$LF$bbase" ;; esac done bases="$bases$LF$bbases" elif test -z "$refs" ; then # Push current branch refs="HEAD$LF$(git symbolic-ref -q HEAD)" fi test -z "$refs" && die "No refs to push" refs=$(echo "$refs" | sort -u) for ref in $bases $refs do test "$(git cat-file -t $ref^{})" != commit && die "$(basename $0): $ref is not a commit" done header="To $remoteurl" test -n "$verbose" && echo "Pushing to $remoteurl" && echo $header && header= # Find what is/is not a fast-forward, up to date or new # As "git bundle" does not support refspecs we must push all matching branches for ref in $refs ; do text= bchanged= case $ref in refs/tags/*) bshort=$(echo $ref | sed -e "s|^refs/tags/||") newtext="new tag";; refs/heads/*|HEAD) bshort=$(echo $ref | sed -e "s|^refs/heads/||") newtext="new branch" ;; esac newhash=$(git rev-parse $ref) || die "Ref $ref not valid" newshort=$(git rev-parse --short $ref) bheads= test -e "$remoteurl" && bheads="$(git bundle list-heads $remoteurl)" for bhead in $bheads do bhash=$(echo $bhead | cut -d " " -f 1) bref=$(echo $bhead | cut -d " " -f 2) # Find the matching ref in the bundle test "$bref" != "$ref" && continue oldshort=$(git rev-parse --short $bhash) mergebase= case $ref in refs/tags/*) # Only test if it is different mergebase=$newhash;; refs/heads/*|HEAD) mergebase=$(git merge-base $bref $bhash);; esac case $newhash,$bhash,$mergebase,$force in $bhash,$newhash,*) # No changes text=" = [up to date] $bshort -> $bshort" ;; *,*,$bhash,*) # Fast-forward bchanged=t text=" $oldshort..$newshort $bshort -> $bshort" ;; *,t) # Forced non fast-forward bchanged=t text=" + $oldshort...$newshort $bshort -> $bshort (forced update)" ;; *) bchanged=t nonff=t text=" ! [rejected] $bshort -> $bshort (non-fast forward)" esac break done test -z "$text" && text=" * [$newtext] $bshort -> $bshort" && bchanged=t if test -n "$bchanged" || test -n "$verbose" then test -n "$header" && echo $header && header= echo $text fi test -n "$bchanged" && changed=t done # Recreate the bundle if --full and the current bundle is not full test -n "$full" && bases= && test -n "$bbases" && changed=t test -n "$nonff" && die "error: failed to push some refs to $remoteurl" test -z "$changed" && die "Everything up-to-date" test -n "$bases" && bases="--not$LF$bases" git bundle create $remoteurl $refs $bases || die "Cannot create bundle \"$remoteurl\"" test "$remote" != "$remoteurl" && { git fetch -q "$remote" || die "Error fetch from bundle \"$remoteurl\"" ; } exit 0
Attachment:
git-bpush
Description: Binary data