summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2018-01-24 16:15:40 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2018-01-24 16:15:40 +0100
commitff768f012bfef1bf264d06214aead70a58c0ff90 (patch)
tree00fae2f78283cf61698b2b8fd2474a1f6a5802c8
parentd5280828118b27372c5ea9be1c0cd8e55c818ff0 (diff)
parentcb4eedcdca4fc5f58e83abe2aadc9abb59b4918c (diff)
downloadbuilder-ff768f012bfef1bf264d06214aead70a58c0ff90.tar.xz
Merge branch 'master' into opcodes
-rwxr-xr-xbin/bootstrap-mysql112
-rwxr-xr-xbin/build-master-status-from-mysql54
-rwxr-xr-xbin/common-functions27
-rwxr-xr-xbin/db-update60
-rwxr-xr-xbin/delete-packages2
-rwxr-xr-xbin/get-assignment15
-rwxr-xr-xbin/get-package-updates39
-rwxr-xr-xbin/ii-connect12
-rwxr-xr-xbin/mysql-functions266
-rwxr-xr-xbin/opcode49
-rwxr-xr-xbin/return-assignment115
-rwxr-xr-xbin/sanity-check8
-rwxr-xr-xbin/seed-build-list7
-rwxr-xr-xbin/slave-build-connect9
-rwxr-xr-xconf/default.conf2
-rwxr-xr-x[-rw-r--r--]lib/opcode_list (renamed from conf/Opcode_list)0
-rw-r--r--web-scripts/broken-packages.php157
-rw-r--r--web-scripts/build-slaves.php44
-rw-r--r--web-scripts/packages.php20
-rw-r--r--web-scripts/statistics.php179
20 files changed, 948 insertions, 229 deletions
diff --git a/bin/bootstrap-mysql b/bin/bootstrap-mysql
index 3069863..46678f7 100755
--- a/bin/bootstrap-mysql
+++ b/bin/bootstrap-mysql
@@ -2,12 +2,26 @@
# shellcheck source=conf/default.conf
. "${0%/*}/../conf/default.conf"
-# shellcheck source=bin/mysql-functions
-. "${base_dir}/bin/mysql-functions"
tmp_dir=$(mktemp -d 'tmp.bootstrap-mysql.XXXXXXXXXX' --tmpdir)
trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT
+exec 9> "${build_list_lock_file}"
+if ! flock -n 9; then
+ >&2 echo 'Cannot get build-list lock.'
+ exit 1
+fi
+exec 8> "${sanity_check_lock_file}"
+if ! flock -s -n 9; then
+ >&2 echo 'Cannot get sanity-check lock.'
+ exit 1
+fi
+exec 7> "${package_database_lock_file}"
+if ! flock -s -n 7; then
+ >&2 echo 'Cannot get package-database lock.'
+ exit 1
+fi
+
for dir in $(ls_master_mirror 'i686'); do
ls_master_mirror "i686/${dir}" | \
sed '
@@ -49,8 +63,8 @@ if [ ! "$1" = 'slim' ]; then
' is_tested BIT' \
' pkgname VARCHAR(64)' \
' architecture SMALLINT :architectures' \
- ' UNIQUE content build_assignment sub_pkgrel pkgname architecture' \
- ' UNIQUE file_name pkgname epoch pkgver pkgrel sub_pkgrel architecture' \
+ ' UNIQUE content build_assignment sub_pkgrel pkgname architecture repository' \
+ ' UNIQUE file_name pkgname epoch pkgver pkgrel sub_pkgrel architecture repository' \
'repositories MEDIUMINT' \
' name VARCHAR(64)' \
' stability MEDIUMINT :repository_stabilities' \
@@ -97,7 +111,18 @@ if [ ! "$1" = 'slim' ]; then
' head VARCHAR(40)' \
' UNIQUE name' \
' UNIQUE url' \
- ' UNIQUE directory'
+ ' UNIQUE directory' \
+ 'fail_reasons SMALLINT' \
+ ' name VARCHAR(32)' \
+ ' identifier VARCHAR(64)' \
+ ' severity SMALLINT' \
+ ' UNIQUE name' \
+ 'failed_builds MEDIUMINT' \
+ ' build_slave MEDIUMINT :build_slaves' \
+ ' build_assignment BIGINT :build_assignments' \
+ ' date DATETIME' \
+ ' reason SMALLINT :fail_reasons' \
+ ' log_file VARCHAR(512)'
)
{
@@ -195,6 +220,9 @@ if [ ! "$1" = 'slim' ]; then
'SELECT' 'buildmaster.*' \
'UPDATE' 'buildmaster.*' \
'RELOAD' '*.*'
+ printf 'GRANT %s ON %s TO '"'"'http'"'"'@'"'"'localhost'"'"';\n' \
+ 'SHOW VIEW' 'buildmaster.*' \
+ 'SELECT' 'buildmaster.*'
printf 'FLUSH PRIVILEGES;\n'
} | \
mysql -u root -p buildmaster
@@ -208,6 +236,47 @@ fi
sed 's|,$||'
printf ';\n'
# shellcheck disable=SC2016
+ printf 'INSERT IGNORE INTO `fail_reasons` (`identifier`,`name`,`severity`) VALUES '
+ printf '(from_base64("%s"),"%s",%s),' \
+ "$(
+ printf '%s' '==> ERROR: A failure occurred in build()\.' | \
+ base64 -w0
+ )" 'build()' 0 \
+ "$(
+ printf '%s' '==> ERROR: Could not download sources\.' | \
+ base64 -w0
+ )" 'source' 1 \
+ "$(
+ printf '%s' '.*error: failed to commit transaction (invalid or corrupted package)' | \
+ base64 -w0
+ )" 'package-cache' 2 \
+ "$(
+ printf '%s' '==> ERROR: A failure occurred in prepare()\.' | \
+ base64 -w0
+ )" 'prepare()' 2 \
+ "$(
+ printf '%s' '==> ERROR: A failure occurred in package\(_\S\+\)\?()\.' | \
+ base64 -w0
+ )" 'package()' 3 \
+ "$(
+ printf '%s' '==> ERROR: A failure occurred in check()\.' | \
+ base64 -w0
+ )" 'check()' 4 \
+ "$(
+ printf '%s' '==> ERROR: '"'"'pacman'"'"' failed to install missing dependencies\.' | \
+ base64 -w0
+ )" 'dependencies' 1 \
+ "$(
+ printf '%s' '==> ERROR: Running makepkg as root is not allowed as it can cause permanent,.*' | \
+ base64 -w0
+ )" 'run-as-root' 1 \
+ "$(
+ printf '.*' | \
+ base64 -w0
+ )" 'unknown' 100 | \
+ sed 's|,$||'
+ printf ';\n'
+ # shellcheck disable=SC2016
printf 'INSERT IGNORE INTO `git_repositories` (`name`,`url`,`directory`,`head`) VALUES'
{
for repo in ${repo_names}; do
@@ -307,7 +376,8 @@ fi
'testing' '"Packages:Testing"' \
'staging' 'NULL' \
'standalone' 'NULL' \
- 'unbuilt' '"Packages:Build-list"'
+ 'unbuilt' '"Packages:Build-list"' \
+ 'forbidden' 'NULL'
printf ';\n'
} | \
sed 's|,;|;|'
@@ -321,7 +391,8 @@ fi
'community-testing:testing:AQ==' \
'staging:staging:AQ==' \
'community-staging:staging:AQ==' \
- 'build-list:unbuilt:AA=='; do
+ 'build-list:unbuilt:AA==' \
+ 'deletion-list:forbidden:AA=='; do
# shellcheck disable=SC2016
printf 'INSERT IGNORE INTO `repositories` (`name`,`stability`,`is_on_master_mirror`) SELECT'
# shellcheck disable=SC2016
@@ -363,6 +434,7 @@ find "${work_dir}/package-states" \
-name '*.tested' \
\) \
-exec sed '
+ 1!d
s@^.*-\([^-]\+\)-\([^-.]\+\)\.pkg\.tar\.xz$@{} \1 \2 \0@
s@^\S*/@@
s/^\(\S\+\)\.\(done\|testing\|tested\) /\1 /
@@ -390,6 +462,32 @@ tr ' ' '.' < \
mysql_generate_package_metadata "${state_file}"
done
+# shellcheck disable=SC2016
+find "${work_dir}/package-states" -name '*.blocked' -printf '%p %f\n' | \
+ sed '
+ s|\.\([^. ]\+\)\.\([^. ]\+\)\.\([^. ]\+\)\.blocked$| \1 \2 \3|
+ ' | \
+ while read -r state_file pkgbase git_revision mod_git_revision repository; do
+ printf 'UPDATE `build_assignments`'
+ printf ' JOIN `%s` ON `%s`.`id`=`%s`.`%s`' \
+ 'package_sources' 'package_sources' 'build_assignments' 'package_source' \
+ 'upstream_repositories' 'upstream_repositories' 'package_sources' 'upstream_package_repository'
+ printf ' SET `build_assignments`.`is_blocked`=from_base64("%s")' \
+ "$(
+ tr -d '\n' < \
+ "${state_file}" | \
+ base64 -w0
+ )"
+ printf ' WHERE'
+ printf ' `package_sources`.`%s`=from_base64("%s") AND' \
+ 'pkgbase' "$(printf '%s' "${pkgbase}" | base64 -w0)" \
+ 'git_revision' "$(printf '%s' "${git_revision}" | base64 -w0)" \
+ 'mod_git_revision' "$(printf '%s' "${mod_git_revision}" | base64 -w0)"
+ printf ' `upstream_repositories`.`name`=from_base64("%s");\n' \
+ "$(printf '%s' "${repository}" | base64 -w0)"
+ done | \
+ ${mysql_command}
+
grep '^\('"$(
# shellcheck disable=SC2086
printf '%s\\|' ${standalone_package_repositories} ${stable_package_repositories}
diff --git a/bin/build-master-status-from-mysql b/bin/build-master-status-from-mysql
index 6dacc5e..a0c2b4f 100755
--- a/bin/build-master-status-from-mysql
+++ b/bin/build-master-status-from-mysql
@@ -4,36 +4,32 @@
# shellcheck source=conf/default.conf
. "${0%/*}/../conf/default.conf"
-# shellcheck source=bin/mysql-functions
-. "${base_dir}/bin/mysql-functions"
-# shellcheck disable=SC2016
-${mysql_command} -e '
- SELECT `build_slaves`.`name`,`build_slaves`.`operator`,`package_sources`.`pkgbase`,`build_slaves`.`last_connection`
- FROM `build_slaves`
- LEFT JOIN `build_assignments` ON
- `build_slaves`.`currently_building`=`build_assignments`.`id`
- LEFT JOIN `package_sources` ON
- `build_assignments`.`package_source`=`package_sources`.`id`
- ORDER BY `build_slaves`.`last_connection`
-' --html | \
- sed '
- s,</TR>,\0\n,g
- ' | \
- sed '
- \,</TH></TR>$, {
- s,<TH>pkgbase</TH>,<TH>currently building</TH>,
- y,_, ,
- }
- \,</TH></TR>$, ! {
- s,<TD>NULL</TD>,<TD>\&nbsp;</TD>,
- }
- 1 i <html><head><title>list of build slaves</title></head><body>
- $ a </body></html>
- ' | \
- sponge "${webserver_directory}/build-slaves.html"
-
-mysql_sanity_check | \
+{
+ mysql_sanity_check || true
+ {
+ # shellcheck disable=SC2016
+ {
+ printf 'SELECT `package_sources`.`pkgbase`,`package_sources`.`git_revision`,`package_sources`.`mod_git_revision`,`upstream_repositories`.`name`'
+ printf ' FROM `package_sources`'
+ printf ' JOIN `%s` ON `%s`.`%s`=`%s`.`id`' \
+ 'upstream_repositories' 'package_sources' 'upstream_package_repository' 'upstream_repositories' \
+ 'build_assignments' 'build_assignments' 'package_source' 'package_sources' \
+ 'binary_packages' 'binary_packages' 'build_assignment' 'build_assignments' \
+ 'repositories' 'binary_packages' 'repository' 'repositories'
+ printf ' WHERE `repositories`.`name`="build-list"'
+ } | \
+ ${mysql_command} --batch | \
+ sed '
+ 1d
+ y/\t/ /
+ s/^/+ /
+ '
+ sed 's/^/- /' "${work_dir}/build-list"
+ } | \
+ sort -k2 -k1,1 | \
+ uniq -uf1
+} | \
sed '
s,^-.*$,<font color="#FF0000">\0</font>,
s,^+.*$,<font color="#00FF00">\0</font>,
diff --git a/bin/common-functions b/bin/common-functions
index 1fd5db7..d5b6eaa 100755
--- a/bin/common-functions
+++ b/bin/common-functions
@@ -522,7 +522,7 @@ remove_old_package_versions() {
' | \
sort -u > \
"${tmp_dir}/packages-to-delete"
- # this file contains a list of packages to be delete, one on each line:
+ # this file contains a list of packages to be deleted, one on each line:
# $architecture-directory $repository-directory $package-name $pkgver-$pkgrel-$package-architecture.pkg.tar.xz
cut -d' ' -f1,2 < \
@@ -560,6 +560,30 @@ remove_old_package_versions() {
done < \
"${tmp_dir}/repositories-to-modify"
+ # shellcheck disable=SC2016
+ sed '
+ s/\.pkg\.tar\.xz$//
+ s/^\S\+ //
+ s/-\([^-. ]\+\)\(-[^- ]\+\)$/-\1.0\2/
+ s/ \([^-: ]\+\(-[^- ]\+\)\{2\}\)$/ 0:\1/
+ s/ \([^-.]\+\):\([^-:]\+\)-\([^-.]\+\)\.\([^-.]\+\)-\([^-]\+\)$/ \1 \2 \3 \4 \5/
+ ' "${tmp_dir}/packages-to-delete" | \
+ while read -r repo pkgname epoch pkgver pkgrel sub_pkgrel arch; do
+ printf 'DELETE FROM `binary_packages` WHERE'
+ printf ' `binary_packages`.`%s`=(SELECT `%s`.`id` FROM `%s` WHERE `%s`.`name`=from_base64("%s")) AND' \
+ 'architecture' 'architectures' 'architectures' 'architectures' "$(printf '%s' "${arch}" | base64 -w0)" \
+ 'repository' 'repositories' 'repositories' 'repositories' "$(printf '%s' "${repo}" | base64 -w0)"
+ printf ' `binary_packages`.`%s`=from_base64("%s") AND' \
+ 'pkgname' "$(printf '%s' "${pkgname}" | base64 -w0)" \
+ 'epoch' "$(printf '%s' "${epoch}" | base64 -w0)" \
+ 'pkgver' "$(printf '%s' "${pkgver}" | base64 -w0)" \
+ 'pkgrel' "$(printf '%s' "${pkgrel}" | base64 -w0)" \
+ 'sub_pkgrel' "$(printf '%s' "${sub_pkgrel}" | base64 -w0)" | \
+ sed 's/ AND$//'
+ printf ';\n'
+ done | \
+ ${mysql_command}
+
sed '
s| \(\S\+\)$|-\1|
y| |/|
@@ -1233,6 +1257,7 @@ next_sub_pkgrel() {
git_repo=$(find_git_repository_to_package_repository "${repository}")
temp_dir=$(mktemp -d 'tmp.common-functions.next_sub_pkgrel.XXXXXXXXXX' --tmpdir)
+ trap 'rm -rf --one-file-system "${temp_dir}"' EXIT
find_pkgbuilds "${package}" "${repository}" "${git_repo}" "${git_revision}" "${mod_git_revision}"
extract_source_directory "${git_repo}" "${git_revision}" "${mod_git_revision}" "${temp_dir}" '0'
diff --git a/bin/db-update b/bin/db-update
index 827dc05..fe45f41 100755
--- a/bin/db-update
+++ b/bin/db-update
@@ -20,6 +20,12 @@
# track packages in stable, too
# know _exactly_ in which repository the packages are
+# TODO: fully integrate database (in other scripts too) - e.g. rely on
+# info in db instead of state-files
+
+# TODO: add possibility to manually clone a (binary) package (e.g.
+# for build-support) - this should also be possible via email
+
# shellcheck disable=SC2039
# shellcheck source=conf/default.conf
. "${0%/*}/../conf/default.conf"
@@ -160,7 +166,7 @@ move_packages() {
exit 2
fi
done < \
- "${tmp_dir}/tmp/${package}.parts"
+ "${tmp_dir}/tmp/${package}.parts_and_signatures"
mkdir -p "${tmp_dir}/tmp/${from_repo}"
mkdir -p "${tmp_dir}/tmp/${to_repo}"
@@ -323,9 +329,55 @@ move_packages() {
done < \
"${tmp_dir}/tmp/packages"
- if ! ${no_action}; then
- ${dummynator} trigger_mirror_refreshs
- fi
+ # shellcheck disable=SC2016
+ while read -r package; do
+ while read -r part; do
+ printf 'UPDATE `binary_packages`'
+ printf ' JOIN `repositories` ON `binary_packages`.`repository`=`repositories`.`id`'
+ printf ' JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id`'
+ printf ' SET `binary_packages`.`repository`=(SELECT `repositories`.`id` FROM `repositories` WHERE `repositories`.`name`=from_base64("%s"))' \
+ "$(
+ base64_encode_each < \
+ "${tmp_dir}/tmp/${package}.to_repo"
+ )"
+ printf ' WHERE'
+ printf ' `repositories`.`name`=from_base64("%s")' \
+ "$(
+ base64_encode_each < \
+ "${tmp_dir}/tmp/${package}.from_repo"
+ )"
+ printf '%s\n' "${part}" | \
+ sed '
+ s/\.pkg\.tar\.xz$//
+ s/-\([^-.]\+\)\(-[^-]\+\)$/-\1.0\2/
+ s/-\([^-:]\+\)\(\(-[^-]\+\)\{2\}\)$/-0:\1\2/
+ s/^\(.\+\)-\([^-:]\+\):\([^-:]\+\)-\([^-.]\+\)\.\([^-.]\+\)-\([^-]\+\)$/\1\n\2\n\3\n\4\n\5\n\6/
+ ' | \
+ base64_encode_each | \
+ tr '\n' ' ' | \
+ sed '
+ s,\(\S\+\) \(\S\+\) \(\S\+\) \(\S\+\) \(\S\+\) \(\S\+\) $,'"$(
+ printf ' AND `binary_packages`.`%s`=from_base64("%s")' \
+ 'pkgname' '\1' \
+ 'epoch' '\2' \
+ 'pkgver' '\3' \
+ 'pkgrel' '\4' \
+ 'sub_pkgrel' '\5'
+ printf ' AND `architectures`.`name`=from_base64("\\6")'
+ )"',
+ '
+ printf ';\n'
+ done < \
+ "${tmp_dir}/tmp/${package}.parts"
+ done < \
+ "${tmp_dir}/tmp/packages" | \
+ if ${no_action}; then
+ sed 's|^|mysql: |'
+ else
+ ${mysql_command}
+ fi
+
+ ${dummynator} trigger_mirror_refreshs
rm -rf --one-file-system "${tmp_dir:?}/tmp"
diff --git a/bin/delete-packages b/bin/delete-packages
index a6e3f14..26d323a 100755
--- a/bin/delete-packages
+++ b/bin/delete-packages
@@ -13,6 +13,8 @@
# shellcheck source=conf/default.conf
. "${0%/*}/../conf/default.conf"
+# TODO: finish this
+
# shellcheck disable=SC2016
usage() {
>&2 echo ''
diff --git a/bin/get-assignment b/bin/get-assignment
index a81a54d..d256248 100755
--- a/bin/get-assignment
+++ b/bin/get-assignment
@@ -50,33 +50,26 @@ hand_out_assignment() {
} | \
sort -u | \
sponge "${work_dir}/package-states/$1.$2.$3.$4.locked"
- ${mysql_command} -e "$(
- # shellcheck disable=SC2016
+ # shellcheck disable=SC2016
+ {
printf 'UPDATE `build_slaves`'
- # shellcheck disable=SC2016
printf ' SET `currently_building` = ('
- # shellcheck disable=SC2016
printf ' SELECT `build_assignments`.`id`'
- # shellcheck disable=SC2016
printf ' FROM `build_assignments`'
- # shellcheck disable=SC2016
printf ' JOIN `package_sources` ON `build_assignments`.`package_source`=`package_sources`.`id`'
- # shellcheck disable=SC2016
printf ' JOIN `upstream_repositories` ON `package_sources`.`upstream_package_repository`=`upstream_repositories`.`id`'
printf ' WHERE'
- # shellcheck disable=SC2016
printf ' `package_sources`.`%s` = from_base64("%s") AND' \
'pkgbase' "$(printf '%s' "$1" | base64 -w0)" \
'git_revision' "$(printf '%s' "$2" | base64 -w0)" \
'mod_git_revision' "$(printf '%s' "$3" | base64 -w0)"
- # shellcheck disable=SC2016
printf ' `upstream_repositories`.`name` = from_base64("%s")' \
"$(printf '%s' "$4" | base64 -w0)"
printf ')'
- # shellcheck disable=SC2016
printf ' WHERE `build_slaves`.`name`=from_base64("%s");' \
"$(printf '%s' "${slave}" | base64 -w0)"
- )"
+ } | \
+ ${mysql_command}
# lock every loop this package breaks
find "${work_dir}/build-list.loops" -maxdepth 1 -regextype grep \
diff --git a/bin/get-package-updates b/bin/get-package-updates
index cbe8b14..801aadd 100755
--- a/bin/get-package-updates
+++ b/bin/get-package-updates
@@ -9,6 +9,10 @@
# TODO: Find out, why sometimes package updates are missed.
+# TODO: mark loops in mysql database
+
+# TODO: test_exclusion does not yet cooperate with the database
+
# shellcheck disable=SC2016
usage() {
>&2 echo ''
@@ -54,7 +58,7 @@ do
-x|--test-exclusion)
shift
if [ -n "${test_exclusion}" ]; then
- >&2 printf 'I already have --test-exlusion=%s and you gave me another one.\n' "${test_exclusion}"
+ >&2 printf 'I already have --test-exclusion=%s and you gave me another one.\n' "${test_exclusion}"
>&2 printf 'But I can only handle one exclusion test at a time.\n'
exit 2
fi
@@ -88,6 +92,20 @@ delete_package() {
echo "$1" >> \
"${work_dir}/deletion-list.new"
sed -i "/^$(str_to_regex "${1}") /d" "${work_dir}/build-list.new"
+ # shellcheck disable=SC2016
+ {
+ printf 'UPDATE `binary_packages`'
+ printf ' JOIN `%s` ON `%s`.`id`=`binary_packages`.`%s`' \
+ 'repositories' 'repositories' 'repository' \
+ 'build_assignments' 'build_assignments' 'build_assignment'
+ printf ' JOIN `%s` ON `%s`.`id`=`%s`.`%s`' \
+ 'package_sources' 'package_sources' 'build_assignments' 'package_source'
+ printf ' SET `binary_packages`.`repository`=(SELECT `repositories`.`id` FROM `repositories` WHERE `repositories`.`name`="deletion-list")'
+ printf ' WHERE `repositories`.`name`="build-list"'
+ printf ' AND `package_sources`.`pkgbase`=from_base64("%s");' \
+ "$(printf '%s' "$1" | base64 -w0)"
+ } | \
+ ${mysql_command}
}
# create tmp_dir and trap
@@ -268,6 +286,25 @@ done | \
echo "${package} ${git_revision} ${new_repo_revisions__archlinux32} ${repository}" >> \
"${work_dir}/build-list.new"
sed -i "/^$(str_to_regex "${package}")\$/d" "${work_dir}/deletion-list.new"
+ # shellcheck disable=SC2016
+ {
+ # delete old build assignment and associated binary packages
+ # which are not yet build or on the deletion list
+ printf 'DELETE `build_assignments`,`binary_packages`'
+ printf ' FROM `binary_packages`'
+ printf ' JOIN `%s` ON `%s`.`id`=`%s`.`%s`' \
+ 'build_assignments' 'build_assignments' 'binary_packages' 'build_assignment' \
+ 'package_sources' 'package_sources' 'build_assignments' 'package_source' \
+ 'repositories' 'repositories' 'binary_packages' 'repository'
+ printf ' WHERE `package_sources`.`pkgbase`=from_base64("%s")' \
+ "$(
+ printf '%s' "${package}" | \
+ base64 -w0
+ )"
+ printf ' AND (`repositories`.`name`="build-list" OR `repositories`.`name`="deletion-list");\n'
+ } | \
+ ${mysql_command}
+ mysql_generate_package_metadata "${package}" "${git_revision}" "${new_repo_revisions__archlinux32}" "${repository}"
continue
fi
diff --git a/bin/ii-connect b/bin/ii-connect
index b703d77..54e1eb0 100755
--- a/bin/ii-connect
+++ b/bin/ii-connect
@@ -15,8 +15,8 @@ fi
# register if not yet done
if tail -n1 "${irc_dir}/nickserv/out" 2> /dev/null | \
grep -qF 'This nickname is registered. Please choose a different nickname'; then
- printf 'identify %s\n' "${irc_password}" > \
- "${irc_dir}/nickserv/in"
+ printf 'identify %s\n' "${irc_password}" | \
+ sponge "${irc_dir}/nickserv/in"
fi
# join #archlinux-ports if not yet done
@@ -26,8 +26,8 @@ if ! grep ' buildmaster\.archlinux32\.org .* buildmaster$' "${irc_dir}/out" | \
{
echo '/j #archlinux-ports'
echo '/WHO buildmaster'
- } > \
- "${irc_dir}/in"
+ } | \
+ sponge "${irc_dir}/in"
fi
# start watch daemon if not running yet
@@ -69,8 +69,8 @@ if [ "$1" = 'watch' ]; then
echo "${reason}" | \
head -n5
printf '... (%s lines total)\n' "$(echo "${reason}" | wc -l)"
- fi > \
- "${out_file%/out}/in"
+ fi | \
+ sponge "${out_file%/out}/in"
done
sed -i "/${regex}/d" "${out_file}"
fi
diff --git a/bin/mysql-functions b/bin/mysql-functions
index 7b9e724..ec2bf4c 100755
--- a/bin/mysql-functions
+++ b/bin/mysql-functions
@@ -37,20 +37,19 @@ mysql_add_package_source() {
done
values="${values% }"
- ${mysql_command} -e "$(
+ {
printf 'INSERT IGNORE INTO package_sources'
- {
- printf ' ('
- printf '`%s`, ' ${names}
- printf ') SELECT'
- printf ' from_base64("%s"), ' ${values% *}
- printf ' `upstream_repositories`.`id`'
- printf ' FROM `upstream_repositories`'
- printf ' WHERE `upstream_repositories`.`name` = from_base64("%s");' \
- "${values##* }"
- } | \
- sed 's|, )|)|g'
- )"
+ printf ' ('
+ printf '`%s`, ' ${names}
+ printf ') SELECT'
+ printf ' from_base64("%s"), ' ${values% *}
+ printf ' `upstream_repositories`.`id`'
+ printf ' FROM `upstream_repositories`'
+ printf ' WHERE `upstream_repositories`.`name` = from_base64("%s");' \
+ "${values##* }"
+ } | \
+ sed 's|, )|)|g' | \
+ ${mysql_command}
}
# mysql_add_binary_package $pkgbase $git_revision $mod_git_revision $upstream_package_repository $pkgname $sub_pkgrel $architecture $repository
@@ -68,33 +67,32 @@ mysql_add_binary_package() {
shift
done
- ${mysql_command} -e "$(
+ {
printf 'INSERT IGNORE INTO binary_packages'
- {
- printf ' ('
- printf '`%s`, ' 'sub_pkgrel' 'pkgname' 'package_source' 'repository' 'architecture'
- printf ') SELECT'
- printf ' from_base64("%s"), ' "${sub_pkgrel}" "${pkgname}"
- printf ' `%s`.`id`,' 'package_sources' 'repositories' 'architectures'
- printf ' FROM'
- printf ' `%s` JOIN' 'package_sources' 'repositories' 'architectures'
- printf ' `upstream_repositories` ON `package_sources`.`upstream_package_repository` = `upstream_repositories`.`id`'
- printf ' WHERE'
- printf ' `%s`.`name` = from_base64("%s") AND' \
- 'repositories' "${repository}" \
- 'architectures' "${architecture}"
- printf ' `package_sources`.`%s` = from_base64("%s") AND' \
- 'pkgbase' "${pkgbase}" \
- 'git_revision' "${git_revision}" \
- 'mod_git_revision' "${mod_git_revision}"
- printf ' `upstream_repositories`.`name` = from_base64("%s")' \
- "${upstream_package_repository}"
- } | \
- sed '
- s|, )|)|g
- s|, FROM| FROM|g
- '
- )"
+ printf ' ('
+ printf '`%s`, ' 'sub_pkgrel' 'pkgname' 'package_source' 'repository' 'architecture'
+ printf ') SELECT'
+ printf ' from_base64("%s"), ' "${sub_pkgrel}" "${pkgname}"
+ printf ' `%s`.`id`,' 'package_sources' 'repositories' 'architectures'
+ printf ' FROM'
+ printf ' `%s` JOIN' 'package_sources' 'repositories' 'architectures'
+ printf ' `upstream_repositories` ON `package_sources`.`upstream_package_repository` = `upstream_repositories`.`id`'
+ printf ' WHERE'
+ printf ' `%s`.`name` = from_base64("%s") AND' \
+ 'repositories' "${repository}" \
+ 'architectures' "${architecture}"
+ printf ' `package_sources`.`%s` = from_base64("%s") AND' \
+ 'pkgbase' "${pkgbase}" \
+ 'git_revision' "${git_revision}" \
+ 'mod_git_revision' "${mod_git_revision}"
+ printf ' `upstream_repositories`.`name` = from_base64("%s")' \
+ "${upstream_package_repository}"
+ } | \
+ sed '
+ s|, )|)|g
+ s|, FROM| FROM|g
+ ' | \
+ ${mysql_command}
}
# mysql_show_binary_package $pkgname $pkgver $pkgrel $sub_pkgrel
@@ -113,45 +111,44 @@ mysql_show_binary_package() {
done
local joint
- ${mysql_command} -e "$(
- {
- printf 'SELECT'
- printf ' `%s`.`%s`,' \
- 'repositories' 'name' \
- 'binary_packages' 'pkgname' \
- 'package_sources' 'pkgver' \
- 'package_sources' 'pkgrel' \
- 'binary_packages' 'sub_pkgrel' \
- 'architectures' 'name' \
- 'package_sources' 'pkgbase' \
- 'package_sources' 'git_revision' \
- 'package_sources' 'mod_git_revision' \
- 'upstream_repositories' 'name'
- printf ' FROM `binary_packages`'
- for joint in \
- 'architectures:binary_packages:architecture' \
- 'package_sources:binary_packages:package_source' \
- 'repositories:binary_packages:repository' \
- 'upstream_repositories:package_sources:upstream_package_repository'; do
- printf ' JOIN `%s` ON `%s`.`id` =' \
- "${joint%%:*}" "${joint%%:*}"
- joint="${joint#*:}"
- printf ' `%s`.`%s`' \
- "${joint%:*}" "${joint#*:}"
- done
- printf ' WHERE'
- printf ' `%s`.`%s` = from_base64("%s") AND' \
- 'binary_packages' 'pkgname' "${pkgname}" \
- 'binary_packages' 'sub_pkgrel' "${sub_pkgrel}" \
- 'package_sources' 'pkgver' "${pkgver}" \
- 'package_sources' 'pkgrel' "${pkgrel}"
- printf ';'
- } | \
- sed '
- s|, FROM| FROM|g
- s|AND;|;|g
- '
- )" --html
+ {
+ printf 'SELECT'
+ printf ' `%s`.`%s`,' \
+ 'repositories' 'name' \
+ 'binary_packages' 'pkgname' \
+ 'package_sources' 'pkgver' \
+ 'package_sources' 'pkgrel' \
+ 'binary_packages' 'sub_pkgrel' \
+ 'architectures' 'name' \
+ 'package_sources' 'pkgbase' \
+ 'package_sources' 'git_revision' \
+ 'package_sources' 'mod_git_revision' \
+ 'upstream_repositories' 'name'
+ printf ' FROM `binary_packages`'
+ for joint in \
+ 'architectures:binary_packages:architecture' \
+ 'package_sources:binary_packages:package_source' \
+ 'repositories:binary_packages:repository' \
+ 'upstream_repositories:package_sources:upstream_package_repository'; do
+ printf ' JOIN `%s` ON `%s`.`id` =' \
+ "${joint%%:*}" "${joint%%:*}"
+ joint="${joint#*:}"
+ printf ' `%s`.`%s`' \
+ "${joint%:*}" "${joint#*:}"
+ done
+ printf ' WHERE'
+ printf ' `%s`.`%s` = from_base64("%s") AND' \
+ 'binary_packages' 'pkgname' "${pkgname}" \
+ 'binary_packages' 'sub_pkgrel' "${sub_pkgrel}" \
+ 'package_sources' 'pkgver' "${pkgver}" \
+ 'package_sources' 'pkgrel' "${pkgrel}"
+ printf ';'
+ } | \
+ sed '
+ s|, FROM| FROM|g
+ s|AND;|;|g
+ ' | \
+ ${mysql_command} --html
}
# mysql_add_install_target $install_target
@@ -164,12 +161,12 @@ mysql_add_install_target() {
base64 -w0
)
- ${mysql_command} -e "$(
+ {
printf 'INSERT IGNORE INTO `install_targets` (`name`)'
printf ' VALUES (from_base64("%s"))' \
"${install_target}"
- printf '\n'
- )"
+ } | \
+ ${mysql_command}
}
# mysql_generate_package_metadata $package $git_revision $mod_git_revision $repository
@@ -191,16 +188,19 @@ mysql_generate_package_metadata() {
''|*[!0-9]*)
unset forced_sub_pkgrel
current_repository=$(
- echo 'build-list' | \
- base64_encode_each
+ printf 'build-list' | \
+ base64 -w0
)
;;
*)
- forced_sub_pkgrel="$1"
+ forced_sub_pkgrel=$(
+ printf '%s' "$1" | \
+ base64 -w0
+ )
shift
current_repository=$(
- echo "$1" | \
- base64_encode_each
+ printf '%s' "$1" | \
+ base64 -w0
)
shift
;;
@@ -292,7 +292,7 @@ mysql_generate_package_metadata() {
} | \
while read -r arch; do
printf 'INSERT IGNORE INTO `build_assignments` (`package_source`,`architecture`,`is_blocked`)'
- printf ' SELECT `package_sources`.`id`,`architectures`.`id`,0'
+ printf ' SELECT `package_sources`.`id`,`architectures`.`id`,NULL'
printf ' FROM `architectures` JOIN `package_sources`'
printf ' WHERE `architectures`.`name` = from_base64("%s")' \
"$(
@@ -400,30 +400,45 @@ mysql_generate_package_metadata() {
sed 's/[<>=].*$//' | \
base64_encode_each
)
- sub_pkgrel=$(
- if [ -n "${forced_sub_pkgrel}" ]; then
- echo "${forced_sub_pkgrel}"
- else
- ${mysql_command} -e "$(
- printf 'SELECT count(*) FROM `binary_packages` JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id` WHERE'
- printf ' `binary_packages`.`%s`=from_base64("%s") AND' \
- 'epoch' "${epoch}" \
- 'pkgver' "${pkgver}" \
- 'pkgrel' "${pkgrel}" \
- 'pkgname' "${pkgname}"
- if printf '%s' "${arch}" | base64 -d | grep -qxF 'any'; then
- # 'any' gets higher sub_pkgrel than any architecture
- printf ' 1'
- else
- # not-'any' gets higher sub_pkgrel than same or 'any' architecture
- printf ' (`architectures`.`name`=from_base64("%s") OR `architectures`.`name`="any")' \
- "${arch}"
- fi
- )" | \
- tail -n1
- fi | \
- base64_encode_each
- )
+ if [ -n "${forced_sub_pkgrel}" ]; then
+ sub_pkgrel='from_base64("'"${forced_sub_pkgrel}"'")'
+ else
+ sub_pkgrel=$(
+ printf '(SELECT COALESCE('
+ # do not add binary packages which are currently on the build-list
+ printf '(SELECT `sub_pkgrel` FROM `binary_packages`'
+ printf ' JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id`'
+ printf ' JOIN `repositories` ON `binary_packages`.`repository`=`repositories`.`id`'
+ printf ' WHERE'
+ printf ' `binary_packages`.`%s`=from_base64("%s") AND' \
+ 'epoch' "${epoch}" \
+ 'pkgver' "${pkgver}" \
+ 'pkgrel' "${pkgrel}" \
+ 'pkgname' "${pkgname}"
+ printf ' `architectures`.`name`=from_base64("%s")' \
+ "${arch}"
+ printf ' AND `repositories`.`name`="build-list"),'
+ # max(sub_pkgrel)+1
+ printf '(SELECT 1+MAX(`binary_packages`.`sub_pkgrel`) FROM `binary_packages`'
+ printf ' JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id`'
+ printf ' WHERE'
+ printf ' `binary_packages`.`%s`=from_base64("%s") AND' \
+ 'epoch' "${epoch}" \
+ 'pkgver' "${pkgver}" \
+ 'pkgrel' "${pkgrel}" \
+ 'pkgname' "${pkgname}"
+ if printf '%s' "${arch}" | base64 -d | grep -qxF 'any'; then
+ # 'any' gets higher sub_pkgrel than any architecture
+ printf ' 1'
+ else
+ # not-'any' gets higher sub_pkgrel than same or 'any' architecture
+ printf ' (`architectures`.`name`=from_base64("%s") OR `architectures`.`name`="any")' \
+ "${arch}"
+ fi
+ printf ')'
+ printf ',0))'
+ )
+ fi
{
printf 'INSERT IGNORE INTO `binary_packages` ('
printf '`%s`,' \
@@ -433,8 +448,8 @@ mysql_generate_package_metadata() {
'epoch' \
'pkgver' \
'pkgrel' \
- 'sub_pkgrel' \
'pkgname' \
+ 'sub_pkgrel' \
'has_issues' \
'is_tested'
printf ') SELECT '
@@ -446,9 +461,9 @@ mysql_generate_package_metadata() {
"${epoch}" \
"${pkgver}" \
"${pkgrel}" \
- "${sub_pkgrel}" \
"${pkgname}"
- printf '0,0 FROM'
+ printf '%s,0,0 FROM' \
+ "${sub_pkgrel}"
printf ' `%s` JOIN' \
'repositories' \
'architectures' \
@@ -547,8 +562,9 @@ mysql_generate_package_metadata() {
'epoch' "${epoch}" \
'pkgver' "${pkgver}" \
'pkgrel' "${pkgrel}" \
- 'sub_pkgrel' "${sub_pkgrel}" \
'pkgname' "${pkgname}"
+ printf ' `binary_packages`.`sub_pkgrel` = %s AND' \
+ "${sub_pkgrel}"
printf ' `architectures`.`name` = from_base64("%s") AND' \
"${arch}"
printf ' `repositories`.`name` = from_base64("%s");\n' \
@@ -564,7 +580,7 @@ mysql_generate_package_metadata() {
done
printf '.' >&2
- ${mysql_command} -e "$(
+ {
if [ -s "${temp_dir}/add-build-assignments-command" ]; then
cat "${temp_dir}/add-build-assignments-command"
fi
@@ -574,7 +590,8 @@ mysql_generate_package_metadata() {
if [ -s "${temp_dir}/add-install-targets-command" ]; then
cat "${temp_dir}/add-install-targets-command"
fi
- )"
+ } | \
+ ${mysql_command}
printf '.' >&2
)
@@ -603,13 +620,14 @@ mysql_sanity_check() {
"${temp_dir}/master-mirror-listing"
# shellcheck disable=SC2016
- ${mysql_command} -e '
- SELECT `repositories`.`name`,`pkgname`,`epoch`,`pkgver`,`pkgrel`,`sub_pkgrel`,`architectures`.`name`
- FROM `binary_packages`
- JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id`
- JOIN `repositories` ON `binary_packages`.`repository`=`repositories`.`id`
- WHERE `repositories`.`is_on_master_mirror`
- ' --batch | \
+ {
+ printf 'SELECT `repositories`.`name`,`pkgname`,`epoch`,`pkgver`,`pkgrel`,`sub_pkgrel`,`architectures`.`name`'
+ printf ' FROM `binary_packages`'
+ printf ' JOIN `architectures` ON `binary_packages`.`architecture`=`architectures`.`id`'
+ printf ' JOIN `repositories` ON `binary_packages`.`repository`=`repositories`.`id`'
+ printf ' WHERE `repositories`.`is_on_master_mirror`'
+ } | \
+ ${mysql_command} --batch | \
sed '
1d
s,\t,/,
diff --git a/bin/opcode b/bin/opcode
index de1b3f8..8840e97 100755
--- a/bin/opcode
+++ b/bin/opcode
@@ -24,6 +24,9 @@
# with Opcode_WILLAMETTE_Base
# * Remove all line in Opcode_ARM_THUMB
# return values
+
+# shellcheck disable=SC2001,SC2034,SC2086
+
EXIT_FOUND=0
EXIT_NOT_FOUND=1
EXIT_USAGE=2
@@ -42,7 +45,8 @@ Line_Numbers=false
Leading_Context=0
Trailing_Context=0
-source "${0%/*}/../conf/Opcode_list" # include opcodes from a separate file
+# shellcheck source=lib/opcode_list
+source "${0%/*}/../lib/opcode_list" # include opcodes from a separate file
# GAS-specific opcodes (unofficial names) belonging to the x64 instruction set.
# They are generated by GNU tools (e.g. GDB, objdump) and specify a variant of ordinal opcodes like NOP and MOV.
@@ -162,7 +166,7 @@ usage() {
echo "The script uses Intel opcode syntax. When used in conjunction with objdump, \`-M intel' must be set in order to prevent opcode translation using AT&T syntax."
echo
echo "BE AWARE THAT THE LIST OF KNOWN INSTRUCTIONS OR INSTRUCTIONS SUPPORTED BY PARTICULAR ARCHITECTURES (ESPECIALLY AMD'S) IS ONLY TENTATIVE AND MAY CONTAIN MISTAKES!"
- kill -TRAP $TOP_PID
+ kill -TRAP "$TOP_PID"
}
list_contains() { # Returns 0 if $2 is in array $1, 1 otherwise.
@@ -175,25 +179,25 @@ list_contains() { # Returns 0 if $2 is in array $1, 1 otherwise.
build_instruction_set() { # $1 = enum { Arch, InstSet }, $2 = architecture or instruction set as obtained using -L or -l, $3 = "architecture"/"instruction set" to be used in error message
local e
- list_contains "`eval echo \\\$${1}List`" "$2" || (echo "$2 is not a valid $3."; usage) # Test if the architecture/instruction set is valid.
- if [ -n "`eval echo \\\$${1}_${2}`" ]; then # Add the instruction set(s) if any.
- for e in `eval echo \\\$${1}_${2}`; do # Skip duplicates.
+ list_contains "$(eval echo \\\$${1}List)" "$2" || (echo "$2 is not a valid $3."; usage) # Test if the architecture/instruction set is valid.
+ if [ -n "$(eval echo \\\$${1}_${2})" ]; then # Add the instruction set(s) if any.
+ for e in $(eval echo \\\$${1}_${2}); do # Skip duplicates.
list_contains "$InstSet_Base" $e || InstSet_Base="$e $InstSet_Base"
done
fi
if [ $Recursive = true ]; then
- for a in `eval echo \\\$${1}Dep_$2`; do
+ for a in $(eval echo \\\$${1}Dep_$2); do
build_instruction_set $1 $a "$3"
done
fi
- InstSet_Base="`echo $InstSet_Base | sed 's/$ *//'`" # Remove trailing space.
+ InstSet_Base=$(echo $InstSet_Base | sed 's/$ *//') # Remove trailing space.
}
-trap "exit $EXIT_USAGE" TRAP # Allow usage() function to abort script execution.
+trap 'exit $EXIT_USAGE' TRAP # Allow usage() function to abort script execution.
export TOP_PID=$$ # PID of executing process.
# Parse command line arguments.
-while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
+while getopts ":ra:s:LliIcf:d:D:CvVm:nB:A:h" o; do
case $o in
r) Recursive=true ;;
a) build_instruction_set Arch "$OPTARG" "architecture" ;;
@@ -205,19 +209,19 @@ while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
echo $InstSet_Base
exit $EXIT_USAGE
else
- echo -e "No instruction set or architecture set.\n"
+ echo -e "No instruction set or architecture set.\\n"
usage
fi
;;
I)
if [ -n "$InstSet_Base" ]; then
for s in $InstSet_Base; do
- echo -ne "\e[31;1m$s:\e[0m "
+ echo -ne "\\e[31;1m$s:\\e[0m "
eval echo "\$Opcode_$s"
done
exit $EXIT_USAGE
else
- echo -e "No instruction set or architecture set.\n"
+ echo -e "No instruction set or architecture set.\\n"
usage
fi
;;
@@ -226,12 +230,12 @@ while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
# Unlike architectures, instruction sets are disjoint.
Found=false
for s in $InstSetList; do
- for b in `eval echo \\\$InstSet_$s`; do
+ for b in $(eval echo \\\$InstSet_$s); do
Found_In_Base=false
- for i in `eval echo \\\$Opcode_$b`; do
+ for i in $(eval echo \\\$Opcode_$b); do
if [[ "$i" =~ ^$OPTARG$ ]]; then
- $Found_In_Base || echo -ne "Instruction set \e[33;1m$s\e[0m (base instruction set \e[32;1m$b\e[0m):"
- echo -ne " \e[31;1m$i\e[0m"
+ $Found_In_Base || echo -ne "Instruction set \\e[33;1m$s\\e[0m (base instruction set \\e[32;1m$b\\e[0m):"
+ echo -ne " \\e[31;1m$i\\e[0m"
Found_In_Base=true
Found=true
fi
@@ -240,7 +244,7 @@ while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
done
done
if [ $Found = false ]; then
- echo -e "Operation code \e[31;1m$OPTARG\e[0m has not been found in the database of known instructions." \
+ echo -e "Operation code \\e[31;1m$OPTARG\\e[0m has not been found in the database of known instructions." \
"Perhaps it is translated using other than Intel syntax. If obtained from objdump, check if the \`-M intel' flag is set." \
"Be aware that the search is case sensitive by default (you may use the -C flag, otherwise only lower case opcodes are accepted)."
exit $EXIT_NOT_FOUND
@@ -259,13 +263,13 @@ while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
A) Trailing_Context=$OPTARG ;;
h) usage ;;
\?)
- echo -e "Unknown option: -$OPTARG\n"
+ echo -e "Unknown option: -$OPTARG\\n"
usage
;;
esac
done
shift $((OPTIND-1))
-[ -n "$1" ] && echo -e "Unknown command line parameter: $1\n" && usage
+[ -n "$1" ] && echo -e "Unknown command line parameter: $1\\n" && usage
[ -z "$InstSet_Base" ] && usage
# Create list of grep parameters.
@@ -279,12 +283,13 @@ Grep_Params="--color=auto -B $Leading_Context -A $Trailing_Context"
# Build regular expression for use in grep.
RegEx=""
for s in $InstSet_Base; do
- eval RegEx=\"$RegEx \$Opcode_$s\"
+ eval 'RegEx="$RegEx $Opcode_'"$s"'"'
done
# Add leading and trailing opcode separators to prevent false positives.
-RegEx="$Leading_Separator`echo $RegEx | sed "s/ /$(echo "$Trailing_Separator"|sed 's/[\/&]/\\\&/g')|$(echo "$Leading_Separator"|sed 's/[\/&]/\\\&/g')/g"`$Trailing_Separator"
+RegEx="$Leading_Separator$(echo $RegEx | sed "s/ /$(echo "$Trailing_Separator"|sed 's/[\/&]/\\\&/g')|$(echo "$Leading_Separator"|sed 's/[\/&]/\\\&/g')/g")$Trailing_Separator"
-[ $Verbose = true -a $Count_Matching = false ] && RegEx="$RegEx|\$"
+[ $Verbose = true ] && [ $Count_Matching = false ] && RegEx="$RegEx|\$"
+# shellcheck disable=SC2086
# The actual search.
grep $Grep_Params -E "$RegEx" && exit $EXIT_FOUND || exit $EXIT_NOT_FOUND
diff --git a/bin/return-assignment b/bin/return-assignment
index ebaa73a..cd6d30e 100755
--- a/bin/return-assignment
+++ b/bin/return-assignment
@@ -60,12 +60,14 @@ if [ "$5" = 'ERROR' ]; then
fi
# save sent build logs
- tar -x \
- -C "${build_log_directory}/error" \
- --wildcards \
- --no-wildcards-match-slash \
- --transform="s|^|$1.$2.$3.$4.|" \
- '*.build-log.gz'
+ saved_build_logs=$(
+ tar -vx \
+ -C "${build_log_directory}/error" \
+ --wildcards \
+ --no-wildcards-match-slash \
+ --transform="s|^|$1.$2.$3.$4.|" \
+ '*.build-log.gz'
+ )
if [ -f "${work_dir}/package-states/$1.$2.$3.$4.broken" ]; then
was_broken_before=true
@@ -76,20 +78,76 @@ if [ "$5" = 'ERROR' ]; then
# shellcheck disable=SC2154
echo "${slave}" >> \
"${work_dir}/package-states/$1.$2.$3.$4.broken"
- ${mysql_command} -e "$(
- # shellcheck disable=SC2016
+ # shellcheck disable=SC2016
+ {
+ if [ -n "${saved_build_logs}" ]; then
+ printf 'CREATE TEMPORARY TABLE `failures` ('
+ printf '`%s` %s,' \
+ 'date' 'DATETIME' \
+ 'reason' 'SMALLINT' \
+ 'log_file' 'VARCHAR(512)' | \
+ sed 's/,$//'
+ printf ');\n'
+ printf 'INSERT INTO `failures` (`date`,`reason`,`log_file`) VALUES'
+ fail_reason_identifiers=$(
+ {
+ printf 'SELECT `fail_reasons`.`id`,replace(to_base64(`fail_reasons`.`identifier`),"\\n","")'
+ printf ' FROM `fail_reasons` ORDER BY `fail_reasons`.`severity`'
+ } | \
+ ${mysql_command} --raw --batch | \
+ sed '1d'
+ )
+ for saved_build_log in ${saved_build_logs}; do
+ printf '%s' "${fail_reason_identifiers}" | \
+ while read -r reason_id identifier; do
+ if zgrep -q "^$(
+ printf '%s' "${identifier}" | \
+ base64 -d
+ )\$" \
+ "${build_log_directory}/error/$1.$2.$3.$4.${saved_build_log}"; then
+
+ printf ' (from_base64("%s"),%s,from_base64("%s")),' \
+ "$(
+ printf '%s' "${saved_build_log}" | \
+ sed 's|\.build-log\.gz$||;s|^.*\.||' | \
+ base64 -w0
+ )" \
+ "${reason_id}" \
+ "$(
+ printf '%s' "$1.$2.$3.$4.${saved_build_log}" | \
+ base64 -w0
+ )"
+ break
+ fi
+ done
+ done | \
+ sed 's/,$//'
+ printf ';\n'
+ printf 'INSERT INTO `failed_builds` (`build_slave`,`build_assignment`,`date`,`reason`,`log_file`)'
+ printf ' SELECT '
+ printf '`build_slaves`.`%s`,' \
+ 'id' 'currently_building'
+ printf '`failures`.`%s`,' \
+ 'date' 'reason' 'log_file' | \
+ sed 's/,$//'
+ printf ' FROM `build_slaves` JOIN `failures`'
+ printf ' WHERE `build_slaves`.`name`=from_base64("%s");\n' \
+ "$(
+ printf '%s' "${slave}" | \
+ base64 -w0
+ )"
+ printf 'DROP TABLE `failures`;\n'
+ fi
printf 'UPDATE `build_assignments`'
- # shellcheck disable=SC2016
printf ' JOIN `build_slaves` ON `build_slaves`.`currently_building`=`build_assignments`.`id`'
- # shellcheck disable=SC2016
printf ' SET `build_assignments`.`is_broken`=1, `build_slaves`.`currently_building`=NULL'
- # shellcheck disable=SC2016
printf ' WHERE `build_slaves`.`name`=from_base64("%s");\n' \
"$(
printf '%s' "${slave}" | \
base64 -w0
)"
- )"
+ } | \
+ ${mysql_command}
# shellcheck disable=SC2154
sed -i '
@@ -163,9 +221,8 @@ if [ "$5" = 'ERROR' ]; then
sed 's/,$/./'
fi
printf '\n'
- } | tee /dev/stderr > \
- "${irc_dir}/#archlinux-ports/in"
- # why do we need tee there in order for the redirection to work???
+ } | \
+ sponge "${irc_dir}/#archlinux-ports/in"
fi
fi
@@ -368,6 +425,34 @@ if ! [ "${destination}" = 'build-support' ]; then
printf '%s\n' ${packages} > \
"${work_dir}/package-states/$1.$2.$3.$4.done"
fi
+# shellcheck disable=SC2016
+{
+ printf 'UPDATE `build_assignments`'
+ printf ' JOIN `build_slaves` ON `build_slaves`.`currently_building`=`build_assignments`.`id`'
+ printf ' JOIN `binary_packages` ON `binary_packages`.`build_assignment`=`build_assignments`.`id`'
+ printf ' SET'
+ printf ' `build_assignments`.`is_broken`=0,'
+ printf ' `binary_packages`.`repository`=(SELECT `repositories`.`id` FROM `repositories` WHERE `repositories`.`name`=from_base64("%s")),' \
+ "$(
+ printf '%s' "${destination}" | \
+ base64 -w0
+ )"
+ printf ' `binary_packages`.`has_issues`=0,'
+ printf ' `binary_packages`.`is_tested`=0'
+ printf ' WHERE `build_slaves`.`name`=from_base64("%s");\n' \
+ "$(
+ printf '%s' "${slave}" | \
+ base64 -w0
+ )"
+ printf 'UPDATE `build_slaves` SET'
+ printf ' `build_slaves`.`currently_building`=NULL'
+ printf ' WHERE `build_slaves`.`name`=from_base64("%s");\n' \
+ "$(
+ printf '%s' "${slave}" | \
+ base64 -w0
+ )"
+} | \
+ ${mysql_command}
rm -f \
"${work_dir}/package-states/$1.$2.$3.$4.locked" \
"${work_dir}/package-states/$1.$2.$3.$4.broken"
diff --git a/bin/sanity-check b/bin/sanity-check
index 65ac5f3..8736d47 100755
--- a/bin/sanity-check
+++ b/bin/sanity-check
@@ -19,8 +19,8 @@ usage() {
i_am_insane() {
if [ ! -s "${work_dir}/build-master-sanity" ]; then
- printf '\001ACTION goes insane.\001\n' > \
- "${irc_dir}/#archlinux-ports/in"
+ printf '\001ACTION goes insane.\001\n' | \
+ sponge "${irc_dir}/#archlinux-ports/in"
fi
echo 'build master is insane' > \
"${work_dir}/build-master-sanity"
@@ -398,6 +398,6 @@ done
if [ -f "${work_dir}/build-master-sanity" ]; then
rm "${work_dir}/build-master-sanity"
- printf '\001ACTION resumes sanity.\001\n' > \
- "${irc_dir}/#archlinux-ports/in"
+ printf '\001ACTION resumes sanity.\001\n' | \
+ sponge "${irc_dir}/#archlinux-ports/in"
fi
diff --git a/bin/seed-build-list b/bin/seed-build-list
index feea704..acf25c3 100755
--- a/bin/seed-build-list
+++ b/bin/seed-build-list
@@ -5,6 +5,8 @@
# shellcheck source=conf/default.conf
. "${0%/*}/../conf/default.conf"
+# TODO: put new packages also in mysql database
+
# shellcheck disable=SC2016
usage() {
>&2 echo ''
@@ -282,6 +284,11 @@ if ${update}; then
"${tmp_dir}/build-list.new" | \
tee -a "${work_dir}/build-list"
+ while read -r git_revision mod_git_revision repository pkgbase; do
+ mysql_generate_package_metadata "${pkgbase}" "${git_revision}" "${mod_git_revision}" "${repository}"
+ done < \
+ "${tmp_dir}/build-list.new"
+
# Remove the lock file
rm -f "${build_list_lock_file}"
diff --git a/bin/slave-build-connect b/bin/slave-build-connect
index 86ab14b..2ca72a3 100755
--- a/bin/slave-build-connect
+++ b/bin/slave-build-connect
@@ -18,18 +18,17 @@ if [ "${SSH_ORIGINAL_COMMAND%% *}" = "get-assignment" ] || \
printf '%s %s %s\n' "$(date '+%F %T')" "$1" "${SSH_ORIGINAL_COMMAND}" >> \
"${work_dir}/ssh-log"
- ${mysql_command} -e "$(
- # shellcheck disable=SC2016
+ # shellcheck disable=SC2016
+ {
printf 'UPDATE `build_slaves`'
- # shellcheck disable=SC2016
printf ' SET `build_slaves`.`last_connection`=NOW()'
- # shellcheck disable=SC2016
printf ' WHERE `build_slaves`.`name`=from_base64("%s")\n' \
"$(
printf '%s' "$1" | \
base64 -w0
)"
- )"
+ } | \
+ ${mysql_command}
slave="$1" /bin/sh -c "${base_dir}/bin/${SSH_ORIGINAL_COMMAND}"
diff --git a/conf/default.conf b/conf/default.conf
index b2882ac..6ee991b 100755
--- a/conf/default.conf
+++ b/conf/default.conf
@@ -16,6 +16,8 @@ fi
# shellcheck source=bin/common-functions
. "${base_dir}/bin/common-functions"
+# shellcheck source=bin/mysql-functions
+. "${base_dir}/bin/mysql-functions"
work_dir="${base_dir}/work"
diff --git a/conf/Opcode_list b/lib/opcode_list
index 213321f..213321f 100644..100755
--- a/conf/Opcode_list
+++ b/lib/opcode_list
diff --git a/web-scripts/broken-packages.php b/web-scripts/broken-packages.php
new file mode 100644
index 0000000..268e296
--- /dev/null
+++ b/web-scripts/broken-packages.php
@@ -0,0 +1,157 @@
+<html>
+<head>
+<title>List of broken package builds</title>
+<link rel="stylesheet" type="text/css" href="/static/style.css">
+</head>
+<body>
+<a href="build-logs/">build logs</a><br>
+<?php
+
+$mysql = new mysqli("localhost", "webserver", "empty", "buildmaster");
+if ($mysql->connect_error) {
+ die("Connection failed: " . $mysql->connect_error);
+}
+
+$result = $mysql -> query(
+ "SELECT " .
+ "`build_assignments`.`id`," .
+ "`build_assignments`.`is_blocked`," .
+ "`package_sources`.`pkgbase`," .
+ "`package_sources`.`git_revision`," .
+ "`package_sources`.`mod_git_revision`," .
+ "`upstream_repositories`.`name`," .
+ "EXISTS (SELECT * " .
+ "FROM `binary_packages` `broken_bin` " .
+ "JOIN `dependencies` ON `dependencies`.`dependent` = `broken_bin`.`id` " .
+ "JOIN `install_target_providers` ON `install_target_providers`.`install_target` = `dependencies`.`depending_on` " .
+ "JOIN `binary_packages` `to_be_built` ON `to_be_built`.`id` = `install_target_providers`.`package` " .
+ "JOIN `repositories` ON `to_be_built`.`repository` = `repositories`.`id` " .
+ "WHERE `broken_bin`.`build_assignment`=`build_assignments`.`id` ".
+ "AND `repositories`.`name`=\"community-testing\"" .
+ ") AS `dependencies_pending`," .
+ "(SELECT count(*) " .
+ "FROM `build_dependency_loops` " .
+ "WHERE `build_dependency_loops`.`build_assignment`=`build_assignments`.`id`" .
+ ") AS `loops` " .
+ "FROM `build_assignments` " .
+ "JOIN `package_sources` ON `build_assignments`.`package_source` = `package_sources`.`id` " .
+ "JOIN `upstream_repositories` ON `package_sources`.`upstream_package_repository` = `upstream_repositories`.`id` " .
+ "WHERE `build_assignments`.`is_broken` OR `build_assignments`.`is_blocked` IS NOT NULL"
+);
+if ($result -> num_rows > 0) {
+
+ $count = 0;
+
+ while($row = $result->fetch_assoc()) {
+
+foreach ($row as $key => $val)
+
+ $fail_result = $mysql -> query(
+ "SELECT " .
+ "`fail_reasons`.`name`, " .
+ "`failed_builds`.`log_file` " .
+ "FROM `failed_builds` " .
+ "JOIN `build_assignments` ON `failed_builds`.`build_assignment`=`build_assignments`.`id` ".
+ "JOIN `fail_reasons` ON `failed_builds`.`reason`=`fail_reasons`.`id` ".
+ "WHERE `build_assignments`.`id`=".$row["id"]." " .
+ "ORDER BY `failed_builds`.`date`"
+ );
+
+ unset($reasons);
+ unset($last_log);
+ $rows[$count]["trials"] = $fail_result -> num_rows;
+ if ($rows[$count]["trials"] > 0) {
+ while($fail_row = $fail_result->fetch_assoc()) {
+ $reasons[$fail_row["name"]] = $fail_row["name"];
+ $last_log = $fail_row["log_file"];
+ }
+ }
+ if (isset($reasons)) {
+ $to_print="";
+ foreach ($reasons as $reason) {
+ $to_print=$to_print.", ".$reason;
+ }
+ $rows[$count]["fail_reasons"]=substr($to_print,2);
+ } else {
+ $rows[$count]["fail_reasons"]="&nbsp;";
+ }
+
+ $rows[$count]["loops"] = $row["loops"];
+ $rows[$count]["pkgbase"] = $row["pkgbase"];
+ if ($row["dependencies_pending"]=="1")
+ $rows[$count]["pkgbase_print"] = "(" . $rows[$count]["pkgbase"] . ")";
+ else
+ $rows[$count]["pkgbase_print"] = $rows[$count]["pkgbase"];
+ $rows[$count]["git_revision"] = $row["git_revision"];
+ $rows[$count]["mod_git_revision"] = $row["mod_git_revision"];
+ $rows[$count]["name"] = $row["name"];
+ if (isset($last_log))
+ $rows[$count]["print_trials"]="<a href=\"/build-logs/error/".$last_log."\">". $rows[$count]["trials"] ."</a>";
+ else
+ $rows[$count]["print_trials"]=$rows[$count]["trials"];
+ if ($row["is_blocked"]=="") {
+ $rows[$count]["is_blocked"]="&nbsp;";
+ }
+ else {
+ $rows[$count]["is_blocked"] = preg_replace(
+ array (
+ "/FS32#(\\d+)/",
+ "/FS#(\\d+)/"
+ ),
+ array (
+ "<a href=\"https://bugs.archlinux32.org/index.php?do=details&task_id=$1\">$0</a>",
+ "<a href=\"https://bugs.archlinux.org/task/$1\">$0</a>"
+ ),
+ $row["is_blocked"]
+ );
+ }
+ $count++;
+ }
+
+ usort(
+ $rows,
+ function (array $a, array $b) {
+ if ($a["trials"] < $b["trials"])
+ return -1;
+ if ($a["trials"] > $b["trials"])
+ return 1;
+ return strcmp($a["pkgbase"],$b["pkgbase"]);
+ }
+ );
+
+ print "<table>\n";
+ print "<tr>";
+ print "<th>package</th>";
+ print "<th>git revision</th>";
+ print "<th>modification git revision</th>";
+ print "<th>package repository</th>";
+ print "<th>compilations</th>";
+ print "<th>loops</th>";
+// print "<th>dependent</th>";
+ print "<th>build error</th>";
+ print "<th>blocked</th>";
+ print "</tr>\n";
+
+ foreach($rows as $row) {
+
+ print "<tr>";
+
+ print "<td><a href=\"/graphs/".$row["pkgbase"].".png\">".$row["pkgbase_print"]."</a></td>";
+ print "<td><p style=\"font-size:8px\">".$row["git_revision"]."</p></td>";
+ print "<td><p style=\"font-size:8px\">".$row["mod_git_revision"]."</p></td>";
+ print "<td>".$row["name"]."</td>";
+ print "<td>".$row["print_trials"]."</td>";
+ print "<td>".$row["loops"]."</td>";
+// <td>0</td>
+ print "<td>".$row["fail_reasons"]."</td>";
+ print "<td>".$row["is_blocked"]."</td>";
+
+ print "</tr>\n";
+ }
+
+ print "</table>\n";
+}
+
+?>
+</body>
+</html>
diff --git a/web-scripts/build-slaves.php b/web-scripts/build-slaves.php
new file mode 100644
index 0000000..0b8ae6a
--- /dev/null
+++ b/web-scripts/build-slaves.php
@@ -0,0 +1,44 @@
+<html><head><title>list of build slaves</title></head><body>
+<?php
+
+ $conn = new mysqli("localhost","http","http","buildmaster");
+ if ($conn->connect_error) {
+ die("Connection to mysql database failed: " . $conn->connect_error);
+ }
+
+ $result =
+ $conn->query(
+ "SELECT" .
+ " `build_slaves`.`name`," .
+ "`build_slaves`.`operator`," .
+ "`package_sources`.`pkgbase`," .
+ "`build_slaves`.`last_connection`" .
+ " FROM `build_slaves`" .
+ " LEFT JOIN `build_assignments` ON" .
+ " `build_slaves`.`currently_building`=`build_assignments`.`id`" .
+ " LEFT JOIN `package_sources` ON" .
+ " `build_assignments`.`package_source`=`package_sources`.`id`" .
+ " ORDER BY `build_slaves`.`last_connection`"
+ );
+
+ print "<table border=1>\n";
+ if ($result->num_rows > 0) {
+ print "<tr><th>name</th><th>operator</th><th>currently building</th><th>last connection</th></tr>\n";
+ while ($row = $result -> fetch_assoc()) {
+ foreach ($row as $key => $value) {
+ if ($value=="") {
+ $row[$key]="&nbsp;";
+ }
+ }
+ print "<tr>";
+ print "<td>".$row["name"]."</td>";
+ print "<td>".$row["operator"]."</td>";
+ print "<td>".$row["pkgbase"]."</td>";
+ print "<td>".$row["last_connection"]."</td>";
+ print "</tr>\n";
+ }
+ }
+ print "</table>\n";
+
+?>
+</body></html>
diff --git a/web-scripts/packages.php b/web-scripts/packages.php
new file mode 100644
index 0000000..b8b5dda
--- /dev/null
+++ b/web-scripts/packages.php
@@ -0,0 +1,20 @@
+<?php
+
+ $mysql = new mysqli("localhost", "http", "http");
+ if ($mysql->connect_error) {
+ die("Connection to mysql database failed: " . $mysql->connect_error);
+ }
+
+ $result = $mysql -> query("SELECT * FROM buildmaster.binary_packages");
+ if ($result -> num_rows > 0) {
+ while($row = $result->fetch_assoc()) {
+ foreach ($row as $key => $val) {
+ print $key .": ".$val." - ";
+ }
+ print "<br>\n";
+ }
+ }
+
+ print 'OK';
+
+?>
diff --git a/web-scripts/statistics.php b/web-scripts/statistics.php
new file mode 100644
index 0000000..279aa39
--- /dev/null
+++ b/web-scripts/statistics.php
@@ -0,0 +1,179 @@
+<?php
+
+$columns = array(
+ 'stable',
+ 'tasks',
+ 'pending_packages',
+ 'staging',
+ 'testing',
+ 'broken',
+ 'loops',
+ 'looped_packages',
+ 'locked',
+ 'blocked',
+ 'next_pending',
+ 'tested'
+);
+
+$print_columns = array(
+ 'tasks',
+ 'pending_packages',
+ 'staging',
+ 'testing',
+ 'tested',
+ 'broken',
+ 'loops',
+ 'looped_packages',
+ 'locked',
+ 'blocked',
+ 'next_pending'
+);
+
+$t_min = -1;
+$t_max = -1;
+$val_max = -1;
+
+foreach (explode("\n",trim(file_get_contents('/srv/http/statistics'))) as $val) {
+ $val = explode(" ",$val);
+ if (($t_min == -1) || ($t_min > $val[0]))
+ $t_min = $val[0];
+ if (($t_max == -1) || ($t_max < $val[0]))
+ $t_max = $val[0];
+ foreach ($columns as $id => $column) {
+ if (count($val) > $id+1)
+ $values[$column][$val[0]] = $val[$id+1];
+ };
+ foreach ($print_columns as $column) {
+ if (array_key_exists($column,$values))
+ if (($val_max == -1) || ($val_max < $values[$column][$val[0]]))
+ $val_max = $values[$column][$val[0]];
+ }
+};
+
+$max_len = 0;
+foreach ($print_columns as $column) {
+ $len = strlen($values[$column][$t_max])+1;
+ if ($len > $max_len)
+ $max_len = $len;
+}
+
+$width = 1600;
+$height = 600;
+$border = 5;
+$legend_line_length = 10;
+$legend_height = 3 * ImageFontHeight(5) + $legend_line_length;
+
+$im = @ImageCreate ($width + $legend_line_length + $max_len * ImageFontWidth(5), $height + $legend_height)
+ or die ("Cannot create new gd-image-stream");
+
+$background_color = ImageColorAllocate ($im, 255, 255, 255);
+$foreground_color = ImageColorAllocate ($im, 0, 0, 0);
+
+$colors['stable'] = ImageColorAllocate ($im, 0, 0, 0);
+$colors['tasks'] = ImageColorAllocate ($im, 0, 0, 128);
+$colors['pending_packages'] = ImageColorAllocate ($im, 0, 0, 255);
+$colors['staging'] = ImageColorAllocate ($im, 0, 100, 0);
+$colors['testing'] = ImageColorAllocate ($im, 0, 200, 0);
+$colors['tested'] = ImageColorAllocate ($im, 100, 255, 0);
+$colors['broken'] = ImageColorAllocate ($im, 255, 0, 0);
+$colors['loops'] = ImageColorAllocate ($im, 128, 128, 0);
+$colors['looped_packages'] = ImageColorAllocate ($im, 255, 128, 128);
+$colors['locked'] = ImageColorAllocate ($im, 128, 128, 128);
+$colors['blocked'] = ImageColorAllocate ($im, 128, 0, 0);
+$colors['next_pending'] = ImageColorAllocate ($im, 0, 255, 255);
+
+function scale($x, $x_min, $x_max, $scale, $log) {
+ if ($log) {
+ $x = log($x + 10);
+ $x_min = log($x_min + 10);
+ $x_max = log($x_max + 10);
+ };
+ if ($x_max == $x_min)
+ $frac = 0;
+ else
+ $frac = ($x - $x_min)/($x_max - $x_min);
+ if ($scale < 0)
+ return ($frac-1) * $scale;
+ else
+ return $frac * $scale;
+};
+
+function print_graph($data, $color) {
+ global $width, $height, $im, $t_min, $t_max, $val_max, $border, $legend_line_length;
+ ksort($data);
+ $last_t = -1;
+ $last_val = -1;
+ foreach ($data as $t => $val) {
+ if ($last_t != -1)
+ ImageLine(
+ $im,
+ scale($last_t,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ scale($last_val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ scale($t,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $color
+ );
+ $last_t = $t;
+ $last_val = $val;
+ }
+ ImageString(
+ $im,
+ 5,
+ $width+$legend_line_length,
+ scale($last_val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border - ImageFontHeight(5)/2,
+ " ".$data[$t_max],
+ $color
+ );
+};
+
+ImageRectangle($im, $legend_line_length, 0, $width-1+$legend_line_length, $height-1, $foreground_color);
+
+ImageString($im, 5, $legend_line_length, $height + $legend_line_length + 2*ImageFontHeight(5), "( ".trim(shell_exec("uptime | sed 's|^.*\\s\\(load\\)|\\1|'"))." )", $foreground_color);
+
+$xpos = $legend_line_length;
+foreach ($print_columns as $column) {
+ print_graph($values[$column], $colors[$column]);
+ ImageString($im, 5, $xpos, $height + $legend_line_length + ImageFontHeight(5), $column, $colors[$column]);
+ $xpos += (strlen($column) + 1.75) * ImageFontWidth(5);
+}
+
+ImageString($im, 5, $legend_line_length, $height + $legend_line_length, date('Y-m-d H:i', $t_min), $foreground_color);
+$s = date('Y-m-d H:i', $t_max);
+ImageString($im, 5, $width+$legend_line_length - strlen($s)*ImageFontWidth(5), $height + $legend_line_length, $s, $foreground_color);
+
+for ($t=ceil($t_min/24/60/60); $t<=floor($t_max/24/60/60); $t++)
+ ImageLine(
+ $im,
+ scale($t*24*60*60,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ $height,
+ scale($t*24*60*60,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ $height+$legend_line_length,
+ $foreground_color
+ );
+
+for ($val=0; $val<=$val_max;) {
+ ImageLine(
+ $im,
+ 0,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $legend_line_length,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $foreground_color
+ );
+ if (! isset($_GET["log"]))
+ $val+=pow(10,round(log($val_max)/log(10))-1);
+ elseif ($val==0)
+ $val++;
+ else
+ $val=$val*10;
+}
+
+// ImageString ($im, 1, 5, 5, "Test-String ".rand(), $foreground_color);
+
+header ("Content-type: image/png");
+
+ImagePNG ($im);
+
+// passthru('wc -l /srv/http/statistics');
+
+?>