chiark / gitweb /
git-debpush: check for pushing the dgit view to the maintainer view
[dgit.git] / git-debpush
index 74cb4aa1ecd665dd0dc8961aa390a83aa7d8d509..6c41908633f10c3fca193e07ea872eacce515d89 100755 (executable)
@@ -20,7 +20,7 @@
 set -e$DGIT_TEST_DEBPUSH_DEBUG
 set -o pipefail
 
-# PRINCIPLES OF OPERATION
+# DESIGN PRINCIPLES
 #
 # - do not invoke dgit, do anything involving any tarballs, no network
 #   access except `git push` right at the end
@@ -63,10 +63,33 @@ get_file_from_ref () {
     fi
 }
 
+failed_check=false
+fail_check () {
+    if $force; then
+        echo >&2 "$us: warning: $*"
+    else
+        echo >&2 "$us: $*"
+        failed_check=true
+    fi
+}
+
+find_last_tag () {
+    local prefix=$1
+
+    set +o pipefail             # perl will SIGPIPE git-log(1) here
+    git log --pretty=format:'%D' --decorate=full "$branch" \
+        | perl -wne 'use Dpkg::Version;
+            @pieces = split /, /, $_;
+            @debian_tag_vs = sort { version_compare($b, $a) }
+                map { m|tag: refs/tags/'"$prefix"'(.+)| ? $1 : () } @pieces;
+            if (@debian_tag_vs) { print "'"$prefix"'$debian_tag_vs[0]\n"; exit }'
+    set -o pipefail
+}
+
 # ---- Parse command line
 
 getopt=$(getopt -s bash -o 'nfu:' \
-              -l 'no-push,force,branch:,remote:,distro:,quilt:,gbp,dpm,\
+              -l 'no-push,force,branch:,remote:,distro:,upstream:,quilt:,gbp,dpm,\
 baredebian,baredebian+git,baredebian+tarball' \
               -n "$us" -- "$@")
 eval "set - $getopt"
@@ -90,11 +113,13 @@ while true; do
         '--remote')       remote=$2;               shift 2; continue ;;
         '--distro')       distro=$2;               shift 2; continue ;;
         '--quilt')        quilt_mode=$2;           shift 2; continue ;;
+        '--upstream')     upstream_tag=$2;         shift 2; continue ;;
 
         '--baredebian'|'--baredebian+git')
             quilt_mode=baredebian;         shift; continue ;;
         '--baredebian+tarball')
-            quilt_mode=baredebian+tarball; shift; continue ;;
+            fail "--baredebian+tarball quilt mode not supported"
+            ;;
 
         '--') shift; break ;;
        *) badusage "unknown option $1" ;;
@@ -106,8 +131,9 @@ if [ $# != 0 ]; then
 fi
 
 case "$quilt_mode" in
-    linear|auto|smash|nofix|gbp|dpm|unapplied|baredebian|baredebian+tarball|'') ;;
+    linear|auto|smash|nofix|gbp|dpm|unapplied|baredebian|'') ;;
     baredebian+git) quilt_mode="baredebian" ;;
+    baredebian+tarball) fail "--baredebian+tarball quilt mode not supported" ;;
     *) badusage "invalid quilt mode: $quilt_mode" ;;
 esac
 
@@ -172,24 +198,36 @@ target=$(cd $temp; dpkg-parsechangelog -SDistribution)
 rm -rf "$temp"
 trap - EXIT
 
+# ---- Gather git history information
+
+last_debian_tag=$(find_last_tag "debian/")
+last_archive_tag=$(find_last_tag "archive/debian/")
+
 # ---- Useful sanity checks
 
-if ! $force; then
+if [ "$target" = "UNRELEASED" ]; then
+    fail_check "UNRELEASED changelog"
+fi
 
-    if [ "$target" = "UNRELEASED" ]; then
-        fail "UNRELEASED changelog"
+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 \
+"looks like you might be trying to push the dgit view to the maintainer branch?"
     fi
+fi
 
-    # TODO additional checks we might do:
-    #
-    # - are we uploading to a different suite from the last tag
-    #   (e.g. unstable after experimental)?  user should pass option to
-    #   confirm
-    #
-    # - 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
+# TODO additional checks we might do:
+#
+# - are we uploading to a different suite from the last tag
+#   (e.g. unstable after experimental)?  user should pass option to
+#   confirm
 
+if ! $force && $failed_check; then
+    fail "some checks failed; you can override with --force"
 fi
 
 # ---- Create the git tag
@@ -214,10 +252,26 @@ esac
 
 upstream_info=""
 if $upstream; then
-    # xxx want way to override this
-    upstream_tag=$(git deborig --just-print --version="$version" \
-                       | head -n1)
-    upstream_committish=$(git rev-parse ${upstream_tag}^{})
+    if [ "x$upstream_tag" = x ]; then
+       upstream_tag=$(
+           set +e
+           git deborig --just-print --version="$version" \
+                          | head -n1
+           ps="${PIPESTATUS[*]}"
+           set -e
+           case "$ps" in
+               "0 0"|"141 0") ;; # ok or SIGPIPE
+               *" 0")
+                   echo >&2 \
+ "$us: git-deborig failed; maybe try $us --upstream=TAG"
+                   exit 0
+                   ;;
+               *) exit 127; # presumably head will have complained
+           esac
+       )
+       if [ "x$upstream_tag" = x ]; then exit 127; fi
+    fi
+    upstream_committish=$(git rev-parse "refs/tags/${upstream_tag}"^{})
     upstream_info=" upstream-tag=$upstream_tag upstream=$upstream_committish"
 fi
 
@@ -229,15 +283,9 @@ 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(1) here
-    tag=$(git log --pretty=format:'%D' --decorate=full "$branch" \
-        | perl -wne 'use Dpkg::Version;
-               @pieces = split /, /, $_;
-               @debian_tag_vs = sort {version_compare($b, $a)}
-                    map { m|tag: refs/tags/debian/(.+)| ? $1 : () } @pieces;
-               if (@debian_tag_vs) { print "debian/$debian_tag_vs[0]\n"; exit }')
-    if [ "x$tag" != "x" ]; then
-        quilt_mode=$(git cat-file -p $(git rev-parse "$tag") \
+    set +o pipefail             # perl will SIGPIPE git-cat-file(1) here
+    if [ "x$last_debian_tag" != "x" ]; then
+        quilt_mode=$(git cat-file -p $(git rev-parse "$last_debian_tag") \
                          | perl -wne \
                                 'm/^\[dgit.*--quilt=([a-z+]+).*\]$/;
                                  if ($1) { print "$1\n"; exit }')