summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/bootstrap-mysql2
-rwxr-xr-xbin/repo-copy92
-rwxr-xr-xbin/sanity-check9
-rwxr-xr-xlib/mysql-functions75
4 files changed, 159 insertions, 19 deletions
diff --git a/bin/bootstrap-mysql b/bin/bootstrap-mysql
index 8b01c38..afe1850 100755
--- a/bin/bootstrap-mysql
+++ b/bin/bootstrap-mysql
@@ -32,6 +32,8 @@ done | \
sort -k2,2 > \
"${tmp_dir}/master-mirror-listing"
+# TODO: include hash of binary package in mysql database
+
if [ ! "$1" = 'slim' ]; then
tables=$(
printf '%s\n' \
diff --git a/bin/repo-copy b/bin/repo-copy
new file mode 100755
index 0000000..8566d7c
--- /dev/null
+++ b/bin/repo-copy
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+# Rudimentary copy a package from one repository to another.
+# Note, that we do _not_ need to have the package itself, since all
+# relevant information is already in the original package database.
+
+# "Rudimentary" means the following restrictions:
+# - no arguments are accepted
+# - no database signatures are handled
+# - only *.db.tar.gz and *.files.tar.gz are recognized as database
+
+usage() {
+ >&2 echo 'usage:'
+ >&2 echo ' repo-copy from-repo.db.tar.gz to-repo.db.tar.gz package1 package2 ...'
+ >&2 echo
+ >&2 echo 'Note, that the packages must be given with version, e.g. "linux-4.15.7-1.0".'
+ exit 2
+}
+
+if [ $# -le 2 ]; then
+ usage
+fi
+
+from_repo="$1"
+to_repo="$2"
+shift
+shift
+
+tmp_dir=$(mktemp -d)
+trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT
+
+# extract the databases
+for repo in 'from' 'to'; do
+ for archive in 'db' 'files'; do
+ eval 'repo_db="${'"${repo}"'_repo}"'
+ if [ "${repo_db}" = "${repo_db%.db.tar.gz}" ]; then
+ >&2 printf '"%s" has an invalid suffix.\n' "${repo_db}"
+ usage
+ fi
+ if [ "${archive}" = 'files' ]; then
+ repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
+ fi
+ if [ ! -f "${repo_db}" ]; then
+ >&2 printf 'Cannot open file "%s".\n' "${repo_db}"
+ usage
+ fi
+ mkdir "${tmp_dir}/${repo}.${archive}"
+ bsdtar -C "${tmp_dir}/${repo}.${archive}" -xf "${repo_db}"
+ done
+done
+
+# move the packages
+for package in "$@"; do
+ errors=$(
+ find "${tmp_dir}/to.db" "${tmp_dir}/to.files" -mindepth 1 -maxdepth 1 \
+ -printf '%f\n' | \
+ sed 's/-[^-]\+-[^-]\+$//' | \
+ grep -xF "${package%-*-*}"
+ )
+ if [ -n "${errors}" ]; then
+ >&2 printf 'The target repository "%s" already contains the following packages - "repo-remove" them first:\n' \
+ "${to_repo}"
+ >&2 printf '%s\n' "${errors}"
+ exit 2
+ fi
+ for archive in 'db' 'files'; do
+ if [ ! -d "${tmp_dir}/from.${archive}/${package}" ]; then
+ >&2 printf 'Repository "%s" does not contain package "%s"\n' \
+ "${from_repo}" "${package}"
+ exit 2
+ fi
+ mv "${tmp_dir}/from.${archive}/${package}" "${tmp_dir}/to.${archive}/"
+ done
+done
+
+# pack the database
+for archive in 'db' 'files'; do
+ repo_db="${to_repo}"
+ if [ "${archive}" = 'files' ]; then
+ repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
+ fi
+ bsdtar -C "${tmp_dir}" -czf "${tmp_dir}/${repo_db##*/}" --strip-components=1 "to.${archive}"
+done
+
+# move the database in place
+for archive in 'db' 'files'; do
+ repo_db="${to_repo}"
+ if [ "${archive}" = 'files' ]; then
+ repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
+ fi
+ mv "${tmp_dir}/${repo_db##*/}" "${repo_db}"
+done
diff --git a/bin/sanity-check b/bin/sanity-check
index 601a940..824b7a2 100755
--- a/bin/sanity-check
+++ b/bin/sanity-check
@@ -395,7 +395,14 @@ while [ $# -gt 0 ]; do
if [ ${silence} -le 1 ]; then
printf '\nThere is something wrong with the database:\n'
cat "${webserver_directory}/mysql-sanity.html"
- fi
+ fi >> \
+ "${tmp_dir}/messages"
+ i_am_insane
+ fi
+
+ if find "${work_dir}" -mindepth 1 -maxdepth 1 -name 'tmp.mysql-functions.query.*' | \
+ grep '\S' >> \
+ "${tmp_dir}/messages"; then
i_am_insane
fi
diff --git a/lib/mysql-functions b/lib/mysql-functions
index 26d3db8..d87b79e 100755
--- a/lib/mysql-functions
+++ b/lib/mysql-functions
@@ -25,31 +25,70 @@ base64_encode_each() {
# mysql_run_query
# wrapper function to query mysql
mysql_run_query() {
+ local query_file
if [ -s "${work_dir}/build-master-sanity" ]; then
+ # If the build master is insane, the calling command should only check
+ # if the build master is still insane - we do not want to log that.
${mysql_command} -N --raw --batch "$@"
else
- {
- printf '%s %s: ' "$0" "${mysql_command} -N --raw --batch $*"
- date
- } \
- | tee -a "${work_dir}/mysql.stdin" \
- | tee -a "${work_dir}/mysql.stdout" \
- >> "${work_dir}/mysql.stderr"
- tee -a "${work_dir}/mysql.stdin" \
- | ${mysql_command} -N --raw --batch "$@" \
- 2>> "${work_dir}/mysql.stderr" \
- | tee -a "${work_dir}/mysql.stdout"
- for s in \
- "${work_dir}/mysql.stdin" \
- "${work_dir}/mysql.stdout" \
- "${work_dir}/mysql.stderr"; do
+ # we save the query in a file and delete that file if the query succeeded
+ query_file=$(mktemp "${work_dir}/tmp.mysql-functions.query.$(date +'%Y-%m-%dT%T').XXXXXX")
+ cat > "${query_file}"
+ for i in {1..10}; do
{
- tail -n 10000 "$s"
- printf '%s %s done: ' "$0" "${mysql_command} $*"
+ printf '%s %s: ' "$0" "${mysql_command} -N --raw --batch $*"
date
} \
- | sponge "$s"
+ | tee -a "${work_dir}/mysql.stdin" \
+ | tee -a "${work_dir}/mysql.stdout" \
+ >> "${work_dir}/mysql.stderr"
+ cat "${query_file}" \
+ >> "${work_dir}/mysql.stdin"
+ {
+ ${mysql_command} -N --raw --batch "$@" \
+ < "${query_file}" \
+ 2>> "${work_dir}/mysql.stderr" \
+ && rm "${query_file}"
+ } \
+ | tee -a "${work_dir}/mysql.stdout"
+ if ! [ -f "${query_file}" ]; then
+ # success!
+ for s in \
+ "${work_dir}/mysql.stdin" \
+ "${work_dir}/mysql.stdout" \
+ "${work_dir}/mysql.stderr"; do
+ {
+ tail -n 10000 "$s"
+ printf '%s %s done: ' "$0" "${mysql_command} $*"
+ date
+ } \
+ | sponge "$s"
+ done
+ break
+ fi
+ for s in \
+ "${work_dir}/mysql.stdin" \
+ "${work_dir}/mysql.stdout" \
+ "${work_dir}/mysql.stderr"; do
+ {
+ printf '%s %s FAILED: ' "$0" "${mysql_command} $*"
+ date
+ } \
+ >> "$s"
+ done
done
+ # a present query_file means there was an error
+ if [ -f "${query_file}" ]; then
+ >&2 printf 'I could not complete a mysql query!\n'
+ if [ ! -s "${work_dir}/build-master-sanity" ]; then
+ printf '\001ACTION failed to execute a mysql query - can you have a look at "%s"?.\001\n' \
+ "${query_file##*/}" \
+ | sponge "${irc_dir}/#archlinux-ports/in"
+ fi
+ echo 'A mysql query failed.' > \
+ "${work_dir}/build-master-sanity"
+ return 2
+ fi
fi
}