Projects
Kolab:Winterfell
erlang-relx
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 5
View file
erlang-relx.spec
Changed
@@ -1,7 +1,7 @@ %define bname relx Name: erlang-%bname -Version: 3.21.1 -Release: 2 +Version: 3.26.0 +Release: 1 Summary: A release assembler for Erlang License: Apache-2.0 Group: Development/Tools/Other @@ -98,6 +98,9 @@ %changelog +* Thu Jul 19 2018 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.26.0-1 +- Check in version 3.26.0 + * Thu May 25 2017 Timotheus Pokorra <tp@tbits.net> 3.21.1-2 - fix for Fedora 25, there is no debugging information
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +erlang-relx (3.26.0-1) unstable; urgency=low + + * Check in version 3.26.0 + + -- Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Thu, 19 Jul 2018 22:26:56 +0000 + erlang-relx (3.21.1-1) unstable; urgency=low * Initial Release.
View file
erlang-relx.dsc
Changed
@@ -2,7 +2,7 @@ Source: erlang-relx Binary: erlang-relx Architecture: any -Version: 3.21.1-1 +Version: 3.26.0-1 Maintainer: hede <kolab983@der-he.de> Homepage: http://erlware.github.io/relx Standards-Version: 3.9.4 @@ -10,4 +10,4 @@ Package-List: erlang-relx deb devel optional arch=any Files: - 00000000000000000000000000000000 0 relx-3.21.1.tar.xz + 00000000000000000000000000000000 0 relx-3.26.0.tar.gz
View file
relx-3.21.1.tar.gz/.travis.yml -> relx-3.26.0.tar.gz/.travis.yml
Changed
@@ -1,17 +1,34 @@ language: erlang -otp_release: - - 19.1 - - 18.3 - - 17.0 - - R16B03-1 - - R15B03 +matrix: + include: + - os: linux + sudo: required + otp_release: 17.5 + - os: linux + sudo: required + otp_release: 18.3 + - os: linux + sudo: required + otp_release: 19.3 + - os: linux + sudo: required + otp_release: 20.0 + - os: osx + sudo: required + language: generic before_script: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi + ## should eventually use a tap that has previous erlang versions here + ## as this only uses the latest erlang available via brew + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install erlang; fi - wget https://s3.amazonaws.com/rebar3/rebar3 - chmod +x rebar3 script: "./rebar3 update && ./rebar3 ct" branches: only: - master +addons: + hostname: travis.dev notifications: email: - core@erlware.org
View file
relx-3.21.1.tar.gz/README.md -> relx-3.26.0.tar.gz/README.md
Changed
@@ -28,9 +28,9 @@ To build relx and generate a standalone escript executable: $ ./rebar3 update - $ ./rebar3 escriptize + $ ./rebar3 as escript escriptize -This creates the executable `_build/default/bin/relx`. +This creates the executable `_build/escript/bin/relx`. Building on Windows -------------------
View file
relx-3.21.1.tar.gz/bootstrap.cmd -> relx-3.26.0.tar.gz/bootstrap.cmd
Changed
@@ -3,7 +3,7 @@ :: Get dependencies, compile and escriptize relx @cmd /c @rebar3 update -@cmd /c @rebar3 escriptize +@cmd /c @rebar3 as escript escriptize :: Create a shortcut file for running the relx command @set relx_cmd=relx.cmd
View file
relx-3.26.0.tar.gz/pr2relnotes.sh
Added
@@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +if [ -z $1 ] +then + echo "pr2relnotes.sh: prints list of pull requests merged since <tag>" + echo " usage: $0 <tag> [pull-request-url (default: https://github.com/erlware/relx/pull/)]" + exit 0 +fi +export url=${2:-"https://github.com/erlware/relx/pull/"} + +git log --merges --pretty=medium $1..HEAD | \ +awk -v url=$url ' + # first line of a merge commit entry + /^commit / {mode="new"} + + # merge commit default message + / +Merge pull request/ { + page_id=substr($4, 2, length($4)-1); + mode="started"; + next; + } + + # line of content including title + mode=="started" && / [^ ]+/ { + print "- [" substr($0, 5) "](" url page_id ")"; mode="done" + }'
View file
relx-3.21.1.tar.gz/priv/templates/bin -> relx-3.26.0.tar.gz/priv/templates/bin
Changed
@@ -13,6 +13,7 @@ ERTS_VSN="{{ erts_vsn }}" REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN" ERL_OPTS="{{ erl_opts }}" +export ESCRIPT_NAME="${ESCRIPT_NAME-$SCRIPT}" find_erts_dir() { __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN" @@ -22,7 +23,7 @@ else __erl="$(which erl)" code="io:format(\"~s\", [code:root_dir()]), halt()." - __erl_root="$("$__erl" -noshell -eval "$code")" + __erl_root="$("$__erl" -boot no_dot_erlang -noshell -eval "$code")" ERTS_DIR="$__erl_root/erts-$ERTS_VSN" ROOTDIR="$__erl_root" fi @@ -74,4 +75,4 @@ set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" -boot "$REL_DIR/$BOOTFILE" "$ARGS" # Boot the release -$BINDIR/erlexec $@ +exec $BINDIR/erlexec $@
View file
relx-3.21.1.tar.gz/priv/templates/bin_windows -> relx-3.26.0.tar.gz/priv/templates/bin_windows
Changed
@@ -11,14 +11,14 @@ @for %%A in ("%script_dir%\..") do ( set "release_root_dir=%%~fA" ) -@set rel_dir=%release_root_dir%\releases\%rel_vsn% +@set "rel_dir=%release_root_dir%\releases\%rel_vsn%" @call :find_erts_dir @call :find_sys_config @call :set_boot_script_var -@set rootdir=%release_root_dir% -@set bindir=%erts_dir%\bin +@set "rootdir=%release_root_dir%" +@set "bindir=%erts_dir%\bin" @set progname=erl @set erl=%bindir%\erl @@ -41,7 +41,7 @@ :: Find the ERTS dir :find_erts_dir -@set erts_dir=%release_root_dir%\erts-%erts_vsn% +@set "erts_dir=%release_root_dir%\erts-%erts_vsn%" @if exist %erts_dir% ( goto :set_erts_dir_from_default ) else ( @@ -60,34 +60,27 @@ @for /f "delims=" %%i in ('where erl') do ( set erl=%%i ) -@set dir_cmd="%erl%" -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop +@set dir_cmd="%erl%" -boot no_dot_erlang -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop @for /f "delims=" %%i in ('%%dir_cmd%%') do ( set erl_root=%%i ) -@set erts_dir=%erl_root%\erts-%erts_vsn% +@set "erts_dir=%erl_root%\erts-%erts_vsn%" @set rootdir=%erl_root% @goto :eof :: Find the sys.config file :find_sys_config -@set possible_sys=%rel_dir%\sys.config +@set "possible_sys=%rel_dir%\sys.config" @if exist "%possible_sys%" ( set sys_config=-config "%possible_sys%" ) -@if exist "%possible_sys%".orig ( - ren "%possible_sys%".orig "%possible_sys%" - set sys_config=-config "%possible_sys%" -) -@if exist "%rel_dir%\vm.args".orig ( - ren "%rel_dir%\vm.args" ".orig %rel_dir%\vm.args" -) @goto :eof :: set boot_script variable :set_boot_script_var @if exist "%rel_dir%\%rel_name%.boot" ( - set boot_script=%rel_dir%\%rel_name% + set "boot_script=%rel_dir%\%rel_name%" ) else ( - set boot_script=%rel_dir%\start + set "boot_script=%rel_dir%\start" ) @goto :eof
View file
relx-3.26.0.tar.gz/priv/templates/builtin_hook_pid
Added
@@ -0,0 +1,12 @@ +#!/bin/bash + +# loop until the VM starts responding to pings +while ! $(relx_nodetool "ping">/dev/null) +do + sleep 1 +done + +# get the beam pid and write it to the file passed as +# argument +PID="$(relx_get_pid)" +echo $PID > $1
View file
relx-3.26.0.tar.gz/priv/templates/builtin_hook_status
Added
@@ -0,0 +1,3 @@ +#!/bin/bash + +echo $(relx_nodetool eval "application:which_applications().")
View file
relx-3.26.0.tar.gz/priv/templates/builtin_hook_wait_for_process
Added
@@ -0,0 +1,17 @@ +#!/bin/bash + +# loop until the VM starts responding to pings +while ! $(relx_nodetool "ping">/dev/null) +do + sleep 1 +done + +# loop until the name provided as argument gets +# registered +while true +do + if [ "$(relx_nodetool eval "whereis($1).")" != "undefined" ] + then + break + fi +done
View file
relx-3.26.0.tar.gz/priv/templates/builtin_hook_wait_for_vm_start
Added
@@ -0,0 +1,7 @@ +#!/bin/bash + +# loop until the VM starts responding to pings +while ! $(relx_nodetool "ping">/dev/null) +do + sleep 1 +done
View file
relx-3.21.1.tar.gz/priv/templates/extended_bin -> relx-3.26.0.tar.gz/priv/templates/extended_bin
Changed
@@ -2,19 +2,125 @@ set -e -SCRIPT=$(readlink $0 || true) -if [ -z $SCRIPT ]; then - SCRIPT=$0 -fi; +# http://erlang.org/doc/man/run_erl.html +# If defined, disables input and output flow control for the pty +# opend by run_erl. Useful if you want to remove any risk of accidentally +# blocking the flow control by using Ctrl-S (instead of Ctrl-D to detach), +# which can result in blocking of the entire Beam process, and in the case +# of running heart as supervisor even the heart process becomes blocked +# when writing log message to terminal, leaving the heart process unable +# to do its work. +RUN_ERL_DISABLE_FLOWCNTRL=${RUN_ERL_DISABLE_FLOWCNTRL:-true} +export $RUN_ERL_DISABLE_FLOWCNTRL + +if [ "$TERM" = "dumb" -o -z "$TERM" ]; then + export TERM=screen +fi + +# OSX does not support readlink '-f' flag, work +# around that +case $OSTYPE in + darwin*) + SCRIPT=$(readlink $0 || true) + ;; + *) + SCRIPT=$(readlink -f $0 || true) + ;; +esac +[ -z $SCRIPT ] && SCRIPT=$0 SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)" RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)" -REL_NAME="{{ rel_name }}" +# Make the value available to variable substitution calls below +export REL_NAME="{{ rel_name }}" REL_VSN="{{ rel_vsn }}" ERTS_VSN="{{ erts_vsn }}" CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}" REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN" ERL_OPTS="{{ erl_opts }}" RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}" +export ESCRIPT_NAME="${ESCRIPT_NAME-$SCRIPT}" + +# start/stop/install/upgrade pre/post hooks +PRE_START_HOOKS="{{{ pre_start_hooks }}}" +POST_START_HOOKS="{{{ post_start_hooks }}}" +PRE_STOP_HOOKS="{{{ pre_stop_hooks }}}" +POST_STOP_HOOKS="{{{ post_stop_hooks }}}" +PRE_INSTALL_UPGRADE_HOOKS="{{{ pre_install_upgrade_hooks }}}" +POST_INSTALL_UPGRADE_HOOKS="{{{ post_install_upgrade_hooks }}}" +STATUS_HOOK="{{{ status_hook }}}" +EXTENSIONS="{{{ extensions }}}" + +relx_usage() { + command="$1" + + case "$command" in + unpack) + echo "Usage: $REL_NAME unpack [VERSION]" + echo "Unpacks a release package VERSION, it assumes that this" + echo "release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>.tar.gz" + ;; + install) + echo "Usage: $REL_NAME install [VERSION]" + echo "Installs a release package VERSION, it assumes that this" + echo "release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>.tar.gz" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + uninstall) + echo "Usage: $REL_NAME uninstall [VERSION]" + echo "Uninstalls a release VERSION, it will only accept" + echo "versions that are not currently in use" + ;; + upgrade) + echo "Usage: $REL_NAME upgrade [VERSION]" + echo "Upgrades the currently running release to VERSION, it assumes" + echo "that a release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>.tar.gz" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + downgrade) + echo "Usage: $REL_NAME downgrade [VERSION]" + echo "Downgrades the currently running release to VERSION, it assumes" + echo "that a release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>-<version>.tar.gz" + echo " releases/<version>/<relname>.tar.gz" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + status) + echo "Usage: $REL_NAME status" + echo "Obtains node status information." + ;; + *) + # check for extension + IS_EXTENSION=$(relx_is_extension $command) + if [ "$IS_EXTENSION" = "1" ]; then + EXTENSION_SCRIPT=$(relx_get_extension_script $command) + relx_run_extension $EXTENSION_SCRIPT help + else + EXTENSIONS=`echo $EXTENSIONS | sed -e 's/|undefined//g'` + echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|rpc|rpcterms|eval|status|$EXTENSIONS}" + fi + ;; + esac +} find_erts_dir() { __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN" @@ -24,7 +130,7 @@ else __erl="$(which erl)" code="io:format(\"~s\", [code:root_dir()]), halt()." - __erl_root="$("$__erl" -noshell -eval "$code")" + __erl_root="$("$__erl" -boot no_dot_erlang -sasl errlog_type error -noshell -eval "$code")" ERTS_DIR="$__erl_root/erts-$ERTS_VSN" ROOTDIR="$__erl_root" fi @@ -44,7 +150,10 @@ relx_get_nodename() { id="longname$(relx_gen_id)-${NAME}" - "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id + "$BINDIR/erl" -boot start_clean \ + -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \ + -eval '[_,H]=re:split(atom_to_list(node()),"@",[unicode,{return,list}]), io:format("~s~n",[H]), halt()' \ + -noshell ${NAME_TYPE} $id } # Connect to a remote node @@ -59,7 +168,7 @@ # Setup remote shell command to control node exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot start_clean \ -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \ - -setcookie "$COOKIE" -hidden -kernel net_ticktime $TICKTIME + -setcookie "$COOKIE" -hidden -kernel net_ticktime $TICKTIME $VM_ARGS } # Generate a random id @@ -71,6 +180,8 @@ relx_nodetool() { command="$1"; shift + escript_emulator_args $ROOTDIR/bin/nodetool + "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \ -setcookie "$COOKIE" "$command" $@ } @@ -83,82 +194,260 @@ "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@ } -# Output a start command for the last argument of run_erl -relx_start_command() { - printf "exec \"%s\" \"%s\"" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \ - "$START_OPTION" +relx_get_code_paths() { + code="{ok, [{release,_,_,Apps}]} = file:consult(\"$REL_DIR/$REL_NAME.rel\"),"\ +"lists:foreach(fun(A) ->"\ +" io:fwrite(\"$ROOTDIR/lib/~p-~s/ebin \", [element(1, A), element(2, A)]) "\ +"end, Apps),"\ +"halt()." + + "$BINDIR/erl" -noshell -boot start_clean -eval "$code" } -# Use $CWD/vm.args if exists, otherwise releases/VSN/vm.args -if [ -z "$VMARGS_PATH" ]; then - if [ -f "$RELEASE_ROOT_DIR/vm.args" ]; then - VMARGS_PATH="$RELEASE_ROOT_DIR/vm.args" +make_out_file_path() { + # Use output directory provided in the RELX_OUT_FILE_PATH environment variable + # (default to the current location of vm.args and sys.config) + DIR=$(dirname $1) + [ -d "${RELX_OUT_FILE_PATH}" ] && DIR="${RELX_OUT_FILE_PATH}" + FILE=$(basename $1) + IN="${DIR}/${FILE}" +
View file
relx-3.21.1.tar.gz/priv/templates/extended_bin_windows -> relx-3.26.0.tar.gz/priv/templates/extended_bin_windows
Changed
@@ -10,6 +10,7 @@ :: * ping - check if the node is running :: * console - start the Erlang release in a `werl` Windows shell :: * attach - connect to a running node and open an interactive console +:: * remote_console - alias for attach :: * list - display a listing of installed Erlang services :: * usage - display available commands @@ -25,7 +26,7 @@ @for %%A in ("%script_dir%\..") do @( set release_root_dir=%%~fA ) -@set rel_dir=%release_root_dir%\releases\%rel_vsn% +@set "rel_dir=%release_root_dir%\releases\%rel_vsn%" @call :find_erts_dir @call :find_sys_config @@ -48,6 +49,30 @@ set node_name=%%J ) +@for /f "delims=@ tokens=1-2" %%I in ("%node_name%") do @( + set node_name=%%I + set hostname=%%J +) + +:: if no hostname is set, attempt to pick one from the env +@if "" == "%hostname%" @( + if "-sname" == "%node_type%" ( + if not "" == "%COMPUTERNAME%" ( + set "hostname=%COMPUTERNAME%" + ) + ) else ( + if not "" == "%COMPUTERNAME%" ( + if not "" == "%USERDNSDOMAIN%" ( + set "hostname=%COMPUTERNAME%.%USERDNSDOMAIN%" + ) + ) + ) +) +:: Add @ to hostname if not empty so that we can just concatenate values safely +@if not "" == "%hostname%" @( + set "hostname=@%hostname%" +) + :: Extract cookie from vm.args @for /f "usebackq tokens=1-2" %%I in (`findstr /b \-setcookie "%vm_args%"`) do @( set cookie=%%J @@ -56,6 +81,19 @@ :: Write the erl.ini file to set up paths relative to this script @call :write_ini +:: Collect any additional VM args into erl_opts +@setlocal EnableDelayedExpansion +@for /f "usebackq tokens=1-2" %%I in (`findstr /r "^[^#]" "%vm_args%"`) do @( + if not "%%I" == "-name" ( + if not "%%I" == "-sname" ( + if not "%%I" == "-setcookie" ( + set erl_opts=!erl_opts! %%I %%J + ) + ) + ) +) +@endlocal && set erl_opts=%erl_opts% + :: If a start.boot file is not present, copy one from the named .boot file @if not exist "%rel_dir%\start.boot" ( copy "%rel_dir%\%rel_name%.boot" "%rel_dir%\start.boot" >nul @@ -72,6 +110,7 @@ @if "%1"=="ping" @goto ping @if "%1"=="list" @goto list @if "%1"=="attach" @goto attach +@if "%1"=="remote_console" @goto attach @if "%1"=="" @goto usage @echo Unknown command: "%1" @@ -79,7 +118,7 @@ :: Find the ERTS dir :find_erts_dir -@set possible_erts_dir=%release_root_dir%\erts-%erts_vsn% +@set "possible_erts_dir=%release_root_dir%\erts-%erts_vsn%" @if exist "%possible_erts_dir%" ( call :set_erts_dir_from_default ) else ( @@ -89,8 +128,8 @@ :: Set the ERTS dir from the passed in erts_vsn :set_erts_dir_from_default -@set erts_dir=%possible_erts_dir% -@set rootdir=%release_root_dir% +@set "erts_dir=%possible_erts_dir%" +@set "rootdir=%release_root_dir%" @goto :eof :: Set the ERTS dir from erl @@ -98,17 +137,17 @@ @for /f "delims=" %%i in ('where erl') do @( set erl=%%i ) -@set dir_cmd="%erl%" -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop +@set dir_cmd="%erl%" -boot no_dot_erlang -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop @for /f "delims=" %%i in ('%%dir_cmd%%') do @( set erl_root=%%i ) -@set erts_dir=%erl_root%\erts-%erts_vsn% -@set rootdir=%erl_root% +@set "erts_dir=%erl_root%\erts-%erts_vsn%" +@set "rootdir=%erl_root%" @goto :eof :: Find the sys.config file :find_sys_config -@set possible_sys=%rel_dir%\sys.config +@set "possible_sys=%rel_dir%\sys.config" @if exist %possible_sys% ( set sys_config=-config "%possible_sys%" ) @@ -117,9 +156,9 @@ :: set boot_script variable :set_boot_script_var @if exist "%rel_dir%\%rel_name%.boot" ( - set boot_script=%rel_dir%\%rel_name% + set "boot_script=%rel_dir%\%rel_name%" ) else ( - set boot_script=%rel_dir%\start + set "boot_script=%rel_dir%\start" ) @goto :eof @@ -136,7 +175,7 @@ :: Display usage information :usage -@echo usage: %~n0 ^(install^|uninstall^|start^|stop^|restart^|upgrade^|downgrade^|console^|ping^|list^|attach^) +@echo usage: %~n0 ^(install^|uninstall^|start^|stop^|restart^|upgrade^|downgrade^|console^|ping^|list^|attach^|remote_console^) @goto :eof :: Install the release as a Windows service @@ -147,9 +186,7 @@ set description=Erlang node %node_name% in %rootdir% @if "" == "%2" ( :: Install the service - %erlsrv% add %service_name% %node_type% "%node_name%" -c "%description%" ^ - -w "%rootdir%" -m "%start_erl%" -args "%args%" ^ - -stopaction "init:stop()." + %erlsrv% add %service_name% %node_type% "%node_name%" -c "%description%" -w "%rootdir%" -m "%start_erl%" -args "%args%" -stopaction "init:stop()." ) else ( :: relup and reldown goto relup @@ -175,13 +212,12 @@ :: Relup and reldown :relup @if "" == "%2" ( - echo Missing package argument - echo Usage: %rel_name% %1 {package base name} - echo NOTE {package base name} MUST NOT include the .tar.gz suffix + echo Missing version argument + echo Usage: %rel_name% %1 {version} set ERRORLEVEL=1 exit /b %ERRORLEVEL% ) -@%escript% "%rootdir%/bin/install_upgrade.escript" "%rel_name%" "%node_name%" "%cookie%" "%2" +@%escript% "%rootdir%/bin/install_upgrade.escript" "install" "{'%rel_name%', \"%node_type%\", '%node_name%%hostname%', '%cookie%'}" "%2" "%3" @goto :eof :: Start a console @@ -193,7 +229,7 @@ :: Ping the running node :ping -@%escript% %nodetool% ping %node_type% "%node_name%" -setcookie "%cookie%" +@%escript% %nodetool% ping %node_type% "%node_name%%hostname%" -setcookie "%cookie%" @goto :eof :: List installed Erlang services @@ -205,5 +241,5 @@ :attach @set boot=-boot "%clean_boot_script%" -boot_var RELEASE_DIR "%release_root_dir%" @start "%node_name% attach" %werl% %boot% ^ - -remsh %node_name% %node_type% console -setcookie %cookie% + -remsh %node_name%%hostname% %node_type% console -setcookie %cookie% @goto :eof
View file
relx-3.21.1.tar.gz/priv/templates/install_upgrade_escript -> relx-3.26.0.tar.gz/priv/templates/install_upgrade_escript
Changed
@@ -6,75 +6,231 @@ -define(TIMEOUT, 300000). -define(INFO(Fmt,Args), io:format(Fmt,Args)). -%% Unpack or upgrade to a new tar.gz release -main(["unpack", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) -> +main([Command0, DistInfoStr | CommandArgs]) -> + %% convert the distribution info arguments string to an erlang term + {ok, Tokens, _} = erl_scan:string(DistInfoStr ++ "."), + {ok, DistInfo} = erl_parse:parse_term(Tokens), + %% convert arguments into a proplist + Opts = parse_arguments(CommandArgs), + %% invoke the command passed as argument + F = case Command0 of + "install" -> fun(A, B) -> install(A, B) end; + "unpack" -> fun(A, B) -> unpack(A, B) end; + "upgrade" -> fun(A, B) -> upgrade(A, B) end; + "downgrade" -> fun(A, B) -> downgrade(A, B) end; + "uninstall" -> fun(A, B) -> uninstall(A, B) end; + "versions" -> fun(A, B) -> versions(A, B) end + end, + F(DistInfo, Opts); +main(Args) -> + ?INFO("unknown args: ~p\n", [Args]), + erlang:halt(1). + +unpack({RelName, NameTypeArg, NodeName, Cookie}, Opts) -> TargetNode = start_distribution(NodeName, NameTypeArg, Cookie), - WhichReleases = which_releases(TargetNode), - Version = parse_version(VersionArg), - case proplists:get_value(Version, WhichReleases) of - undefined -> - %% not installed, so unpack tarball: - ?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]), - ReleasePackage = Version ++ "/" ++ RelName, - case rpc:call(TargetNode, release_handler, unpack_release, - [ReleasePackage], ?TIMEOUT) of - {ok, Vsn} -> - ?INFO("Unpacked successfully: ~p~n", [Vsn]); - {error, UnpackReason} -> - print_existing_versions(TargetNode), - ?INFO("Unpack failed: ~p~n",[UnpackReason]), - erlang:halt(2) - end; + Version = proplists:get_value(version, Opts), + case unpack_release(RelName, TargetNode, Version) of + {ok, Vsn} -> + ?INFO("Unpacked successfully: ~p~n", [Vsn]); old -> %% no need to unpack, has been installed previously - ?INFO("Release ~s is marked old, switching to it.~n",[Version]); + ?INFO("Release ~s is marked old.~n",[Version]); unpacked -> - ?INFO("Release ~s is already unpacked, now installing.~n",[Version]); + ?INFO("Release ~s is already unpacked.~n",[Version]); current -> - ?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]); + ?INFO("Release ~s is already installed and current.~n",[Version]); permanent -> - ?INFO("Release ~s is already installed, and set permanent.~n",[Version]) + ?INFO("Release ~s is already installed and set permanent.~n",[Version]); + {error, Reason} -> + ?INFO("Unpack failed: ~p~n",[Reason]), + print_existing_versions(TargetNode), + erlang:halt(2) end; -main(["install", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) -> +unpack(_, Args) -> + ?INFO("unpack: unknown args ~p\n", [Args]). + +install({RelName, NameTypeArg, NodeName, Cookie}, Opts) -> TargetNode = start_distribution(NodeName, NameTypeArg, Cookie), - WhichReleases = which_releases(TargetNode), - Version = parse_version(VersionArg), - case proplists:get_value(Version, WhichReleases) of - undefined -> - %% not installed, so unpack tarball: - ?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]), - ReleasePackage = Version ++ "/" ++ RelName, - case rpc:call(TargetNode, release_handler, unpack_release, - [ReleasePackage], ?TIMEOUT) of - {ok, Vsn} -> - ?INFO("Unpacked successfully: ~p~n", [Vsn]), - install_and_permafy(TargetNode, RelName, Vsn); - {error, UnpackReason} -> - print_existing_versions(TargetNode), - ?INFO("Unpack failed: ~p~n",[UnpackReason]), - erlang:halt(2) - end; + Version = proplists:get_value(version, Opts), + case unpack_release(RelName, TargetNode, Version) of + {ok, Vsn} -> + ?INFO("Unpacked successfully: ~p~n", [Vsn]), + check_and_install(TargetNode, Vsn), + maybe_permafy(TargetNode, RelName, Vsn, Opts); old -> %% no need to unpack, has been installed previously ?INFO("Release ~s is marked old, switching to it.~n",[Version]), - install_and_permafy(TargetNode, RelName, Version); + check_and_install(TargetNode, Version), + maybe_permafy(TargetNode, RelName, Version, Opts); unpacked -> ?INFO("Release ~s is already unpacked, now installing.~n",[Version]), - install_and_permafy(TargetNode, RelName, Version); - current -> %% installed and in-use, just needs to be permanent - ?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]), - permafy(TargetNode, RelName, Version); + check_and_install(TargetNode, Version), + maybe_permafy(TargetNode, RelName, Version, Opts); + current -> + case proplists:get_value(permanent, Opts, true) of + true -> + ?INFO("Release ~s is already installed and current, making permanent.~n", + [Version]), + permafy(TargetNode, RelName, Version); + false -> + ?INFO("Release ~s is already installed and current.~n", + [Version]) + end; permanent -> - ?INFO("Release ~s is already installed, and set permanent.~n",[Version]) + %% this release is marked permanent, however it might not the + %% one currently running + case current_release_version(TargetNode) of + Version -> + ?INFO("Release ~s is already installed, running and set permanent.~n", + [Version]); + CurrentVersion -> + ?INFO("Release ~s is the currently running version.~n", + [CurrentVersion]), + check_and_install(TargetNode, Version), + maybe_permafy(TargetNode, RelName, Version, Opts) + end; + {error, Reason} -> + ?INFO("Unpack failed: ~p~n",[Reason]), + print_existing_versions(TargetNode), + erlang:halt(2) end; -main(_) -> - erlang:halt(1). +install(_, Args) -> + ?INFO("install: unknown args ~p\n", [Args]). + +upgrade(DistInfo, Args) -> + install(DistInfo, Args). + +downgrade(DistInfo, Args) -> + install(DistInfo, Args). + +uninstall({_RelName, NameTypeArg, NodeName, Cookie}, Opts) -> + TargetNode = start_distribution(NodeName, NameTypeArg, Cookie), + WhichReleases = which_releases(TargetNode), + Version = proplists:get_value(version, Opts), + case proplists:get_value(Version, WhichReleases) of + undefined -> + ?INFO("Release ~s is already uninstalled.~n", [Version]); + old -> + ?INFO("Release ~s is marked old, uninstalling it.~n", [Version]), + remove_release(TargetNode, Version); + unpacked -> + ?INFO("Release ~s is marked unpacked, uninstalling it~n", + [Version]), + remove_release(TargetNode, Version); + current -> + ?INFO("Uninstall failed: Release ~s is marked current.~n", [Version]), + erlang:halt(2); + permanent -> + ?INFO("Uninstall failed: Release ~s is running.~n", [Version]), + erlang:halt(2) + end; +uninstall(_, Args) -> + ?INFO("uninstall: unknown args ~p\n", [Args]). + +versions({_RelName, NameTypeArg, NodeName, Cookie}, []) -> + TargetNode = start_distribution(NodeName, NameTypeArg, Cookie), + print_existing_versions(TargetNode). + +parse_arguments(Args) -> + parse_arguments(Args, []). + +parse_arguments([], Acc) -> Acc; +parse_arguments(["--no-permanent"|Rest], Acc) -> + parse_arguments(Rest, [{permanent, false}] ++ Acc); +parse_arguments([VersionStr|Rest], Acc) -> + Version = parse_version(VersionStr), + parse_arguments(Rest, [{version, Version}] ++ Acc). + +unpack_release(RelName, TargetNode, Version) -> + WhichReleases = which_releases(TargetNode), + case proplists:get_value(Version, WhichReleases) of + undefined -> + %% not installed, so unpack tarball: + %% look for a release package with the intended version in the following order: + %% releases/<relname>-<version>.tar.gz + %% releases/<version>/<relname>-<version>.tar.gz + %% releases/<version>/<relname>.tar.gz + case find_and_link_release_package(Version, RelName) of + {_, undefined} -> + {error, release_package_not_found}; + {ReleasePackage, ReleasePackageLink} ->
View file
relx-3.21.1.tar.gz/priv/templates/nodetool -> relx-3.26.0.tar.gz/priv/templates/nodetool
Changed
@@ -57,7 +57,7 @@ % spaces, so this converts all of that to a single string to parse String = binary_to_list( list_to_binary( - string:join(ListOfArgs," ") + join(ListOfArgs," ") ) ), @@ -126,16 +126,16 @@ nodename(Name) -> - case string:tokens(Name, "@") of + case re:split(Name, "@", [{return, list}, unicode]) of [_Node, _Host] -> list_to_atom(Name); [Node] -> - [_, Host] = string:tokens(atom_to_list(node()), "@"), + [_, Host] = re:split(atom_to_list(node()), "@", [{return, list}, unicode]), list_to_atom(lists:concat([Node, "@", Host])) end. append_node_suffix(Name, Suffix) -> - case string:tokens(Name, "@") of + case re:split(Name, "@", [{return, list}, unicode]) of [Node, Host] -> list_to_atom(lists:concat([Node, Suffix, os:getpid(), "@", Host])); [Node] -> @@ -165,3 +165,13 @@ {more, Cont1} -> consult(Cont1, eof, Acc) end. + +%% string:join/2 copy; string:join/2 is getting obsoleted +%% and replaced by lists:join/2, but lists:join/2 is too new +%% for version support (only appeared in 19.0) so it cannot be +%% used. Instead we just adopt join/2 locally and hope it works +%% for most unicode use cases anyway. +join([], Sep) when is_list(Sep) -> + []; +join([H|T], Sep) -> + H ++ lists:append([Sep ++ X || X <- T]).
View file
relx-3.21.1.tar.gz/priv/templates/vm_args -> relx-3.26.0.tar.gz/priv/templates/vm_args
Changed
@@ -17,3 +17,14 @@ ## Tweak GC to run more often ##-env ERL_FULLSWEEP_AFTER 10 + +# +B [c | d | i] +# Option c makes Ctrl-C interrupt the current shell instead of invoking the emulator break +# handler. Option d (same as specifying +B without an extra option) disables the break handler. # Option i makes the emulator ignore any break signal. +# If option c is used with oldshell on Unix, Ctrl-C will restart the shell process rather than +# interrupt it. +# Disable the emulator break handler +# it easy to accidentally type ctrl-c when trying +# to reach for ctrl-d. ctrl-c on a live node can +# have very undesirable results +##+Bi
View file
relx-3.21.1.tar.gz/rebar.config -> relx-3.26.0.tar.gz/rebar.config
Changed
@@ -1,9 +1,9 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- %% Dependencies ================================================================ -{deps, [{erlware_commons, "0.21.0"}, - {providers, "1.6.0"}, - {getopt, "0.8.2"}, - {cf, "0.2.1"}, +{deps, [{erlware_commons, "1.2.0"}, + {providers, "1.7.0"}, + {getopt, "1.0.1"}, + {cf, "0.2.2"}, {bbmustache, "1.0.4"} ]}. @@ -17,7 +17,7 @@ [{platform_define, "^[0-9]+", namespaced_types}, {platform_define, "^1[8|9]", rand_module}, {platform_define, "^2", rand_module}, - no_debug_info, + {platform_define, "^2", unicode_str}, warnings_as_errors, inline]}. @@ -32,20 +32,30 @@ {profiles, [{dev, [{plugins, [rebar3_neotoma_plugin]}]}, - {test, [{erl_opts, [debug_info]}]}, + {test, [{erl_opts, [nowarn_export_all, debug_info]}]}, {dialyze, [{overrides, [{add, erlware_commons, [{erl_opts, [debug_info]}]}, {add, providers, [{erl_opts, [debug_info]}]}, {add, getopt, [{erl_opts, [debug_info]}]}, {add, bbmustache, [{erl_opts, [debug_info]}]}, {add, cf, [{erl_opts, [debug_info]}]}]}, - {erl_opts, [debug_info]}]} + {erl_opts, [debug_info]}]}, + {escript, [ + {overrides, [{add, erlware_commons, [{erl_opts, [no_debug_info]}]}, + {add, providers, [{erl_opts, [no_debug_info]}]}, + {add, getopt, [{erl_opts, [no_debug_info]}]}, + {add, bbmustache, [{erl_opts, [no_debug_info]}]}, + {add, cf, [{erl_opts, [no_debug_info]}]}]}, + {erl_opts, [no_debug_info]} + ]} ]}. {overrides, [{override, erlware_commons, [ {erl_opts, [{platform_define, "^[0-9]+", namespaced_types}, {platform_define, "^R1[4|5]", deprecated_crypto}, {platform_define, "^((1[8|9])|2)", rand_module}, + {platform_define, "^2", unicode_str}, + {platform_define, "^(R|1|20)", fun_stacktrace}, no_debug_info, warnings_as_errors ]}, @@ -54,7 +64,8 @@ {override, bbmustache, [ {erl_opts, [no_debug_info]}, {deps, []}, {plugins, []}]}, - {override, getopt, [{erl_opts, [no_debug_info]}]}, + {override, getopt, [{erl_opts, [no_debug_info, + {platform_define, "^2", unicode_str}]}]}, {override, providers, [{erl_opts, [no_debug_info]}]} ]}.
View file
relx-3.21.1.tar.gz/rebar.lock -> relx-3.26.0.tar.gz/rebar.lock
Changed
@@ -1,5 +1,14 @@ +{"1.1.0", [{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.0.4">>},0}, - {<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0}, - {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.21.0">>},0}, - {<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0}, - {<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0}]. + {<<"cf">>,{pkg,<<"cf">>,<<"0.2.2">>},0}, + {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.2.0">>},0}, + {<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}, + {<<"providers">>,{pkg,<<"providers">>,<<"1.7.0">>},0}]}. +[ +{pkg_hash,[ + {<<"bbmustache">>, <<"7BA94F971C5AFD7B6617918A4BB74705E36CAB36EB84B19B6A1B7EE06427AA38">>}, + {<<"cf">>, <<"7F2913FFF90ABCABD0F489896CFEB0B0674F6C8DF6C10B17A83175448029896C">>}, + {<<"erlware_commons">>, <<"2BAB99CF88941145767A502F1209886F1F0D31695EEF21978A30F15E645721E0">>}, + {<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}, + {<<"providers">>, <<"BBF730563914328EC2511D205E6477A94831DB7297DE313B3872A2B26C562EAB">>}]} +].
View file
relx-3.21.1.tar.gz/src/rlx_app_discovery.erl -> relx-3.26.0.tar.gz/src/rlx_app_discovery.erl
Changed
@@ -40,7 +40,7 @@ ec_cmd_log:info(rlx_state:log(State), fun() -> ["Resolving OTP Applications from directories:\n", - string:join([[rlx_util:indent(2), LibDir] || LibDir <- LibDirs], "\n")] + rlx_string:join([[rlx_util:indent(2), LibDir] || LibDir <- LibDirs], "\n")] end), resolve_app_metadata(State, LibDirs). @@ -293,10 +293,21 @@ -spec get_deps(binary(), atom(), string(), proplists:proplist()) -> {ok, rlx_app_info:t()} | {error, Reason::term()}. get_deps(AppDir, AppName, AppVsn, AppDetail) -> - ActiveApps = proplists:get_value(applications, AppDetail, []), + %% ensure that at least stdlib and kernel are defined as application deps + ActiveApps = ensure_stdlib_kernel(AppName, + proplists:get_value(applications, AppDetail, [])), LibraryApps = proplists:get_value(included_applications, AppDetail, []), rlx_app_info:new(AppName, AppVsn, AppDir, ActiveApps, LibraryApps). +-spec ensure_stdlib_kernel(AppName :: atom(), + Apps :: list(atom())) -> list(atom()). +ensure_stdlib_kernel(kernel, Deps) -> Deps; +ensure_stdlib_kernel(stdlib, Deps) -> Deps; +ensure_stdlib_kernel(_AppName, []) -> + %% minimum required deps are kernel and stdlib + [kernel, stdlib]; +ensure_stdlib_kernel(_AppName, Deps) -> Deps. + %%%=================================================================== %%% Test Functions %%%===================================================================
View file
relx-3.21.1.tar.gz/src/rlx_cmd_args.erl -> relx-3.26.0.tar.gz/src/rlx_cmd_args.erl
Changed
@@ -282,6 +282,9 @@ Erts when is_list(Erts) -> {include_erts, Erts} end; +create(warnings_as_errors, Opts) -> + WarningsAsErrors = proplists:get_value(warnings_as_errors, Opts, false), + {warnings_as_errors, WarningsAsErrors}; create(_, _) -> [].
View file
relx-3.21.1.tar.gz/src/rlx_config.erl -> relx-3.26.0.tar.gz/src/rlx_config.erl
Changed
@@ -173,6 +173,8 @@ {ok, rlx_state:skip_apps(State0, SkipApps0)}; load_terms({exclude_apps, ExcludeApps0}, {ok, State0}) -> {ok, rlx_state:exclude_apps(State0, ExcludeApps0)}; +load_terms({exclude_modules, ExcludeModules0}, {ok, State0}) -> + {ok, rlx_state:exclude_modules(State0, ExcludeModules0)}; load_terms({debug_info, DebugInfo}, {ok, State0}) -> {ok, rlx_state:debug_info(State0, DebugInfo)}; load_terms({overrides, Overrides0}, {ok, State0}) -> @@ -254,10 +256,14 @@ {ok, rlx_state:vm_args(State, false)}; load_terms({vm_args, VmArgs}, {ok, State}) -> {ok, rlx_state:vm_args(State, filename:absname(VmArgs))}; +load_terms({vm_args_src, VmArgs}, {ok, State}) -> + {ok, rlx_state:vm_args_src(State, filename:absname(VmArgs))}; load_terms({sys_config, false}, {ok, State}) -> {ok, rlx_state:sys_config(State, false)}; load_terms({sys_config, SysConfig}, {ok, State}) -> {ok, rlx_state:sys_config(State, filename:absname(SysConfig))}; +load_terms({sys_config_src, SysConfigSrc}, {ok, State}) -> + {ok, rlx_state:sys_config_src(State, filename:absname(SysConfigSrc))}; load_terms({root_dir, Root}, {ok, State}) -> {ok, rlx_state:root_dir(State, filename:absname(Root))}; load_terms({output_dir, OutputDir}, {ok, State}) -> @@ -267,6 +273,8 @@ NewOverlayVars0 = list_of_overlay_vars_files(OverlayVars), NewOverlayVars1 = CurrentOverlayVars ++ NewOverlayVars0, {ok, rlx_state:put(State, overlay_vars, NewOverlayVars1)}; +load_terms({warnings_as_errors, WarningsAsErrors}, {ok, State}) -> + {ok, rlx_state:warnings_as_errors(State, WarningsAsErrors)}; load_terms({Name, Value}, {ok, State}) when erlang:is_atom(Name) -> {ok, rlx_state:put(State, Name, Value)}; @@ -336,8 +344,8 @@ parse_vsn(Vsn) when Vsn =:= semver ; Vsn =:= "semver" -> {ok, V} = ec_git_vsn:vsn(ec_git_vsn:new()), V; -parse_vsn({semver, _}) -> - {ok, V} = ec_git_vsn:vsn(ec_git_vsn:new()), +parse_vsn({semver, Data}) -> + {ok, V} = ec_git_vsn:vsn(Data), V; parse_vsn({cmd, Command}) -> V = os:cmd(Command),
View file
relx-3.21.1.tar.gz/src/rlx_depsolver.erl -> relx-3.26.0.tar.gz/src/rlx_depsolver.erl
Changed
@@ -113,7 +113,7 @@ %% type %%============================================================================ -ifdef(namespaced_types). --type dep_graph() :: gb_tree:tree(). +-type dep_graph() :: gb_trees:tree(). -else. -type dep_graph() :: gb_tree(). -endif. @@ -484,8 +484,7 @@ {value, {PkgName, Constraints0}} -> Constraints0 end, - [{PkgName, [{PkgConstraint, {SrcPkg, SrcVsn}} | Constraints1]} - | lists:keydelete(PkgName, 1, PkgsConstraints)]. + lists:keydelete(PkgName, 1, PkgsConstraints)++[{PkgName, [{PkgConstraint, {SrcPkg, SrcVsn}} | Constraints1]}]. %% @doc %% Extend the currently active constraints correctly for the given constraints. @@ -625,7 +624,7 @@ F = fun (Vsn) -> Deps = get_dep_constraints(DepGraph, Pkg, Vsn), UConstraints = extend_constraints(Pkg, Vsn, Constraints, Deps), - DepPkgs =[dep_pkg(Dep) || Dep <- Deps], + DepPkgs = [dep_pkg(Dep) || Dep <- Deps], NewVisited = [{Pkg, Vsn} | Visited], Res = all_pkgs(DepGraph, NewVisited, DepPkgs ++ OtherPkgs, UConstraints, PathInd), Res
View file
relx-3.21.1.tar.gz/src/rlx_goal.erl -> relx-3.26.0.tar.gz/src/rlx_goal.erl
Changed
@@ -10,8 +10,6 @@ -define(p_seq,true). -define(p_string,true). - --compile(export_all). -spec file(file:name()) -> any(). file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -> Err end.
View file
relx-3.21.1.tar.gz/src/rlx_prv_app_discover.erl -> relx-3.26.0.tar.gz/src/rlx_prv_app_discover.erl
Changed
@@ -132,7 +132,7 @@ add_environment_lib_dir(_State) -> case os:getenv("ERL_LIBS") of false -> []; - Libs -> [erlang:iolist_to_binary(L) || L <- string:tokens(Libs, ":")] + Libs -> [erlang:iolist_to_binary(L) || L <- rlx_string:lexemes(Libs, ":")] end. %% Order matters so this slow dedup needs to be used
View file
relx-3.21.1.tar.gz/src/rlx_prv_assembler.erl -> relx-3.26.0.tar.gz/src/rlx_prv_assembler.erl
Changed
@@ -86,8 +86,17 @@ format_error({ec_file_error, AppDir, TargetDir, E}) -> io_lib:format("Unable to copy OTP App from ~s to ~s due to ~p", [AppDir, TargetDir, E]); +format_error({vmargs_does_not_exist, Path}) -> + io_lib:format("The vm.args file specified for this release (~s) does not exist!", + [Path]); +format_error({vmargs_src_does_not_exist, Path}) -> + io_lib:format("The vm.args.src file specified for this release (~s) does not exist!", + [Path]); format_error({config_does_not_exist, Path}) -> - io_lib:format("The config file specified for this release (~s) does not exist!", + io_lib:format("The sys.config file specified for this release (~s) does not exist!", + [Path]); +format_error({config_src_does_not_exist, Path}) -> + io_lib:format("The sys.config.src file specified for this release (~s) does not exist!", [Path]); format_error({sys_config_parse_error, ConfigPath, Reason}) -> io_lib:format("The config file (~s) specified for this release could not be opened or parsed: ~s", @@ -111,17 +120,20 @@ io_lib:format("Unable to symlink directory ~s to ~s because \n~s~s", [AppDir, TargetDir, rlx_util:indent(2), file:format_error(Reason)]); -format_error(start_clean_script_generation_error) -> +format_error(boot_script_generation_error) -> "Unknown internal release error generating start_clean.boot"; -format_error({start_clean_script_generation_warning, Module, Warnings}) -> +format_error({boot_script_generation_warning, Module, Warnings}) -> ["Warnings generating start_clean.boot \s", rlx_util:indent(2), Module:format_warning(Warnings)]; -format_error({start_clean_script_generation_error, Module, Errors}) -> +format_error({boot_script_generation_error, Module, Errors}) -> ["Errors generating start_clean.boot \n", rlx_util:indent(2), Module:format_error(Errors)]; format_error({strip_release, Reason}) -> io_lib:format("Stripping debug info from release beam files failed becuase ~s", - [beam_lib:format_error(Reason)]). + [beam_lib:format_error(Reason)]); +format_error({rewrite_app_file, AppFile, Error}) -> + io_lib:format("Unable to rewrite .app file ~s due to ~p", + [AppFile, Error]). %%%=================================================================== %%% Internal Functions @@ -162,7 +174,7 @@ false end, lists:flatten(ec_plists:map(fun(App) -> - copy_app(LibDir, App, IncludeSrc, IncludeErts) + copy_app(State, LibDir, App, IncludeSrc, IncludeErts) end, Apps))), case Result of [E | _] -> @@ -179,7 +191,7 @@ Apps end. -copy_app(LibDir, App, IncludeSrc, IncludeErts) -> +copy_app(State, LibDir, App, IncludeSrc, IncludeErts) -> AppName = erlang:atom_to_list(rlx_app_info:name(App)), AppVsn = rlx_app_info:original_vsn(App), AppDir = rlx_app_info:dir(App), @@ -196,57 +208,75 @@ true -> []; false -> - copy_app_(App, AppDir, TargetDir, IncludeSrc) + copy_app_(State, App, AppDir, TargetDir, IncludeSrc) end; _ -> - copy_app_(App, AppDir, TargetDir, IncludeSrc) + copy_app_(State, App, AppDir, TargetDir, IncludeSrc) end end. is_erts_lib(Dir) -> lists:prefix(filename:split(list_to_binary(code:lib_dir())), filename:split(Dir)). -copy_app_(App, AppDir, TargetDir, IncludeSrc) -> +copy_app_(State, App, AppDir, TargetDir, IncludeSrc) -> remove_symlink_or_directory(TargetDir), case rlx_app_info:link(App) of true -> link_directory(AppDir, TargetDir), - rewrite_app_file(App, AppDir); + rewrite_app_file(State, App, AppDir); false -> - copy_directory(AppDir, TargetDir, IncludeSrc), - rewrite_app_file(App, TargetDir) + copy_directory(State, App, AppDir, TargetDir, IncludeSrc), + rewrite_app_file(State, App, TargetDir) end. %% If excluded apps exist in this App's applications list we must write a new .app -rewrite_app_file(App, TargetDir) -> +rewrite_app_file(State, App, TargetDir) -> Name = rlx_app_info:name(App), ActiveDeps = rlx_app_info:active_deps(App), IncludedDeps = rlx_app_info:library_deps(App), AppFile = filename:join([TargetDir, "ebin", ec_cnv:to_list(Name) ++ ".app"]), - {ok, [{application, AppName, AppData}]} = file:consult(AppFile), - OldActiveDeps = proplists:get_value(applications, AppData, []), - OldIncludedDeps = proplists:get_value(included_applications, AppData, []), - - case {OldActiveDeps, OldIncludedDeps} of - {ActiveDeps, IncludedDeps} -> - ok; - _ -> - AppData1 = lists:keyreplace(applications - ,1 - ,AppData - ,{applications, ActiveDeps}), - AppData2 = lists:keyreplace(included_applications - ,1 - ,AppData1 - ,{included_applications, IncludedDeps}), - Spec = io_lib:format("~p.\n", [{application, AppName, AppData2}]), - write_file_if_contents_differ(AppFile, Spec) + {ok, [{application, AppName, AppData0}]} = file:consult(AppFile), + OldActiveDeps = proplists:get_value(applications, AppData0, []), + OldIncludedDeps = proplists:get_value(included_applications, AppData0, []), + OldModules = proplists:get_value(modules, AppData0, []), + ExcludedModules = proplists:get_value(Name, + rlx_state:exclude_modules(State), []), + + %% maybe replace excluded apps + AppData2 = + case {OldActiveDeps, OldIncludedDeps} of + {ActiveDeps, IncludedDeps} -> + AppData0; + _ -> + AppData1 = lists:keyreplace(applications + ,1 + ,AppData0 + ,{applications, ActiveDeps}), + lists:keyreplace(included_applications + ,1 + ,AppData1 + ,{included_applications, IncludedDeps}) + end, + %% maybe replace excluded modules + AppData3 = + case ExcludedModules of + [] -> AppData2; + _ -> + lists:keyreplace(modules + ,1 + ,AppData2 + ,{modules, OldModules -- ExcludedModules}) + end, + Spec = [{application, AppName, AppData3}], + case write_file_if_contents_differ(AppFile, Spec) of + ok -> ok; + Error -> ?RLX_ERROR({rewrite_app_file, AppFile, Error}) end. -write_file_if_contents_differ(Filename, Bytes) -> - ToWrite = iolist_to_binary(Bytes), - case file:read_file(Filename) of - {ok, ToWrite} -> +write_file_if_contents_differ(Filename, Spec) -> + ToWrite = io_lib:format("~p.\n", Spec), + case file:consult(Filename) of + {ok, Spec} -> ok; {ok, _} -> file:write_file(Filename, ToWrite); @@ -275,8 +305,8 @@ ok end. -copy_directory(AppDir, TargetDir, IncludeSrc) -> - [copy_dir(AppDir, TargetDir, SubDir) +copy_directory(State, App, AppDir, TargetDir, IncludeSrc) -> + [copy_dir(State, App, AppDir, TargetDir, SubDir) || SubDir <- ["ebin", "include", "priv", @@ -289,13 +319,20 @@ [] end]]. -copy_dir(AppDir, TargetDir, SubDir) -> +copy_dir(State, App, AppDir, TargetDir, SubDir) -> SubSource = filename:join(AppDir, SubDir), SubTarget = filename:join(TargetDir, SubDir), case ec_file:is_dir(SubSource) of true -> ok = rlx_util:mkdir_p(SubTarget), - case ec_file:copy(SubSource, SubTarget, [recursive]) of + %% get a list of the modules to be excluded from this app + AppName = rlx_app_info:name(App), + ExcludedModules = proplists:get_value(AppName, rlx_state:exclude_modules(State), + []), + ExcludedFiles = [filename:join([binary_to_list(SubSource), + atom_to_list(M) ++ ".beam"]) || + M <- ExcludedModules], + case copy_dir(SubSource, SubTarget, ExcludedFiles) of {error, E} -> ?RLX_ERROR({ec_file_error, AppDir, SubTarget, E});
View file
relx-3.21.1.tar.gz/src/rlx_prv_overlay.erl -> relx-3.26.0.tar.gz/src/rlx_prv_overlay.erl
Changed
@@ -245,6 +245,7 @@ -spec generate_release_vars(rlx_release:t()) -> proplists:proplist(). generate_release_vars(Release) -> [{erts_vsn, rlx_release:erts(Release)}, + {erts_dir, code:root_dir()}, {release_erts_version, rlx_release:erts(Release)}, {release_name, rlx_release:name(Release)}, {rel_vsn, rlx_release:vsn(Release)}, @@ -308,6 +309,28 @@ -spec do_individual_overlay(rlx_state:t(), list(), proplists:proplist(), OverlayDirective::term()) -> {ok, rlx_state:t()} | relx:error(). +do_individual_overlay(State, _Files, OverlayVars, {chmod, Mode, Path}) -> + % mode can be specified directly as an integer value, or if it is + % not an integer we assume it's a template, which we render and convert + % blindly to an integer. So this will crash with an exception if for + % some reason something other than an integer is used + NewMode = + case is_integer(Mode) of + true -> Mode; + false -> erlang:list_to_integer(erlang:binary_to_list(render_string (OverlayVars, Mode))) + end, + + Root = rlx_state:output_dir(State), + file_render_do(OverlayVars, Path, + fun(NewPath) -> + Absolute = absolutize(State, + filename:join(Root,erlang:iolist_to_binary (NewPath))), + case file:change_mode(Absolute, NewMode) of + {error, Error} -> + ?RLX_ERROR({unable_to_chmod, NewMode, NewPath, Error}); + ok -> ok + end + end); do_individual_overlay(State, _Files, OverlayVars, {mkdir, Dir}) -> case rlx_util:render(erlang:iolist_to_binary(Dir), OverlayVars) of {ok, IoList} -> @@ -379,10 +402,8 @@ erlang:iolist_to_binary(filename:join(ToFile1, filename:basename(FromFile1))) end, - case ec_file:copy(FromFile1, ToFile2, [recursive]) of + case ec_file:copy(FromFile1, ToFile2, [recursive, {file_info, [mode, time]}]) of ok -> - {ok, FileInfo} = file:read_file_info(FromFile1), - ok = file:write_file_info(ToFile2, FileInfo), ok; {error, Err} -> ?RLX_ERROR({copy_failed, @@ -461,10 +482,17 @@ {ok, IoData} -> case filelib:ensure_dir(ToFile) of ok -> + %% we were asked to render a template + %% onto a symlink, this would cause an overwrite + %% of the original file, so we delete the symlink + %% and go ahead with the template render + case ec_file:is_symlink(ToFile) of + true -> ec_file:remove(ToFile); + false -> ok + end, case file:write_file(ToFile, IoData) of ok -> - {ok, FileInfo} = file:read_file_info(FromFile), - ok = file:write_file_info(ToFile, FileInfo), + ok = ec_file:copy_file_info(ToFile, FromFile, [mode, time]), ok; {error, Reason} -> ?RLX_ERROR({unable_to_write, ToFile, Reason})
View file
relx-3.21.1.tar.gz/src/rlx_prv_release.erl -> relx-3.26.0.tar.gz/src/rlx_prv_release.erl
Changed
@@ -202,7 +202,7 @@ ErtsDir -> try [Erts | _] = filelib:wildcard(filename:join(ErtsDir, "erts-*")), - [_, ErtsVsn] = string:tokens(filename:basename(Erts), "-"), + [_, ErtsVsn] = rlx_string:lexemes(filename:basename(Erts), "-"), {ok, rlx_state:add_realized_release(State, rlx_release:erts(Release1, ErtsVsn))} catch _:_ ->
View file
relx-3.21.1.tar.gz/src/rlx_prv_relup.erl -> relx-3.26.0.tar.gz/src/rlx_prv_relup.erl
Changed
@@ -65,6 +65,15 @@ {missing_sasl, _}}}) -> "Unfortunately, due to requirements in systools, you need to have the sasl application " "in both the current release and the release to upgrade from."; +format_error({relup_script_generation_warn, systools_relup, + [{erts_vsn_changed, _}, + {erts_vsn_changed, _}]}) -> + "It has been detected that the ERTS version changed while generating the relup between versions, " + "please be aware that an instruction that will automatically restart the VM will be inserted in " + "this case"; +format_error({relup_script_generation_warn, Module, Warnings}) -> + ["Warnings generating relup \n", + rlx_util:indent(2), Module:format_warning(Warnings)]; format_error({relup_script_generation_error, Module, Errors}) -> ["Errors generating relup \n", rlx_util:indent(2), Module:format_error(Errors)]. @@ -119,10 +128,20 @@ make_upfrom_script(State, Release, UpFrom) -> OutputDir = rlx_state:output_dir(State), + WarningsAsErrors = rlx_state:warnings_as_errors(State), Options = [{outdir, OutputDir}, {path, rlx_util:get_code_paths(Release, OutputDir) ++ rlx_util:get_code_paths(UpFrom, OutputDir)}, silent], + %% the following block can be uncommented + %% when systools:make_relup/4 returns + %% {error,Module,Errors} instead of error + %% when taking the warnings_as_errors option + %% ++ + %% case WarningsAsErrors of + %% true -> [warnings_as_errors]; + %% false -> [] + % end, CurrentRel = strip_rel(rlx_release:relfile(Release)), UpFromRel = strip_rel(rlx_release:relfile(UpFrom)), ec_cmd_log:debug(rlx_state:log(State), @@ -138,14 +157,26 @@ [UpFromRel, CurrentRel]), {ok, State}; error -> - ?RLX_ERROR({relup_script_generation_error, CurrentRel, UpFromRel}); + ?RLX_ERROR({relup_generation_error, CurrentRel, UpFromRel}); {ok, RelUp, _, []} -> write_relup_file(State, Release, RelUp), ec_cmd_log:info(rlx_state:log(State), "relup successfully created!"), {ok, State}; - {ok,_, Module,Warnings} -> - ?RLX_ERROR({relup_script_generation_warn, Module, Warnings}); + {ok, RelUp, Module,Warnings} -> + case WarningsAsErrors of + true -> + %% since we don't pass the warnings_as_errors option + %% the relup file gets generated anyway, we need to delete + %% it + file:delete(filename:join([OutputDir, "relup"])), + ?RLX_ERROR({relup_script_generation_warn, Module, Warnings}); + false -> + write_relup_file(State, Release, RelUp), + ec_cmd_log:warn(rlx_state:log(State), + format_error({relup_script_generation_warn, Module, Warnings})), + {ok, State} + end; {error,Module,Errors} -> ?RLX_ERROR({relup_script_generation_error, Module, Errors}) end.
View file
relx-3.21.1.tar.gz/src/rlx_rel_discovery.erl -> relx-3.26.0.tar.gz/src/rlx_rel_discovery.erl
Changed
@@ -42,7 +42,7 @@ ec_cmd_log:info(rlx_state:log(State), fun() -> ["Resolving available OTP Releases from directories:\n", - string:join([[rlx_util:indent(2), LibDir] || LibDir <- LibDirs], "\n")] + rlx_string:join([[rlx_util:indent(2), LibDir] || LibDir <- LibDirs], "\n")] end), resolve_rel_metadata(State, LibDirs, AppMeta) end.
View file
relx-3.21.1.tar.gz/src/rlx_release.erl -> relx-3.26.0.tar.gz/src/rlx_release.erl
Changed
@@ -39,6 +39,7 @@ realized/1, metadata/1, start_clean_metadata/1, + no_dot_erlang_metadata/1, canonical_name/1, config/1, config/2, @@ -144,7 +145,12 @@ {ok, t()}. realize(Rel, Pkgs0, World0) -> World1 = subset_world(Pkgs0, World0), - process_specs(realize_erts(Rel), World1). + case rlx_topo:sort_apps(World1) of + {ok, Pkgs1} -> + process_specs(realize_erts(Rel), Pkgs1); + Error={error, _} -> + Error + end. %% @doc this gives the application specs for the release. This can only be %% populated by the 'realize' call in this module. @@ -193,6 +199,12 @@ ?RLX_ERROR({not_realized, Name, Vsn}) end. +%% The no_dot_erlang.rel.src file is a literal copy of start_clean.rel.src +%% in Erlang/OTP itself. +-spec no_dot_erlang_metadata(t()) -> term(). +no_dot_erlang_metadata(T) -> + start_clean_metadata(T). + %% @doc produce the canonical name (<name>-<vsn>) for this release -spec canonical_name(t()) -> string(). canonical_name(#release_t{name=Name, vsn=Vsn}) -> @@ -239,6 +251,8 @@ rlx_depsolver:format_constraint(Constraint). -spec format_error(Reason::term()) -> iolist(). +format_error({topo_error, E}) -> + rlx_topo:format_error(E); format_error({failed_to_parse, Con}) -> io_lib:format("Failed to parse constraint ~p", [Con]); format_error({invalid_constraint, _, Con}) -> @@ -370,7 +384,7 @@ AppName -> {ok, Release#release_t{annotations=ec_dictionary:add(AppName, NewAnnots, Annots), - goals = [Constraint | Goals]}} + goals = Goals++[Constraint]}} end. -spec parse_constraint(application_constraint()) ->
View file
relx-3.21.1.tar.gz/src/rlx_state.erl -> relx-3.26.0.tar.gz/src/rlx_state.erl
Changed
@@ -54,8 +54,12 @@ hooks/2, vm_args/1, vm_args/2, + vm_args_src/1, + vm_args_src/2, sys_config/1, sys_config/2, + sys_config_src/1, + sys_config_src/2, root_dir/1, root_dir/2, add_configured_release/2, @@ -82,8 +86,11 @@ upfrom/1, upfrom/2, format/1, - format/2]). - + format/2, + exclude_modules/1, + exclude_modules/2, + warnings_as_errors/1, + warnings_as_errors/2]). -export_type([t/0, releases/0, @@ -103,10 +110,13 @@ available_apps=[] :: [rlx_app_info:t()], default_configured_release :: {rlx_release:name() | undefined, rlx_release:vsn() |undefined} | undefined, vm_args :: file:filename() | false | undefined, + vm_args_src :: file:filename() | undefined, sys_config :: file:filename() | false | undefined, + sys_config_src :: file:filename() | undefined, overrides=[] :: [{AppName::atom(), Directory::file:filename()}], skip_apps=[] :: [AppName::atom()], exclude_apps=[] :: [AppName::atom()], + exclude_modules=[] :: [{App::atom(), [Module::atom()]}], debug_info=keep :: keep | strip, configured_releases :: releases(), realized_releases :: releases(), @@ -114,7 +124,8 @@ include_src=true :: boolean(), upfrom :: string() | binary() | undefined, config_values :: ec_dictionary:dictionary(Key::atom(), - Value::term())}). + Value::term()), + warnings_as_errors=false :: boolean()}). %%============================================================================ %% types @@ -200,6 +211,15 @@ exclude_apps(State, SkipApps) -> State#state_t{exclude_apps=SkipApps}. +-spec exclude_modules(t()) -> [{App::atom(), [Module::atom()]}]. +exclude_modules(#state_t{exclude_modules=Modules}) -> + Modules. + +%% @doc modules to be excluded from the release +-spec exclude_modules(t(), [{App::atom(), [Module::atom()]}]) -> t(). +exclude_modules(State, SkipModules) -> + State#state_t{exclude_modules=SkipModules}. + -spec debug_info(t()) -> keep | strip. debug_info(#state_t{debug_info=DebugInfo}) -> DebugInfo. @@ -270,6 +290,14 @@ vm_args(State, VmArgs) -> State#state_t{vm_args=VmArgs}. +-spec vm_args_src(t()) -> file:filename() | undefined. +vm_args_src(#state_t{vm_args_src=VmArgs}) -> + VmArgs. + +-spec vm_args_src(t(), undefined | file:filename()) -> t(). +vm_args_src(State, VmArgs) -> + State#state_t{vm_args_src=VmArgs}. + -spec sys_config(t()) -> file:filename() | false | undefined. sys_config(#state_t{sys_config=SysConfig}) -> SysConfig. @@ -278,6 +306,14 @@ sys_config(State, SysConfig) -> State#state_t{sys_config=SysConfig}. +-spec sys_config_src(t()) -> file:filename() | undefined. +sys_config_src(#state_t{sys_config_src=SysConfigSrc}) -> + SysConfigSrc. + +-spec sys_config_src(t(), file:filename() | undefined) -> t(). +sys_config_src(State, SysConfigSrc) -> + State#state_t{sys_config_src=SysConfigSrc}. + -spec root_dir(t()) -> file:filename() | undefined. root_dir(#state_t{root_dir=RootDir}) -> RootDir. @@ -442,6 +478,14 @@ Provider = providers:get_provider(Target, Providers), providers:hooks(Provider). +-spec warnings_as_errors(t()) -> boolean(). +warnings_as_errors(#state_t{warnings_as_errors=WarningsAsErrors}) -> + WarningsAsErrors. + +-spec warnings_as_errors(t(), boolean()) -> t(). +warnings_as_errors(State, WarningsAsErrors) -> + State#state_t{warnings_as_errors=WarningsAsErrors}. + %% =================================================================== %% Internal functions %% ===================================================================
View file
relx-3.26.0.tar.gz/src/rlx_string.erl
Added
@@ -0,0 +1,23 @@ +%% Compatibility module for the string API changes between +%% OTP-19 and OTP-21, where Unicode support means the deprecation +%% of a lot of string functions. +-module(rlx_string). +-export([concat/2, lexemes/2, join/2]). + +-ifdef(unicode_str). +concat(Str1, Str2) -> unicode:characters_to_list([Str1,Str2]). +lexemes(Str, Separators) -> string:lexemes(Str, Separators). +-else. +concat(Str1, Str2) -> string:concat(Str1, Str2). +lexemes(Str, Separators) -> string:tokens(Str, Separators). +-endif. + +%% string:join/2 copy; string:join/2 is getting obsoleted +%% and replaced by lists:join/2, but lists:join/2 is too new +%% for version support (only appeared in 19.0) so it cannot be +%% used. Instead we just adopt join/2 locally and hope it works +%% for most unicode use cases anyway. +join([], Sep) when is_list(Sep) -> + []; +join([H|T], Sep) -> + H ++ lists:append([Sep ++ X || X <- T]).
View file
relx-3.26.0.tar.gz/src/rlx_topo.erl
Added
@@ -0,0 +1,190 @@ +%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%------------------------------------------------------------------- +%%% @author Joe Armstrong +%%% @author Eric Merritt +%%% @author Konstantin Tcepliaev +%%% @doc +%%% This is a pretty simple topological sort for erlang. It was +%%% originally written for ermake by Joe Armstrong back in '98. It +%%% has been pretty heavily modified by Eric Merritt since '06 and modified again for Relx. +%%% Konstantin Tcepliaev rewrote the algorithm in 2017. +%%% +%%% A partial order on the set S is a set of pairs {Xi,Xj} such that +%%% some relation between Xi and Xj is obeyed. +%%% +%%% A topological sort of a partial order is a sequence of elements +%%% [X1, X2, X3 ...] such that if whenever {Xi, Xj} is in the partial +%%% order i < j +%%% +%%% This particular implementation guarantees that nodes closer to +%%% the top level of the graph will be put as close as possible to +%%% the beginning of the resulting list - this ensures that dependencies +%%% are started as late as possible, and top-level apps are started +%%% as early as possible. +%%% @end +%%%------------------------------------------------------------------- +-module(rlx_topo). + +-export([sort_apps/1, + format_error/1]). + +-include("relx.hrl"). + +%%==================================================================== +%% API +%%==================================================================== + +%% @doc This only does a topo sort on the list of applications and +%% assumes that there is only *one* version of each app in the list of +%% applications. This implies that you have already done the +%% constraint solve before you pass the list of apps here to be +%% sorted. +-spec sort_apps([rlx_app_info:t()]) -> + {ok, [rlx_app_info:t()]} | + relx:error(). +sort_apps(Apps) -> + AppDeps = [{rlx_app_info:name(App), + rlx_app_info:active_deps(App) ++ rlx_app_info:library_deps(App)} + || App <- Apps], + {AppNames, _} = lists:unzip(AppDeps), + case lists:foldl(fun iterator/2, {ok, [], AppDeps, []}, AppNames) of + {ok, Names, _, _} -> + {ok, names_to_apps(lists:reverse(Names), Apps)}; + E -> + E + end. + +%% @doc nicely format the error from the sort. +-spec format_error(Reason::term()) -> iolist(). +format_error({cycle, App, Path}) -> + ["Cycle detected in dependency graph, this must be resolved " + "before we can continue:\n", + rlx_util:indent(2), + [[erlang:atom_to_list(A), " -> "] || A <- lists:reverse(Path)], + erlang:atom_to_list(App)]. + +%%==================================================================== +%% Internal Functions +%%==================================================================== + +-type name() :: AppName::atom(). +-type app_dep() :: {AppName::name(), [DepName::name()]}. +-type iterator_state() :: {ok, [Acc::name()], + [Apps::app_dep()], + [Path::name()]}. + +-spec iterator(name(), iterator_state() | relx:error()) -> + iterator_state() | relx:error(). +iterator(App, {ok, Acc, Apps, Path}) -> + case lists:member(App, Acc) of + false -> + %% haven't seen this app yet + case lists:keytake(App, 1, Apps) of + {value, {App, Deps}, NewApps} -> + DepInit = {ok, Acc, NewApps, [App | Path]}, + %% recurse over deps + case lists:foldl(fun iterator/2, DepInit, Deps) of + {ok, DepAcc, DepApps, _} -> + {ok, [App | DepAcc], DepApps, Path}; + Error -> + Error + end; + false -> + %% we have visited this app before, + %% that means there's a cycle + ?RLX_ERROR({cycle, App, Path}) + end; + true -> + %% this app and its deps were already processed + {ok, Acc, Apps, Path} + end; +iterator(_, Error) -> + Error. + +-spec names_to_apps([atom()], [rlx_app_info:t()]) -> [rlx_app_info:t()]. +names_to_apps(Names, Apps) -> + [find_app_by_name(Name, Apps) || Name <- Names]. + +-spec find_app_by_name(atom(), [rlx_app_info:t()]) -> rlx_app_info:t(). +find_app_by_name(Name, Apps) -> + {ok, App1} = + ec_lists:find(fun(App) -> + rlx_app_info:name(App) =:= Name + end, Apps), + App1. + +%%==================================================================== +%% Tests +%%==================================================================== +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +topo_apps_cycle_test() -> + {ok, App1} = rlx_app_info:new(app1, "0.1", "/no-dir", [app2], [stdlib]), + {ok, App2} = rlx_app_info:new(app2, "0.1", "/no-dir", [app1], []), + Apps = [App1, App2], + ?assertMatch({error, {_, {cycle, app1, [app2, app1]}}}, + sort_apps(Apps)). + +topo_apps_good_test() -> + Apps = [App || + {ok, App} <- + [rlx_app_info:new(app1, "0.1", "/no-dir", [app2, zapp1], [stdlib, kernel]), + rlx_app_info:new(app2, "0.1", "/no-dir", [app3], []), + rlx_app_info:new(app3, "0.1", "/no-dir", [kernel], []), + rlx_app_info:new(zapp1, "0.1", "/no-dir", [app2,app3,zapp2], []), + rlx_app_info:new(stdlib, "0.1", "/no-dir", [], []), + rlx_app_info:new(kernel, "0.1", "/no-dir", [], []), + rlx_app_info:new(zapp2, "0.1", "/no-dir", [], [])]], + {ok, Sorted} = sort_apps(Apps), + ?assertMatch([kernel, app3, app2, zapp2, zapp1, stdlib, app1], + [rlx_app_info:name(App) || App <- Sorted]). + +topo_apps_1_test() -> + Apps = [App || + {ok, App} <- + [rlx_app_info:new(app0, "0.1", "/no-dir", [], [stdlib, dep1, dep2, dep3]), + rlx_app_info:new(app1, "0.1", "/no-dir", [], [stdlib, kernel]), + rlx_app_info:new(dep1, "0.1", "/no-dir", [], []), + rlx_app_info:new(dep2, "0.1", "/no-dir", [], []), + rlx_app_info:new(dep3, "0.1", "/no-dir", [], []), + rlx_app_info:new(stdlib, "0.1", "/no-dir", [], []), + rlx_app_info:new(kernel, "0.1", "/no-dir", [], [])]], + {ok, Sorted} = sort_apps(Apps), + ?assertMatch([stdlib, dep1, dep2, dep3, app0, kernel, app1], + [rlx_app_info:name(App) || App <- Sorted]). + +topo_apps_2_test() -> + Apps = [App || + {ok, App} <- + [rlx_app_info:new(app1, "0.1", "/no-dir", [app2, app3, app4, app5, + stdlib, kernel], + []), + rlx_app_info:new(app2, "0.1", "/no-dir", [stdlib, kernel], []), + rlx_app_info:new(app3, "0.1", "/no-dir", [stdlib, kernel], []), + rlx_app_info:new(app4, "0.1", "/no-dir", [stdlib, kernel], []), + rlx_app_info:new(app5, "0.1", "/no-dir", [stdlib, kernel], []), + rlx_app_info:new(stdlib, "0.1", "/no-dir", [], []), + rlx_app_info:new(kernel, "0.1", "/no-dir", [], []) + ]], + {ok, Sorted} = sort_apps(Apps), + ?assertMatch([stdlib, kernel, app2, + app3, app4, app5, app1], + [rlx_app_info:name(App) || App <- Sorted]). + +-endif.
View file
relx-3.21.1.tar.gz/src/rlx_util.erl -> relx-3.26.0.tar.gz/src/rlx_util.erl
Changed
@@ -41,6 +41,8 @@ intensity/0, symlink_or_copy/2]). +-export([os_type/1]). + -define(DFLT_INTENSITY, high). -define(ONE_LEVEL_INDENT, " "). %%============================================================================ @@ -326,6 +328,31 @@ Mode end. +os_type(State) -> + case include_erts_is_win32(State) of + true -> {win32,nt}; + false -> os:type() + end. + +include_erts_is_win32(State) -> + case rlx_state:get(State, include_erts, true) of + true -> false; + false -> false; + Path -> is_win32_erts(Path,State) + end. + +is_win32_erts(Path,State) -> + case filelib:wildcard(filename:join([Path,"bin","erl.exe"])) of + [] -> false; + _ -> + ec_cmd_log:info(rlx_state:log(State), + "Including Erts is win32 ~n", []), + true + end. + + + + %%%=================================================================== %%% Test Functions %%%===================================================================
View file
relx-3.21.1.tar.gz/test/rlx_archive_SUITE.erl -> relx-3.26.0.tar.gz/test/rlx_archive_SUITE.erl
Changed
@@ -249,6 +249,8 @@ TestDirFull = filename:join([LibDir1, TestDir]), TestFileFull = filename:join(TestDirFull, TestFile), SecondTestDir = "second_test_dir", + TestScript = "test_script", + TestScript2 = "test_script2", rlx_test_utils:write_config(ConfigFile, [{overlay_vars, [OverlayVars1, OverlayVars2]}, {overlay, [{mkdir, "{{target_dir}}/fooo"}, @@ -260,9 +262,17 @@ "{{target_dir}}/{{yahoo}}/vars.link.config"}, {copy, TestDirFull, "{{target_dir}}/"++SecondTestDir++"/"}, + {copy, TestScript, + "{{target_dir}}/"++SecondTestDir++"/"++TestScript}, + {chmod, 8#00700, + "{{target_dir}}/"++SecondTestDir++"/"++TestScript}, + {copy, TestScript2, + "{{target_dir}}/"++SecondTestDir++"/"++TestScript2}, + {chmod, "{{test_script_perm}}", + "{{target_dir}}/"++SecondTestDir++"/"++TestScript2}, {template, Template, "{{target_dir}}/test_template_resolved"}, - {template, Template, + {template, Template, "bin/{{default_release_name}}-{{default_release_version}}"}]}, {release, {foo, "0.0.1"}, [goal_app_1, @@ -272,7 +282,8 @@ rlx_test_utils:write_config(VarsFile1, [{yahoo, "yahoo"}, {yahoo2, [{foo, "bar"}]}, {foo_yahoo, "foo_{{yahoo}}"}, - {foo_dir, "foodir"}]), + {foo_dir, "foodir"}, + {test_script_perm,8#00770}]), VarsFile2 = filename:join([LibDir1, "vars2.config"]), rlx_test_utils:write_config(VarsFile2, [{google, "yahoo"}, @@ -283,6 +294,11 @@ rlx_test_utils:write_config(VarsFile3, [{google, "yahoo"}, {yahoo4, "{{yahoo}}/{{yahoo2}}4"}]), + TestScriptFile = filename:join([LibDir1,TestScript]), + ok = file:write_file(TestScriptFile, <<"#!/bin/sh\necho \"hello world\"">>), + TestScriptFile2 = filename:join([LibDir1,TestScript2]), + ok = file:write_file(TestScriptFile2, <<"#!/bin/sh\necho \"hello world 2\"">>), + ok = rlx_util:mkdir_p(TestDirFull), ok = file:write_file(TestFileFull, rlx_test_utils:test_template_contents()), @@ -312,6 +328,19 @@ ?assert(lists:member({goal_app_2, "0.0.1"}, AppSpecs)), ?assert(lists:member({lib_dep_1, "0.0.1", load}, AppSpecs)), + % check that the chmod of our file worked + ChmodedFile = filename:join([OutputDir,"foo",SecondTestDir,TestScript]), + {ok, ChmodedInfo} = file:read_file_info (ChmodedFile), + % mode from file_info is a bitmask which might have other bits set, but + % if we mask those we care about and check we should get true, see details + % here http://stackoverflow.com/questions/13183838/how-to-use-erlang-fileread-file-info-permissions-mode-info + ?assert(ChmodedInfo#file_info.mode band 8#00700 =:= 8#00700), + + % check that the templated chmod of our file worked + ChmodedFile2 = filename:join([OutputDir,"foo",SecondTestDir,TestScript2]), + {ok, ChmodedInfo2} = file:read_file_info (ChmodedFile2), + ?assert(ChmodedInfo2#file_info.mode band 8#00770 =:= 8#00770), + TarFile = filename:join([OutputDir, "foo", "foo-0.0.1.tar.gz"]), {ok, Files} = erl_tar:table(TarFile, [compressed]), ?assert(lists:any(fun(X) -> re:run(X, "lib/stdlib-.*/src/.*") =/= nomatch end, Files)),
View file
relx-3.21.1.tar.gz/test/rlx_depsolver_tester.erl -> relx-3.26.0.tar.gz/test/rlx_depsolver_tester.erl
Changed
@@ -406,7 +406,7 @@ process_line(Device, io:get_line(Device, ""), Acc); process_line(Device, [$\s | Rest], [{Pkg, Vsn, Deps} | Acc]) -> - [DepPackage, Type, DepVsn] = string:tokens(Rest, " \n"), + [DepPackage, Type, DepVsn] = rlx_string:lexemes(Rest, " \n"), Dep = case Type of "=" -> @@ -417,7 +417,7 @@ process_line(Device, io:get_line(Device, ""), [{Pkg, Vsn, [Dep | Deps]} | Acc]); process_line(Device, Pkg, Acc) -> - [Package, Vsn] = string:tokens(Pkg, " \n"), + [Package, Vsn] = rlx_string:lexemes(Pkg, " \n"), process_line(Device, io:get_line(Device, ""), [{Package, Vsn, []} | Acc]). @@ -427,7 +427,7 @@ end, rlx_depsolver:new_graph(), Pkgs). get_constraints(ConLine) -> - AppVsns = string:tokens(ConLine, " \n"), + AppVsns = rlx_string:lexemes(ConLine, " \n"), lists:map(fun(AppCon) -> parse_app(AppCon, []) end, AppVsns).
View file
relx-3.21.1.tar.gz/test/rlx_depsolver_tests.erl -> relx-3.26.0.tar.gz/test/rlx_depsolver_tests.erl
Changed
@@ -42,9 +42,9 @@ case rlx_depsolver:solve(Dom0, [{app1, "0.1"}]) of - {ok,[{app3,{{0,3},{[],[]}}}, + {ok,[{app1,{{0,1},{[],[]}}}, {app2,{{0,2},{[],[<<"build">>,33]}}}, - {app1,{{0,1},{[],[]}}}]} -> + {app3,{{0,3},{[],[]}}}]} -> ok; E -> erlang:throw({invalid_result, E}) @@ -71,10 +71,10 @@ X = rlx_depsolver:solve(Dom0, [{app1, "0.1"}, {app2, "0.3"}]), - ?assertMatch({ok, [{app3,{{0,3},{[],[]}}}, - {app2,{{0,3},{[],[]}}}, + ?assertMatch({ok, [{app1,{{0,1},{[],[]}}}, {app4,{{0,2},{[],[]}}}, - {app1,{{0,1},{[],[]}}}]}, + {app2,{{0,3},{[],[]}}}, + {app3,{{0,3},{[],[]}}}]}, X). third_test() -> @@ -107,19 +107,19 @@ {"2.0.0", []}, {"6.0.0", []}]}]), - ?assertMatch({ok, [{app5,{{6,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{6,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{3,0},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{6,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{6,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [{app1, "3.0"}])), - ?assertMatch({ok, [{app5,{{6,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{6,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{3,0},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{6,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{6,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [app1])). fail_test() -> @@ -176,18 +176,18 @@ {"2.0.0", []}, {"6.0.0", []}]}]), - ?assertMatch({ok, [{app5,{{2,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{5,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{3,0},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{5,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{2,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [{app1, "3.0"}])), - ?assertMatch({ok, [{app5,{{2,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{5,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{3,0},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{5,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{2,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [app1, app2, app5])). @@ -196,7 +196,7 @@ Dom0 = rlx_depsolver:add_packages(rlx_depsolver:new_graph(), [{app1, [{"0.1.0", [app2]}]}, {app2, [{"0.0.1", [app1]}]}]), - ?assertMatch({ok, [{app1,{{0,1,0},{[],[]}}},{app2,{{0,0,1},{[],[]}}}]}, + ?assertMatch({ok, [{app2,{{0,0,1},{[],[]}}},{app1,{{0,1,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [{app1, "0.1.0"}])). conflicting_failing_test() -> @@ -217,12 +217,12 @@ Ret = rlx_depsolver:solve(Dom0, [app1, app3]), _ = rlx_depsolver:format_error(Ret), ?assertMatch({error, - [{[{[app1], + [{[{[app3], + [{app3,{{0,1,0},{[],[]}}},[[{app5,{{6,0,0},{[],[]}}}]]]}, + {[app1], [{app1,{{3,0},{[],[]}}}, - [[{app4,{{5,0,0},{[],[]}}}], - [{app2,{{0,0,1},{[],[]}}},[[{app4,{{5,0,0},{[],[]}}}]]]]]}, - {[app3], - [{app3,{{0,1,0},{[],[]}}},[[{app5,{{6,0,0},{[],[]}}}]]]}], + [[{app2,{{0,0,1},{[],[]}}},[[{app4,{{5,0,0},{[],[]}}}]]], + [{app4,{{5,0,0},{[],[]}}}]]]}], [{{app4,{{5,0,0},{[],[]}}},[{app5,{{2,0,0},{[],[]}}}]}, {{app1,{{3,0},{[],[]}}},[{app5,{{2,0,0},{[],[]}},'='}]}]}]}, Ret). @@ -259,11 +259,11 @@ {"0.3.0", []}, {"2.0.0", []}, {"6.0.0", []}]}]), - ?assertMatch({ok, [{app5,{{6,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{6,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{2,1,5},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{6,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{6,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [{app1, "3.0"}])). pessimistic_major_minor_test() -> @@ -297,11 +297,11 @@ {"0.3.0", []}, {"2.0.0", []}, {"6.0.0", []}]}]), - ?assertMatch({ok, [{app5,{{6,0,0},{[],[]}}}, - {app3,{{0,1,3},{[],[]}}}, - {app4,{{6,0,0},{[],[]}}}, + ?assertMatch({ok, [{app1,{{3,0},{[],[]}}}, {app2,{{2,2},{[],[]}}}, - {app1,{{3,0},{[],[]}}}]}, + {app4,{{6,0,0},{[],[]}}}, + {app3,{{0,1,3},{[],[]}}}, + {app5,{{6,0,0},{[],[]}}}]}, rlx_depsolver:solve(Dom0, [{app1, "3.0"}])). filter_versions_test() ->
View file
relx-3.21.1.tar.gz/test/rlx_eunit_SUITE.erl -> relx-3.26.0.tar.gz/test/rlx_eunit_SUITE.erl
Changed
@@ -23,7 +23,8 @@ all/0, depsolver/1, goal/1, - app_info/1]). + app_info/1, + topo/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -38,7 +39,7 @@ ok. all() -> - [depsolver, goal, app_info]. + [depsolver, goal, app_info, topo]. depsolver(_Config) -> ok = eunit:test(rlx_depsolver). @@ -48,3 +49,6 @@ app_info(_Config) -> ok = eunit:test(rlx_app_info). + +topo(_Config) -> + ok = eunit:test(rlx_topo).
View file
relx-3.21.1.tar.gz/test/rlx_extended_bin_SUITE.erl -> relx-3.26.0.tar.gz/test/rlx_extended_bin_SUITE.erl
Changed
@@ -22,13 +22,41 @@ end_per_suite/1, init_per_testcase/2, all/0, + start_sname_in_other_argsfile/1, + start_preserves_arguments/1, + start_nodetool_with_data_from_argsfile/1, + start_upgrade_escript_with_argsfile_data/1, + start_fail_when_no_name/1, + start_fail_when_multiple_names/1, + start_fail_when_missing_argsfile/1, + start_fail_when_nonreadable_argsfile/1, + start_fail_when_relative_argsfile/1, + start_fail_when_circular_argsfiles/1, ping/1, + shortname_ping/1, + longname_ping/1, attach/1, pid/1, restart/1, reboot/1, escript/1, - remote_console/1]). + remote_console/1, shortname_remote_console/1, + replace_os_vars/1, + replace_os_vars_sys_config_vm_args_src/1, + replace_os_vars_multi_node/1, + replace_os_vars_included_config/1, + replace_os_vars_custom_location/1, + replace_os_vars_dev_mode/1, + replace_os_vars_twice/1, + custom_start_script_hooks/1, + builtin_wait_for_vm_start_script_hook/1, + builtin_pid_start_script_hook/1, + builtin_wait_for_process_start_script_hook/1, + mixed_custom_and_builtin_start_script_hooks/1, + builtin_status_script/1, custom_status_script/1, + extension_script/1, + extension_script_exit_code/1, + extension_script_fail_when_no_exit/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -53,22 +81,111 @@ {state, State1} | Config]. all() -> - [ping, attach, pid, restart, reboot, escript, - remote_console]. + [start_sname_in_other_argsfile, start_preserves_arguments, start_nodetool_with_data_from_argsfile, + start_upgrade_escript_with_argsfile_data, start_fail_when_no_name, start_fail_when_multiple_names, + start_fail_when_missing_argsfile, start_fail_when_nonreadable_argsfile, + start_fail_when_relative_argsfile, start_fail_when_circular_argsfiles, + ping, shortname_ping, longname_ping, attach, pid, restart, reboot, escript, + remote_console, shortname_remote_console, replace_os_vars, replace_os_vars_sys_config_vm_args_src, replace_os_vars_multi_node, + replace_os_vars_included_config, + replace_os_vars_custom_location, replace_os_vars_dev_mode, replace_os_vars_twice, custom_start_script_hooks, + builtin_wait_for_vm_start_script_hook, builtin_pid_start_script_hook, + builtin_wait_for_process_start_script_hook, mixed_custom_and_builtin_start_script_hooks, + builtin_status_script, custom_status_script, + extension_script, + extension_script_exit_code, + extension_script_fail_when_no_exit]. ping(Config) -> LibDir1 = proplists:get_value(lib1, Config), + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + %% a ping should fail after stopping a node + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + +shortname_ping(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + VmArgs = filename:join([LibDir1, "vm.args"]), + + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {vm_args, VmArgs}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + ec_file:write(VmArgs, "-sname foo\n\n" + "-setcookie cookie\n"), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + %% a ping should fail after stopping a node + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + +longname_ping(Config) -> + LibDir1 = proplists:get_value(lib1, Config), rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), ConfigFile = filename:join([LibDir1, "relx.config"]), + VmArgs = filename:join([LibDir1, "vm.args"]), + rlx_test_utils:write_config(ConfigFile, [{release, {foo, "0.0.1"}, [goal_app]}, {lib_dirs, [filename:join(LibDir1, "*")]}, + {vm_args, VmArgs}, {generate_start_script, true}, {extended_start_script, true} ]), + + ec_file:write(VmArgs, "-name foo\n\n" + "-setcookie cookie\n"), OutputDir = filename:join([proplists:get_value(priv_dir, Config), rlx_test_utils:create_random_name("relx-output")]), @@ -87,7 +204,7 @@ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), %% a ping should fail after stopping a node - {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). attach(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -121,7 +238,7 @@ {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo attach", "&"])), timer:sleep(2000), {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), - {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). pid(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -154,7 +271,7 @@ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), {ok, _Pid} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), - {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). restart(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -191,7 +308,7 @@ timer:sleep(2000), {ok, Pid2} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), - {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), ?assertEqual(Pid1, Pid2). reboot(Config) -> @@ -231,7 +348,7 @@ timer:sleep(2000), {ok, Pid2} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), - {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {error, 1, _} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), ?assertNotEqual(Pid1, Pid2).
View file
relx-3.21.1.tar.gz/test/rlx_release_SUITE.erl -> relx-3.26.0.tar.gz/test/rlx_release_SUITE.erl
Changed
@@ -46,14 +46,18 @@ make_relup_release2/1, make_one_app_top_level_release/1, make_dev_mode_release/1, + make_dev_mode_template_release/1, make_config_script_release/1, make_release_twice/1, make_release_twice_dev_mode/1, make_erts_release/1, make_erts_config_release/1, make_included_nodetool_release/1, + make_not_included_nodetool_release/1, make_src_release/1, - make_excluded_src_release/1]). + make_excluded_src_release/1, + make_exclude_modules_release/1, + make_release_with_sys_config_vm_args_src/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -85,10 +89,12 @@ make_implicit_config_release, make_rerun_overridden_release, overlay_release, make_goalless_release, make_depfree_release, make_invalid_config_release, make_relup_release, make_relup_release2, - make_one_app_top_level_release, make_dev_mode_release, + make_one_app_top_level_release, make_dev_mode_release, make_dev_mode_template_release, make_config_script_release, make_release_twice, make_release_twice_dev_mode, - make_erts_release, make_erts_config_release, make_included_nodetool_release, - make_src_release, make_excluded_src_release]. + make_erts_release, make_erts_config_release, + make_included_nodetool_release, make_not_included_nodetool_release, + make_src_release, make_excluded_src_release, make_exclude_modules_release, + make_release_with_sys_config_vm_args_src]. add_providers(Config) -> LibDir1 = proplists:get_value(lib1, Config), @@ -672,7 +678,8 @@ {template, Template, "{{target_dir}}/test_template_resolved"}, {template, Template, - "bin/{{default_release_name}}-{{default_release_version}}"}]}, + "bin/{{default_release_name}}-{{default_release_version}}"}, + {copy, "{{erts_dir}}/bin/erl", "bin/copy.erl"}]}, {release, {foo, "0.0.1"}, [goal_app_1, goal_app_2]}]), @@ -724,6 +731,7 @@ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "foodir", "vars1.config"]))), ?assert(ec_file:exists(filename:join([OutputDir, "foo", "yahoo", "vars1.config"]))), ?assert(ec_file:exists(filename:join([OutputDir, "foo", SecondTestDir, TestDir, TestFile]))), + ?assert(ec_file:exists(filename:join([OutputDir, "foo", "bin", "copy.erl"]))), TemplateData = case file:consult(filename:join([OutputDir, "foo", "test_template_resolved"])) of {ok, Details} -> @@ -1010,9 +1018,9 @@ ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "goal_app_2-0.0.1"]))), ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "lib_dep_1-0.0.1"]))), ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "releases", "0.0.1", - "sys.config.orig"]))), + "sys.config"]))), ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "releases", "0.0.1", - "vm.args.orig"]))); + "vm.args"]))); {win32, _} -> ?assert(filelib:is_dir(filename:join([OutputDir, "foo", "lib", "non_goal_1-0.0.1"]))), ?assert(filelib:is_dir(filename:join([OutputDir, "foo", "lib", "non_goal_2-0.0.1"]))), @@ -1025,6 +1033,66 @@ "vm.args"]))) end. +make_dev_mode_template_release(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", + [stdlib,kernel,non_goal_1], []), + rlx_test_utils:create_app(LibDir1, "lib_dep_1", "0.0.1", + [stdlib,kernel], []), + rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.1", + [stdlib,kernel,goal_app_1,non_goal_2], []), + rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", + [stdlib,kernel], [lib_dep_1]), + rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", + [stdlib,kernel], []), + + SysConfig = filename:join([LibDir1, "config", "sys.config"]), + SysConfigTerm = [{this_is_a_test, "yup it is"}, + {this_is_an_overlay_var, "{{var1}}"}], + rlx_test_utils:write_config(SysConfig, SysConfigTerm), + + VmArgs = filename:join([LibDir1, "config", "vm.args"]), + ec_file:write(VmArgs, "-sname {{nodename}}"), + + VarsFile1 = filename:join([LibDir1, "config", "vars1.config"]), + rlx_test_utils:write_config(VarsFile1, [{var1, "indeed it is"}, + {nodename, "testnode"}]), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{dev_mode, true}, + {sys_config, SysConfig}, + {vm_args, VmArgs}, + {overlay_vars, [VarsFile1]}, + {overlay, [ + {template, "config/sys.config", + "releases/{{release_version}}/sys.config"}, + {template, "config/vm.args", + "releases/{{release_version}}/vm.args"}]}, + {release, {foo, "0.0.1"}, + [goal_app_1, + goal_app_2]}]), + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + {ok, State} = relx:do(undefined, undefined, [], [LibDir1], 3, + OutputDir, ConfigFile), + [{{foo, "0.0.1"}, _Release}] = ec_dictionary:to_list(rlx_state:realized_releases(State)), + + ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "non_goal_1-0.0.1"]))), + ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "non_goal_2-0.0.1"]))), + ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "goal_app_1-0.0.1"]))), + ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "goal_app_2-0.0.1"]))), + ?assert(ec_file:is_symlink(filename:join([OutputDir, "foo", "lib", "lib_dep_1-0.0.1"]))), + ?assert(not ec_file:is_symlink(filename:join([OutputDir, "foo", "releases", "0.0.1", + "sys.config"]))), + ?assert(not ec_file:is_symlink(filename:join([OutputDir, "foo", "releases", "0.0.1", + "vm.args"]))), + %% ensure that the original sys.config didn't get overwritten + ?assertMatch({ok, SysConfigTerm}, file:consult(SysConfig)), + %% ensure that the original vm.args didn't get overwritten + ?assertMatch({ok, <<"-sname {{nodename}}">>}, ec_file:read(VmArgs)). + make_config_script_release(Config) -> LibDir1 = proplists:get_value(lib1, Config), FooRoot = filename:join([LibDir1, "foodir1", "foodir2"]), @@ -1246,6 +1314,36 @@ OutputDir, ConfigFile), [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rlx_state:realized_releases(State)), AppSpecs = rlx_release:applications(Release), + ?assert(ec_file:exists(filename:join([OutputDir, "foo", "bin", "nodetool"]))), + ?assert(lists:keymember(stdlib, 1, AppSpecs)), + ?assert(lists:keymember(kernel, 1, AppSpecs)), + ?assertEqual(ErtsVsn, rlx_release:erts(Release)). + +make_not_included_nodetool_release(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [kernel,stdlib], []), + rlx_test_utils:create_app(LibDir1, "lib_dep_1", "0.0.1", [kernel,stdlib], []), + rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.1", [kernel,stdlib], []), + rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [kernel,stdlib], []), + rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", [kernel,stdlib], []), + + ErtsVsn = erlang:system_info(version), + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, {erts, ErtsVsn}, + [goal_app_1]}, + {extended_start_script, true}, + {include_nodetool, false}]), + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + {ok, State} = relx:do(undefined, undefined, [], [LibDir1], 3, + OutputDir, ConfigFile), + [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rlx_state:realized_releases(State)), + AppSpecs = rlx_release:applications(Release), + %% extended start script needs nodetool to work, so the + %% {include_nodetool, false} option is simply ignored + ?assert(ec_file:exists(filename:join([OutputDir, "foo", "bin", "nodetool"]))), ?assert(lists:keymember(stdlib, 1, AppSpecs)), ?assert(lists:keymember(kernel, 1, AppSpecs)), ?assertEqual(ErtsVsn, rlx_release:erts(Release)). @@ -1308,6 +1406,113 @@ ?assert(not ec_file:exists(filename:join([OutputDir, "foo", "lib", "goal_app_1-0.0.1", "src"]))). +%% Test to ensure that excluded modules don't end up in the release +make_exclude_modules_release(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [stdlib,kernel, non_goal_1], []), + rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app_1]}, + {exclude_modules, [{non_goal_1, [a_real_beamnon_goal_1]}]}]), + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + {ok, Cwd} = file:get_cwd(), + {ok, State} = relx:do(Cwd, undefined, undefined, [], [LibDir1], 3, + OutputDir, [], + ConfigFile), + [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rlx_state:realized_releases(State)), + AppSpecs = rlx_release:applications(Release), + ?assert(lists:keymember(stdlib, 1, AppSpecs)), + ?assert(lists:keymember(kernel, 1, AppSpecs)), + ?assert(lists:member({goal_app_1, "0.0.1"}, AppSpecs)), + %% ensure that the excluded module beam file didn't get copied + ?assert(not ec_file:exists(filename:join([OutputDir, "foo", "lib", + "non_goal_1-0.0.1", "ebin",
View file
relx-3.21.1.tar.gz/test/rlx_test_utils.erl -> relx-3.26.0.tar.gz/test/rlx_test_utils.erl
Changed
@@ -6,27 +6,33 @@ create_app(Dir, Name, Vsn, Deps, LibDeps) -> AppDir = filename:join([Dir, Name ++ "-" ++ Vsn]), - write_app_file(AppDir, Name, Vsn, Deps, LibDeps), + write_app_file(AppDir, Name, Vsn, app_modules(Name), Deps, LibDeps), write_src_file(AppDir, Name), - write_beam_file(AppDir, Name), + compile_src_files(AppDir), + rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, + Deps, []). + +create_full_app(Dir, Name, Vsn, Deps, LibDeps) -> + AppDir = filename:join([Dir, Name ++ "-" ++ Vsn]), + write_full_app_files(AppDir, Name, Vsn, Deps, LibDeps), + compile_src_files(AppDir), rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, Deps, []). create_empty_app(Dir, Name, Vsn, Deps, LibDeps) -> AppDir = filename:join([Dir, Name ++ "-" ++ Vsn]), - write_app_file(AppDir, Name, Vsn, Deps, LibDeps), + write_app_file(AppDir, Name, Vsn, [], Deps, LibDeps), rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, Deps, []). -write_beam_file(Dir, Name) -> - Beam = filename:join([Dir, "ebin", "not_a_real_beam" ++ Name ++ ".beam"]), - ok = filelib:ensure_dir(Beam), - ok = ec_file:write_term(Beam, testing_purposes_only). +app_modules(Name) -> + [list_to_atom(M ++ Name) || + M <- ["a_real_beam"]]. write_src_file(Dir, Name) -> - Src = filename:join([Dir, "src", "not_a_real_beam" ++ Name ++ ".erl"]), + Src = filename:join([Dir, "src", "a_real_beam" ++ Name ++ ".erl"]), ok = filelib:ensure_dir(Src), - ok = ec_file:write_term(Src, testing_purposes_only). + ok = file:write_file(Src, beam_file_contents("a_real_beam"++Name)). write_appup_file(AppInfo, DownVsn) -> Dir = rlx_app_info:dir(AppInfo), @@ -36,20 +42,112 @@ ok = filelib:ensure_dir(Filename), ok = ec_file:write_term(Filename, {Vsn, [{DownVsn, []}], [{DownVsn, []}]}). -write_app_file(Dir, Name, Version, Deps, LibDeps) -> +write_app_file(Dir, Name, Version, Modules, Deps, LibDeps) -> Filename = filename:join([Dir, "ebin", Name ++ ".app"]), ok = filelib:ensure_dir(Filename), - ok = ec_file:write_term(Filename, get_app_metadata(Name, Version, Deps, LibDeps)). + ok = ec_file:write_term(Filename, get_app_metadata(Name, Version, Modules, + Deps, LibDeps)). -get_app_metadata(Name, Vsn, Deps, LibDeps) -> +compile_src_files(Dir) -> + %% compile all *.erl files in src to ebin + SrcDir = filename:join([Dir, "src"]), + OutputDir = filename:join([Dir, "ebin"]), + lists:foreach(fun(SrcFile) -> + {ok, _} = compile:file(SrcFile, [{outdir, OutputDir}, + return_errors]) + end, ec_file:find(SrcDir, "\\.erl")), + ok. + +get_app_metadata(Name, Vsn, Modules, Deps, LibDeps) -> {application, erlang:list_to_atom(Name), [{description, ""}, {vsn, Vsn}, - {modules, []}, + {modules, Modules}, {included_applications, LibDeps}, {registered, []}, {applications, Deps}]}. +write_full_app_files(Dir, Name, Vsn, Deps, LibDeps) -> + %% write out the .app file + AppFilename = filename:join([Dir, "ebin", Name ++ ".app"]), + ok = filelib:ensure_dir(AppFilename), + ok = ec_file:write_term(AppFilename, + get_full_app_metadata(Name, Vsn, Deps, LibDeps)), + %% write out the _app.erl file + ApplicationFilename = filename:join([Dir, "src", Name ++ "_app.erl"]), + ok = filelib:ensure_dir(ApplicationFilename), + ok = file:write_file(ApplicationFilename, full_application_contents(Name)), + %% write out the supervisor + SupervisorFilename = filename:join([Dir, "src", Name ++ "_sup.erl"]), + ok = filelib:ensure_dir(SupervisorFilename), + ok = file:write_file(SupervisorFilename, supervisor_contents(Name)), + %% and finally the gen_server + GenServerFilename = filename:join([Dir, "src", Name ++ "_srv.erl"]), + ok = filelib:ensure_dir(GenServerFilename), + ok = file:write_file(GenServerFilename, gen_server_contents(Name)), + ok. + +get_full_app_metadata(Name, Vsn, Deps, LibDeps) -> + {application, erlang:list_to_atom(Name), + [{description, ""}, + {vsn, Vsn}, + {modules, [goal_app_app,goal_app_sup,goal_app_srv]}, + {mod, {erlang:list_to_atom(Name ++ "_app"), + []}}, + {included_applications, LibDeps}, + {registered, []}, + {applications, Deps}]}. + +full_application_contents(Name) -> + "-module("++Name++"_app).\n" + "-behaviour(application).\n" + "-export([start/2, stop/1]).\n" + "start(_StartType, _StartArgs) ->\n" + " "++Name++"_sup:start_link().\n" + "stop(_State) ->\n" + " ok.\n". + +supervisor_contents(Name) -> + "-module("++Name++"_sup).\n" + "-behaviour(supervisor).\n" + "-export([start_link/0]).\n" + "-export([init/1]).\n" + "-define(SERVER, ?MODULE).\n" + "start_link() ->\n" + " supervisor:start_link({local, ?SERVER}, ?MODULE, []).\n" + "init([]) ->\n" + " {ok, { {one_for_all, 0, 1},\n" + " [{"++Name++"_srv, {"++Name++"_srv, start_link, []},\n" + " transient, 5000, worker, ["++Name++"_srv]}\n" + " ]\n" + " }}.\n". + +gen_server_contents(Name) -> + "-module("++Name++"_srv).\n" + "-behaviour(gen_server).\n" + "-record(state, {}).\n" + "-export([start_link/0]).\n" + "-export([init/1,handle_call/3,handle_cast/2,\n" + " handle_info/2,terminate/2,code_change/3]).\n" + "start_link() ->\n" + " gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).\n" + "init([]) ->\n" + " erlang:send_after(4000, self(), register_signal)," + " {ok, #state{}}.\n" + "handle_call(_Event, _From, State) ->\n" + " {reply, ok, State}.\n" + "handle_cast(_Event, State) ->\n" + " {noreply, State}.\n" + "handle_info(register_signal, State) ->\n" + " erlang:register(goal_app_srv_signal, spawn(fun() -> timer:sleep(200000) end)),\n" + " {noreply, State};\n" + "handle_info(_Info, State) ->\n" + " {noreply, State}.\n" + "terminate(_Reason, _State) ->\n" + " ok.\n" + "code_change(_OldVsn, State, _Extra) ->\n" + " {ok, State}.\n". + create_random_name(Name) -> Name ++ erlang:integer_to_list(random_uniform(1000000)). @@ -63,6 +161,9 @@ ok = ec_file:write(Filename, [io_lib:format("~p.\n", [Val]) || Val <- Values]). +beam_file_contents(Name) -> + "-module("++Name++").". + test_template_contents() -> "{erts_vsn, \"{{erts_vsn}}\"}.\n" "{release_erts_version, \"{{release_erts_version}}\"}.\n" @@ -110,3 +211,7 @@ {error, Error} -> Error end. + +unescape_string(String) -> + re:replace(String, "\"", "", + [global, {return, list}]).
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.