From: "Santi Béjar" <santi@agolina.net>
To: "git list" <git@vger.kernel.org>
Subject: git-bpush: Pushing to a bundle
Date: Tue, 9 Dec 2008 10:49:14 +0100 [thread overview]
Message-ID: <adf1fd3d0812090149m158fcb9as15bacce58c61a1a3@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 5090 bytes --]
Hi *,
I've made a script to push to a bundle that tries to behave as the
normal push.
It has some limitations, but for the normal cases it works fine.
The basic idea is:
- Easily create bundles with the current branch.
- Be able to push to defined bundles in remote.<remote>.url
- Only add new objects by default (do not lose objects)
- Reuse existing bundles (keep the basis and the branches)
- Check that the branches fast-forward
- Keep the pushed branches in refs/remotes/<remote>/*
But it also has some limitations:
- Do not allow refspec (git-bundle do not support them), only branch/tags names.
- Push all branches or none (consequence of the above)
- ...
Hope this helps,
Santi
The scripts follows, but also attatched.
#!/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 [ $# != 0 ] ; do
case "$1" in
-v) verbose=t;;
--full) full=t;;
-f|--force) force=t;;
--) shift; break;;
*) usage;;
esac
shift
done
[ -n "$1" ] && remote=$1 && shift
while [ $# != 0 ] ; do
refs="$refs$LF$1" && shift
done
[ -z "$remote" ] && remote=$(get_default_remote)
remoteurl=$(git config remote.${remote}.url)
[ -z "$remoteurl" ] && remoteurl=$remote
[ -d "$remoteurl" ] && die "$remoteurl is a directory"
# Default bases in bundle.base
# Default {refs,base} can be specified in remote.<remote>.{push,bundlebase}
if [ "$remote" != "$remoteurl" ] ; then
[ -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
[ "$ref" = HEAD ] && head=t && break
done
[ -n "$bases" ] && bases=$(git rev-parse --revs-only $bases | sort -u)
# Full symbolic refs to be uniq
[ -n "$refs" ] && \
refs=$(git-rev-parse --symbolic-full-name --revs-only $refs | sort -u) && \
[ -n "$head" ] && refs="HEAD$LF$refs"
if [ -e "$remoteurl" ] ; then
# Find the bundle's bases
refs="$refs$LF$(git bundle list-heads $remoteurl | cut -d " " -f 2)"
requires=
for line in $(git bundle verify "$remoteurl" 2>/dev/null) ; do
case "$line" in "The bundle requires"*) requires=t && continue; esac
[ -z "$requires" ] && continue
bbase=$(echo $line | cut -d " " -f 1)
[ -z "$bbases" ] && bbases=$bbase && continue
bbases="$bbases$LF$bbase"
done
bbases=$(echo "$bbases" | sort -u)
[ -z "$bases" ] && bases="$bbases" || bases="$bases$LF$bbases"
elif [ -z "$refs" ] ; then
# Push current branch
refs="HEAD$LF$(git symbolic-ref -q HEAD)"
fi
[ -z "$refs" ] && die "No refs to push"
refs=$(echo "$refs" | sort -u)
for ref in $bases $refs ; do
[ "$(git cat-file -t $ref^{})" != commit ] && \
die "$(basename $0): $ref is not a commit"
done
header="To $remoteurl"
[ -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
case $ref in
refs/tags/*) type=tags; newtext="new tag";;
refs/heads/*|HEAD) type=heads ; newtext="new branch" ;;
esac
newhash=$(git rev-parse $ref)
newshort=$(git rev-parse --short $ref)
bshort=$(echo $ref | sed -e "s|^refs/$type/||")
if [ -e "$remoteurl" ] ; then
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)
[ "$bref" != "$ref" ] && continue
oldshort=$(git-rev-parse --short $bhash)
case $type in
tags)
base=$newhash;;
heads)
base=$(git merge-base $bref $bhash);;
esac
if [ "$base" != $bhash ] ; then
[ -n "$header" ] && echo $header && header=
if [ -z "$force" ] ; then
nonff=t
echo " ! [rejected] $bshort -> $bshort (non-fast forward)"
else
changed=t
echo " + $oldshort...$newshort $bshort -> $bshort (forced update)"
fi
continue 2
fi
if [ "$newhash" != "$bhash" ] ; then
changed=t
[ -n "$header" ] && echo $header && header=
echo " $oldshort..$newshort $bshort -> $bshort"
elif [ -n "$verbose" ] ; then
[ -n "$header" ] && echo $header && header=
echo " = [up to date] $bshort -> $bshort"
fi
continue 2
done
fi
[ -n "$header" ] && echo $header && header=
echo " * [$newtext] $bshort -> $bshort"
changed=t
done
[ -n "$full" ] && bases= && [ -n "$bbases" ] && changed=t
[ -n "$nonff" ] && die "error: failed to push some refs to $remoteurl"
[ -z "$changed" ] && die "Everything up-to-date"
[ -n "$bases" ] && bases="--not$LF$bases"
git bundle create $remoteurl $refs $bases
[ "$remote" != "$remoteurl" ] && git fetch -q "$remote"
exit 0
[-- Attachment #2: git-bpush --]
[-- Type: application/octet-stream, Size: 4351 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 [ $# != 0 ] ; do
case "$1" in
-v) verbose=t;;
--full) full=t;;
-f|--force) force=t;;
--) shift; break;;
*) usage;;
esac
shift
done
[ -n "$1" ] && remote=$1 && shift
while [ $# != 0 ] ; do
refs="$refs$LF$1" && shift
done
[ -z "$remote" ] && remote=$(get_default_remote)
remoteurl=$(git config remote.${remote}.url)
[ -z "$remoteurl" ] && remoteurl=$remote
[ -d "$remoteurl" ] && die "$remoteurl is a directory"
# Default bases in bundle.base
# Default {refs,base} can be specified in remote.<remote>.{push,bundlebase}
if [ "$remote" != "$remoteurl" ] ; then
[ -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
[ "$ref" = HEAD ] && head=t && break
done
[ -n "$bases" ] && bases=$(git rev-parse --revs-only $bases | sort -u)
# Full symbolic refs to be uniq
[ -n "$refs" ] && \
refs=$(git-rev-parse --symbolic-full-name --revs-only $refs | sort -u) && \
[ -n "$head" ] && refs="HEAD$LF$refs"
if [ -e "$remoteurl" ] ; then
# Find the bundle's bases
refs="$refs$LF$(git bundle list-heads $remoteurl | cut -d " " -f 2)"
requires=
for line in $(git bundle verify "$remoteurl" 2>/dev/null) ; do
case "$line" in "The bundle requires"*) requires=t && continue; esac
[ -z "$requires" ] && continue
bbase=$(echo $line | cut -d " " -f 1)
[ -z "$bbases" ] && bbases=$bbase && continue
bbases="$bbases$LF$bbase"
done
bbases=$(echo "$bbases" | sort -u)
[ -z "$bases" ] && bases="$bbases" || bases="$bases$LF$bbases"
elif [ -z "$refs" ] ; then
# Push current branch
refs="HEAD$LF$(git symbolic-ref -q HEAD)"
fi
[ -z "$refs" ] && die "No refs to push"
refs=$(echo "$refs" | sort -u)
for ref in $bases $refs ; do
[ "$(git cat-file -t $ref^{})" != commit ] && \
die "$(basename $0): $ref is not a commit"
done
header="To $remoteurl"
[ -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
case $ref in
refs/tags/*) type=tags; newtext="new tag";;
refs/heads/*|HEAD) type=heads ; newtext="new branch" ;;
esac
newhash=$(git rev-parse $ref)
newshort=$(git rev-parse --short $ref)
bshort=$(echo $ref | sed -e "s|^refs/$type/||")
if [ -e "$remoteurl" ] ; then
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)
[ "$bref" != "$ref" ] && continue
oldshort=$(git-rev-parse --short $bhash)
case $type in
tags)
base=$newhash;;
heads)
base=$(git merge-base $bref $bhash);;
esac
if [ "$base" != $bhash ] ; then
[ -n "$header" ] && echo $header && header=
if [ -z "$force" ] ; then
nonff=t
echo " ! [rejected] $bshort -> $bshort (non-fast forward)"
else
changed=t
echo " + $oldshort...$newshort $bshort -> $bshort (forced update)"
fi
continue 2
fi
if [ "$newhash" != "$bhash" ] ; then
changed=t
[ -n "$header" ] && echo $header && header=
echo " $oldshort..$newshort $bshort -> $bshort"
elif [ -n "$verbose" ] ; then
[ -n "$header" ] && echo $header && header=
echo " = [up to date] $bshort -> $bshort"
fi
continue 2
done
fi
[ -n "$header" ] && echo $header && header=
echo " * [$newtext] $bshort -> $bshort"
changed=t
done
[ -n "$full" ] && bases= && [ -n "$bbases" ] && changed=t
[ -n "$nonff" ] && die "error: failed to push some refs to $remoteurl"
[ -z "$changed" ] && die "Everything up-to-date"
[ -n "$bases" ] && bases="--not$LF$bases"
git bundle create $remoteurl $refs $bases
[ "$remote" != "$remoteurl" ] && git fetch -q "$remote"
exit 0
next reply other threads:[~2008-12-09 9:50 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-09 9:49 Santi Béjar [this message]
2008-12-09 10:07 ` git-bpush: Pushing to a bundle Johannes Schindelin
2008-12-09 10:21 ` Santi Béjar
[not found] ` <493E545B.6010609@viscovery.net>
2008-12-09 14:58 ` Santi Béjar
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=adf1fd3d0812090149m158fcb9as15bacce58c61a1a3@mail.gmail.com \
--to=santi@agolina.net \
--cc=git@vger.kernel.org \
/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).