Re: git-bpush: Pushing to a bundle
From: Santi Béjar <hidden>
Date: 2016-06-15 22:45:45
2008/12/9 Johannes Sixt [off-list ref]:
Santi Béjar schrieb:quoted
2008/12/9 Johannes Schindelin [off-list ref]:quoted
On Tue, 9 Dec 2008, Santi Béjar wrote:quoted
while [ $# != 0 ] ; do refs="$refs$LF$1" && shift doneThat 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 Attachments
- git-bpush [application/octet-stream] 4493 bytes