fix(package): migrator: index_of subshell issue

This commit is contained in:
2025-12-06 04:47:31 +00:00
parent 3b506a7888
commit 373a3fe3f0
8 changed files with 166 additions and 52 deletions

View File

@@ -14,16 +14,12 @@
set -eu set -eu
if ! command -v psql >/dev/null; then
log error "Required tool (psql) are not installed."
exit 127
fi
VERSION='0.0.1' VERSION='0.0.1'
MIGRATION_DIR="${MIGRATION_DIR:-migration}" MIGRATION_DIR="${MIGRATION_DIR:-migration}"
quote() { printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g")"; }
REMAINING_ARS= REMAINING_ARS=
quote() { printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g")"; }
# cat filename | sha256sum() # cat filename | sha256sum()
# sha256sum(filename) # sha256sum(filename)
sha256sum() { sha256sum() {
@@ -32,32 +28,6 @@ sha256sum() {
cksum --algorithm=sha256 --untagged "$file" | awk '{printf $1}' cksum --algorithm=sha256 --untagged "$file" | awk '{printf $1}'
} }
while [ $# -gt 0 ]; do
log debug "arg: $1"
case $1 in
migrate|create|fetch|list|init)
[ "${SUBCOMMAND+x}" ] && {
log error "ambiguous subcommand, decide ${WHITE}$SUBCOMMAND ${NC}or ${WHITE}$1";
exit 2;
}
SUBCOMMAND=$1
shift
;;
--migration-dir|-d)
MIGRATION_DIR=$2
shift 2
;;
--inherits)
INHERITS_LIST="${INHERITS_LIST+$INHERITS_LIST\"}$2"
shift 2
;;
--*|-*) REMAINING_ARS="$REMAINING_ARS $(quote "$1")"; shift ;; # unknown global -> pass through
*) REMAINING_ARS="$REMAINING_ARS $(quote "$1")"; shift ;;
esac
done
[ ${INHERITS_LIST+x} ] && INHERITS_LIST="$(printf '%s' "$INHERITS_LIST" | sed -E 's/"/,/g; s/([^,]+)/"\1"/g')"
# shellcheck disable=SC2120 # shellcheck disable=SC2120
init() { init() {
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
@@ -192,8 +162,6 @@ EOF
printf '%s' "$sql" printf '%s' "$sql"
} }
[ "${SUBCOMMAND+x}" ] || { log error "no subcomand specified"; exit 1; }
help() { help() {
# inherits: List one or more tables the migration table must inherit from # inherits: List one or more tables the migration table must inherit from
echo help echo help
@@ -269,6 +237,24 @@ migration_list() {
find "$MIGRATION_DIR" -maxdepth 1 -type d -regextype posix-extended -regex '^.*/[0-9]{14}-.*$' -printf '%f\n' | sort find "$MIGRATION_DIR" -maxdepth 1 -type d -regextype posix-extended -regex '^.*/[0-9]{14}-.*$' -printf '%f\n' | sort
} }
# index_of(array, name)
index_of() {
local list name m i=1
list=$1
name=$2
[ -z "$name" ] && return 1
# no subshell, no pipeline
while IFS= read -r m; do
[ "$m" = "$name" ] && { printf '%s\n' "$i"; return 0; }
i=$((i+1))
done <<EOF
$list
EOF
return 1
}
migrate() { migrate() {
local fs_migrations db_migrations db_migration fs_migration psql_args var #target_migration local fs_migrations db_migrations db_migration fs_migration psql_args var #target_migration
MIGRATOR_REMAINING_ARS= MIGRATOR_REMAINING_ARS=
@@ -342,21 +328,20 @@ migrate() {
eval "set -- $MIGRATOR_REMAINING_ARS" eval "set -- $MIGRATOR_REMAINING_ARS"
target_migration="$("migrate_$MIGRATE_SUBCOMMAND" "$@")" target_migration="$("migrate_$MIGRATE_SUBCOMMAND" "$@")"
log debug "target_migration: ${target_migration}" if [ -z "$db_migrations" ]; then
log info "it'll firs migration"
current_idx=0
else
current_migration=$(printf '%s\n' "$db_migrations" | tail -n1)
current_idx=$(index_of "$fs_migrations" "$current_migration")
fi
index_of log debug "[$WHITE$fs_migrations$NC]"
log debug "$target_migration"
} target_idx=$(index_of "$fs_migrations" "$target_migration")
idx_of() { log debug "indexes $WHITE$current_idx$NC $WHITE${target_idx}"
name=$1
[ -z "$name" ] && { echo 0; return; }
i=1
printf '%s\n' "$fs_migrations" | while IFS= read -r m; do
[ "$m" = "$name" ] && { echo "$i"; return; }
i=$((i+1))
done
echo 0
} }
form_psql_args() { form_psql_args() {
@@ -493,8 +478,43 @@ generate_word() {
printf '%s' "$w" printf '%s' "$w"
} }
log debug "subcommand: $WHITE$SUBCOMMAND" if ! command -v psql >/dev/null; then
log debug "subcommand args: $WHITE$REMAINING_ARS" log error "Required tool (psql) are not installed."
exit 127
fi
eval "set -- $REMAINING_ARS" if ! [ "${AS_LIBRARY+x}" ]; then
"$SUBCOMMAND" "$@" while [ $# -gt 0 ]; do
log debug "arg: $1"
case $1 in
migrate|create|fetch|list|init)
[ "${SUBCOMMAND+x}" ] && {
log error "ambiguous subcommand, decide ${WHITE}$SUBCOMMAND ${NC}or ${WHITE}$1";
exit 2;
}
SUBCOMMAND=$1
shift
;;
--migration-dir|-d)
MIGRATION_DIR=$2
shift 2
;;
--inherits)
INHERITS_LIST="${INHERITS_LIST+$INHERITS_LIST\"}$2"
shift 2
;;
--*|-*) REMAINING_ARS="$REMAINING_ARS $(quote "$1")"; shift ;; # unknown global -> pass through
*) REMAINING_ARS="$REMAINING_ARS $(quote "$1")"; shift ;;
esac
done
[ ${INHERITS_LIST+x} ] && INHERITS_LIST="$(printf '%s' "$INHERITS_LIST" | sed -E 's/"/,/g; s/([^,]+)/"\1"/g')"
[ "${SUBCOMMAND+x}" ] || { log error "no subcomand specified"; exit 1; }
log debug "subcommand: $WHITE$SUBCOMMAND"
log debug "subcommand args: $WHITE$REMAINING_ARS"
eval "set -- $REMAINING_ARS"
"$SUBCOMMAND" "$@"
fi

View File

@@ -35,7 +35,7 @@
mkPgTest = testName: testDrv: pkgs.runCommand "migrator-test-${testName}" mkPgTest = testName: testDrv: pkgs.runCommand "migrator-test-${testName}"
{ {
nativeBuildInputs = [ pkgs.coreutils pkgs.gnugrep pkgs.gnused ]; nativeBuildInputs = [ pkgs.coreutils pkgs.gnugrep pkgs.gnused ];
buildInputs = [ migrator pkgs.postgresql ]; buildInputs = [ pkgs.which migrator pkgs.postgresql ];
} '' } ''
${builtins.readFile self.legacyPackages.${system}.helpers.posix-shell.log} ${builtins.readFile self.legacyPackages.${system}.helpers.posix-shell.log}
test=${testDrv} test=${testDrv}

View File

@@ -0,0 +1,17 @@
# shellcheck disable=SC2034
AS_LIBRARY=
# shellcheck disable=SC1090
. "$(which migrator)"
log notice "test case: ${WHITE}generate word"
if ! answer=$(generate_word); then
log error "test failed: ${WHITE}error during generate_word call"
exit 1
fi
if [ "$(printf '%s' "$answer" | wc -c)" -ne 6 ]; then
log error "test failed: ${WHITE}word length must be 6 chars"
exit 1
fi
log notice "test passed"

View File

@@ -0,0 +1,47 @@
# shellcheck disable=SC2034
AS_LIBRARY=
# shellcheck disable=SC1090
. "$(which migrator)"
array='item1
item2
item3
item4
item5
item6
item7'
log notice "test case: ${WHITE}index of"
if ! answer=$(index_of "$array" 'item4'); then
log error "test failed: ${WHITE}error during index_of call"
exit 1
fi
is_number "$answer" >/dev/null || { log error "test failed: ${WHITE}answer not a number"; exit 1; }
if [ "$answer" -ne 4 ]; then
log error "test failed: ${WHITE}wrong answer"
exit 1
fi
log notice "test case: ${WHITE}error: item not found"
if answer=$(index_of "$array" 'item10'); then
log error "test failed: ${WHITE} must return an error"
exit 1
fi
log notice "test case: ${WHITE}one element"
array='20251104192425-add-info-to-profile'
item='20251104192425-add-info-to-profile'
if ! answer=$(index_of "$array" "$item"); then
log error "test failed: ${WHITE}error during index_of call"
exit 1
fi
if [ "$answer" -ne 1 ]; then
log error "test failed: ${WHITE}wrong answer"
exit 1
fi
log notice "test passed"

View File

@@ -0,0 +1,17 @@
# shellcheck disable=SC2034
AS_LIBRARY=
# shellcheck disable=SC1090
. "$(which migrator)"
log notice "test case: ${WHITE}migration list"
if ! answer=$(migration_list); then
log error "test failed: ${WHITE}error during migration_list call"
exit 1
fi
if [ "$answer" != "20251104192425-add-info-to-profile" ]; then
log error "test failed: ${WHITE}unexpected \`migration list\` answer"
exit 1
fi
log notice "test passed"

View File

@@ -0,0 +1 @@
ALTER TABLE profile ADD COLUMN info TEXT;

View File

@@ -6,3 +6,15 @@ columns() {
FROM information_schema.columns FROM information_schema.columns
WHERE table_name = '"${1};" WHERE table_name = '"${1};"
} }
# is_number(var)
is_number() {
case "$1" in
*[!0-9]*)
return 1
;;
*)
return 0
;;
esac
}