From: "Santi Béjar" <santi@agolina.net>
To: "Johannes Sixt" <j.sixt@viscovery.net>
Cc: "Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"git list" <git@vger.kernel.org>
Subject: Re: git-bpush: Pushing to a bundle
Date: Tue, 9 Dec 2008 15:58:20 +0100 [thread overview]
Message-ID: <adf1fd3d0812090658q14001019re8977b912386c256@mail.gmail.com> (raw)
In-Reply-To: <493E545B.6010609@viscovery.net>
[-- Attachment #1: Type: text/plain, Size: 5667 bytes --]
2008/12/9 Johannes Sixt <j.sixt@viscovery.net>:
> Santi Béjar schrieb:
>> 2008/12/9 Johannes Schindelin <Johannes.Schindelin@gmx.de>:
>>> 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 #2: git-bpush --]
[-- Type: application/octet-stream, Size: 4493 bytes --]
#!/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
next prev parent reply other threads:[~2008-12-09 14:59 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-09 9:49 git-bpush: Pushing to a bundle Santi Béjar
2008-12-09 10:07 ` Johannes Schindelin
2008-12-09 10:21 ` Santi Béjar
[not found] ` <493E545B.6010609@viscovery.net>
2008-12-09 14:58 ` Santi Béjar [this message]
2008-12-09 17:32 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adf1fd3d0812090658q14001019re8977b912386c256@mail.gmail.com \
--to=santi@agolina.net \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=j.sixt@viscovery.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).