pkgbuildup |
|
---|---|
pkgbuildup is a helper tool for
This script uses quite a few external programs during its execution. You
need to have at least the following installed to function:
|
#!/usr/bin/bash
|
InstallRun command |
|
Variables and functions for application |
|
Application name and version |
appname="pkgbuildup"
version="0.1"
|
Show help message |
show_help() {
printf "Description:\n"
printf " ${appname} is a helper tool for AUR package maintainer to automatic update PKGBUILD files\n"
printf "\n"
printf "Usage:\n"
printf " ${appname} [-p <file>] [-l <file>] [-h] [-v]\n"
printf "\n"
printf "Options:\n"
printf " -p <file>\n"
printf " Use an alternate update script (instead of '${UPDATE_SCRIPT}')\n"
printf " -l, --listvar <file>\n"
printf " List variables in a template file\n"
printf " -h, --help\n"
printf " Prints help message\n"
printf " -v, --version\n"
printf " Prints version information\n"
exit 1
}
|
Show version |
show_version() {
printf "${appname} ${version}\n"
exit 1
}
|
Global variables, could be overwrite in PKGBUILDUP |
|
Ignore warning message. Valid: |
IGNORE_WARN="false"
|
Log file name |
PKGBUILDUP_LOG="${appname}_result.log"
|
Command to upload package to AUR. |
UPLOAD_CMD="burp -v %s"
|
File integrity check to use. Valid: |
INTEGRITY_CHECK="md5"
|
Command to get web page content. |
GET_PAGE_CMD='/usr/bin/curl -sfL --retry 3 --retry-delay 3 %s'
|
The download utilities that should use to acquire sources
Format: |
DLAGENTS=('ftp::/usr/bin/curl -fC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u'
'http::/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u'
'https::/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u'
'rsync::/usr/bin/rsync --no-motd -z %u %o'
'scp::/usr/bin/scp -C %u %o')
|
Overwrite existed file when downloading. Valid: |
DOWNLOAD_OVERWRITE="false"
|
Update script name for |
UPDATE_SCRIPT='PKGBUILDUP'
|
Update script name for |
PKGBUILD_SCRIPT='PKGBUILD'
|
Basic functions |
|
Show message |
msg() {
local mesg=$1; shift
printf "==> ${mesg}\n" "$@" >&2
}
|
Show message in level two |
msg2() {
local mesg=$1; shift
printf " -> ${mesg}\n" "$@" >&2
}
|
Show warning message |
warning() {
if [ "${IGNORE_WARN}" = "true" ]; then
local mesg=$1; shift
printf "==> $(gettext "WARNING:") ${mesg}\n" "$@" >&2
fi
}
|
Show error message |
error() {
local mesg=$1; shift
printf "==> $(gettext "ERROR:") ${mesg}\n" "$@" >&2
}
|
Show error message then exit |
abort() {
error "$@"
error "$(gettext "Aborting...")"
exit 1
}
|
Abort if a variable is empty |
abort_if_var_empty() {
local arg=$1
local argname=$2
if [[ -z "${arg}" ]]; then
abort "$(gettext "variable \$%s is empty")" "${argname}"
fi
}
|
Warning if a variable is empty |
warn_if_var_empty() {
local arg=$1
local argname=$2
if [[ -z "${arg}" ]]; then
warning "$(gettext "variable \$%s is empty")" "${argname}"
fi
}
|
Write message to log file |
first_log="true"
log() {
local mesg=$1; shift
if [ "${first_log}" = "true" ]; then
printf "${mesg}\n" "$@" >${PKGBUILDUP_LOG}
first_log="false"
else
printf "${mesg}\n" "$@" >>${PKGBUILDUP_LOG}
fi
}
|
Write success message to log file |
log_success() {
log "$(gettext "[SUCCESS] ")$@"
}
|
Write failed message to log file |
log_failed() {
log "$(gettext "[FAILED] ")$@"
}
|
Source other script file safely |
source_safe() {
shopt -u extglob
if ! source "$@"; then
abort "$(gettext "Failed to source %s")" "$1"
fi
shopt -s extglob
}
|
Extract the protocol from a source entry
Return |
get_protocol() {
if [[ $1 = *://* ]]; then
local proto="${1##*::}" # strip leading filename
printf "%s\n" "${proto%%://*}"
elif [[ $1 = *lp:* ]]; then
local proto="${1##*::}"
printf "%s\n" "${proto%%lp:*}"
else
printf "%s\n" local
fi
}
|
Get download client |
get_downloadclient() {
local proto=$1
#- loop through `DOWNLOAD_AGENTS` variable looking for protocol
local i
for i in "${DLAGENTS[@]}"; do
local handler="${i%%::*}"
if [[ $proto = "$handler" ]]; then
local agent="${i##*::}"
break
fi
done
#- if we didn't find an agent, return an error
if [[ -z $agent ]]; then
error "$(gettext "Unknown download protocol: %s")" "$proto"
return 1
fi
#- ensure specified program is installed
local program="${agent%% *}"
if [[ ! -x $program ]]; then
local baseprog="${program##*/}"
error "$(gettext "The download program %s is not installed.")" "$baseprog"
return 1
fi
printf "%s\n" "$agent"
}
|
Download file Arguments:
|
download_file() {
local url=$1
local filename=$2
#- check arguments
if [ -z "${filename}" ]; then
filename="$(basename ${url})"
fi
local proto=$(get_protocol "$url")
#- find the client we should use for this URL
local dlcmd
dlcmd=$(get_downloadclient "$proto") || exit $?
if [[ $proto = "scp" ]]; then
#- scp downloads should not pass the protocol in the url
url="${url##*://}"
fi
msg2 "$(gettext "Downloading %s...")" "$filename"
if [ "${DOWNLOAD_OVERWRITE}" != "true" ]; then
if [ -e "${filename}" ]; then
msg2 "$(gettext "File existed, skip download")"
return
fi
fi
#- temporary download file, default to last component of the URL
local dlfile="${url##*/}"
#- replace `%o` by the temporary dlfile if it exists
if [[ $dlcmd = *%o* ]]; then
dlcmd="${dlcmd//\%o/\"$filename.part\"}"
dlfile="$filename.part"
fi
#- add the URL, either in place of `%u` or at the end
if [[ $dlcmd = *%u* ]]; then
dlcmd="${dlcmd//\%u/\"$url\"}"
else
dlcmd="$dlcmd \"$url\""
fi
local ret=0
eval "$dlcmd || ret=\$?"
if (( ret )); then
[[ ! -s $dlfile ]] && rm -f -- "$dlfile"
error "$(gettext "Failure while downloading %s")" "$filename"
return 1
fi
#- rename the temporary download file to the final destination
if [[ $dlfile != "$filename" ]]; then
mv -f "$dlfile" "$filename"
fi
}
|
List variables in template file Arguments:
|
listvar() {
tplfile=$1
if [ ! -e "${tplfile}" ]; then
abort "$(gettext "file does not exist, %s")" "${tplfile}"
fi
awk '
BEGIN {
varreg="(^.*){% *(\\w+) *%}(.*$)"
}
varreg {
while ($0 ~ varreg) {
var=gensub(varreg, "\\2", "")
$0=gensub(varreg, "\\1\\3", "")
if (var in vars == 0) {
vars[var]=l++
}
}
}
END {
PROCINFO["sorted_in"] = "@val_num_asc"
for (var in vars) {
print var
}
}
' ${tplfile}
}
|
Join multi-line strings to one line |
joinline() {
echo $*
}
|
Decode url string, such as convert |
urldecode() {
local tmpstr="$(cat - | sed -e 's/%/\\x/g')"
printf "${tmpstr}\n"
}
|
Get latest package file name by parsing web page Used variables:
Arguments:
|
get_latest_file_by_parsing_web_page() {
msg2 "$(gettext "Parsing web page to get latest package file name...")"
local url=$1
local filereg=$2
abort_if_var_empty "${url}" "url"
abort_if_var_empty "${filereg}" "filereg"
msg2 "$(gettext " url: %s")" "${url}"
msg2 "$(gettext " regexp: %s")" "${filereg}"
#- get web page content
local get_page_cmd=$(printf "${GET_PAGE_CMD}" ${url})
local web_content=$(eval "${get_page_cmd}")
#- decode url and get latest file
: ${FILENAME_CMD:="grep -o -P \"%s\" | sort -n | tail -1"}
filename_cmd="echo '${web_content}' | urldecode | ""$(printf "${FILENAME_CMD}" "${filereg}")"
local latestfn="$(eval "${filename_cmd}")"
if [[ -z "${latestfn}" ]]; then
error "$(gettext "Get latest package file name failed")"
return 1
fi
printf "%s\n" "${latestfn}"
}
|
Generate Arguments:
|
generate_pkgbuild() {
msg2 "$(gettext "Generating PKGBUILD from template file...")"
local tplfile=$1
local varvalues=$2
local pkgfile=$3
#- check arguments
abort_if_var_empty "${tplfile}" "tplfile"
warn_if_var_empty "${varvalues}" "varvalues"
if [[ -z "${pkgfile}" ]]; then
pkgfile="$(dirname ${tplfile})/${PKGBUILD_SCRIPT}"
fi
#- replace variables to values in template file to generate PKGBUILD
#- file, if variable is undefined, just replace to empty
msg2 "$(gettext "Variable values: %s")" "$(joinline ${varvalues})"
msg2 "$(gettext "Generate '%s' through template file '%s'")" "${pkgfile}" "${tplfile}"
awk -v varvalues_str="${varvalues}" '
BEGIN {
varreg="(^.*){% *(\\w+) *%}(.*$)"
#- build varvalues array
split(varvalues_str, lines, "\n")
for (i in lines) {
split(lines[i], arr, "=")
varvalues[arr[1]]=arr[2]
}
}
varreg {
tmpstr=$0
while (tmpstr ~ varreg) {
var=gensub(varreg, "\\2", "", tmpstr)
if (var in varvalues) {
value=varvalues[var]
$0=gensub("{% *"var" *%}", value, "g")
}
#- no matter there are undefined variables, just
#- remove it in tmpstr to avoid infinity loop
tmpstr=gensub(varreg, "\\1\\3", "g", tmpstr)
}
print
}
' ${tplfile} > ${pkgfile}
#- check if all the template variables were replaced
local vars=$(listvar ${pkgfile})
if [ -n "${vars}" ]; then
warning "$(gettext "there are undefined variables in %s: %s")" \
"${pkgfile}" "$(joinline ${vars})"
fi
}
|
Generate checksum for file |
generate_checksum() {
local file=$1
local integ=${INTEGRITY_CHECK}
msg2 "$(gettext "Generating checksum for file: %s")" ${file}
if ! type -p openssl >/dev/null; then
error "$(gettext "Cannot find the command '%s'")" "openssl"
return 1
fi
case "$integ" in
md5|sha1|sha256|sha384|sha512) : ;;
*)
error "$(gettext "Invalid integrity algorithm '%s' specified")" "$integ"
return 1 ;;
esac
local sum="$(openssl dgst -${integ} "${file}")"
sum=${sum##* }
printf "%s" "${sum}"
}
|
Run |
run_makepkg() {
local pkgdir=$1
(cd "${pkgdir}"; rm -rf src pkg; makepkg -f) || return 1
}
|
Upload source package to AUR |
upload_package() {
local pkgdir=$1
#- generate a new package source
(cd "${pkgdir}"; makepkg -fS) || return 1;
local pkgsrc="$(ls --format=single-column --sort=time "${pkgdir}"/*.src.tar.gz | head -1)"
local upcmd="$(printf ${UPLOAD_CMD} ${pkgsrc})"
msg2 "$(gettext "Uploading package source to AUR: %s...")" ${pkgsrc}
eval "${upcmd}" || return 1
}
|
Helper functions, could use directly |
|
Update Used variables:
Arguments:
|
do_update_pkgbuild_for_source_site() {
msg "$(gettext "Update PKGBUILD which package file living in other linux distribution source site...")"
local tplfile=$1
local pkgverreg=$2
local pkgrelreg=$3
local makepkg="${4:-true}"
local upload="${5:-true}"
local varvalues="" # values for template variable
abort_if_var_empty "${FILE_INFO[0]}" "FILE_INFO"
abort_if_var_empty "${tplfile}" "tplfile"
abort_if_var_empty "${pkgverreg}" "pkgverreg"
msg2 "$(gettext "Updating %s...")" "${tplfile}"
#- parse variable FILE_INFO to get each package file's latest name and check-sum
local mainfn=""
for info in "${FILE_INFO[@]}"; do
local filename_var="$(echo $info | awk -F '::' '{print $1}')"
local checksum_var="$(echo $info | awk -F '::' '{print $2}')"
local url="$(echo $info | awk -F '::' '{print $3}')"
local filereg="$(echo $info | awk -F '::' '{print $4}')"
local latestfn
latestfn=$(get_latest_file_by_parsing_web_page "${url}" "${filereg}") || return 1
varvalues=$(printf "%s\n%s" "${varvalues}" "${filename_var}=${latestfn}")
#- download latest package file
local fileurl="${url}/${latestfn}"
local savefile="$(dirname ${tplfile})/${latestfn}"
download_file ${fileurl} ${savefile} || return 1
#- generate integrity checks
local checksum
checksum=$(generate_checksum ${savefile}) || return 1
varvalues=$(printf "%s\n%s" "${varvalues}" "${checksum_var}=${checksum}")
#- set first package as the main package, and mark its latest
#- file name to get package version later
if [ -z "${mainfn}" ]; then
mainfn=${latestfn}
fi
done
#- get package version
: ${PKGVER_CMD:="grep -o -P \"%s\" | tail -1"}
pkgver_cmd="echo ${mainfn} | ""$(printf "${PKGVER_CMD}" "${pkgverreg}")"
msg2 "$(gettext "Getting package version, regexp: %s")" "${pkgverreg}"
msg2 "$(gettext "Command: %s")" "${pkgver_cmd}"
local pkgver="$(eval "${pkgver_cmd}")"
varvalues="$(printf "%s\n%s" "${varvalues}" "pkgver=${pkgver}")"
#- get package release
: ${PKGREL_CMD:="grep -o -P \"%s\" | tail -1"}
pkgrel_cmd="echo ${mainfn} | ""$(printf "${PKGREL_CMD}" "${pkgrelreg}")"
msg2 "$(gettext "Getting package release, regexp: %s")" "${pkgrelreg}"
msg2 "$(gettext "Command: %s")" "${pkgrel_cmd}"
local pkgrel="$(eval "${pkgrel_cmd}")"
varvalues="$(printf "%s\n%s" "${varvalues}" "pkgrel=${pkgrel}")"
#- generate new PKGBUILD
generate_pkgbuild "${tplfile}" "${varvalues}"
#- run makepkg
local pkgdir="$(dirname ${tplfile})"
if [ "${makepkg}" = "true" ]; then
run_makepkg ${pkgdir} || return 1
fi
#- upload package
if [ "${upload}" = "true" ]; then
upload_package ${pkgdir} || return 1
fi
}
|
Wrapper for |
update_pkgbuild_for_source_site() {
local tplfile=$1
do_update_pkgbuild_for_source_site "$@"
if (( $? )); then
log_failed "${tplfile}"
else
log_success "${tplfile}"
fi
}
|
Main loop |
|
Setup bash |
shopt -s extglob
|
Dispatch arguments |
arg_update_script="${PWD}/${UPDATE_SCRIPT}"
arg_listvar=""
arg_help=""
arg_version=""
while [ $# -gt 0 ]; do
case $1 in
-p) arg_update_script="$2"; shift; break ;;
-l|--listvar) arg_listvar="$2"; shift; break ;;
-h|--help) arg_help=t; break ;;
-v|--version) arg_version=t; break ;;
--) shift; break ;;
*) abort "$(gettext "Unknown argument: %s")" "$@" ;;
esac
done
|
Show help message |
if [ "${arg_help}" ]; then
show_help
fi
|
Show version |
if [ "${arg_version}" ]; then
show_version
fi
|
List variables in template file |
if [ "${arg_listvar}" ]; then
listvar ${arg_listvar}
exit
fi
|
Load update script, default name is |
source_safe "${arg_update_script}"
|
LicenseGNU General Public License, Version 3.0 |
|
| |