blob: 1746129bac1f933a0bc1619f794421fa6baf6e75 [file] [log] [blame]
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Make sure that bash version meets the pre-requisite
if [[ -z "${BASH_VERSINFO[0]}" ]] \
|| [[ "${BASH_VERSINFO[0]}" -lt 3 ]] \
|| [[ "${BASH_VERSINFO[0]}" -eq 3 && "${BASH_VERSINFO[1]}" -lt 2 ]]; then
echo "bash v3.2+ is required. Sorry."
exit 1
fi
this="${BASH_SOURCE-$0}"
BINDIR=$(cd -P -- "$(dirname -- "${this}")" >/dev/null && pwd -P)
#shellcheck disable=SC2034
QATESTMODE=false
# dummy functions
function add_vote_table
{
true
}
function add_footer_table
{
true
}
function big_console_header
{
true
}
function add_test
{
true
}
## @description Clean the filesystem as appropriate and then exit
## @audience private
## @stability evolving
## @replaceable no
## @param runresult
function cleanup_and_exit
{
local result=$1
if [[ ${PATCH_DIR} =~ ^/tmp/yetus
&& -d ${PATCH_DIR} ]]; then
rm -rf "${PATCH_DIR}"
fi
# shellcheck disable=SC2086
exit ${result}
}
## @description Setup the default global variables
## @audience public
## @stability stable
## @replaceable no
function setup_defaults
{
common_defaults
}
## @description Print the usage information
## @audience public
## @stability stable
## @replaceable no
function yetus_usage
{
echo "smart-apply-patch.sh [OPTIONS] patch"
echo ""
echo "Where:"
echo " patch is a file, URL, or bugsystem-compatible location of the patch file"
echo ""
echo "Options:"
echo ""
yetus_add_option "--committer" "Apply patches like a boss."
yetus_add_option "--debug" "If set, then output some extra stuff to stderr"
yetus_add_option "--dry-run" "Check for patch viability without applying"
yetus_add_option "--list-plugins" "List all installed plug-ins and then exit"
yetus_add_option "--modulelist=<list>" "Specify additional modules to test (comma delimited)"
yetus_add_option "--offline" "Avoid connecting to the Internet"
yetus_add_option "--patch-dir=<dir>" "The directory for working and output files (default '/tmp/yetus-(random))"
yetus_add_option "--personality=<file>" "he personality file to load"
yetus_add_option "--plugins=<list>" "Specify which plug-ins to add/delete (comma delimited; use 'all' for all found)"
yetus_add_option "--project=<name>" "The short name for project currently using test-patch (default 'yetus')"
yetus_add_option "--skip-system-plugins" "Do not load plugins from ${BINDIR}/test-patch.d"
yetus_add_option "--user-plugins=<dir>" "A directory of user provided plugins. see test-patch.d for examples (default empty)"
yetus_add_option "--version" "Print release version information and exit"
yetus_add_option "--gpg-sign" "GPG sign the commit using gpg keys"
yetus_generic_columnprinter "${YETUS_OPTION_USAGE[@]}"
yetus_reset_usage
echo ""
echo "Shell binary overrides:"
yetus_add_option "--awk-cmd=<cmd>" "The 'awk' command to use (default 'awk')"
yetus_add_option "--curl-cmd=<cmd>" "The 'curl' command to use (default 'curl')"
yetus_add_option "--diff-cmd=<cmd>" "The GNU-compatible 'diff' command to use (default 'diff')"
yetus_add_option "--file-cmd=<cmd>" "The 'file' command to use (default 'file')"
yetus_add_option "--git-cmd=<cmd>" "The 'git' command to use (default 'git')"
yetus_add_option "--grep-cmd=<cmd>" "The 'grep' command to use (default 'grep')"
yetus_add_option "--patch-cmd=<cmd>" "The 'patch' command to use (default 'patch')"
yetus_add_option "--sed-cmd=<cmd>" "The 'sed' command to use (default 'sed')"
yetus_generic_columnprinter "${YETUS_OPTION_USAGE[@]}"
yetus_reset_usage
echo ""
importplugins
unset TESTFORMATS
unset TESTTYPES
unset BUILDTOOLS
for plugin in ${BUGSYSTEMS}; do
if declare -f ${plugin}_usage >/dev/null 2>&1; then
echo ""
echo "${plugin} plugin usage options:"
"${plugin}_usage"
yetus_generic_columnprinter "${YETUS_OPTION_USAGE[@]}"
yetus_reset_usage
fi
done
}
## @description Interpret the command line parameters
## @audience private
## @stability stable
## @replaceable no
## @param $@
## @return May exit on failure
function parse_args
{
local i
common_args "$@"
for i in "$@"; do
case ${i} in
--committer)
COMMITMODE=true
;;
--gpg-sign)
GPGSIGN=true
;;
--dry-run)
PATCH_DRYRUNMODE=true
;;
--*)
## PATCH_OR_ISSUE can't be a --. So this is probably
## a plugin thing.
continue
;;
*)
PATCH_OR_ISSUE=${i#*=}
;;
esac
done
if [[ ! -d ${PATCH_DIR} ]]; then
mkdir -p "${PATCH_DIR}"
if [[ $? != 0 ]] ; then
yetus_error "ERROR: Unable to create ${PATCH_DIR}"
cleanup_and_exit 1
fi
fi
}
## @description git am dryrun
## @replaceable no
## @audience private
## @stability evolving
function gitam_dryrun
{
# there is no dryrun method for git-am, so just
# use apply instead.
gitapply_dryrun "$@"
if [[ ${PATCH_METHOD} = "gitapply" ]]; then
PATCH_METHOD="gitam"
fi
}
## @description git am signoff
## @replaceable no
## @audience private
## @stability evolving
function gitam_apply
{
declare patchfile=$1
declare gpg=$2
if [[ ${gpg} = true ]]; then
EXTRA_ARGS="-S"
fi
echo "Applying the patch:"
yetus_run_and_redirect "${PATCH_DIR}/apply-patch-git-am.log" \
"${GIT}" am --signoff ${EXTRA_ARGS} --whitespace=fix "-p${PATCH_LEVEL}" "${patchfile}"
RESULT=$?
${GREP} -v "^Checking" "${PATCH_DIR}/apply-patch-git-am.log"
# fallback
if [[ ${RESULT} -gt 0 && ${PATCH_SYSTEM} == 'jira' ]]; then
echo "Use git apply and commit with the information from jira."
gitapply_and_commit "${patchfile}"
fi
}
## @description get author and summary from jira and commit it.
## if the author and the summary contains " or *,
## the function does not work correctly because
## the characters are used for delimiters.
## @replaceable no
## @audience private
## @stability evolving
function gitapply_and_commit
{
declare patchfile=$1
declare jsontmpfile
declare assigneeline
declare assigneefile
declare name
declare email
declare author
declare summary
yetus_debug "gitapply_and_commit: fetching ${JIRA_URL}/rest/api/2/issue/${PATCH_OR_ISSUE}"
if ! jira_http_fetch "rest/api/2/issue/${PATCH_OR_ISSUE}" "${PATCH_DIR}/issue"; then
yetus_debug "gitapply_and_commit: not a JIRA."
return 1
fi
jsontmpfile="${PATCH_DIR}/jsontmpfile"
# cannot set " as delimiter for cut command in script, so replace " with *
tr ',' '\n' < "${PATCH_DIR}/issue" | ${SED} 's/\"/*/g' > "${jsontmpfile}"
assigneeline=$(${GREP} -n -E "^\*assignee\*:" "${jsontmpfile}" | cut -f1 -d":")
assigneefile="${PATCH_DIR}/assigneefile"
tail -n +"${assigneeline}" "${jsontmpfile}" | head -n 20 > "${assigneefile}"
name=$(${GREP} "displayName" "${assigneefile}" | cut -f4 -d"*")
email=$(${GREP} "emailAddress" "${assigneefile}" | cut -f4 -d"*" \
| ${SED} 's/ at /@/g' | ${SED} 's/ dot /./g')
author="${name} <${email}>"
summary=$(${GREP} -E "^\*summary\*:" "${jsontmpfile}" | cut -f4 -d"*")
gitapply_apply "${patchfile}"
${GIT} add --all
echo "Committing with author: ${author}, summary: ${summary}"
yetus_run_and_redirect "${PATCH_DIR}/apply-patch-git-am-fallback.log" \
"${GIT}" commit ${EXTRA_ARGS} --signoff -m "${PATCH_OR_ISSUE}. ${summary}" \
--author="${author}"
}
## @description import core library routines
## @audience private
## @stability evolving
function import_core
{
declare filename
for filename in "${BINDIR}/core.d"/*; do
# shellcheck disable=SC1091
# shellcheck source=core.d/01-common.sh
. "${filename}"
done
}
trap "cleanup_and_exit 1" HUP INT QUIT TERM
import_core
setup_defaults
parse_args "$@"
importplugins
yetus_debug "Removing BUILDTOOLS, TESTTYPES, and TESTFORMATS from installed plug-in list"
unset BUILDTOOLS
unset TESTTYPES
unset TESTFORMATS
parse_args_plugins "$@"
plugins_initialize
locate_patch
if [[ ${COMMITMODE} = true ]]; then
status=$(${GIT} status --porcelain)
if [[ "$status" != "" ]] ; then
yetus_error "ERROR: Can't use --committer option in a workspace that contains the following modifications:"
yetus_error "${status}"
cleanup_and_exit 1
fi
PATCH_METHODS=("gitam" "${PATCH_METHODS[@]}")
fi
patchfile_dryrun_driver "${PATCH_DIR}/patch"
RESULT=$?
if [[ ${RESULT} -gt 0 ]]; then
yetus_error "ERROR: Aborting! ${PATCH_OR_ISSUE} cannot be verified."
cleanup_and_exit ${RESULT}
fi
if [[ ${PATCH_DRYRUNMODE} == false ]]; then
patchfile_apply_driver "${PATCH_DIR}/patch" "${GPGSIGN}"
RESULT=$?
fi
if [[ ${COMMITMODE} = true
&& ${PATCH_METHOD} != "gitam" ]]; then
yetus_debug "Running git add -A"
git add -A
fi
cleanup_and_exit ${RESULT}