summaryrefslogtreecommitdiff
path: root/otp_patch_apply
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2015-03-17 10:41:39 +0100
committerRickard Green <rickard@erlang.org>2015-03-17 12:06:48 +0100
commit700dde22b771cf535703a42887971a146202eae1 (patch)
tree47c594eff6c15aa97fabf7727f6c4f361d1e22a6 /otp_patch_apply
parent5fde23474656c1934250e8b8a9c7399dc00d5bdf (diff)
downloaderlang-700dde22b771cf535703a42887971a146202eae1.tar.gz
Add support for patching of individual applications
Diffstat (limited to 'otp_patch_apply')
-rwxr-xr-xotp_patch_apply465
1 files changed, 465 insertions, 0 deletions
diff --git a/otp_patch_apply b/otp_patch_apply
new file mode 100755
index 0000000000..a1f244eab3
--- /dev/null
+++ b/otp_patch_apply
@@ -0,0 +1,465 @@
+#!/bin/sh
+#
+# Copyright Ericsson AB 2014. All Rights Reserved.
+#
+
+version="1.0.1"
+
+force=
+lib_path=
+orig_dir=
+sdir=
+idir="/broken/path/here"
+cleanup=no
+install_docs=yes
+
+invalid_src="does not seem to be a valid OTP source tree"
+not_built="Source in has not been built"
+doc_not_built="Documentation has not been built. Either build the
+documentation and re-run 'otp_patch_apply', or re-run 'otp_patch_apply'
+with the '-n' switch."
+
+print_usage()
+{
+ cat <<EOF
+otp_patch_apply -s <Dir> -i <Dir> [-l <Dir>] [-c] [-f] [-h] [-n] [-v] \\
+ <App1> [... <AppN>]
+
+ -s <Dir> -- OTP source directory that contain build results.
+ -i <Dir> -- OTP installation directory to patch.
+ -l <Dir> -- Alternative OTP source library directory path(s) containing
+ build results of OTP applications. Multiple paths should be
+ colon separated.
+ -c -- Cleanup (remove) old versions of applications patched
+ in the installation.
+ -f -- Force patch of application(s) even though dependencies are
+ not fullfilled.
+ -h -- Print this help then exit.
+ -n -- Do not install documentation.
+ -v -- Print version then exit.
+ <AppX> -- Application to patch.
+
+Environment Variable:
+ ERL_LIBS -- Alternative OTP source library directory path(s) containing
+ build results of OTP applications. Multiple paths should be
+ colon separated.
+
+NOTE:
+ * Complete build environment is required while running otp_patch_apply.
+ * Before applying a patch you need to build all of OTP in the source
+ directory.
+ * All source directories identified by -s and -l should contain build
+ results of OTP applications.
+
+Version: $version
+
+EOF
+
+}
+
+error()
+{
+ echo "ERROR:" "$@" 1>&2
+ exit 1
+}
+
+usage_error()
+{
+ echo "ERROR:" "$@" 1>&2
+ echo "" 1>&2
+ print_usage 1>&2
+ exit 1
+}
+
+usage()
+{
+ print_usage
+ exit 0
+}
+
+alt_lib_path()
+{
+ app=$1
+ save_ifs=$IFS
+ IFS=:
+
+ cd "$orig_dir" || error "Cannot change directory to $orig_dir"
+
+ for lib in $lib_path; do
+ # Want absolute path
+ case "$lib" in
+ /*)
+ ;;
+ *)
+ cd "$lib" || error "Cannot change directory to $lib"
+ lib=`pwd`
+ cd "$orig_dir" || error "Cannot change directory to $orig_dir"
+ esac
+ if [ -d "$lib/$app" ]; then
+ echo "$lib/$app"
+ IFS=$save_ifs
+ return 0
+ fi
+ done
+
+ IFS=$save_ifs
+
+ return 1
+}
+
+prog_in_mod_path()
+{
+ chk_path="/bin:$PATH"
+ PROG=$1
+ save_ifs=$IFS
+ IFS=:
+ if [ "X$TARGET" = "Xwin32" ]; then
+ for p in $chk_path; do
+ if [ -f "$p/$PROG.exe" ]; then
+ IFS=$save_ifs
+ echo "$p/$PROG.exe"
+ return 0
+ fi
+ done
+ else
+ for p in $chk_path; do
+ if [ -x "$p/$PROG" ]; then
+ IFS=$save_ifs
+ echo "$p/$PROG"
+ return 0
+ fi
+ done
+ fi
+ IFS=$save_ifs
+ return 1
+}
+
+find_prog()
+{
+ prog_in_mod_path "$1"
+ if [ $? -ne 0 ]; then
+ echo "$1"
+ fi
+ return 0
+}
+
+# Parse arguments
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ "-s")
+ shift
+ if [ ! $# -gt 0 ]; then
+ usage_error "Missing OTP source directory"
+ fi
+ sdir="$1";;
+ "-i")
+ shift
+ if [ ! $# -gt 0 ]; then
+ usage_error "Missing OTP install directory"
+ fi
+ idir="$1";;
+ "-l")
+ shift
+ if [ ! $# -gt 0 ]; then
+ usage_error "Missing OTP library directory"
+ fi
+ if [ "x$lib_path" = "x" ]; then
+ lib_path="$1"
+ else
+ lib_path="$lib_path:$1"
+ fi;;
+ "-f")
+ force="-force";;
+ "-c")
+ cleanup=yes;;
+ "-h")
+ usage;;
+ "-n")
+ install_docs=no;;
+ "-v")
+ echo "otp_patch_apply version $version"
+ exit 0;;
+ *)
+ app="$1"
+ applications="$applications $app";;
+ esac
+ shift
+done
+
+# Check that we got mandatory arguments
+test "x$sdir" != "x" || usage_error "Missing OTP source directory"
+test "x$idir" != "x" || usage_error "Missing OTP install directory"
+test "x$applications" != "x" || usage_error "Missing applications"
+
+orig_dir=`pwd`
+
+# Check that the source directory seems sane
+cd "$sdir" 2>/dev/null || error "Cannot change directory to $sdir"
+
+# Want absolute path
+case "$sdir" in
+ /*) ;;
+ *) sdir=`pwd`;;
+esac
+
+export ERL_TOP="$sdir"
+test -f "$sdir/otp_build" || error "$ERL_TOP" $invalid_src
+test -f "$sdir/OTP_VERSION" || error "$ERL_TOP" $invalid_src
+test -f "$sdir/otp_versions.table" || error "$ERL_TOP" $invalid_src
+test -f "$sdir/erts/autoconf/config.guess" || error "$ERL_TOP" $invalid_src
+test -f "$sdir/make/verify_runtime_dependencies" || error "$ERL_TOP" $invalid_src
+test -x "$sdir/bootstrap/bin/erl" || error $not_built
+test -x "$sdir/bootstrap/bin/erlc" || error $not_built
+test -x "$sdir/bootstrap/bin/escript" || error $not_built
+test -f "$sdir/make/otp_built" || error $not_built
+
+if [ $install_docs = yes ]; then
+ test -f "$sdir/make/otp_doc_built" || usage_error $doc_not_built
+fi
+
+otp_rel=`sed 's|\([0-9]*\).*|\1|' < $ERL_TOP/OTP_VERSION` || \
+ error "Failed to read $ERL_TOP/OTP_VERSION"
+
+case "$otp_rel" in
+ 1[7-9]|[2-9][0-9]) ;; # ok; release 17-99
+ *) error "Invalid OTP release: $otp_rel";;
+esac
+
+export PATH="$ERL_TOP/bootstrap/bin:$PATH"
+erlc="$ERL_TOP/bootstrap/bin/erlc"
+erl="$ERL_TOP/bootstrap/bin/erl"
+
+erl_otp_rel=`$erl -noshell -noinput -eval "io:format(\"~s~n\", [erlang:system_info(otp_release)]), erlang:halt(0)"` || \
+ error "Failed to execute: $erl"
+
+test "$otp_rel" = "$erl_otp_rel" || error "Inconsistent source: $sdir"
+
+app_dirs=
+for app in $applications; do
+ case "$app" in
+ "erts")
+ dir="$ERL_TOP/erts";;
+ *)
+ dir="$ERL_TOP/lib/$app";;
+ esac
+ if [ ! -d "$dir" ]; then
+ dir=`alt_lib_path "$app"`
+ if [ $? -ne 0 ]; then
+ error "Application missing in source: $app"
+ fi
+ fi
+ app_dirs="$app_dirs $dir"
+done
+
+cd "$orig_dir" 2>/dev/null || error "Cannot change directory to $orig_dir"
+
+# Check that the install directory seems sane
+cd "$idir" 2>/dev/null || error "Cannot change directory to $idir"
+
+# Want absolute path
+case "$idir" in
+ /*) ;;
+ *) idir=`pwd`;;
+esac
+
+test -d "$idir/releases/$otp_rel" || \
+ error "No OTP-$otp_rel installation present in $idir"
+
+cd "$ERL_TOP" 2>/dev/null || error "Cannot change directory to $ERL_TOP"
+
+# Some tools we use
+rm=`find_prog rm`
+rmdir=`find_prog rmdir`
+cp=`find_prog cp`
+mv=`find_prog mv`
+mkdir=`find_prog mkdir`
+
+# Setup build stuff
+if [ "x$TARGET" = "x" ]; then
+ TARGET=`$ERL_TOP/erts/autoconf/config.guess`
+fi
+BUILDSYS=$TARGET
+if [ -z "$MAKE" ]; then
+ case $TARGET in
+ win32)
+ MAKE=make;;
+ *)
+ prog_in_mod_path gmake >/dev/null
+ if [ $? -eq 0 ]; then
+ MAKE=gmake
+ else
+ MAKE=make
+ fi;;
+ esac
+fi
+if [ X`$MAKE is_cross_configured` = Xyes ]; then
+ TARGET=`$MAKE target_configured`
+elif [ "x$OVERRIDE_TARGET" != "x" -a "x$OVERRIDE_TARGET" != "xwin32" ]; then
+ TARGET=$OVERRIDE_TARGET
+fi
+
+# Check for cleanup
+inst_app_vers="$idir/releases/$otp_rel/installed_application_versions"
+rm_app_vers=
+if [ $cleanup = yes ]; then
+ $mv "$inst_app_vers" "${inst_app_vers}.save" || \
+ error "Failed to save $inst_app_vers"
+ for app in $applications; do
+ tmp=`grep "$app-*" "${inst_app_vers}.save"`
+ rm_app_vers="$rm_app_vers $tmp"
+ done
+ $cp "${inst_app_vers}.save" "$inst_app_vers"
+ for rm_app_ver in $rm_app_vers; do
+ $cp "$inst_app_vers" "${inst_app_vers}.tmp"
+ grep -v $rm_app_ver "${inst_app_vers}.tmp" > "$inst_app_vers"
+ done
+ $rm -f "${inst_app_vers}.tmp"
+fi
+
+# Verify runtime dependencies
+$ERL_TOP/make/verify_runtime_dependencies -release "$otp_rel" \
+ -source "$ERL_TOP" -target "$idir" $force $applications || {
+ test ! -f "${inst_app_vers}.save" || \
+ $mv "${inst_app_vers}.save" "$inst_app_vers"
+ exit 1
+}
+
+# Update OTP_VERSION in installation
+otp_version=`cat "$idir/releases/$otp_rel/OTP_VERSION"` || {
+ test ! -f "${inst_app_vers}.save" || \
+ $mv "${inst_app_vers}.save" "$inst_app_vers"
+ error "Not able to read $idir/releases/$otp_rel/OTP_VERSION"
+}
+
+{
+ echo "$otp_version" | sed "s|^\([^\*]*\)\**|\1\*\*|g" > \
+ "$idir/releases/$otp_rel/OTP_VERSION"
+} 2>/dev/null || {
+ test ! -f "${inst_app_vers}.save" || \
+ $mv "${inst_app_vers}.save" "$inst_app_vers"
+ error "Not able to update $idir/releases/$otp_rel/OTP_VERSION"
+}
+
+# Do actual cleanup
+if [ "x$rm_app_vers" != "x" ]; then
+ for app_ver in $rm_app_vers; do
+ case x"$app_ver" in
+ x)
+ ;;
+ xerts-*)
+ $rm -rf "$idir/$app_ver" ;;
+ x*)
+ $rm -rf "$idir/lib/$app_ver" ;;
+ esac
+ done
+ $rm -f "${inst_app_vers}.save"
+fi
+
+# Install application from built source
+for app_dir in $app_dirs; do
+ (cd "$app_dir" && \
+ $MAKE MAKE="$MAKE" TARGET=$TARGET RELEASE_ROOT="$idir" \
+ RELEASE_PATH="$idir" TESTROOT="$idir" release) || exit 1
+done
+
+if [ $install_docs = yes ]; then
+# Documentation have been built and should be installed
+
+ for app_dir in $app_dirs; do
+ (cd "$app_dir" && \
+ $MAKE MAKE="$MAKE" RELEASE_ROOT="$idir" RELEASE_PATH="$idir" \
+ TESTROOT="$idir" release_docs) || exit 1
+ done
+
+ (cd "$sdir/system/doc/top" && $MAKE clean)
+
+ (cd "$sdir/system/doc/top" && \
+ $MAKE MAKE="$MAKE" RELEASE_ROOT="$idir" RELEASE_PATH="$idir" \
+ TESTROOT="$idir" release_docs) || exit 1
+
+ echo ""
+ echo "*"
+ echo "* NOTE! In order to update pre-formatted man pages you"
+ echo "* need to run the 'Install' script located in:"
+ echo "* $idir"
+ echo "*"
+fi
+
+# If erts, kernel, stdlib or sasl is included, find versions
+for app in $applications; do
+ case "$app" in
+ erts)
+ erts_vsn=`grep '^VSN' erts/vsn.mk | sed "s|^VSN.*=[^0-9]*\([0-9].*\)$|\1|g"`
+ update_rel=true;;
+ kernel)
+ kernel_vsn=`sed "s|^KERNEL_VSN[^=]*=[^0-9]*\([0-9].*\)$|\1|g" lib/kernel/vsn.mk`
+ update_rel=true;;
+ stdlib)
+ stdlib_vsn=`sed "s|^STDLIB_VSN[^=]*=[^0-9]*\([0-9].*\)$|\1|g" lib/stdlib/vsn.mk`
+ update_rel=true;;
+ sasl)
+ sasl_vsn=`sed "s|^SASL_VSN[^=]*=[^0-9]*\([0-9].*\)$|\1|g" lib/sasl/vsn.mk`
+ update_rel=true;;
+ *)
+ ;;
+ esac
+done
+
+# and find the old versions for those not included
+if [ "X$update_rel" != "X" ]; then
+ if [ "X$erts_vsn" = "X" ]; then
+ erts_vsns=`ls -d "$idir"/erts-* | sed "s|$idir/erts-\([0-9\.].*\)|\1|g"`
+ erts_vsn=`echo "$erts_vsns" | sort -t '.' -g | tail -n 1`
+ fi
+ if [ "X$kernel_vsn" = "X" ]; then
+ kernel_vsns=`ls -d "$idir"/lib/kernel-* | sed "s|$idir/lib/kernel-\([0-9\.].*\)|\1|g"`
+ kernel_vsn=`echo "$kernel_vsns" | sort -t '.' -g | tail -n 1`
+ fi
+ if [ "X$stdlib_vsn" = "X" ]; then
+ stdlib_vsns=`ls -d "$idir"/lib/stdlib-* | sed "s|$idir/lib/stdlib-\([0-9\.].*\)|\1|g"`
+ stdlib_vsn=`echo "$stdlib_vsns" | sort -t '.' -g | tail -n 1`
+ fi
+ if [ "X$sasl_vsn" = "X" ]; then
+ sasl_vsns=`ls -d "$idir"/lib/sasl-* | sed "s|$idir/lib/sasl-\([0-9\.].*\)|\1|g"`
+ sasl_vsn=`echo "$sasl_vsns" | sort -t '.' -g | tail -n 1`
+ fi
+
+ # Generate .rel, .script and .boot - to tmp dir
+ start_clean="{release, {\"Erlang/OTP\",\"$otp_rel\"}, {erts, \"$erts_vsn\"}, [{kernel,\"$kernel_vsn\"}, {stdlib,\"$stdlib_vsn\"}]}."
+ start_sasl="{release, {\"Erlang/OTP\",\"$otp_rel\"}, {erts, \"$erts_vsn\"}, [{kernel,\"$kernel_vsn\"}, {stdlib,\"$stdlib_vsn\"}, {sasl,\"$sasl_vsn\"}]}."
+
+ tmp_dir="$idir/tmp";
+ if [ ! -d "$tmp_dir" ]; then
+ $mkdir "$tmp_dir"
+ fi
+ echo "$start_sasl" > "$tmp_dir/start_sasl.rel"
+ echo "$start_clean" > "$tmp_dir/start_clean.rel"
+ echo "$start_clean" > "$tmp_dir/no_dot_erlang.rel"
+
+ $erlc -I"$idir"/lib/*/ebin -o"$tmp_dir" "$tmp_dir/start_sasl.rel" || exit 1
+ $erlc -I"$idir"/lib/*/ebin -o"$tmp_dir" +no_warn_sasl "$tmp_dir/start_clean.rel" || exit 1
+ $erlc -I"$idir"/lib/*/ebin -o"$tmp_dir" +no_warn_sasl +no_dot_erlang "$tmp_dir/no_dot_erlang.rel" || exit 1
+
+ # Generate RELEASES file
+ "$erl" -noinput +B -eval "release_handler:create_RELEASES(\"%ERL_ROOT%\", \"$tmp_dir\", \"$tmp_dir/start_sasl.rel\", []), halt()" || exit 1
+
+ # If all good so far, move generated files into target area
+ $mv "$tmp_dir/RELEASES" "$idir/releases/RELEASES.src"
+ $mv "$tmp_dir"/* "$idir/releases/$otp_rel"
+ $rmdir "$tmp_dir"
+
+ # Remove old start scripts (forces a new run of Install)
+ $rm -f "$idir"/releases/RELEASES
+ $rm -f "$idir"/bin/*.script
+ $rm -f "$idir"/bin/*.boot
+ $rm -f "$idir"/bin/erl
+
+ echo ""
+ echo "*"
+ echo "* NOTE! In order to get a runnable OTP system again you"
+ echo "* need to run the 'Install' script located in:"
+ echo "* $idir"
+ echo "*"
+fi
+