X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=git-debpush;h=67f6555b17b5135465d65227c2eef8da2a9c8e73;hb=8ac199c88ddd9a81119c936a9a702c57e1169fc8;hp=bd699179985493e5b768670f73f61b01a03a6ce3;hpb=a293b893d1b3fdf98e55d6c565c579f509f20ae4;p=dgit.git diff --git a/git-debpush b/git-debpush index bd699179..67f6555b 100755 --- a/git-debpush +++ b/git-debpush @@ -17,164 +17,164 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -set -e${DGIT_TEST_DEBPUSH_DEBUG-x} +set -e$DGIT_TEST_DEBPUSH_DEBUG set -o pipefail -# DEBUG - -# Principles of operation - -# - do not invoke dgit, anything involving any tarballs, no network -# except `git push` - -# - do not look at the working tree, like `git push` `git tag`, and so -# we can later add functionality to debpush any branch - -# - we are always in split brain mode, because this means the push won't -# fail because dgit needs to append commits - +# PRINCIPLES OF OPERATION +# +# - do not invoke dgit, do anything involving any tarballs, no network +# access except `git push` right at the end +# +# - do not look at the working tree, like `git push` `git tag` +# +# - we are always in split brain mode, because that fits this workflow, +# and avoids pushes failing just because dgit in the intermediary +# service wants to append commits +# # - if there is no previous tag created by this script, require a quilt # mode; if there is a previous tag, and no quilt mode provided, assume -# same quilt mode +# same quilt mode as in previous tag created by this script -# Other notes (which should be converted to a manpage/usage) +# ---- Helper functions and variables -# - arguments after '--' passed to `git push` - -# ---- Helper functions +us="$(basename $0)" cleanup() { - if [ -d "$TEMP" ]; then - rm -rf "$TEMP" + if [ -d "$temp" ]; then + rm -rf "$temp" fi } -# ---- Parse command line +fail () { + echo >&2 "$us: $*"; + exit 127; +} -us="$(basename $0)" +badusage () { + fail "bad usage: $*"; +} + +get_file_from_ref () { + local path=$1 -fail () { echo >&2 "$us: $*"; exit 127; } -badusage () { fail "bad usage: $*"; } + if git ls-tree --name-only -r "$branch" \ + | grep -Eq "^$path$"; then + git cat-file blob $branch:$path + fi +} + +# ---- Parse command line getopt=$(getopt -s bash -o 'nfu:' \ - -l 'no-push,force,branch:,remote:,distro:,quilt:,gbp,dpm,baredebian,\ -baredebian+git,baredebian+tarball,linear' \ + -l 'no-push,force,branch:,remote:,distro:,quilt:,gbp,dpm,\ +baredebian,baredebian+git,baredebian+tarball' \ -n "$us" -- "$@") eval "set - $getopt" -set -e${DGIT_TEST_DEBPUSH_DEBUG-x} +set -e$DGIT_TEST_DEBPUSH_DEBUG git_tag_opts=() pushing=true +force=false distro=debian - quilt_mode="" +branch="HEAD" + while true; do case "$1" in - '-n'|'--no-push') - pushing=false - shift - continue - ;; - '-u') - git_tag_opts+=(-u "$2") - shift 2 - continue - ;; - '-f'|'--force') - force='yes' - shift - continue - ;; - '--gbp') - quilt_mode='gbp' - shift - continue - ;; - '--dpm') - quilt_mode='dpm' - shift - continue - ;; + '-n'|'--no-push') pushing=false; shift; continue ;; + '-u') git_tag_opts+=(-u "$2"); shift 2; continue ;; + '-f'|'--force') force=true; shift; continue ;; + '--gbp') quilt_mode='gbp'; shift; continue ;; + '--dpm') quilt_mode='dpm'; shift; continue ;; + '--branch') branch=$2; shift 2; continue ;; + '--remote') remote=$2; shift 2; continue ;; + '--distro') distro=$2; shift 2; continue ;; + '--quilt') quilt_mode=$2; shift 2; continue ;; + '--baredebian'|'--baredebian+git') - quilt_mode=baredebian - shift - continue - ;; + quilt_mode=baredebian; shift; continue ;; '--baredebian+tarball') - quilt_mode=baredebian+tarball - shift - continue - ;; - '--branch') branch=$2; shift 2; continue ;; - '--remote') remote=$2; shift 2; continue ;; - '--distro') distro=$2; shift 2; continue ;; - '--quilt') quilt_mode=$2; shift 2; continue ;; - '--') - shift - break - ;; - *) - badusage "unknown option $1" - ;; + quilt_mode=baredebian+tarball; shift; continue ;; + '--') shift; break ;; + *) badusage "unknown option $1" ;; esac done -if [ $# != 0 ]; then badusage 'no positional arguments allowed'; fi +if [ $# != 0 ]; then + badusage 'no positional arguments allowed' +fi case "$quilt_mode" in - 'linear'|'auto'|'smash'|'nofix'|'gbp'|'dpm'|'unapplied'|'baredebian'|'baredebian+tarball'|'') - ;; - 'baredebian+git') - quilt_mode="baredebian" - ;; - *) - badusage " invalid quilt mode: $quilt_mode" - ;; + linear|auto|smash|nofix|gbp|dpm|unapplied|baredebian|baredebian+tarball|'') ;; + baredebian+git) quilt_mode="baredebian" ;; + *) badusage "invalid quilt mode: $quilt_mode" ;; esac +# ---- Gather git information + remoteconfigs=() push_branch=() -if [ ! "$branch" ]; then - branch=HEAD - branchref="$(git symbolic-ref -q HEAD || test $? = 1)" - case "$branchref" in - refs/heads/*) - b=${branchref#refs/heads/} - remoteconfigs+=( branch.$b.pushRemote branch.$b.remote ) - push_branch+=("$b") - ;; - esac +# Maybe $branch is a symbolic ref. If so, resolve it +branchref="$(git symbolic-ref -q $branch || test $? = 1)" +if [ "x$branchref" != "x" ]; then + branch="$branchref" fi +# If $branch is the name of a branch but it does not start with +# 'refs/heads/', prepend 'refs/heads/', so that we can know later +# whether we are tagging a branch or some other kind of committish +case "$branch" in + refs/heads/*) ;; + *) + branchref="$(git for-each-ref --format='%(objectname)' \ + '[r]efs/heads/$branch')" + if [ "x$branchref" != "x" ]; then + branch="refs/heads/$branch" + fi + ;; +esac + +# If our tag will point at a branch, push that branch, and add its +# pushRemote and remote to the things we'll check if the user didn't +# supply a remote +case "$branch" in + refs/heads/*) + b=${branch#refs/heads/} + push_branch+=("$b") + remoteconfigs+=( branch.$b.pushRemote branch.$b.remote ) + ;; +esac +# also check, if the branch does not have its own pushRemote or +# remote, whether there's a default push remote configured remoteconfigs+=(remote.pushDefault) -if $pushing && [ ! "$remote" ]; then +if $pushing && [ "x$remote" = "x" ]; then for c in "${remoteconfigs[@]}"; do remote=$(git config "$c" || test $? = 1) - if [ "x$remote" ]; then break; fi + if [ "x$remote" != "x" ]; then break; fi done - if [ ! "$remote" ]; then + if [ "x$remote" = "x" ]; then fail "pushing, but could not determine remote, so need --remote=" fi fi # ---- Gather source package information -TEMP=$(mktemp -d) +temp=$(mktemp -d) trap cleanup EXIT -mkdir "$TEMP/debian" -git cat-file blob HEAD:debian/changelog >"$TEMP/debian/changelog" -version=$(cd $TEMP; dpkg-parsechangelog -SVersion) -source=$(cd $TEMP; dpkg-parsechangelog -SSource) -target=$(cd $TEMP; dpkg-parsechangelog -SDistribution) -rm -rf "$TEMP" +mkdir "$temp/debian" +git cat-file blob "$branch":debian/changelog >"$temp/debian/changelog" +version=$(cd $temp; dpkg-parsechangelog -SVersion) +source=$(cd $temp; dpkg-parsechangelog -SSource) +target=$(cd $temp; dpkg-parsechangelog -SDistribution) +rm -rf "$temp" trap - EXIT # ---- Useful sanity checks -if [ "$force" != "yes" ]; then +if ! $force; then if [ "$target" = "UNRELEASED" ]; then fail "UNRELEASED changelog" @@ -189,24 +189,14 @@ if [ "$force" != "yes" ]; then # - walking backwards from $branch, if there is an archive/ strictly # before we reach most recent debian/ tag, error, this might be a # push of the dgit view to the maintainer branch - # - # - check for UNRELEASED changelog fi # ---- Create the git tag -get_file_from_ref () { - local path=$1 - if git ls-tree --name-only -r "$branch" \ - | grep -Eq "^$path$"; then - git cat-file blob $branch:$path - fi -} - format="$(get_file_from_ref debian/source/format)" case "$format" in - '3.0 (quilt)') upstream=true ;; + '3.0 (quilt)') upstream=true ;; '3.0 (native)') upstream=false ;; '1.0'|'') if get_file_from_ref debian/source/options | grep '^-sn *$'; then @@ -214,7 +204,7 @@ case "$format" in elif get_file_from_ref debian/source/options | grep '^-sk *$'; then upstream=true else - fail 'xxxx see sn /sk docs' + fail 'please see "SOURCE FORMAT 1.0" in git-debpush(1)' fi ;; *) @@ -222,6 +212,7 @@ case "$format" in ;; esac +upstream_info="" if $upstream; then upstream_tag=$(git deborig --just-print --version="$version" \ | head -n1) @@ -234,8 +225,10 @@ git_version=$(echo $version | tr ':~' '%_' | sed 's/\.(?=\.|$|lock$)/.#/g') debian_tag="$distro/$git_version" +# If the user didn't supply a quilt mode, look for it in a previous +# tag made by this script if [ "x$quilt_mode" = "x" ] && [ "$format" = "3.0 (quilt)" ]; then - set +o pipefail # perl will SIGPIPE git-log here + set +o pipefail # perl will SIGPIPE git-log(1) here tag=$(git log --pretty=format:'%D' --decorate=full "$branch" \ | perl -wne 'use Dpkg::Version; @pieces = split /, /, $_;