#!/bin/bash
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
ROOT_DIR=$(cd "${SCRIPT_DIR}/.." && pwd)
MAKESELF_VERSION="2.5.0"
MAKESELF_REPO="cann-src-third-party/makeself"
MAKESELF_BRANCH="master"
MAKESELF_DIR="${ROOT_DIR}/makeself"
MAKESELF_SCRIPT="${MAKESELF_DIR}/makeself.sh"
MAKESELF_HEADER="${MAKESELF_DIR}/makeself-header.sh"
MAKESELF_TAR="makeself-release-${MAKESELF_VERSION}.tar.gz"
MAKESELF_PATCH="makeself-${MAKESELF_VERSION}.patch"
MAKESELF_API_BASE="https://gitcode.com/api/v5/repos/${MAKESELF_REPO}/contents"
patch_file=""
fetch_download_url() {
local file="$1"
local url=""
url=$(python3 - "$file" <<'PY'
import json
import sys
import urllib.request
file_name = sys.argv[1]
api_url = (
f"https://gitcode.com/api/v5/repos/cann-src-third-party/makeself/contents/"
f"{file_name}?ref=master"
)
try:
with urllib.request.urlopen(api_url) as resp:
data = json.load(resp)
download_url = data.get("download_url", "")
if not download_url:
raise ValueError("download_url is empty")
print(download_url)
except Exception as exc:
print(f"ERROR: failed to resolve download URL for {file_name}: {exc}", file=sys.stderr)
sys.exit(1)
PY
)
if [[ -z "${url}" ]]; then
echo "ERROR: empty download URL for ${file}" >&2
exit 1
fi
printf '%s' "${url}"
}
check_dependency() {
if ! command -v curl &> /dev/null; then
echo "ERROR: please install curl first"
exit 1
fi
if ! command -v python3 &> /dev/null; then
echo "ERROR: please install python3 first"
exit 1
fi
if ! command -v patch &> /dev/null; then
echo "ERROR: please install patch first"
exit 1
fi
}
FIXED_GREP_PATTERN="grep -o -E -e '--[^ ]+'"
SCRIPT_ARGS_CHECK_WARN='log "WARNING" "Unknown argument:'
is_makeself_ready() {
[ -d "${MAKESELF_DIR}" ] && \
[ -f "${MAKESELF_SCRIPT}" ] && \
[ -x "${MAKESELF_SCRIPT}" ] && \
[ -f "${MAKESELF_HEADER}" ] && \
grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" && \
grep -qF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" && \
grep -qF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}"
}
needs_grep_fixup() {
[ -f "${MAKESELF_HEADER}" ] || return 1
grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" || return 1
grep -qF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" && return 1
return 0
}
needs_script_args_check_fixup() {
[ -f "${MAKESELF_HEADER}" ] || return 1
grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" || return 1
grep -qF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}" && return 1
return 0
}
fix_makeself_header() {
python3 - "${MAKESELF_HEADER}" "${FIXED_GREP_PATTERN}" <<'PY'
import re
import sys
from pathlib import Path
header_path = Path(sys.argv[1])
fixed_grep = sys.argv[2]
content = header_path.read_text()
patterns = [
'grep -o -E "\\-\\-[^ ]+"',
'grep -o -E "--[^ ]+"',
]
updated = content
for pattern in patterns:
updated = updated.replace(pattern, fixed_grep)
if updated == content:
updated = re.sub(
r'grep -o -E "\-\-\[\^ \]\+"',
fixed_grep,
content,
count=1,
)
if fixed_grep not in updated:
print("ERROR: failed to fix grep pattern in makeself-header.sh", file=sys.stderr)
sys.exit(1)
needle = "\t--quiet)\n\tquiet=y\n\tshift\n\t;;"
if "\t-q)\n" not in updated and needle in updated:
updated = updated.replace(
needle,
"\t-q)\n\tquiet=y\n\tshift\n\t;;\n" + needle,
1,
)
script_args_check_exit = """ MS_Help
exit 1
}"""
script_args_check_warn = """ log "WARNING" "Unknown argument: $1"
return
}"""
if script_args_check_exit in updated:
updated = updated.replace(script_args_check_exit, script_args_check_warn, 1)
header_path.write_text(updated)
PY
}
cleanup_patch_file() {
if [[ -n "${patch_file}" ]]; then
rm -f "${patch_file}"
patch_file=""
fi
}
main() {
if is_makeself_ready; then
echo "makeself is ready: ${MAKESELF_DIR}"
exit 0
fi
if needs_grep_fixup || needs_script_args_check_fixup; then
echo "Fixing makeself header..."
fix_makeself_header
chmod +x "${MAKESELF_SCRIPT}"
if is_makeself_ready; then
echo "makeself is ready: ${MAKESELF_DIR}"
exit 0
fi
fi
echo "makeself is missing, incomplete, or not patched, preparing..."
rm -rf "${MAKESELF_DIR}"
mkdir -p "${MAKESELF_DIR}"
local tar_url patch_url
tar_url=$(fetch_download_url "${MAKESELF_TAR}")
patch_url=$(fetch_download_url "${MAKESELF_PATCH}")
echo "Downloading ${MAKESELF_TAR} from GitCode..."
curl -sSL --retry 3 --fail "${tar_url}" \
| tar -xz -C "${MAKESELF_DIR}" --strip-components=1
patch_file=$(mktemp)
if [[ -z "${patch_file}" || ! -f "${patch_file}" ]]; then
echo "ERROR: failed to create temporary patch file" >&2
exit 1
fi
trap cleanup_patch_file EXIT
echo "Downloading ${MAKESELF_PATCH} from GitCode..."
curl -sSL --retry 3 --fail "${patch_url}" -o "${patch_file}"
echo "Applying ${MAKESELF_PATCH}..."
patch -d "${MAKESELF_DIR}" -p1 --forward < "${patch_file}"
echo "Fixing makeself header quirks..."
fix_makeself_header
chmod +x "${MAKESELF_SCRIPT}"
if ! is_makeself_ready; then
echo "ERROR: failed to prepare patched makeself" >&2
echo " Script_Args_Check: $(grep -c 'Script_Args_Check' "${MAKESELF_HEADER}" || true)" >&2
echo " fixed grep pattern: $(grep -cF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" || true)" >&2
echo " script args check warn: $(grep -cF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}" || true)" >&2
exit 1
fi
echo "makeself preparation completed: ${MAKESELF_DIR}"
trap - EXIT
cleanup_patch_file
}
check_dependency
main