[dbscripts,1/8] Fix quoting around variables, especially arrays.

Message ID 20180314015205.20781-2-lukeshu@lukeshu.com
State Superseded
Headers show
Series Backports from Parabola | expand

Commit Message

Luke Shumaker March 14, 2018, 1:51 a.m. UTC
From: Luke Shumaker <lukeshu@parabola.nu>

Other than pure quoting, this involved:
 - swapping */@ for array access in a few places
 - fiddling with printf in a pipeline
 - replacing `$(echo ${array[@]})` with `${array[*]}`
 - replacing `echo $(...)` with `...`

When searching for these things, I used the command:

    grep -Prn --exclude-dir=.git '(?<!["=]|\[\[ |\[\[ -[zn] )\$(?!{?#|\(|\? )'

and ignored a bunch of false positives.
---
 config                                       |  2 +-
 cron-jobs/check_archlinux/parse_pkgbuilds.sh | 52 ++++++++--------
 cron-jobs/devlist-mailer                     |  2 +-
 cron-jobs/ftpdir-cleanup                     | 34 +++++-----
 cron-jobs/integrity-check                    |  6 +-
 cron-jobs/sourceballs                        | 42 ++++++-------
 cron-jobs/update-web-db                      | 20 +++---
 db-functions                                 | 92 ++++++++++++++--------------
 db-move                                      | 58 +++++++++---------
 db-remove                                    | 22 +++----
 db-repo-add                                  | 22 +++----
 db-repo-remove                               | 22 +++----
 db-update                                    | 36 +++++------
 testing2x                                    | 34 +++++-----
 14 files changed, 221 insertions(+), 223 deletions(-)

Comments

Emil Velikov via arch-projects March 14, 2018, 4:11 a.m. UTC | #1
On 03/13/2018 09:51 PM, Luke Shumaker wrote:
> From: Luke Shumaker <lukeshu@parabola.nu>
> 
> Other than pure quoting, this involved:
>  - swapping */@ for array access in a few places
>  - fiddling with printf in a pipeline
>  - replacing `$(echo ${array[@]})` with `${array[*]}`
>  - replacing `echo $(...)` with `...`
> 
> When searching for these things, I used the command:
> 
>     grep -Prn --exclude-dir=.git '(?<!["=]|\[\[ |\[\[ -[zn] )\$(?!{?#|\(|\? )'
> 
> and ignored a bunch of false positives.

I don't really see the need to quote every variable just because it is a
variable, at least in cases where the variable is fairly statically
defined... I'd like to see path components that could have spaces
quoted, and arrays I guess because semantically that's how you iterate
over an array. Also you introduced some bugs, in cases where we actually
want whitespace splitting...

>  backup_package_variables() {
> -	for var in ${splitpkg_overrides[@]}; do
> +	for var in "${splitpkg_overrides[@]}"; do
>  		indirect="${var}_backup"
> -		eval "${indirect}=(\${$var[@]})"
> +		eval "${indirect}=(\"\${$var[@]}\")"
>  	done
>  }
>  
>  restore_package_variables() {
> -	for var in ${splitpkg_overrides[@]}; do
> +	for var in "${splitpkg_overrides[@]}"; do
>  		indirect="${var}_backup"
>  		if [ -n "${!indirect}" ]; then
> -			eval "${var}=(\${$indirect[@]})"
> +			eval "${var}=(\"\${$indirect[@]}\")"
>  		else
> -			unset ${var}
> +			unset "${var}"
>  		fi
>  	done

This is too much escaping and metaprogramming, there are better ways of
backing up a variable to begin with. :/

We do it in makepkg, I will have us do it here as well. Advantage: using
declare -p means the shell auto-escapes things where needed.

> -	if ! ${CLEANUP_DRYRUN}; then
> +	if ! "${CLEANUP_DRYRUN}"; then

This is a variable being run as a command, so if there were to be spaces
in it we'd end up trying to run a command with a space in it. Arguably
we should not be running this as a command (even though they are set to
true/false which is a shell builtin blah blah blah) but since we are it
would be illogical to indicate that if there are spaces they should be
interpreted as string literals in an executable filename.


> -${CLEANUP_DRYRUN} && warning 'dry run mode is active'
> +"${CLEANUP_DRYRUN}" && warning 'dry run mode is active'

Same.

> -		if ! ${CLEANUP_DRYRUN}; then
> +		if ! "${CLEANUP_DRYRUN}"; then

Same.

>  # Create a readable file for each repo with the following format
>  # <pkgbase|pkgname> <pkgver>-<pkgrel> <arch> <license>[ <license>]

When we consume this file...

>  	while read line; do
> -		pkginfo=(${line})
> +		pkginfo=("${line}")

That's completely wrong, just look at the next five lines.

>  		pkgbase=${pkginfo[0]}
>  		pkgver=${pkginfo[1]}
>  		pkgarch=${pkginfo[2]}
> -		pkglicense=(${pkginfo[@]:3})
> +		pkglicense=("${pkginfo[@]:3}")

How will we extract elements of this array, if your quoting squashes
everything down into one array element? ${pkginfo[0]} will have too
much, and the other elements simply won't exist at all.

We go from having:

declare -a pkginfo=([0]="foo" [1]="1.0-1" [2]="any" [3]="GPL")

to having:

declare -a pkginfo=([0]="foo 1.0-1 any GPL")

> -		if ! ([[ -z ${ALLOWED_LICENSES[@]} ]] || chk_license ${pkglicense[@]} || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then
> +		if ! ([[ -z ${ALLOWED_LICENSES[*]} ]] || chk_license "${pkglicense[@]}" || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then

What's the check here anyways? This considers ALLOWED_LICENSES=('') to
be non-empty, so we might as well check the length of
${#ALLOWED_LICENSES[@]} which is a clearer read.


> -	${SOURCE_CLEANUP_DRYRUN} && warning 'dry run mode is active'
> -	for old_pkg in ${old_pkgs[@]}; do
> +	"${SOURCE_CLEANUP_DRYRUN}" && warning 'dry run mode is active'
> +	for old_pkg in "${old_pkgs[@]}"; do
>  		msg2 "${old_pkg}"
> -		if ! ${SOURCE_CLEANUP_DRYRUN}; then
> +		if ! "${SOURCE_CLEANUP_DRYRUN}"; then
>  			mv_acl "$FTP_BASE/${SRCPOOL}/${old_pkg}" "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
>  			touch "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
>  		fi
> @@ -147,9 +147,9 @@ done
>  
>  if (( ${#old_pkgs[@]} >= 1 )); then
>  	msg "Removing old source packages from the cleanup directory..."
> -	for old_pkg in ${old_pkgs[@]}; do
> +	for old_pkg in "${old_pkgs[@]}"; do
>  		msg2 "${old_pkg}"
> -		${SOURCE_CLEANUP_DRYRUN} || rm -f "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
> +		"${SOURCE_CLEANUP_DRYRUN}" || rm -f "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
>  	done

More commands-as-variables where whitespace if it existed would actually
be significant and wanted.

> -	if [[ ! -z "$(echo ${@%\.*} | sed "s/ /\n/g" | sort | uniq -D)" ]]; then
> +	if [[ ! -z "$(printf '%s\n' "${@%\.*}" | sort | uniq -D)" ]]; then

Thanks for noticing this! printf is a lot nicer. I'm also wondering if
it makes more sense to use a single awk 'a[$0]++{exit 1}' rather than
chaining sort/uniq and reading its length in a bash test... the problem
here was always that uniq -D returns successfully even if it prints
nothing. With awk we can actually have an exit code stating whether
duplicates were found.

> -		local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo ${pkgname[@]}))
> -		for svnname in ${svnnames[@]}; do
> -			echo "${svnname}" >> "${repo}/${_pkgarch}/${_pkgbase}/svn"
> -		done
> +		local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo "${pkgname[@]}"))
> +		printf '%s\n' "${svnnames[@]}" >> "${repo}/${_pkgarch}/${_pkgbase}/svn"

Again this does actually look a lot nicer, thanks for spotting this.


> -		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-${pkgarch}${PKGEXTS} 2>/dev/null))
> -		for pkg in ${arch_pkgs[@]} ${any_pkgs[@]}; do
> +		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-"${pkgarch}"${PKGEXTS} 2>/dev/null))
> +		for pkg in "${arch_pkgs[@]}" "${any_pkgs[@]}"; do

Dropping in and out of quotes here a number of times sort of hammers
home the point to me that maybe we really don't need to do this.
Configurable directories need to be quoted, yes, but then dropping out
to expand a wildcard, failing to quote the - for good measure, and
quoting pkgarch only to resort to expanding PKGEXTS as a glob pattern...

It is only possible anyways for $STAGING to have spaces.

> -		${found_source} || die "%s not found in [%s]" "$pkgbase" "$TESTING_REPO"
> +		"${found_source}" || die "%s not found in [%s]" "$pkgbase" "$TESTING_REPO"

command as variable

> -		${found_target} || die "%s not found in any of these repos: %s" "$pkgbase" "${STABLE_REPOS[*]}"
> +		"${found_target}" || die "%s not found in any of these repos: %s" "$pkgbase" "${STABLE_REPOS[*]}"

This too.
Luke Shumaker March 14, 2018, 4:53 a.m. UTC | #2
On Wed, 14 Mar 2018 00:11:05 -0400,
Eli Schwartz via arch-projects wrote:
> >  	while read line; do
> > -		pkginfo=(${line})
> > +		pkginfo=("${line}")
> 
> That's completely wrong, just look at the next five lines.
> 
> >  		pkgbase=${pkginfo[0]}
> >  		pkgver=${pkginfo[1]}
> >  		pkgarch=${pkginfo[2]}
> > -		pkglicense=(${pkginfo[@]:3})
> > +		pkglicense=("${pkginfo[@]:3}")

You're absolutely right.  I realized I screwed up right after I sent
it.

> I don't really see the need to quote every variable just because it is a
> variable, at least in cases where the variable is fairly statically
> defined... I'd like to see path components that could have spaces
> quoted, and arrays I guess because semantically that's how you iterate
> over an array. Also you introduced some bugs, in cases where we actually
> want whitespace splitting...

Part of it is to have a common style.  Trying to rectify two codebases
that diverged 7 years ago is rough.  When trying to come up with clean
diffs, having to guess "did the other one quote this variable?" makes
it harder.  If you can say "always quote (except for the LHS of [[
]])" or something, that makes it a bit easier.

> >  backup_package_variables() {
> > -	for var in ${splitpkg_overrides[@]}; do
> > +	for var in "${splitpkg_overrides[@]}"; do
> >  		indirect="${var}_backup"
> > -		eval "${indirect}=(\${$var[@]})"
> > +		eval "${indirect}=(\"\${$var[@]}\")"
> >  	done
> >  }
> >  
> >  restore_package_variables() {
> > -	for var in ${splitpkg_overrides[@]}; do
> > +	for var in "${splitpkg_overrides[@]}"; do
> >  		indirect="${var}_backup"
> >  		if [ -n "${!indirect}" ]; then
> > -			eval "${var}=(\${$indirect[@]})"
> > +			eval "${var}=(\"\${$indirect[@]}\")"
> >  		else
> > -			unset ${var}
> > +			unset "${var}"
> >  		fi
> >  	done
> 
> This is too much escaping and metaprogramming, there are better ways of
> backing up a variable to begin with. :/
> 
> We do it in makepkg, I will have us do it here as well. Advantage: using
> declare -p means the shell auto-escapes things where needed.

I haven't been keeping my thumb on makepkg git, but the eval lines as
I wrote them exactly match the eval lines in makepkg 5.0.2's version
of {backup,restore}_package_variables (makepkg's versions don't quote
the for loops, or the unset command).

> > -	if ! ${CLEANUP_DRYRUN}; then
> > +	if ! "${CLEANUP_DRYRUN}"; then
> 
> This is a variable being run as a command, so if there were to be spaces
> in it we'd end up trying to run a command with a space in it. Arguably
> we should not be running this as a command (even though they are set to
> true/false which is a shell builtin blah blah blah) but since we are it
> would be illogical to indicate that if there are spaces they should be
> interpreted as string literals in an executable filename.

For the true/false idiom, quoting it is just a style rule.  I figure
accepting the true/false idiom doesn't imply allowing the boolean
variable to have any value.  Having the quotes would help catch the
variable being erroneously set to a different value.

> > -		if ! ([[ -z ${ALLOWED_LICENSES[@]} ]] || chk_license ${pkglicense[@]} || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then
> > +		if ! ([[ -z ${ALLOWED_LICENSES[*]} ]] || chk_license "${pkglicense[@]}" || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then
> 
> What's the check here anyways? This considers ALLOWED_LICENSES=('') to
> be non-empty, so we might as well check the length of
> ${#ALLOWED_LICENSES[@]} which is a clearer read.

Agree.

> > -	if [[ ! -z "$(echo ${@%\.*} | sed "s/ /\n/g" | sort | uniq -D)" ]]; then
> > +	if [[ ! -z "$(printf '%s\n' "${@%\.*}" | sort | uniq -D)" ]]; then
> 
> Thanks for noticing this! printf is a lot nicer. I'm also wondering if
> it makes more sense to use a single awk 'a[$0]++{exit 1}' rather than
> chaining sort/uniq and reading its length in a bash test... the problem
> here was always that uniq -D returns successfully even if it prints
> nothing. With awk we can actually have an exit code stating whether
> duplicates were found.

Yeah.  Awk is probably the better solution here.  Even if it's not,
that !-z could be -n.  This commit was mostly a dumb grep for unquoted
variables (also, awk exiting early is safe, because Bash builtins are
silent when the recieve SIGPIPE).

> > -		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-${pkgarch}${PKGEXTS} 2>/dev/null))
> > -		for pkg in ${arch_pkgs[@]} ${any_pkgs[@]}; do
> > +		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-"${pkgarch}"${PKGEXTS} 2>/dev/null))
> > +		for pkg in "${arch_pkgs[@]}" "${any_pkgs[@]}"; do
> 
> Dropping in and out of quotes here a number of times sort of hammers
> home the point to me that maybe we really don't need to do this.
> Configurable directories need to be quoted, yes, but then dropping out
> to expand a wildcard, failing to quote the - for good measure, and
> quoting pkgarch only to resort to expanding PKGEXTS as a glob pattern...
> 
> It is only possible anyways for $STAGING to have spaces.

At some point, I'd like to have `make lint` run shellcheck over
dbscripts.  That's a long way off, both because of a whole bunch of
changes needed in dbscripts to make it come back clean, and a few
features needed in shellcheck to avoid having to drop entirely too
many shellcheck directives in to the dbscripts source.

Anyway, I know linters should be taken with a grain of salt, but when
there's something simple like this, that you know just about any
linter would complain about... why not?
Emil Velikov via arch-projects March 14, 2018, 6:41 a.m. UTC | #3
On 03/14/2018 12:53 AM, Luke Shumaker wrote:
> Part of it is to have a common style.  Trying to rectify two codebases
> that diverged 7 years ago is rough.  When trying to come up with clean
> diffs, having to guess "did the other one quote this variable?" makes
> it harder.  If you can say "always quote (except for the LHS of [[
> ]])" or something, that makes it a bit easier.

I'm not sure that "specifically for the sole sake of diffs against our
fork" is a valid justification on its own for modifying a coding style.

>>>  backup_package_variables() {
>>> -	for var in ${splitpkg_overrides[@]}; do
>>> +	for var in "${splitpkg_overrides[@]}"; do
>>>  		indirect="${var}_backup"
>>> -		eval "${indirect}=(\${$var[@]})"
>>> +		eval "${indirect}=(\"\${$var[@]}\")"
>>>  	done
>>>  }
>>>  
>>>  restore_package_variables() {
>>> -	for var in ${splitpkg_overrides[@]}; do
>>> +	for var in "${splitpkg_overrides[@]}"; do
>>>  		indirect="${var}_backup"
>>>  		if [ -n "${!indirect}" ]; then
>>> -			eval "${var}=(\${$indirect[@]})"
>>> +			eval "${var}=(\"\${$indirect[@]}\")"
>>>  		else
>>> -			unset ${var}
>>> +			unset "${var}"
>>>  		fi
>>>  	done
>>
>> This is too much escaping and metaprogramming, there are better ways of
>> backing up a variable to begin with. :/
>>
>> We do it in makepkg, I will have us do it here as well. Advantage: using
>> declare -p means the shell auto-escapes things where needed.
> 
> I haven't been keeping my thumb on makepkg git, but the eval lines as
> I wrote them exactly match the eval lines in makepkg 5.0.2's version
> of {backup,restore}_package_variables (makepkg's versions don't quote
> the for loops, or the unset command).

Hmm, I was thinking of:

eval "$restoretrap"
eval "$restoreset"
eval "$restoreshopt"
eval "$restore_envvars"

and similar. Maybe I should fix the backups as well, but that is a
slightly more complicated case there.

>>> -	if ! ${CLEANUP_DRYRUN}; then
>>> +	if ! "${CLEANUP_DRYRUN}"; then
>>
>> This is a variable being run as a command, so if there were to be spaces
>> in it we'd end up trying to run a command with a space in it. Arguably
>> we should not be running this as a command (even though they are set to
>> true/false which is a shell builtin blah blah blah) but since we are it
>> would be illogical to indicate that if there are spaces they should be
>> interpreted as string literals in an executable filename.
> 
> For the true/false idiom, quoting it is just a style rule.  I figure
> accepting the true/false idiom doesn't imply allowing the boolean
> variable to have any value.  Having the quotes would help catch the
> variable being erroneously set to a different value.

So would doing a bash test.

> At some point, I'd like to have `make lint` run shellcheck over
> dbscripts.  That's a long way off, both because of a whole bunch of
> changes needed in dbscripts to make it come back clean, and a few
> features needed in shellcheck to avoid having to drop entirely too
> many shellcheck directives in to the dbscripts source.
> 
> Anyway, I know linters should be taken with a grain of salt, but when
> there's something simple like this, that you know just about any
> linter would complain about... why not?

That would imply one of my long-term goals is being able to run a linter.

If I did, this rule would be the first thing I disabled -- it is far,
far too prone to both false positives and false negatives.

Patch

diff --git a/config b/config
index c03fe50..02ade09 100644
--- a/config
+++ b/config
@@ -34,5 +34,5 @@  PKGEXTS=".pkg.tar.@(gz|bz2|xz|lzo|lrz|Z)"
 ALLOWED_LICENSES=('GPL' 'GPL1' 'GPL2' 'GPL3' 'LGPL' 'LGPL1' 'LGPL2' 'LGPL2.1' 'LGPL3')
 
 # Override default config with config.local
-LOCAL_CONFIG=${DBSCRIPTS_CONFIG:-"$(dirname ${BASH_SOURCE[0]})/config.local"}
+LOCAL_CONFIG=${DBSCRIPTS_CONFIG:-"$(dirname "${BASH_SOURCE[0]}")/config.local"}
 [[ -f "${LOCAL_CONFIG}" ]] && . "${LOCAL_CONFIG}"
diff --git a/cron-jobs/check_archlinux/parse_pkgbuilds.sh b/cron-jobs/check_archlinux/parse_pkgbuilds.sh
index 10457fe..c01bcd6 100755
--- a/cron-jobs/check_archlinux/parse_pkgbuilds.sh
+++ b/cron-jobs/check_archlinux/parse_pkgbuilds.sh
@@ -6,23 +6,23 @@ 
 exit() { return; }
 
 splitpkg_overrides=('depends' 'optdepends' 'provides' 'conflicts')
-variables=('pkgname' 'pkgbase' 'epoch' 'pkgver' 'pkgrel' 'makedepends' 'arch' ${splitpkg_overrides[@]})
+variables=('pkgname' 'pkgbase' 'epoch' 'pkgver' 'pkgrel' 'makedepends' 'arch' "${splitpkg_overrides[@]}")
 readonly -a variables splitpkg_overrides
 
 backup_package_variables() {
-	for var in ${splitpkg_overrides[@]}; do
+	for var in "${splitpkg_overrides[@]}"; do
 		indirect="${var}_backup"
-		eval "${indirect}=(\${$var[@]})"
+		eval "${indirect}=(\"\${$var[@]}\")"
 	done
 }
 
 restore_package_variables() {
-	for var in ${splitpkg_overrides[@]}; do
+	for var in "${splitpkg_overrides[@]}"; do
 		indirect="${var}_backup"
 		if [ -n "${!indirect}" ]; then
-			eval "${var}=(\${$indirect[@]})"
+			eval "${var}=(\"\${$indirect[@]}\")"
 		else
-			unset ${var}
+			unset "${var}"
 		fi
 	done
 }
@@ -42,31 +42,31 @@  print_info() {
 
 	if [ -n "$arch" ]; then
 		echo "%ARCH%"
-		for i in ${arch[@]}; do echo $i; done
+		for i in "${arch[@]}"; do echo "$i"; done
 		echo ""
 	fi
 	if [ -n "$depends" ]; then
 		echo "%DEPENDS%"
-		for i in ${depends[@]}; do
-			echo $i
+		for i in "${depends[@]}"; do
+			echo "$i"
 		done
 		echo ""
 	fi
 	if [ -n "$makedepends" ]; then
 		echo "%MAKEDEPENDS%"
-		for i in ${makedepends[@]}; do
-			echo $i
+		for i in "${makedepends[@]}"; do
+			echo "$i"
 		done
 		echo ""
 	fi
 	if [ -n "$conflicts" ]; then
 		echo "%CONFLICTS%"
-		for i in ${conflicts[@]}; do echo $i; done
+		for i in "${conflicts[@]}"; do echo "$i"; done
 		echo ""
 	fi
 	if [ -n "$provides" ]; then
 		echo "%PROVIDES%"
-		for i in ${provides[@]}; do echo $i; done
+		for i in "${provides[@]}"; do echo "$i"; done
 		echo ""
 	fi
 }
@@ -75,10 +75,10 @@  source_pkgbuild() {
 	ret=0
 	dir=$1
 	pkgbuild=$dir/PKGBUILD
-	for var in ${variables[@]}; do
-		unset ${var}
+	for var in "${variables[@]}"; do
+		unset "${var}"
 	done
-	source $pkgbuild &>/dev/null || ret=$?
+	source "$pkgbuild" &>/dev/null || ret=$?
 
 	# ensure $pkgname and $pkgver variables were found
 	if [ $ret -ne 0 -o -z "$pkgname" -o -z "$pkgver" ]; then
@@ -88,8 +88,8 @@  source_pkgbuild() {
 
 	if [ "${#pkgname[@]}" -gt "1" ]; then
 		pkgbase=${pkgbase:-${pkgname[0]}}
-		for pkg in ${pkgname[@]}; do
-			if [ "$(type -t package_${pkg})" != "function" ]; then
+		for pkg in "${pkgname[@]}"; do
+			if [ "$(type -t "package_${pkg}")" != "function" ]; then
 				echo -e "%INVALID%\n$pkgbuild\n"
 				return 1
 			else
@@ -98,13 +98,13 @@  source_pkgbuild() {
 				while IFS= read -r line; do
 					var=${line%%=*}
 					var="${var#"${var%%[![:space:]]*}"}"   # remove leading whitespace characters
-					for realvar in ${variables[@]}; do
+					for realvar in "${variables[@]}"; do
 						if [ "$var" == "$realvar" ]; then
 							eval $line
 							break
 						fi
 					done
-				done < <(type package_${pkg})
+				done < <(type "package_${pkg}")
 				print_info
 				restore_package_variables
 			fi
@@ -124,14 +124,14 @@  find_pkgbuilds() {
         return
     fi
 
-	if [ -f $1/PKGBUILD ]; then
-		source_pkgbuild $1
+	if [ -f "$1/PKGBUILD" ]; then
+		source_pkgbuild "$1"
 		return
 	fi
 	empty=1
-	for dir in $1/*; do
-		if [ -d $dir ]; then
-			find_pkgbuilds $dir
+	for dir in "$1"/*; do
+		if [ -d "$dir" ]; then
+			find_pkgbuilds "$dir"
 			unset empty
 		fi
 	done
@@ -147,7 +147,7 @@  fi
 CARCH=$1
 shift
 for dir in "$@"; do
-	find_pkgbuilds $dir
+	find_pkgbuilds "$dir"
 done
 
 exit 0
diff --git a/cron-jobs/devlist-mailer b/cron-jobs/devlist-mailer
index 65a5483..1c35115 100755
--- a/cron-jobs/devlist-mailer
+++ b/cron-jobs/devlist-mailer
@@ -23,6 +23,6 @@  echo "Subject: $SUBJECT
 To: $LIST
 From: $FROM
 
-$stdin" | /usr/sbin/sendmail -F$FROM "$LIST"
+$stdin" | /usr/sbin/sendmail -F"$FROM" "$LIST"
 
 fi
diff --git a/cron-jobs/ftpdir-cleanup b/cron-jobs/ftpdir-cleanup
index ff65d46..828fa58 100755
--- a/cron-jobs/ftpdir-cleanup
+++ b/cron-jobs/ftpdir-cleanup
@@ -1,13 +1,13 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/../config"
-. "$(dirname $0)/../db-functions"
+. "$(dirname "$0")/../config"
+. "$(dirname "$0")/../db-functions"
 
 clean_pkg() {
 	local pkg
 	local target
 
-	if ! ${CLEANUP_DRYRUN}; then
+	if ! "${CLEANUP_DRYRUN}"; then
 		for pkg in "$@"; do
 			if [[ -h $pkg ]]; then
 				rm -f "$pkg" "$pkg.sig"
@@ -24,16 +24,16 @@  clean_pkg() {
 
 script_lock
 
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
-		repo_lock ${repo} ${arch} || exit 1
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
+		repo_lock "${repo}" "${arch}" || exit 1
 	done
 done
 
-${CLEANUP_DRYRUN} && warning 'dry run mode is active'
+"${CLEANUP_DRYRUN}" && warning 'dry run mode is active'
 
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
 		if [[ ! -f ${FTP_BASE}/${repo}/os/${arch}/${repo}${DBEXT} ]]; then
 			continue
 		fi
@@ -49,7 +49,7 @@  for repo in ${PKGREPOS[@]}; do
 		missing_pkgs=($(comm -13 "${WORKDIR}/repo-${repo}-${arch}" "${WORKDIR}/db-${repo}-${arch}"))
 		if (( ${#missing_pkgs[@]} >= 1 )); then
 			error "Missing packages in [%s] (%s)..." "$repo" "$arch"
-			for missing_pkg in ${missing_pkgs[@]}; do
+			for missing_pkg in "${missing_pkgs[@]}"; do
 				msg2 "${missing_pkg}"
 			done
 		fi
@@ -57,7 +57,7 @@  for repo in ${PKGREPOS[@]}; do
 		old_pkgs=($(comm -23 "${WORKDIR}/repo-${repo}-${arch}" "${WORKDIR}/db-${repo}-${arch}"))
 		if (( ${#old_pkgs[@]} >= 1 )); then
 			msg "Removing old packages from [%s] (%s)..." "$repo" "$arch"
-			for old_pkg in ${old_pkgs[@]}; do
+			for old_pkg in "${old_pkgs[@]}"; do
 				msg2 "${old_pkg}"
 				clean_pkg "${FTP_BASE}/${repo}/os/${arch}/${old_pkg}"
 			done
@@ -75,7 +75,7 @@  cat "${WORKDIR}"/db-* 2>/dev/null | sort -u > "${WORKDIR}/db"
 old_pkgs=($(comm -23 "${WORKDIR}/pool" "${WORKDIR}/db"))
 if (( ${#old_pkgs[@]} >= 1 )); then
 	msg "Removing old packages from package pool..."
-	for old_pkg in ${old_pkgs[@]}; do
+	for old_pkg in "${old_pkgs[@]}"; do
 		msg2 "${old_pkg}"
 		clean_pkg "$FTP_BASE/${PKGPOOL}/${old_pkg}"
 	done
@@ -90,18 +90,18 @@  for f in "${CLEANUP_DESTDIR}"/**/*${PKGEXTS}; do
 done
 if (( ${#old_pkgs[@]} >= 1 )); then
 	msg "Removing old packages from the cleanup directory..."
-	for old_pkg in ${old_pkgs[@]}; do
+	for old_pkg in "${old_pkgs[@]}"; do
 		msg2 "${old_pkg}"
-		if ! ${CLEANUP_DRYRUN}; then
+		if ! "${CLEANUP_DRYRUN}"; then
 			rm -f "${CLEANUP_DESTDIR}/${old_pkg}"
 			rm -f "${CLEANUP_DESTDIR}/${old_pkg}.sig"
 		fi
 	done
 fi
 
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
-		repo_unlock ${repo} ${arch}
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
+		repo_unlock "${repo}" "${arch}"
 	done
 done
 
diff --git a/cron-jobs/integrity-check b/cron-jobs/integrity-check
index f1e75ab..a12d311 100755
--- a/cron-jobs/integrity-check
+++ b/cron-jobs/integrity-check
@@ -1,6 +1,6 @@ 
 #!/bin/bash
 
-dirname="$(dirname $0)"
+dirname="$(dirname "$0")"
 
 . "${dirname}/../config"
 . "${dirname}/../db-functions"
@@ -13,12 +13,12 @@  fi
 mailto=$1
 
 check() {
-	${dirname}/check_archlinux/check_packages.py \
+	"${dirname}"/check_archlinux/check_packages.py \
 		--repos="${repos}" \
 		--abs-tree="/srv/abs/rsync/${arch},/srv/abs/rsync/any" \
 		--repo-dir="${FTP_BASE}" \
 		--arch="${arch}" \
-	2>&1 | ${dirname}/devlist-mailer "Integrity Check ${arch}: ${repos}" "${mailto}"
+	2>&1 | "${dirname}"/devlist-mailer "Integrity Check ${arch}: ${repos}" "${mailto}"
 }
 
 repos='core,extra,community,multilib'
diff --git a/cron-jobs/sourceballs b/cron-jobs/sourceballs
index 8f089b3..01d21d8 100755
--- a/cron-jobs/sourceballs
+++ b/cron-jobs/sourceballs
@@ -1,15 +1,15 @@ 
 #!/bin/bash
 
-dirname="$(dirname $(readlink -e $0))"
+dirname="$(dirname "$(readlink -e "$0")")"
 . "${dirname}/../config"
 . "${dirname}/../db-functions"
 pushd "${WORKDIR}" >/dev/null
 
 script_lock
 
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
-		repo_lock ${repo} ${arch} || exit 1
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
+		repo_lock "${repo}" "${arch}" || exit 1
 	done
 done
 
@@ -18,8 +18,8 @@  renice +10 -p $$ > /dev/null
 
 # Create a readable file for each repo with the following format
 # <pkgbase|pkgname> <pkgver>-<pkgrel> <arch> <license>[ <license>]
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
 		# Repo does not exist; skip it
 		if [[ ! -f ${FTP_BASE}/${repo}/os/${arch}/${repo}${DBEXT} ]]; then
 			continue
@@ -39,9 +39,9 @@  for repo in ${PKGREPOS[@]}; do
 	done | sort -u > "${WORKDIR}/db-${repo}"
 done
 
-for repo in ${PKGREPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
-		repo_unlock ${repo} ${arch}
+for repo in "${PKGREPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
+		repo_unlock "${repo}" "${arch}"
 	done
 done
 
@@ -53,22 +53,22 @@  for f in "${FTP_BASE}"/${SRCPOOL}/*${SRCEXT}; do
 done | sort -u > "${WORKDIR}/available-src-pkgs"
 
 # Check for all packages if we need to build a source package
-for repo in ${PKGREPOS[@]}; do
+for repo in "${PKGREPOS[@]}"; do
 	newpkgs=()
 	failedpkgs=()
 	while read line; do
-		pkginfo=(${line})
+		pkginfo=("${line}")
 		pkgbase=${pkginfo[0]}
 		pkgver=${pkginfo[1]}
 		pkgarch=${pkginfo[2]}
-		pkglicense=(${pkginfo[@]:3})
+		pkglicense=("${pkginfo[@]:3}")
 
 		# Should this package be skipped?
 		if grep -Fqx "${pkgbase}" "${dirname}/sourceballs.skip"; then
 			continue
 		fi
 		# Check if the license or .force file does not enforce creating a source package
-		if ! ([[ -z ${ALLOWED_LICENSES[@]} ]] || chk_license ${pkglicense[@]} || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then
+		if ! ([[ -z ${ALLOWED_LICENSES[*]} ]] || chk_license "${pkglicense[@]}" || grep -Fqx "${pkgbase}" "${dirname}/sourceballs.force"); then
 			continue
 		fi
 		# Store the expected file name of the source package
@@ -77,7 +77,7 @@  for repo in ${PKGREPOS[@]}; do
 		# Build the source package if its not already there
 		if ! grep -Fqx "${pkgbase}-${pkgver}${SRCEXT}" "${WORKDIR}/available-src-pkgs"; then
 			# Check if we had failed before
-			if in_array "${pkgbase}-${pkgver}${SRCEXT}" ${failedpkgs[@]}; then
+			if in_array "${pkgbase}-${pkgver}${SRCEXT}" "${failedpkgs[@]}"; then
 				continue
 			fi
 
@@ -108,13 +108,13 @@  for repo in ${PKGREPOS[@]}; do
 
 	if [ ${#newpkgs[@]} -ge 1 ]; then
 		msg "Adding source packages for [%s]..." "$repo"
-		for new_pkg in ${newpkgs[@]}; do
+		for new_pkg in "${newpkgs[@]}"; do
 			msg2 "${new_pkg}"
 		done
 	fi
 	if [ ${#failedpkgs[@]} -ge 1 ]; then
 		msg "Failed to create source packages for [%s]..." "$repo"
-		for failed_pkg in ${failedpkgs[@]}; do
+		for failed_pkg in "${failedpkgs[@]}"; do
 			msg2 "${failed_pkg}"
 		done
 	fi
@@ -127,10 +127,10 @@  old_pkgs=($(comm -23 "${WORKDIR}/available-src-pkgs.sort" "${WORKDIR}/expected-s
 
 if (( ${#old_pkgs[@]} >= 1 )); then
 	msg "Removing old source packages..."
-	${SOURCE_CLEANUP_DRYRUN} && warning 'dry run mode is active'
-	for old_pkg in ${old_pkgs[@]}; do
+	"${SOURCE_CLEANUP_DRYRUN}" && warning 'dry run mode is active'
+	for old_pkg in "${old_pkgs[@]}"; do
 		msg2 "${old_pkg}"
-		if ! ${SOURCE_CLEANUP_DRYRUN}; then
+		if ! "${SOURCE_CLEANUP_DRYRUN}"; then
 			mv_acl "$FTP_BASE/${SRCPOOL}/${old_pkg}" "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
 			touch "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
 		fi
@@ -147,9 +147,9 @@  done
 
 if (( ${#old_pkgs[@]} >= 1 )); then
 	msg "Removing old source packages from the cleanup directory..."
-	for old_pkg in ${old_pkgs[@]}; do
+	for old_pkg in "${old_pkgs[@]}"; do
 		msg2 "${old_pkg}"
-		${SOURCE_CLEANUP_DRYRUN} || rm -f "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
+		"${SOURCE_CLEANUP_DRYRUN}" || rm -f "${SOURCE_CLEANUP_DESTDIR}/${old_pkg}"
 	done
 fi
 
diff --git a/cron-jobs/update-web-db b/cron-jobs/update-web-db
index c859ce0..87e8bb0 100755
--- a/cron-jobs/update-web-db
+++ b/cron-jobs/update-web-db
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/../config"
-. "$(dirname $0)/../db-functions"
+. "$(dirname "$0")/../config"
+. "$(dirname "$0")/../db-functions"
 
 # setup paths
 SPATH="/srv/http/archweb"
@@ -43,26 +43,26 @@  case "$cmd" in
 esac
 
 # Lock the repos and get a copy of the db files to work on
-for repo in ${REPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
-		repo_lock ${repo} ${arch} || exit 1
+for repo in "${REPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
+		repo_lock "${repo}" "${arch}" || exit 1
 		dbfile="/srv/ftp/${repo}/os/${arch}/${repo}${dbfileext}"
 		if [[ -f ${dbfile} ]]; then
 			mkdir -p "${WORKDIR}/${repo}/${arch}"
 			cp "${dbfile}" "${WORKDIR}/${repo}/${arch}/${repo}${dbfileext}"
 		fi
-		repo_unlock ${repo} ${arch}
+		repo_unlock "${repo}" "${arch}"
 	done
 done
 
 # Run reporead on our db copy
-pushd $SPATH >/dev/null
-for repo in ${REPOS[@]}; do
-	for arch in ${ARCHES[@]}; do
+pushd "$SPATH" >/dev/null
+for repo in "${REPOS[@]}"; do
+	for arch in "${ARCHES[@]}"; do
 		dbcopy="${WORKDIR}/${repo}/${arch}/${repo}${dbfileext}"
 		if [[ -f ${dbcopy} ]]; then
 			echo "Updating ${repo}-${arch}" >> "${LOGOUT}"
-			./manage.py reporead ${flags} ${arch} "${dbcopy}" >> "${LOGOUT}" 2>&1
+			./manage.py reporead "${flags}" "${arch}" "${dbcopy}" >> "${LOGOUT}" 2>&1
 			echo "" >> "${LOGOUT}"
 		fi
 	done
diff --git a/db-functions b/db-functions
index 8b71cae..59b4152 100644
--- a/db-functions
+++ b/db-functions
@@ -17,7 +17,7 @@  set_umask () {
 }
 
 restore_umask () {
-	umask $UMASK >/dev/null
+	umask "$UMASK" >/dev/null
 }
 
 # Proxy function to check if a file exists. Using [[ -f ... ]] directly is not
@@ -50,7 +50,7 @@  REPO_MODIFIED=0
 script_lock() {
 	local LOCKDIR="$TMPDIR/.scriptlock.${0##*/}"
 	if ! mkdir "$LOCKDIR" >/dev/null 2>&1 ; then
-		local _owner="$(/usr/bin/stat -c %U $LOCKDIR)"
+		local _owner="$(/usr/bin/stat -c %U "$LOCKDIR")"
 		error "Script %s is already locked by %s." "${0##*/}" "$_owner"
 		exit 1
 	else
@@ -78,12 +78,12 @@  cleanup() {
 	local arch
 
 	trap - EXIT INT QUIT TERM
-	for l in ${LOCKS[@]}; do
+	for l in "${LOCKS[@]}"; do
 		repo=${l%.*}
 		arch=${l#*.}
 		if [[ -d $TMPDIR/.repolock.$repo.$arch ]]; then
 			msg "Removing left over lock from [%s] (%s)" "$repo" "$arch"
-			repo_unlock $repo $arch
+			repo_unlock "$repo" "$arch"
 		fi
 	done
 	if [[ -d $TMPDIR/.scriptlock.${0##*/} ]]; then
@@ -96,7 +96,7 @@  cleanup() {
 		date +%s > "${FTP_BASE}/lastupdate"
 	fi
 
-	[[ -n $1 ]] && exit $1
+	[[ -n $1 ]] && exit "$1"
 }
 
 abort() {
@@ -125,7 +125,7 @@  repo_lock () {
 
 	# This is the lock file used by repo-add and repo-remove
 	if [[ -f ${DBLOCKFILE} ]]; then
-		error "Repo [%s] (%s) is already locked by repo-{add,remove} process %s" "$1" "$2" "$(cat $DBLOCKFILE)"
+		error "Repo [%s] (%s) is already locked by repo-{add,remove} process %s" "$1" "$2" "$(cat "$DBLOCKFILE")"
 		return 1
 	fi
 
@@ -139,9 +139,9 @@  repo_lock () {
 	fi
 
 	_count=0
-	while (( _count <= _trial )) || $_lockblock ; do
+	while (( _count <= _trial )) || "$_lockblock" ; do
 		if ! mkdir "$LOCKDIR" >/dev/null 2>&1 ; then
-			_owner="$(/usr/bin/stat -c %U $LOCKDIR)"
+			_owner="$(/usr/bin/stat -c %U "$LOCKDIR")"
 			warning "Repo [%s] (%s) is already locked by %s." "$1" "$2" "$_owner"
 			msg2 "Retrying in %s seconds..." "$LOCK_DELAY"
 		else
@@ -149,7 +149,7 @@  repo_lock () {
 			set_umask
 			return 0
 		fi
-		sleep $LOCK_DELAY
+		sleep "$LOCK_DELAY"
 		let _count=$_count+1
 	done
 
@@ -277,12 +277,12 @@  getpkgfile() {
 		exit 1
 	fi
 
-	echo ${1}
+	echo "${1}"
 }
 
 getpkgfiles() {
 	local f files
-	if [[ ! -z "$(echo ${@%\.*} | sed "s/ /\n/g" | sort | uniq -D)" ]]; then
+	if [[ ! -z "$(printf '%s\n' "${@%\.*}" | sort | uniq -D)" ]]; then
 		error 'Duplicate packages found!'
 		exit 1
 	fi
@@ -291,17 +291,17 @@  getpkgfiles() {
 		files+=("$(getpkgfile "$f")") || exit 1
 	done
 
-	echo ${files[@]}
+	echo "${files[@]}"
 }
 
 check_pkgfile() {
 	local pkgfile=$1
 
-	local pkgname="$(getpkgname ${pkgfile})" || return 1
-	local pkgver="$(getpkgver ${pkgfile})" || return 1
-	local pkgarch="$(getpkgarch ${pkgfile})" || return 1
+	local pkgname="$(getpkgname "${pkgfile}")" || return 1
+	local pkgver="$(getpkgver "${pkgfile}")" || return 1
+	local pkgarch="$(getpkgarch "${pkgfile}")" || return 1
 
-	in_array "${pkgarch}" ${ARCHES[@]} 'any' || return 1
+	in_array "${pkgarch}" "${ARCHES[@]}" 'any' || return 1
 
 	if echo "${pkgfile##*/}" | grep -q "^${pkgname}-${pkgver}-${pkgarch}"; then
 		return 0
@@ -312,13 +312,13 @@  check_pkgfile() {
 
 check_pkgsvn() {
 	local pkgfile="${1}"
-	local _pkgbase="$(getpkgbase ${pkgfile})" || return 1
-	local _pkgname="$(getpkgname ${pkgfile})" || return 1
-	local _pkgver="$(getpkgver ${pkgfile})" || return 1
-	local _pkgarch="$(getpkgarch ${pkgfile})" || return 1
+	local _pkgbase="$(getpkgbase "${pkgfile}")" || return 1
+	local _pkgname="$(getpkgname "${pkgfile}")" || return 1
+	local _pkgver="$(getpkgver "${pkgfile}")" || return 1
+	local _pkgarch="$(getpkgarch "${pkgfile}")" || return 1
 	local repo="${2}"
 
-	in_array "${repo}" ${PKGREPOS[@]} || return 1
+	in_array "${repo}" "${PKGREPOS[@]}" || return 1
 
 	if [[ ! -f ${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase} ]]; then
 		mkdir -p "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}"
@@ -329,8 +329,8 @@  check_pkgsvn() {
 	local svnver="$(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; get_full_version)"
 	[[ "${svnver}" = "${_pkgver}" ]] || return 1
 
-	local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo ${pkgname[@]}))
-	in_array "${_pkgname}" ${svnnames[@]} || return 1
+	local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo "${pkgname[@]}"))
+	in_array "${_pkgname}" "${svnnames[@]}" || return 1
 
 	return 0
 }
@@ -338,7 +338,7 @@  check_pkgsvn() {
 check_splitpkgs() {
 	local repo="${1}"
 	shift
-	local pkgfiles=(${@})
+	local pkgfiles=("${@}")
 	local pkgfile
 	local pkgdir
 	local svnname
@@ -346,11 +346,11 @@  check_splitpkgs() {
 	mkdir -p "${WORKDIR}/check_splitpkgs/"
 	pushd "${WORKDIR}/check_splitpkgs" >/dev/null
 
-	for pkgfile in ${pkgfiles[@]}; do
+	for pkgfile in "${pkgfiles[@]}"; do
 		issplitpkg "${pkgfile}" || continue
-		local _pkgbase="$(getpkgbase ${pkgfile})"
-		local _pkgname="$(getpkgname ${pkgfile})"
-		local _pkgarch="$(getpkgarch ${pkgfile})"
+		local _pkgbase="$(getpkgbase "${pkgfile}")"
+		local _pkgname="$(getpkgname "${pkgfile}")"
+		local _pkgarch="$(getpkgarch "${pkgfile}")"
 		mkdir -p "${repo}/${_pkgarch}/${_pkgbase}"
 		echo "${_pkgname}" >> "${repo}/${_pkgarch}/${_pkgbase}/staging"
 
@@ -360,10 +360,8 @@  check_splitpkgs() {
 				"${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}" >/dev/null || return 1
 		fi
 
-		local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo ${pkgname[@]}))
-		for svnname in ${svnnames[@]}; do
-			echo "${svnname}" >> "${repo}/${_pkgarch}/${_pkgbase}/svn"
-		done
+		local svnnames=($(. "${WORKDIR}/pkgbuilds/${repo}-${_pkgarch}/${_pkgbase}"; echo "${pkgname[@]}"))
+		printf '%s\n' "${svnnames[@]}" >> "${repo}/${_pkgarch}/${_pkgbase}/svn"
 	done
 	popd >/dev/null
 
@@ -382,9 +380,9 @@  check_splitpkgs() {
 check_pkgrepos() {
 	local pkgfile=$1
 
-	local pkgname="$(getpkgname ${pkgfile})" || return 1
-	local pkgver="$(getpkgver ${pkgfile})" || return 1
-	local pkgarch="$(getpkgarch ${pkgfile})" || return 1
+	local pkgname="$(getpkgname "${pkgfile}")" || return 1
+	local pkgver="$(getpkgver "${pkgfile}")" || return 1
+	local pkgarch="$(getpkgarch "${pkgfile}")" || return 1
 
 	is_globfile "${FTP_BASE}/${PKGPOOL}/${pkgname}-${pkgver}-${pkgarch}"${PKGEXTS} && return 1
 	is_globfile "${FTP_BASE}/${PKGPOOL}/${pkgname}-${pkgver}-${pkgarch}"${PKGEXTS}.sig && return 1
@@ -398,7 +396,7 @@  check_pkgrepos() {
 chk_license() {
 	local l
 	for l in "${@}"; do
-		in_array ${l} ${ALLOWED_LICENSES[@]} && return 0
+		in_array "${l}" "${ALLOWED_LICENSES[@]}" && return 0
 	done
 
 	return 1
@@ -410,12 +408,12 @@  check_repo_permission() {
 	(( ${#PKGREPOS[@]} == 0 )) && return 1
 	[[ -z "${PKGPOOL}" ]] && return 1
 
-	in_array "${repo}" ${PKGREPOS[@]} || return 1
+	in_array "${repo}" "${PKGREPOS[@]}" || return 1
 
 	[[ -w $FTP_BASE/${PKGPOOL} ]] || return 1
 
 	local arch
-	for arch in ${ARCHES[@]}; do
+	for arch in "${ARCHES[@]}"; do
 		local dir="${FTP_BASE}/${repo}/os/${arch}/"
 		[[ -w ${dir} ]] || return 1
 		[[ -f ${dir}${repo}${DBEXT} && ! -w ${dir}${repo}${DBEXT} ]] && return 1
@@ -433,9 +431,9 @@  set_repo_permission() {
 
 	if [[ -w ${dbfile} ]]; then
 		local group=$(/usr/bin/stat --printf='%G' "$(dirname "${dbfile}")")
-		chgrp $group "${dbfile}" || error "Could not change group of %s to %s" "$dbfile" "$group"
-		chgrp $group "${filesfile}" || error "Could not change group of %s to %s" "$filesfile" "$group"
-		chmod g+w "${dbfile}" || error "Could not set write permission for group %s to %s" "$group" "$dbfile"
+		chgrp "$group" "${dbfile}"    || error "Could not change group of %s to %s" "$dbfile" "$group"
+		chgrp "$group" "${filesfile}" || error "Could not change group of %s to %s" "$filesfile" "$group"
+		chmod g+w "${dbfile}"    || error "Could not set write permission for group %s to %s" "$group" "$dbfile"
 		chmod g+w "${filesfile}" || error "Could not set write permission for group %s to %s" "$group" "$filesfile"
 	else
 		error "You don't have permission to change %s" "$dbfile"
@@ -445,12 +443,12 @@  set_repo_permission() {
 arch_repo_add() {
 	local repo=$1
 	local arch=$2
-	local pkgs=(${@:3})
+	local pkgs=("${@:3}")
 
 	# package files might be relative to repo dir
 	pushd "${FTP_BASE}/${repo}/os/${arch}" >/dev/null
-	/usr/bin/repo-add -q "${repo}${DBEXT}" ${pkgs[@]} \
-		|| error "repo-add ${repo}${DBEXT} ${pkgs[@]}"
+	/usr/bin/repo-add -q "${repo}${DBEXT}" "${pkgs[@]}" \
+		|| error "repo-add ${repo}${DBEXT} ${pkgs[*]}"
 	popd >/dev/null
 	set_repo_permission "${repo}" "${arch}"
 
@@ -460,15 +458,15 @@  arch_repo_add() {
 arch_repo_remove() {
 	local repo=$1
 	local arch=$2
-	local pkgs=(${@:3})
+	local pkgs=("${@:3}")
 	local dbfile="${FTP_BASE}/${repo}/os/${arch}/${repo}${DBEXT}"
 
 	if [[ ! -f ${dbfile} ]]; then
 		error "No database found at '%s'" "$dbfile"
 		return 1
 	fi
-	/usr/bin/repo-remove -q "${dbfile}" ${pkgs[@]} \
-		|| error "repo-remove ${dbfile} ${pkgs[@]}"
+	/usr/bin/repo-remove -q "${dbfile}" "${pkgs[@]}" \
+		|| error "repo-remove ${dbfile} ${pkgs[*]}"
 	set_repo_permission "${repo}" "${arch}"
 
 	REPO_MODIFIED=1
diff --git a/db-move b/db-move
index fb7ebac..c413dc9 100755
--- a/db-move
+++ b/db-move
@@ -1,37 +1,37 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# < 3 )); then
 	msg "usage: ${0##*/} <repo-from> <repo-to> <pkgname|pkgbase> ..."
 	exit 1
 fi
 
-args=(${@})
+args=("${@}")
 repo_from="${args[0]}"
 repo_to="${args[1]}"
 ftppath_from="${FTP_BASE}/${repo_from}/os/"
 ftppath_to="${FTP_BASE}/${repo_to}/os/"
 
-if ! check_repo_permission $repo_to || ! check_repo_permission $repo_from; then
+if ! check_repo_permission "$repo_to" || ! check_repo_permission "$repo_from"; then
 	die "You don't have permission to move packages from %s to %s" "$repo_from" "$repo_to"
 fi
 
 # TODO: this might lock too much (architectures)
-for pkgarch in ${ARCHES[@]}; do
-	repo_lock ${repo_to} ${pkgarch} || exit 1
-	repo_lock ${repo_from} ${pkgarch} || exit 1
+for pkgarch in "${ARCHES[@]}"; do
+	repo_lock "${repo_to}" "${pkgarch}" || exit 1
+	repo_lock "${repo_from}" "${pkgarch}" || exit 1
 done
 
 # check if packages to be moved exist in svn and ftp dir
 arch_svn checkout -q -N "${SVNREPO}" "${WORKDIR}/svn" >/dev/null
-for pkgbase in ${args[@]:2}; do
+for pkgbase in "${args[@]:2}"; do
 	arch_svn up -q "${WORKDIR}/svn/${pkgbase}" >/dev/null
-	for pkgarch in ${ARCHES[@]} 'any'; do
+	for pkgarch in "${ARCHES[@]}" 'any'; do
 		svnrepo_from="${WORKDIR}/svn/${pkgbase}/repos/${repo_from}-${pkgarch}"
 		if [[ -r ${svnrepo_from}/PKGBUILD ]]; then
-			pkgnames=($(. "${svnrepo_from}/PKGBUILD"; echo ${pkgname[@]}))
+			pkgnames=($(. "${svnrepo_from}/PKGBUILD"; echo "${pkgname[@]}"))
 			if (( ${#pkgnames[@]} < 1 )); then
 				die "Could not read pkgname"
 			fi
@@ -41,15 +41,15 @@  for pkgbase in ${args[@]:2}; do
 				die "Could not read pkgver"
 			fi
 
-			if [[ ${pkgarch} = any ]]; then
-				tarches=(${ARCHES[@]})
+			if [[ "${pkgarch}" = any ]]; then
+				tarches=("${ARCHES[@]}")
 			else
 				tarches=("${pkgarch}")
 			fi
 
-			for pkgname in ${pkgnames[@]}; do
-				for tarch in ${tarches[@]}; do
-					getpkgfile "${ftppath_from}/${tarch}/"${pkgname}-${pkgver}-${pkgarch}${PKGEXTS} >/dev/null
+			for pkgname in "${pkgnames[@]}"; do
+				for tarch in "${tarches[@]}"; do
+					getpkgfile "${ftppath_from}/${tarch}/${pkgname}-${pkgver}-${pkgarch}"${PKGEXTS} >/dev/null
 				done
 			done
 			continue 2
@@ -62,20 +62,20 @@  msg "Moving packages from [%s] to [%s]..." "$repo_from" "$repo_to"
 
 declare -A add_pkgs
 declare -A remove_pkgs
-for pkgbase in ${args[@]:2}; do
+for pkgbase in "${args[@]:2}"; do
 	tag_list=""
-	for pkgarch in ${ARCHES[@]} 'any'; do
+	for pkgarch in "${ARCHES[@]}" 'any'; do
 		svnrepo_from="${WORKDIR}/svn/${pkgbase}/repos/${repo_from}-${pkgarch}"
 		svnrepo_to="${WORKDIR}/svn/${pkgbase}/repos/${repo_to}-${pkgarch}"
 
 		if [[ -f ${svnrepo_from}/PKGBUILD ]]; then
 			if [[ ${pkgarch} = any ]]; then
-				tarches=(${ARCHES[@]})
+				tarches=("${ARCHES[@]}")
 			else
 				tarches=("${pkgarch}")
 			fi
-			msg2 "${pkgbase} ($(echo ${tarches[@]}))"
-			pkgnames=($(. "${svnrepo_from}/PKGBUILD"; echo ${pkgname[@]}))
+			msg2 "${pkgbase} (${tarches[*]})"
+			pkgnames=($(. "${svnrepo_from}/PKGBUILD"; echo "${pkgname[@]}"))
 			pkgver=$(. "${svnrepo_from}/PKGBUILD"; get_full_version)
 
 			if [[ -d ${svnrepo_to} ]]; then
@@ -93,14 +93,14 @@  for pkgbase in ${args[@]:2}; do
 			arch_svn rm --force -q "${svnrepo_from}"
 			tag_list+=", $pkgarch"
 
-			for pkgname in ${pkgnames[@]}; do
-				for tarch in ${tarches[@]}; do
-					pkgpath=$(getpkgfile "${ftppath_from}/${tarch}/"${pkgname}-${pkgver}-${pkgarch}${PKGEXTS})
+			for pkgname in "${pkgnames[@]}"; do
+				for tarch in "${tarches[@]}"; do
+					pkgpath=$(getpkgfile "${ftppath_from}/${tarch}/${pkgname}-${pkgver}-${pkgarch}"${PKGEXTS})
 					pkgfile="${pkgpath##*/}"
 
-					ln -s "../../../${PKGPOOL}/${pkgfile}" ${ftppath_to}/${tarch}/
+					ln -s "../../../${PKGPOOL}/${pkgfile}" "${ftppath_to}/${tarch}/"
 					if [[ -f ${FTP_BASE}/${PKGPOOL}/${pkgfile}.sig ]]; then
-						ln -s "../../../${PKGPOOL}/${pkgfile}.sig" ${ftppath_to}/${tarch}/
+						ln -s "../../../${PKGPOOL}/${pkgfile}.sig" "${ftppath_to}/${tarch}/"
 					fi
 					add_pkgs[${tarch}]+="${FTP_BASE}/${PKGPOOL}/${pkgfile} "
 					remove_pkgs[${tarch}]+="${pkgname} "
@@ -112,14 +112,14 @@  for pkgbase in ${args[@]:2}; do
 	arch_svn commit -q "${WORKDIR}/svn/${pkgbase}" -m "${0##*/}: moved ${pkgbase} from [${repo_from}] to [${repo_to}] (${tag_list})"
 done
 
-for tarch in ${ARCHES[@]}; do
+for tarch in "${ARCHES[@]}"; do
 	if [[ -n ${add_pkgs[${tarch}]} ]]; then
 		arch_repo_add "${repo_to}" "${tarch}" ${add_pkgs[${tarch}]}
 		arch_repo_remove "${repo_from}" "${tarch}" ${remove_pkgs[${tarch}]}
 	fi
 done
 
-for pkgarch in ${ARCHES[@]}; do
-	repo_unlock ${repo_from} ${pkgarch}
-	repo_unlock ${repo_to} ${pkgarch}
+for pkgarch in "${ARCHES[@]}"; do
+	repo_unlock "${repo_from}" "${pkgarch}"
+	repo_unlock "${repo_to}" "${pkgarch}"
 done
diff --git a/db-remove b/db-remove
index 70502bc..2ab878c 100755
--- a/db-remove
+++ b/db-remove
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# < 3 )); then
 	msg "usage: ${0##*/} <repo> <arch> <pkgname|pkgbase> ..."
@@ -10,27 +10,27 @@  fi
 
 repo="$1"
 arch="$2"
-pkgbases=(${@:3})
+pkgbases=("${@:3}")
 
 ftppath="$FTP_BASE/$repo/os"
 svnrepo="$repo-$arch"
 
-if ! check_repo_permission $repo; then
+if ! check_repo_permission "$repo"; then
 	die "You don't have permission to remove packages from %s" "$repo"
 fi
 
 if [[ $arch = any ]]; then
-	tarches=(${ARCHES[@]})
+	tarches=("${ARCHES[@]}")
 else
 	tarches=("$arch")
 fi
 
-for tarch in ${tarches[@]}; do
-	repo_lock $repo $tarch || exit 1
+for tarch in "${tarches[@]}"; do
+	repo_lock "$repo" "$tarch" || exit 1
 done
 
 remove_pkgs=()
-for pkgbase in ${pkgbases[@]}; do
+for pkgbase in "${pkgbases[@]}"; do
 	msg "Removing %s from [%s]..." "$pkgbase" "$repo"
 	arch_svn checkout -q "${SVNREPO}/${pkgbase}" "${WORKDIR}/svn/${pkgbase}" >/dev/null
 
@@ -46,7 +46,7 @@  for pkgbase in ${pkgbases[@]}; do
 	fi
 done
 
-for tarch in ${tarches[@]}; do
-	arch_repo_remove "${repo}" "${tarch}" ${remove_pkgs[@]}
-	repo_unlock $repo $tarch
+for tarch in "${tarches[@]}"; do
+	arch_repo_remove "${repo}" "${tarch}" "${remove_pkgs[@]}"
+	repo_unlock "$repo" "$tarch"
 done
diff --git a/db-repo-add b/db-repo-add
index d7be302..04216ee 100755
--- a/db-repo-add
+++ b/db-repo-add
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# < 3 )); then
 	msg "usage: ${0##*/} <repo> <arch> <pkgfile> ..."
@@ -10,32 +10,32 @@  fi
 
 repo="$1"
 arch="$2"
-pkgfiles=(${@:3})
+pkgfiles=("${@:3}")
 
 ftppath="$FTP_BASE/$repo/os"
 
-if ! check_repo_permission $repo; then
+if ! check_repo_permission "$repo"; then
 	die "You don't have permission to add packages to %s" "$repo"
 fi
 
 if [[ $arch = any ]]; then
-	tarches=(${ARCHES[@]})
+	tarches=("${ARCHES[@]}")
 else
 	tarches=("$arch")
 fi
 
-for tarch in ${tarches[@]}; do
-	repo_lock $repo $tarch || exit 1
+for tarch in "${tarches[@]}"; do
+	repo_lock "$repo" "$tarch" || exit 1
 done
 
-for tarch in ${tarches[@]}; do
-	for pkgfile in ${pkgfiles[@]}; do
+for tarch in "${tarches[@]}"; do
+	for pkgfile in "${pkgfiles[@]}"; do
 		if [[ ! -f ${FTP_BASE}/${repo}/os/${tarch}/${pkgfile##*/} ]]; then
 			die "Package file %s not found in %s" "${pkgfile##*/}" "${FTP_BASE}/${repo}/os/${tarch}/"
 		else
 			msg "Adding %s to [%s]..." "$pkgfile" "$repo"
 		fi
 	done
-	arch_repo_add "${repo}" "${tarch}" ${pkgfiles[@]}
-	repo_unlock $repo $tarch
+	arch_repo_add "${repo}" "${tarch}" "${pkgfiles[@]}"
+	repo_unlock "$repo" "$tarch"
 done
diff --git a/db-repo-remove b/db-repo-remove
index 32d167e..b44d33c 100755
--- a/db-repo-remove
+++ b/db-repo-remove
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# < 3 )); then
 	msg "usage: ${0##*/} <repo> <arch> <pkgname> ..."
@@ -10,28 +10,28 @@  fi
 
 repo="$1"
 arch="$2"
-pkgnames=(${@:3})
+pkgnames=("${@:3}")
 
 ftppath="$FTP_BASE/$repo/os"
 
-if ! check_repo_permission $repo; then
+if ! check_repo_permission "$repo"; then
 	die "You don't have permission to remove packages from %s" "$repo"
 fi
 
 if [[ $arch = any ]]; then
-	tarches=(${ARCHES[@]})
+	tarches=("${ARCHES[@]}")
 else
 	tarches=("$arch")
 fi
 
-for tarch in ${tarches[@]}; do
-	repo_lock $repo $tarch || exit 1
+for tarch in "${tarches[@]}"; do
+	repo_lock "$repo" "$tarch" || exit 1
 done
 
-for tarch in ${tarches[@]}; do
-	for pkgname in ${pkgnames[@]}; do
+for tarch in "${tarches[@]}"; do
+	for pkgname in "${pkgnames[@]}"; do
 		msg "Removing %s from [%s]..." "$pkgname" "$repo"
 	done
-	arch_repo_remove "${repo}" "${tarch}" ${pkgnames[@]}
-	repo_unlock $repo $tarch
+	arch_repo_remove "${repo}" "${tarch}" "${pkgnames[@]}"
+	repo_unlock "$repo" "$tarch"
 done
diff --git a/db-update b/db-update
index 4e17184..5df477c 100755
--- a/db-update
+++ b/db-update
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# >= 1 )); then
 	warning "Calling %s with a specific repository is no longer supported" "${0##*/}"
@@ -16,27 +16,27 @@  mapfile -t -d '' staging_repos < <(
 )
 
 repos=()
-for staging_repo in ${staging_repos[@]##*/}; do
-	if in_array ${staging_repo} ${PKGREPOS[@]}; then
-		repos+=(${staging_repo})
+for staging_repo in "${staging_repos[@]##*/}"; do
+	if in_array "${staging_repo}" "${PKGREPOS[@]}"; then
+		repos+=("${staging_repo}")
 	fi
 done
 
 # TODO: this might lock too much (architectures)
-for repo in ${repos[@]}; do
-	for pkgarch in ${ARCHES[@]}; do
-		repo_lock ${repo} ${pkgarch} || exit 1
+for repo in "${repos[@]}"; do
+	for pkgarch in "${ARCHES[@]}"; do
+		repo_lock "${repo}" "${pkgarch}" || exit 1
 	done
 done
 
 # check if packages are valid
-for repo in ${repos[@]}; do
+for repo in "${repos[@]}"; do
 	if ! check_repo_permission "${repo}"; then
 		die "You don't have permission to update packages in %s" "$repo"
 	fi
 	pkgs=($(getpkgfiles "${STAGING}/${repo}/"*${PKGEXTS}))
 	if (( $? == 0 )); then
-		for pkg in ${pkgs[@]}; do
+		for pkg in "${pkgs[@]}"; do
 			if [[ -h ${pkg} ]]; then
 				die "Package %s is a symbolic link" "$repo/${pkg##*/}"
 			fi
@@ -62,7 +62,7 @@  for repo in ${repos[@]}; do
 				die "Package %s was not built in a chroot" "$repo/${pkg##*/}"
 			fi
 		done
-		if ! check_splitpkgs ${repo} ${pkgs[@]}; then
+		if ! check_splitpkgs "${repo}" "${pkgs[@]}"; then
 			die "Missing split packages for %s" "$repo"
 		fi
 	else
@@ -70,13 +70,13 @@  for repo in ${repos[@]}; do
 	fi
 done
 
-for repo in ${repos[@]}; do
+for repo in "${repos[@]}"; do
 	msg "Updating [%s]..." "$repo"
 	any_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-any${PKGEXTS} 2>/dev/null))
-	for pkgarch in ${ARCHES[@]}; do
+	for pkgarch in "${ARCHES[@]}"; do
 		add_pkgs=()
-		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-${pkgarch}${PKGEXTS} 2>/dev/null))
-		for pkg in ${arch_pkgs[@]} ${any_pkgs[@]}; do
+		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-"${pkgarch}"${PKGEXTS} 2>/dev/null))
+		for pkg in "${arch_pkgs[@]}" "${any_pkgs[@]}"; do
 			pkgfile="${pkg##*/}"
 			msg2 "${pkgfile} (${pkgarch})"
 			# any packages might have been moved by the previous run
@@ -99,8 +99,8 @@  for repo in ${repos[@]}; do
 	done
 done
 
-for repo in ${repos[@]}; do
-	for pkgarch in ${ARCHES[@]}; do
-		repo_unlock ${repo} ${pkgarch}
+for repo in "${repos[@]}"; do
+	for pkgarch in "${ARCHES[@]}"; do
+		repo_unlock "${repo}" "${pkgarch}"
 	done
 done
diff --git a/testing2x b/testing2x
index f0d77cb..2b1de17 100755
--- a/testing2x
+++ b/testing2x
@@ -1,7 +1,7 @@ 
 #!/bin/bash
 
-. "$(dirname $0)/config"
-. "$(dirname $0)/db-functions"
+. "$(dirname "$0")/config"
+. "$(dirname "$0")/db-functions"
 
 if (( $# < 1 )); then
 	msg "usage: ${0##*/} <pkgname|pkgbase> ..."
@@ -10,30 +10,30 @@  fi
 
 # Lock everything to reduce  possibility of interfering task between the different repo-updates
 script_lock
-for repo in  ${TESTING_REPO} ${STABLE_REPOS[@]}; do
-	for pkgarch in ${ARCHES[@]}; do
-		repo_lock ${repo} ${pkgarch} || exit 1
+for repo in "${TESTING_REPO}" "${STABLE_REPOS[@]}"; do
+	for pkgarch in "${ARCHES[@]}"; do
+		repo_lock "${repo}" "${pkgarch}" || exit 1
 	done
 done
 
 declare -A pkgs
 
-for pkgbase in $*; do
+for pkgbase in "$@"; do
 	if [[ ! -d ${WORKDIR}/${pkgbase} ]]; then
 		arch_svn export -q "${SVNREPO}/${pkgbase}/repos" "${WORKDIR}/${pkgbase}" >/dev/null
 
 		found_source=false
-		for pkgarch in ${ARCHES[@]} 'any'; do
+		for pkgarch in "${ARCHES[@]}" 'any'; do
 			svnrepo_from="${WORKDIR}/${pkgbase}/${TESTING_REPO}-${pkgarch}"
 			if [[ -r ${svnrepo_from}/PKGBUILD ]]; then
 				found_source=true
 				break
 			fi
 		done
-		${found_source} || die "%s not found in [%s]" "$pkgbase" "$TESTING_REPO"
+		"${found_source}" || die "%s not found in [%s]" "$pkgbase" "$TESTING_REPO"
 		found_target=false
-		for pkgarch in ${ARCHES[@]} 'any'; do
-			for repo in ${STABLE_REPOS[@]}; do
+		for pkgarch in "${ARCHES[@]}" 'any'; do
+			for repo in "${STABLE_REPOS[@]}"; do
 				svnrepo_to="${WORKDIR}/${pkgbase}/${repo}-${pkgarch}"
 				if [[ -r ${svnrepo_to}/PKGBUILD ]]; then
 					found_target=true
@@ -42,19 +42,19 @@  for pkgbase in $*; do
 				fi
 			done
 		done
-		${found_target} || die "%s not found in any of these repos: %s" "$pkgbase" "${STABLE_REPOS[*]}"
+		"${found_target}" || die "%s not found in any of these repos: %s" "$pkgbase" "${STABLE_REPOS[*]}"
 	fi
 done
 
-for pkgarch in ${ARCHES[@]}; do
-	repo_unlock ${TESTING_REPO} ${pkgarch}
+for pkgarch in "${ARCHES[@]}"; do
+	repo_unlock "${TESTING_REPO}" "${pkgarch}"
 done
-for repo in ${STABLE_REPOS[@]}; do
-	for pkgarch in ${ARCHES[@]}; do
-		repo_unlock ${repo} ${pkgarch}
+for repo in  "${STABLE_REPOS[@]}"; do
+	for pkgarch in "${ARCHES[@]}"; do
+		repo_unlock "${repo}" "${pkgarch}"
 	done
 	if [[ -n ${pkgs[${repo}]} ]]; then
-		"$(dirname $0)/db-move" ${TESTING_REPO} "${repo}" ${pkgs[${repo}]}
+		"$(dirname "$0")/db-move" "${TESTING_REPO}" "${repo}" ${pkgs[${repo}]}
 	fi
 done