#!/bin/bash

#  git-packaging-hooks - git hooks to semi-automate releases and distro packaging
#
#  Copyright 2017 bill-auger <https://github.com/bill-auger/git-packaging-hooks/issues>
#
#  git-packaging-hooks is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 3 as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  git-packaging-hooks is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License version 3
#  along with git-packaging-hooks.  If not, see <http://www.gnu.org/licenses/>.


readonly HOOKS_PATH=$(git config --local core.hooksPath)
readonly COMMON_DEFS_FILE=$HOOKS_PATH/common.sh.inc
source $COMMON_DEFS_FILE
[ ! -f $COMMON_DEFS_FILE ] && TraceError "missing $COMMON_DEFS_FILE - aborting commit" && exit 1


if (($IS_STAGING_BRANCH))
then TraceStage "running staging-specific post-commit hooks"

     # set "release" tag
     for revision_tag in $REVISION_TAGS
     do  TraceStep "removing un-merged revision tag '$revision_tag'"
         git tag --delete $revision_tag > /dev/null
     done
     if   [ ! -f $TAGS_FILE ]
     then TraceStep "adding revision tag '$VERSION_STRING'"
          git tag $VERSION_STRING -m "$VERSION_STRING"
     else declare -a orphaned_tags=( $(cat $TAGS_FILE | sort | uniq) )
          orphaned_minor_tag=${orphaned_tags[0]}
          orphaned_rev_tag=${orphaned_tags[1]}
          orphaned_other_tags=${orphaned_tags[@]:2}
          [ "$orphaned_minor_tag"  ] && TraceStep "restoring minor version tag '$orphaned_minor_tag'"
          [ "$orphaned_rev_tag"    ] && TraceStep "adding revision tag '$orphaned_rev_tag'"
          [ "$orphaned_other_tags" ] && TraceStep "restoring other tags '$orphaned_other_tags'"
          for orphaned_tag in "${orphaned_tags[@]}" ; do git tag $orphaned_tag ; done
          rm $TAGS_FILE
     fi

     # rebuild, install, and verify
     tmp_builddir="tmp_builddir"
     TraceStep "re-configuring meson"
     rm -rf $tmp_builddir > /dev/null
     for compiler in clang gcc; do
       CC=$compiler CXX=$compiler meson $tmp_builddir -Denable_tests=true 2> /dev/null
       TraceStep "verifying re-build/test"
       ninja -C $tmp_builddir test > /dev/null
       #ninja -C $tmp_builddir install > /dev/null
       #ninja -C $tmp_builddir uninstall > /dev/null
       rm -rf $tmp_builddir > /dev/null
     done

     # commit automated changes, and ensure signed
     git add --all
     git diff --exit-code --cached && is_index_clean=1        || is_index_clean=0
     git verify-commit --raw HEAD > /dev/null && has_trusted_signature=1 || has_trusted_signature=0
     echo "index clean $is_index_clean has_trusted_sig $has_trusted_signature"
     (($is_index_clean       )) || TraceStep "amending commit with automated changes"
     (($has_trusted_signature)) || TraceStep "amending commit to ensure signature exists"
     (($is_index_clean)) && (($has_trusted_signature))              || \
     git commit --gpg-sign --amend --reuse-message=HEAD > /dev/null

     TraceStage "completed staging-specific post-commit hooks"
elif (($IS_PACKAGING_BRANCH))
then (($IS_AMEND_COMMIT)) && exit 0

     TraceStage "running packaging-specific post-commit hooks"

     # implode tarball
     TraceStep "imploding tarball"
     rm $TARBALL_FILE $TARBALL_FILE.sig $PKGBUILD_FILE.sig 2> /dev/null
     git archive --prefix=$TARBALL_INNER_DIR/ --output=$TARBALL_FILE $VERSION_STRING

     # generate tarball metadata
     TraceStep "generating checksums"
     TARBALL_MD5SUM="$(   md5sum     $TARBALL_FILE | cut --delimiter=' ' --fields=1)"
     TraceStep "$TARBALL_MD5SUM"
     TARBALL_SHA1SUM="$(  sha1sum    $TARBALL_FILE | cut --delimiter=' ' --fields=1)                        "
     TARBALL_SHA256SUM="$(sha256sum  $TARBALL_FILE | cut --delimiter=' ' --fields=1)"
     FILE_SIZE=$(         wc --bytes $TARBALL_FILE | cut --delimiter=' ' --fields=1)
     PKGBUILD_MD5SUMS="'$TARBALL_MD5SUM'"
     TraceStep "$PKGBUILD_MD5SUMS"

     # inject tarball metadata into packaging files
     TraceStep "preparing packaging files"
     for dsc_file in ${DSC_FILES[@]}
     do  echo "Checksums-Sha1:"                                         >> $dsc_file
         echo " $TARBALL_SHA1SUM $FILE_SIZE $DEB_TARBALL_FILENAME"      >> $dsc_file
         echo "Checksums-Sha256:"                                       >> $dsc_file
         echo " $TARBALL_SHA256SUM $FILE_SIZE $DEB_TARBALL_FILENAME"    >> $dsc_file
         echo "Files:"                                                  >> $dsc_file
         echo " $FAUX_DSC_MD5SUM $FAUX_DSC_SIZE $DEB_TARBALL_FILENAME"  >> $dsc_file
         echo " $FAUX_DSC_MD5SUM $FAUX_DSC_SIZE $DEB_DIFFBALL_FILENAME" >> $dsc_file
     done
     sed --in-place "s/^md5sums=.*$/md5sums=( $PKGBUILD_MD5SUMS )/"        $PKGBUILD_FILE

     # set uniform commit message and ensure signed
     git commit --gpg-sign --amend --allow-empty --message="$GIT_COMMIT_MSG" > /dev/null

     # sign tarball and PKGBUILD
     gpg --detach-sign --yes $TARBALL_FILE
     gpg --detach-sign --yes $PKGBUILD_FILE


     ### gitlab steps ###

     # create upstream tarball
     TraceStep "pushing staging branch, packaging branch, and revision tag to gitlab"
     git push --force $REMOTE_NAME $STAGING_BRANCH $PACKAGING_BRANCH $VERSION_STRING 2> /dev/null

     ## destroy any existing gitlab "tag release" with same tag
     #TraceStep "querying existing gitlab \"tag release\" '$VERSION_STRING'"
     #resp_json=$(curl $CURL_RESP_ARGS --header \"PRIVATE-TOKEN: $GITLAB_AUTH_TOKEN\" $GITLAB_API_URL/$VERSION_STRING)
     #tag_name=$(echo $resp_json | jq '.tag_name')
     #tag_name=${tag_name:1:-1}
     #if [[ $tag_name == $VERSION_STRING ]]
     #then TraceStep "deleting existing gitlab \"tag release\" - id: '$tag_name'"
          #resp_status=$(curl --request DELETE                                   \
                             #--header "PRIVATE-TOKEN: $GITLAB_AUTH_TOKEN" \
                             #--header "Content-Type: application/json"          \
                             #--header "Accept: application/json"                \
                             #--silent --output /dev/null --write-out %{http_code}                                  \
                             #"$GITLAB_API_URL/$tag_name"                        )
         #if   [ "$resp_status" == "200" ]
         #then TraceStep "deleted gitlab \"tag release\" - id: '$tag_name'"
         #else TraceStep "failed to delete gitlab \"tag release\" - id: '$tag_name', resp $resp_status" ; exit 1 ;
         #fi
     #fi

     ### upload signatures to gitlab "tag release" to
     ### be referenced when creating the release
     #for upload_file in ${UPLOAD_FILES[@]}
     #do  filename=$(basename $upload_file)
         #TraceStep "uploading '$filename' to gitlab \"tag release\" '$VERSION_STRING'"
         #file_basename=$(basename $upload_file)
         #resp_status=$(curl --request POST --form "file=@$upload_file"       \
                            #--header "PRIVATE-TOKEN: $GITLAB_AUTH_TOKEN" \
                            #--header "Accept: application/json"                \
                            #--silent --output /tmp/$file_basename --write-out %{http_code}                                  \
                            #${GITLAB_UPLOAD_FILE_URL}                       )
          #if   [ "$resp_status" == "201" ]
          #then TraceStep "uploaded '$upload_file'"
          #else TraceStep "failed to upload '$upload_file'" ; exit 1 ;
          #fi
     #done

     ### create github "tag release"
     #TraceStep "creating gitlab \"tag release\" '$VERSION_STRING'"
     ##content=`cat obs/release_notes.md`
     ##echo $content
     #while read p; do
       #content+="$p\r\n"
     #done <obs/release_notes.md
     #CREATE_RELEASE_JSON="{
       #\"tag_name\": \"$VERSION_STRING\",
       #\"name\": \"$VERSION_STRING\",
       #\"tag_name\": \"$VERSION_STRING\",
       #\"description\": \"$content\",
       #\"assets\": { \"links\": ["
     #for upload_file in ${UPLOAD_FILES[@]}
     #do  filename=$(basename $upload_file)
       #file_url=$(cat /tmp/$filename | jq '.url')
       #file_url=${file_url:1:-1}
       #CREATE_RELEASE_JSON="$CREATE_RELEASE_JSON {
         #\"name\": \"$filename\",
         #\"url\": \"$GITLAB_REPO$file_url\" },"
       #TraceStep "$file_url"
     #done
     #CREATE_RELEASE_JSON="${CREATE_RELEASE_JSON%?} ]
       #} }"

     #resp_status=$(curl --request POST --data "$CREATE_RELEASE_JSON"       \
                        #--header "PRIVATE-TOKEN: $GITLAB_AUTH_TOKEN" \
                        #--header "Content-Type: application/json"          \
                        #--header "Accept: application/json"                \
                        #$CURL_STATUS_ARGS                                  \
                        #$GITLAB_API_URL                                    )
     #if   [ "$resp_status" == "201" ]
     #then TraceStep "created gitlab \"tag release\" '$VERSION_STRING'"
     #else TraceStep "failed to create gitlab \"tag release\" '$VERSION_STRING'" ; exit 1 ;
     #fi


     ### ensure the new github "tag release" is accessible via the API
     #TraceStep "confirming existence of new gitlab \"tag release\" '$VERSION_STRING'"
     #resp_json=$(curl $CURL_RESP_ARGS --header \"PRIVATE-TOKEN: $GITLAB_AUTH_TOKEN\" $GITLAB_API_URL/$VERSION_STRING)
     #tag_name=$(echo $resp_json | jq '.tag_name')
     #tag_name=${tag_name:1:-1}
     #if [[ $tag_name == $VERSION_STRING ]]
     #then TraceStep "confirmed existence of new gitlab \"tag release\" - id: '$tag_name'"
     #else TraceStep "failed to fetch new gitlab \"tag release\" '$VERSION_STRING'" ; exit 1 ;
     #fi


     ## download and verify github "tag release" tarball and PKGBUILD
     TraceStep "downloading remote tarball, PKGBUILD, and signatures"

     _tarball_url="https://git.zrythm.org/cgit/$UPSTREAM_NAME/snapshot/$UPSTREAM_NAME-$VERSION_STRING.tar.gz"
      TraceStep "$_tarball_url"
     curl $CURL_FETCH_ARGS "$_tarball_url"
     TARBALL_MD5SUM="$(   md5sum     $TARBALL_FILE | cut --delimiter=' ' --fields=1)"
     TraceStep "$TARBALL_MD5SUM"
     #TraceStep "curl $CURL_FETCH_ARGS \"$_tarball_url\""
     #curl $CURL_FETCH_ARGS "$GITLAB_REPO/$(cat /tmp/$TARBALL_FILENAME.sig | jq '.url' | sed 's/\"//g')" ;
     #curl $CURL_FETCH_ARGS "$GITLAB_REPO/$(cat /tmp/PKGBUILD | jq '.url' | sed 's/\"//g')" ;
     #curl $CURL_FETCH_ARGS "$GITLAB_REPO/$(cat /tmp/PKGBUILD.sig | jq '.url' | sed 's/\"//g')" ;
     #for remote_file in ${REMOTE_FILENAMES[@]}
     #do  if [ -f $remote_file -a "$(stat --printf='%s' $remote_file)" != "9" ] # 'Not Found'
         #then TraceStep "downloaded $remote_file"
         #else TraceStep "failed to download $remote_file"
              #exit 1
         #fi
     #done
     #if   gpg --verify --verify-options no-show-photos ./$TARBALL_FILENAME.sig 2> /dev/null && \
          #diff $TARBALL_FILE     ./$TARBALL_FILENAME                            > /dev/null && \
          #diff $TARBALL_FILE.sig ./$TARBALL_FILENAME.sig                        > /dev/null && \
          #gpg --verify --verify-options no-show-photos ./PKGBUILD.sig          2> /dev/null && \
          #diff $PKGBUILD_FILE     ./PKGBUILD                                    > /dev/null && \
          #diff $PKGBUILD_FILE.sig ./PKGBUILD.sig                                > /dev/null
     #then TraceStep "verified remote tarball, PKGBUILD, and signatures"
     #else TraceStep "failed to verify remote tarball, PKGBUILD, or signatures"
          #exit 1
     #fi


     ### OBS steps ###

     # copy OBS files to local OSC build directory and trigger remote builds

     TraceStep "populating OSC build directory"
     cd $OSC_DIR/ && rm ./*
     for obs_file in ${OBS_FILES[@]}
     do  cp $obs_file $OSC_DIR/
         osc add ./$(basename $obs_file) > /dev/null
     done
     TraceStep "triggering OSC remote builds"
     osc checkin --message=$OSC_COMMIT_MSG > /dev/null

     # cleanup transient files
     TraceStep "cleaning up transient files"
     cd $PROJECT_DIR
     for transient_file in ${CLEANUP_FILES[@]} ; do rm $transient_file ; done ;
     git clean $GIT_CLEAN_OPTIONS &> /dev/null


     ### debian steps ###

     TraceStage "completed packaging-specific post-commit hooks"
fi
