X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=git-debpush;h=2790560cf21658b5275bcd7d180db9909d696c59;hb=193cfa37a544a2c44f9252b83da54ca1af01c01f;hp=39ff4103150a504bc73971d155f7e2f29ceb51d7;hpb=ae83d742219963877aad83685460f6726d715313;p=dgit.git diff --git a/git-debpush b/git-debpush index 39ff4103..2790560c 100755 --- a/git-debpush +++ b/git-debpush @@ -35,9 +35,11 @@ set -o pipefail # mode; if there is a previous tag, and no quilt mode provided, assume # same quilt mode as in previous tag created by this script -# ---- Helper functions and variables +# **** Helper functions and variables **** us="$(basename $0)" +git_playtree_setup=git-playtree-setup ###substituted### +git_playtree_setup=${DEBPUSH_GIT_PLAYTREE_SETUP-$git_playtree_setup} cleanup() { if [ -d "$temp" ]; then @@ -57,22 +59,35 @@ badusage () { get_file_from_ref () { local path=$1 + # redirect to /dev/null instead of using `grep -Eq` to avoid grep + # SIGPIPEing git-ls-tree if git ls-tree --name-only -r "$branch" \ - | grep -Eq "^$path$"; then + | grep -E "^$path$" >/dev/null; then git cat-file blob $branch:$path fi } failed_check=false fail_check () { - if $force; then - echo >&2 "$us: warning: $*" + local check=$1; shift + local check_is_forced=false + + case ",$force," in + *",$check,"*) check_is_forced=true ;; + esac + if $force_all || $check_is_forced; then + echo >&2 "$us: warning: $* ('$check' check)" else - echo >&2 "$us: $*" + echo >&2 "$us: $* ('$check' check)" failed_check=true fi } +fail_check_upstream_nonidentical () { + fail_check upstream-nonidentical \ + "the upstream source in tag $upstream_tag is not identical to the upstream source in $branch" +} + find_last_tag () { local prefix=$1 @@ -86,10 +101,77 @@ find_last_tag () { set -o pipefail } -# ---- Parse command line +check_treesame () { + local first=$1 + local second=$2 + shift 2 + + set +e + git diff --quiet --exit-code "$first".."$second" -- . "$@" + git_diff_rc=$? + set -e + + # show the user what the difference was + if [ $git_diff_rc = 1 ]; then + git diff --compact-summary "$first".."$second" -- . "$@" + fi + + if [ $git_diff_rc -le 1 ]; then + return $git_diff_rc + else + fail "'git diff' exited with unexpected code $git_diff_rc" + fi +} + +check_patches_apply () { + local should_match_branch="$1" + + local playground="$(git rev-parse --git-dir)/gdp" + local playtree="$playground/apply-patches" + local git_apply_rc=0 + + rm -rf "$playground" + mkdir -p "$playtree" + local pwd="$(pwd)" + cd "$playtree" + "$git_playtree_setup" . + + # checking out the upstream source and then d/patches on top + # ensures this check will work for a variety of quilt modes + git checkout -b upstream "$upstream_committish" + git checkout "$branch_commit" -- debian + + if [ -s "debian/patches/series" ]; then + while read patch; do + shopt -s extglob; patch="${patch%%?( )#*}"; shopt -u extglob + if [ -z "$patch" ]; then continue; fi + set +e + git apply --index "debian/patches/$patch" + git_apply_rc=$? + set -e + if ! [ $git_apply_rc = 0 ]; then + fail_check patches-applicable \ + "'git apply' failed to apply patch $patch" + break + fi + done /dev/null; then + fail_check detached \ + "HEAD is detached; you probably don't want to debpush it" +fi + +# **** Gather git information **** remoteconfigs=() -push_branch=() +to_push=() # Maybe $branch is a symbolic ref. If so, resolve it branchref="$(git symbolic-ref -q $branch || test $? = 1)" @@ -167,11 +270,14 @@ esac case "$branch" in refs/heads/*) b=${branch#refs/heads/} - push_branch+=("$b") + to_push+=("$b") remoteconfigs+=( branch.$b.pushRemote branch.$b.remote ) ;; esac +# resolve $branch to a commit +branch_commit="$(git rev-parse --verify ${branch}^{commit})" + # also check, if the branch does not have its own pushRemote or # remote, whether there's a default push remote configured remoteconfigs+=(remote.pushDefault) @@ -186,7 +292,7 @@ if $pushing && [ "x$remote" = "x" ]; then fi fi -# ---- Gather source package information +# **** Gather source package information **** temp=$(mktemp -d) trap cleanup EXIT @@ -203,9 +309,9 @@ case "$format" in '3.0 (quilt)') upstream=true ;; '3.0 (native)') upstream=false ;; '1.0'|'') - if get_file_from_ref debian/source/options | grep '^-sn *$'; then + if get_file_from_ref debian/source/options | grep -q '^-sn *$'; then upstream=false - elif get_file_from_ref debian/source/options | grep '^-sk *$'; then + elif get_file_from_ref debian/source/options | grep -q '^-sk *$'; then upstream=true else fail 'please see "SOURCE FORMAT 1.0" in git-debpush(1)' @@ -216,7 +322,7 @@ case "$format" in ;; esac -# ---- Gather git history information +# **** Gather git history information **** last_debian_tag=$(find_last_tag "debian/") last_archive_tag=$(find_last_tag "archive/debian/") @@ -244,25 +350,32 @@ if $upstream; then fi upstream_committish=$(git rev-parse "refs/tags/${upstream_tag}"^{}) upstream_info=" upstream-tag=$upstream_tag upstream=$upstream_committish" + to_push+=("$upstream_tag") fi -# ---- Useful sanity checks +# **** Useful sanity checks **** + +# ---- UNRELEASED suite if [ "$target" = "UNRELEASED" ]; then - fail_check "UNRELEASED changelog" + fail_check unreleased "UNRELEASED changelog" fi +# ---- Pushing dgit view to maintainer view + if ! [ "x$last_debian_tag" = "x" ] && ! [ "x$last_archive_tag" = "x" ]; then last_debian_tag_c=$(git rev-parse "$last_debian_tag"^{}) last_archive_tag_c=$(git rev-parse "$last_archive_tag"^{}) if ! [ "$last_debian_tag_c" = "$last_archive_tag_c" ] \ && git merge-base --is-ancestor \ "$last_debian_tag" "$last_archive_tag"; then - fail_check \ + fail_check dgit-view \ "looks like you might be trying to push the dgit view to the maintainer branch?" fi fi +# ---- Targeting different suite + if ! [ "x$last_debian_tag" = "x" ]; then temp=$(mktemp -d) trap cleanup EXIT @@ -273,29 +386,73 @@ if ! [ "x$last_debian_tag" = "x" ]; then trap - EXIT if ! [ "$prev_target" = "$target" ] && ! [ "$target" = "UNRELEASED" ]; then - fail_check \ + fail_check suite \ "last upload targeted $prev_target, now targeting $target; might be a mistake?" fi fi +# ---- Upstream tag is not ancestor of $branch + if ! [ "x$upstream_tag" = "x" ] \ && ! git merge-base --is-ancestor "$upstream_tag" "$branch" \ && ! [ "$quilt_mode" = "baredebian" ]; then - fail_check \ + fail_check upstream-nonancestor \ "upstream tag $upstream_tag is not an ancestor of $branch; probably a mistake" fi +# ---- Quilt mode-specific checks + +case "$quilt_mode" in + gbp) + check_treesame "$upstream_tag" "$branch" ':!debian' ':!**.gitignore' \ + || fail_check_upstream_nonidentical + check_patches_apply false + ;; + unapplied) + check_treesame "$upstream_tag" "$branch" ':!debian' \ + || fail_check_upstream_nonidentical + check_patches_apply false + ;; + baredebian) + check_patches_apply false + ;; + dpm|nofix) + check_patches_apply true + ;; +esac -if ! $force && $failed_check; then - fail "some checks failed; you can override with --force" +# ---- git-debrebase branch format checks + +# only check branches, since you can't run `git debrebase conclude` on +# non-branches +case "$branch" in + refs/heads/*) + # see "STITCHING, PSEUDO-MERGES, FFQ RECORD" in git-debrebase(5) + ffq_prev_ref="refs/ffq-prev/${branch#refs/}" + if git show-ref --quiet --verify "$ffq_prev_ref"; then + fail_check unstitched \ + "this looks like an unstitched git-debrebase branch, which should not be pushed" + fi +esac + +# ---- Summary + +if $failed_check; then + # We don't mention the --force=check options here as those are + # mainly for use by scripts, or when you already know what check + # is going to fail before you invoke git-debpush. Keep the + # script's terminal output as simple as possible. No "see the + # manpage"! + fail "some check(s) failed; you can pass --force to ignore them" fi -# ---- Create the git tag +# **** Create the git tag **** # convert according to DEP-14 rules git_version=$(echo $version | tr ':~' '%_' | sed 's/\.(?=\.|$|lock$)/.#/g') debian_tag="$distro/$git_version" +to_push+=("$debian_tag") # If the user didn't supply a quilt mode, look for it in a previous # tag made by this script @@ -321,19 +478,16 @@ if [ "$format" = "3.0 (quilt)" ]; then fi fi -git tag "${git_tag_opts[@]}" -s -F- "$debian_tag" "$branch" <