chiark / gitweb /
dgit(1) document the presence of the aptget archive-query method
[dgit.git] / git-debpush
index c8295798cab4c408d5fa70be2a2ca41105aad6d9..0ddbfc47301f331a87b3f4a4db219e4d7db5c7ef 100755 (executable)
@@ -73,6 +73,19 @@ fail_check () {
     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:' \
@@ -127,7 +140,7 @@ esac
 # ---- 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)"
@@ -154,7 +167,7 @@ esac
 case "$branch" in
     refs/heads/*)
         b=${branch#refs/heads/}
-        push_branch+=("$b")
+        to_push+=("$b")
         remoteconfigs+=( branch.$b.pushRemote branch.$b.remote )
         ;;
 esac
@@ -185,28 +198,6 @@ target=$(cd $temp; dpkg-parsechangelog -SDistribution)
 rm -rf "$temp"
 trap - EXIT
 
-# ---- Useful sanity checks
-
-if [ "$target" = "UNRELEASED" ]; then
-    fail_check "UNRELEASED changelog"
-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
-
-if ! $force && $failed_check; then
-    fail "some checks failed; you can override with --force"
-fi
-
-# ---- Create the git tag
-
 format="$(get_file_from_ref debian/source/format)"
 case "$format" in
     '3.0 (quilt)')  upstream=true ;;
@@ -225,6 +216,11 @@ case "$format" in
        ;;
 esac
 
+# ---- Gather git history information
+
+last_debian_tag=$(find_last_tag "debian/")
+last_archive_tag=$(find_last_tag "archive/debian/")
+
 upstream_info=""
 if $upstream; then
     if [ "x$upstream_tag" = x ]; then
@@ -248,25 +244,67 @@ 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
+
+if [ "$target" = "UNRELEASED" ]; then
+    fail_check "UNRELEASED changelog"
+fi
+
+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
+
+if ! [ "x$last_debian_tag" = "x" ]; then
+    temp=$(mktemp -d)
+    trap cleanup EXIT
+    mkdir "$temp/debian"
+    git cat-file blob "$last_debian_tag":debian/changelog >"$temp/debian/changelog"
+    prev_target=$(cd $temp; dpkg-parsechangelog -SDistribution)
+    rm -rf "$temp"
+    trap - EXIT
+
+    if ! [ "$prev_target" = "$target" ] && ! [ "$target" = "UNRELEASED" ]; then
+        fail_check \
+"last upload targeted $prev_target, now targeting $target; might be a mistake?"
+    fi
+fi
+
+if ! [ "x$upstream_tag" = "x" ] \
+        && ! git merge-base --is-ancestor "$upstream_tag" "$branch" \
+        && ! [ "$quilt_mode" = "baredebian" ]; then
+    fail_check \
+ "upstream tag $upstream_tag is not an ancestor of $branch; probably a mistake"
+fi
+
+
+if ! $force && $failed_check; then
+    fail "some checks failed; you can override with --force"
+fi
+
+# ---- 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
 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 }')
@@ -295,6 +333,5 @@ EOF
 # ---- Do a git push
 
 if $pushing; then
-    # xxx when user can specify upstream_tag, must cope with spaces
-    git push "$remote" "${push_branch[@]}" $upstream_tag "$debian_tag"
+    git push "$remote" "${to_push[@]}"
 fi