├── .github └── workflows │ ├── main.yml │ ├── shelltest.yml │ └── wintest.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── pr2relnotes.sh ├── priv └── templates │ ├── bin │ ├── bin_windows │ ├── bin_windows_ps │ ├── builtin_hook_pid │ ├── builtin_hook_status │ ├── builtin_hook_wait_for_process │ ├── builtin_hook_wait_for_vm_start │ ├── erl_ini │ ├── erl_script │ ├── extended_bin │ ├── extended_bin_windows │ ├── extended_bin_windows_ps │ ├── install_upgrade_escript │ ├── nodetool │ ├── psutil │ ├── sys_config │ └── vm_args ├── rebar.config ├── rebar.lock ├── shelltests ├── check_undefined_test │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── check_undefined_test │ │ │ └── src │ │ │ ├── check_undefined_test.app.src │ │ │ ├── check_undefined_test_app.erl │ │ │ └── check_undefined_test_sup.erl │ ├── check_undefined_test.test │ ├── config │ │ ├── sys.config │ │ └── vm.args │ └── rebar.config ├── dev_replace_os_vars_tests │ ├── LICENSE │ ├── README.md │ ├── config │ │ ├── included.config │ │ ├── sys.config │ │ └── vm.args │ ├── dev_replace_os_vars_tests.test │ ├── rebar.config │ └── src │ │ ├── replace_os_vars_tests.app.src │ │ └── replace_os_vars_tests.erl ├── extended_start_script_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config │ │ ├── included.config │ │ ├── pathname_escape.sys.config │ │ ├── pathname_escape.vm.args │ │ ├── sys.config │ │ ├── vm-2.args │ │ ├── vm-4.args │ │ ├── vm-5.args │ │ ├── vm-6.args │ │ └── vm.args │ ├── extended_start_script_tests.tests │ ├── extended_start_script_tests_pathname_escape.test │ ├── rebar.config │ └── src │ │ ├── replace_os_vars_tests.app.src │ │ └── replace_os_vars_tests.erl ├── extension_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── bar │ ├── baz │ ├── extension_tests.test │ ├── foo │ ├── rebar.config │ └── src │ │ ├── extension_tests.app.src │ │ └── extension_tests.erl ├── force_nodetool_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── force_nodetool_tests │ │ │ └── src │ │ │ ├── force_nodetool_tests.app.src │ │ │ ├── force_nodetool_tests_app.erl │ │ │ └── force_nodetool_tests_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ ├── force_nodetool_tests.test │ ├── rebar.config │ └── rebar.lock ├── hooks_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config │ │ └── vm.args │ ├── hooks │ │ ├── post_start │ │ ├── post_stop │ │ ├── pre_start │ │ ├── pre_stop │ │ └── status │ ├── hooks_tests.test │ ├── rebar.config │ └── src │ │ ├── hooks_tests.app.src │ │ └── hooks_tests.erl ├── overlay_error_test │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── overlay_error_test │ │ │ └── src │ │ │ ├── overlay_error_test.app.src │ │ │ ├── overlay_error_test_app.erl │ │ │ └── overlay_error_test_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ ├── overlay_error_test.test │ └── rebar.config ├── powershell_release │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── powershell_release │ │ │ └── src │ │ │ ├── powershell_release.app.src │ │ │ ├── powershell_release_app.erl │ │ │ └── powershell_release_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ └── rebar.config ├── reboot_restart_test │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config │ │ └── vm.args │ ├── rebar.config │ ├── reboot_restart_test.test │ └── src │ │ ├── extended_script_tests.app.src │ │ └── extended_script_tests.erl ├── replace_src_vars_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config │ │ ├── sys.config.src │ │ └── vm.args.src │ ├── rebar.config │ ├── replace_src_vars_tests.test │ └── src │ │ ├── replace_os_vars_tests.app.src │ │ └── replace_os_vars_tests.erl ├── run_tests.sh ├── shellcheck_test │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── shellcheck_test │ │ │ └── src │ │ │ ├── shellcheck_test.app.src │ │ │ ├── shellcheck_test_app.erl │ │ │ └── shellcheck_test_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ ├── rebar.config │ ├── rebar.lock │ └── shellcheck_test.test ├── system_libs_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── system_libs_tests │ │ │ └── src │ │ │ ├── system_libs_tests.app.src │ │ │ ├── system_libs_tests_app.erl │ │ │ └── system_libs_tests_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ ├── rebar.config │ ├── rebar.lock │ ├── system_libs │ │ ├── kernel-7.1-test │ │ │ ├── ebin │ │ │ │ ├── application.beam │ │ │ │ └── kernel.app │ │ │ └── include │ │ │ │ ├── dist.hrl │ │ │ │ ├── dist_util.hrl │ │ │ │ ├── eep48.hrl │ │ │ │ ├── file.hrl │ │ │ │ ├── inet.hrl │ │ │ │ ├── inet_sctp.hrl │ │ │ │ ├── logger.hrl │ │ │ │ └── net_address.hrl │ │ └── stdlib-3.13.2-test │ │ │ ├── ebin │ │ │ ├── array.beam │ │ │ └── stdlib.app │ │ │ └── include │ │ │ ├── assert.hrl │ │ │ ├── erl_bits.hrl │ │ │ ├── erl_compile.hrl │ │ │ ├── ms_transform.hrl │ │ │ ├── qlc.hrl │ │ │ └── zip.hrl │ └── system_libs_tests.test ├── upgrade_test │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── apps │ │ └── upgrade_test │ │ │ ├── ebin │ │ │ └── upgrade_test.appup │ │ │ └── src │ │ │ ├── upgrade_test.app.src │ │ │ ├── upgrade_test_app.erl │ │ │ └── upgrade_test_sup.erl │ ├── apps011 │ │ └── upgrade_test │ │ │ ├── ebin │ │ │ └── upgrade_test.appup │ │ │ └── src │ │ │ ├── upgrade_test.app.src │ │ │ ├── upgrade_test_app.erl │ │ │ └── upgrade_test_sup.erl │ ├── config │ │ ├── sys.config │ │ └── vm.args │ ├── rebar.config │ ├── rebar.config011 │ └── upgrade_test.test ├── vm_args_inclusion_tests │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config │ │ ├── sys.config.src │ │ ├── vm.args.src │ │ └── vm.extended.args │ ├── rebar.config │ ├── rebar.lock │ ├── src │ │ ├── vm_args_inclusion_tests.app.src │ │ └── vm_args_inclusion_tests.erl │ └── vm_args_inclusion_tests.test └── wintest.ps1 ├── src ├── relx.app.src ├── relx.erl ├── relx.hrl ├── rlx_app_info.erl ├── rlx_assemble.erl ├── rlx_config.erl ├── rlx_file_utils.erl ├── rlx_log.erl ├── rlx_log.hrl ├── rlx_overlay.erl ├── rlx_release.erl ├── rlx_relup.erl ├── rlx_resolve.erl ├── rlx_state.erl ├── rlx_string.erl ├── rlx_tar.erl └── rlx_util.erl └── test ├── rlx_dscv_util.erl ├── rlx_release_SUITE.erl ├── rlx_relup_SUITE.erl ├── rlx_tar_SUITE.erl └── rlx_test_utils.erl /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Common Test 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'main' 7 | push: 8 | branches: 9 | - 'main' 10 | 11 | jobs: 12 | linux: 13 | name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | otp_version: [23, 24, 26] 19 | os: [ubuntu-20.04] # latest only runs >= 24.2 20 | 21 | container: 22 | image: erlang:${{ matrix.otp_version }} 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Compile 27 | run: rebar3 compile 28 | - name: CT tests 29 | run: rebar3 ct 30 | - name: Xref 31 | run: rebar3 xref 32 | - name: Dialyzer 33 | run: rebar3 dialyzer 34 | 35 | macos: 36 | name: Test on MacOS 37 | runs-on: macos-latest 38 | 39 | steps: 40 | - uses: actions/checkout@v2 41 | - name: Install Erlang 42 | run: brew install erlang 43 | - name: Install rebar3 44 | run: | 45 | wget https://s3.amazonaws.com/rebar3/rebar3 46 | chmod +x rebar3 47 | - name: CT tests 48 | run: ./rebar3 ct 49 | -------------------------------------------------------------------------------- /.github/workflows/shelltest.yml: -------------------------------------------------------------------------------- 1 | name: ShellTestRunner 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'main' 7 | push: 8 | branches: 9 | - 'main' 10 | 11 | jobs: 12 | build: 13 | name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | # TODO: make a batch of tests that runs on nodetool rather 19 | # than the new connectivity mechanism 20 | otp_version: [25, 26] 21 | os: [ubuntu-latest] # latest only runs >= 24.2 22 | 23 | steps: 24 | - uses: actions/checkout@v2 25 | - uses: erlef/setup-beam@v1 26 | with: 27 | otp-version: ${{ matrix.otp_version }} 28 | 29 | - uses: actions/setup-haskell@v1 30 | with: 31 | ghc-version: '8.6.5' 32 | cabal-version: '3.0' 33 | 34 | - name: Update cabal 35 | run: cabal update 36 | - name: Install shelltestrunner 37 | run: cabal install shelltestrunner-1.9 38 | 39 | - name: Install shellcheck 40 | run: cabal install ShellCheck 41 | 42 | - name: Run shell tests 43 | run: shelltests/run_tests.sh 44 | -------------------------------------------------------------------------------- /.github/workflows/wintest.yml: -------------------------------------------------------------------------------- 1 | name: Windows Test 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'main' 7 | push: 8 | branches: 9 | - 'main' 10 | 11 | jobs: 12 | build: 13 | name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | otp_version: [24, 25, 26] 19 | os: [windows-latest] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: erlef/setup-beam@v1 24 | with: 25 | otp-version: ${{ matrix.otp_version }} 26 | - name: Run test 27 | run: shelltests/wintest.ps1 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | .rebar3 3 | deps/* 4 | ebin/* 5 | *.beam 6 | .eunit 7 | .relx_plt 8 | relx 9 | relx.cmd 10 | priv/templates/*.erl 11 | # This is a generated file that should be ignored 12 | src/rcl_goal.erl 13 | logs 14 | test/*_data 15 | _rel/* 16 | erl_crash.dump 17 | rebar 18 | TEST-* 19 | tags 20 | *.swp 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Introduction 5 | ------------ 6 | 7 | This document describes the usages and rules to follow when contributing 8 | to this project. 9 | 10 | It uses the uppercase keywords SHOULD for optional but highly recommended 11 | conditions and MUST for required conditions. 12 | 13 | `git` is a distributed source code versioning system. This document refers 14 | to three different repositories hosting the source code of the project. 15 | `Your local copy` refers to the copy of the repository that you have on 16 | your computer. The remote repository `origin` refers to your fork of the 17 | project's repository that you can find in your GitHub account. The remote 18 | repository `upstream` refers to the official repository for this project. 19 | 20 | Reporting bugs 21 | -------------- 22 | 23 | Upon identifying a bug you SHOULD submit a ticket, regardless of your 24 | plan for fixing it. If you plan to fix the bug, you SHOULD discuss your 25 | plans to avoid having your work rejected. 26 | 27 | Before implementing a new feature, you SHOULD submit a ticket for discussion 28 | on your plans. The feature might have been rejected already, or the 29 | implementation might already be decided. 30 | 31 | Cloning 32 | ------- 33 | 34 | You MUST fork the project's repository to your GitHub account by clicking 35 | on the `Fork` button. 36 | 37 | Then, from your fork's page, copy the `Git Read-Only` URL to your clipboard. 38 | You MUST perform the following commands in the folder you choose, replacing 39 | `$URL` by the URL you just copied, `$UPSTREAM_URL` by the `Git Read-Only` 40 | project of the official repository, and `$PROJECT` by the name of this project. 41 | 42 | ``` bash 43 | $ git clone "$URL" 44 | $ cd $PROJECT 45 | $ git remote add upstream $UPSTREAM_URL 46 | ``` 47 | 48 | Branching 49 | --------- 50 | 51 | Before starting working on the code, you MUST update to `upstream`. The 52 | project is always evolving, and as such you SHOULD always strive to keep 53 | up to date when submitting patches to make sure they can be merged without 54 | conflicts. 55 | 56 | To update the current branch to `upstream`, you can use the following commands. 57 | 58 | ``` bash 59 | $ git fetch upstream 60 | $ git rebase upstream/main 61 | ``` 62 | 63 | It may ask you to stash your changes, in which case you stash with: 64 | 65 | ``` bash 66 | $ git stash 67 | ``` 68 | 69 | And put your changes back in with: 70 | 71 | ``` bash 72 | $ git stash pop 73 | ``` 74 | 75 | You SHOULD use these commands both before working on your patch and before 76 | submitting the pull request. If conflicts arise it is your responsibility 77 | to deal with them. 78 | 79 | You MUST create a new branch for your work. First make sure you have 80 | 'fetched' `main` 81 | 82 | ``` bash 83 | $ git checkout -b $BRANCH upstream/main 84 | ``` 85 | 86 | You MUST use a an insightful branch name. 87 | 88 | If you later need to switch back to an existing branch `$BRANCH`, you can use: 89 | 90 | ``` bash 91 | $ git checkout $BRANCH 92 | ``` 93 | 94 | Source editing 95 | -------------- 96 | 97 | The following rules MUST be followed: 98 | * Indentation uses 4 horizontal spaces 99 | * Tabs should not be used 100 | * Do NOT align code; only indentation is allowed 101 | 102 | 103 | The following rules SHOULD be followed: 104 | * Write small functions whenever possible 105 | * Avoid having too many clauses containing clauses containing clauses 106 | * Lines SHOULD NOT span more than 80 columns 107 | 108 | When in doubt indentation as performed in the Erlang Emacs Mode is 109 | correct. 110 | 111 | Committing 112 | ---------- 113 | 114 | You MUST ensure that all commits pass all tests and do not have extra 115 | Dialyzer warnings. 116 | 117 | You MUST put all the related work in a single commit. Fixing a bug is one 118 | commit, adding a feature is one commit, adding two features is two commits. 119 | 120 | You MUST write a proper commit title and message. The commit title MUST be 121 | at most 72 characters; it is the first line of the commit text. The second 122 | line of the commit text MUST be left blank. The third line and beyond is the 123 | commit message. You SHOULD write a commit message. If you do, you MUST make 124 | all lines smaller than 80 characters. You SHOULD explain what the commit 125 | does, what references you used and any other information that helps 126 | understanding your work. 127 | 128 | Submitting the pull request 129 | --------------------------- 130 | 131 | You MUST push your branch `$BRANCH` to GitHub, using the following command: 132 | 133 | ``` bash 134 | $ git push origin $BRANCH 135 | ``` 136 | 137 | You MUST then submit the pull request by using the GitHub interface to 138 | the `main` branch. You SHOULD provide an explanatory message and refer 139 | to any previous ticket related to this patch. 140 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | ============== 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | ------------------------------------------------------------ 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, 12 | reproduction, and distribution as defined by Sections 1 through 9 13 | of this document. 14 | 15 | "Licensor" shall mean the copyright owner or entity authorized by 16 | the copyright owner that is granting the License. 17 | 18 | "Legal Entity" shall mean the union of the acting entity and all 19 | other entities that control, are controlled by, or are under common 20 | control with that entity. For the purposes of this definition, 21 | "control" means (i) the power, direct or indirect, to cause the 22 | direction or management of such entity, whether by contract or 23 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 24 | outstanding shares, or (iii) beneficial ownership of such entity. 25 | 26 | "You" (or "Your") shall mean an individual or Legal Entity 27 | exercising permissions granted by this License. 28 | 29 | "Source" form shall mean the preferred form for making 30 | modifications, including but not limited to software source code, 31 | documentation source, and configuration files. 32 | 33 | "Object" form shall mean any form resulting from mechanical 34 | transformation or translation of a Source form, including but not 35 | limited to compiled object code, generated documentation, and 36 | conversions to other media types. 37 | 38 | "Work" shall mean the work of authorship, whether in Source or 39 | Object form, made available under the License, as indicated by a 40 | copyright notice that is included in or attached to the work (an 41 | example is provided in the Appendix below). 42 | 43 | "Derivative Works" shall mean any work, whether in Source or Object 44 | form, that is based on (or derived from) the Work and for which the 45 | editorial revisions, annotations, elaborations, or other 46 | modifications represent, as a whole, an original work of 47 | authorship. For the purposes of this License, Derivative Works 48 | shall not include works that remain separable from, or merely link 49 | (or bind by name) to the interfaces of, the Work and Derivative 50 | Works thereof. 51 | 52 | "Contribution" shall mean any work of authorship, including the 53 | original version of the Work and any modifications or additions to 54 | that Work or Derivative Works thereof, that is intentionally 55 | submitted to Licensor for inclusion in the Work by the copyright 56 | owner or by an individual or Legal Entity authorized to submit on 57 | behalf of the copyright owner. For the purposes of this definition, 58 | "submitted" means any form of electronic, verbal, or written 59 | communication sent to the Licensor or its representatives, 60 | including but not limited to communication on electronic mailing 61 | lists, source code control systems, and issue tracking systems that 62 | are managed by, or on behalf of, the Licensor for the purpose of 63 | discussing and improving the Work, but excluding communication that 64 | is conspicuously marked or otherwise designated in writing by the 65 | copyright owner as "Not a Contribution." 66 | 67 | "Contributor" shall mean Licensor and any individual or Legal 68 | Entity on behalf of whom a Contribution has been received by 69 | Licensor and subsequently incorporated within the Work. 70 | 71 | 2. Grant of Copyright License. Subject to the terms and conditions of 72 | this License, each Contributor hereby grants to You a perpetual, 73 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 74 | copyright license to reproduce, prepare Derivative Works of, 75 | publicly display, publicly perform, sublicense, and distribute the 76 | Work and such Derivative Works in Source or Object form. 77 | 78 | 3. Grant of Patent License. Subject to the terms and conditions of 79 | this License, each Contributor hereby grants to You a perpetual, 80 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 81 | (except as stated in this section) patent license to make, have 82 | made, use, offer to sell, sell, import, and otherwise transfer the 83 | Work, where such license applies only to those patent claims 84 | licensable by such Contributor that are necessarily infringed by 85 | their Contribution(s) alone or by combination of their 86 | Contribution(s) with the Work to which such Contribution(s) was 87 | submitted. If You institute patent litigation against any entity 88 | (including a cross-claim or counterclaim in a lawsuit) alleging 89 | that the Work or a Contribution incorporated within the Work 90 | constitutes direct or contributory patent infringement, then any 91 | patent licenses granted to You under this License for that Work 92 | shall terminate as of the date such litigation is filed. 93 | 94 | 4. Redistribution. You may reproduce and distribute copies of the Work 95 | or Derivative Works thereof in any medium, with or without 96 | modifications, and in Source or Object form, provided that You meet 97 | the following conditions: 98 | 99 | (a) You must give any other recipients of the Work or Derivative 100 | Works a copy of this License; and 101 | 102 | (b) You must cause any modified files to carry prominent notices 103 | stating that You changed the files; and 104 | 105 | (c) You must retain, in the Source form of any Derivative Works that 106 | You distribute, all copyright, patent, trademark, and 107 | attribution notices from the Source form of the Work, excluding 108 | those notices that do not pertain to any part of the Derivative 109 | Works; and 110 | 111 | (d) If the Work includes a "NOTICE" text file as part of its 112 | distribution, then any Derivative Works that You distribute must 113 | include a readable copy of the attribution notices contained 114 | within such NOTICE file, excluding those notices that do not 115 | pertain to any part of the Derivative Works, in at least one of 116 | the following places: within a NOTICE text file distributed as 117 | part of the Derivative Works; within the Source form or 118 | documentation, if provided along with the Derivative Works; or, 119 | within a display generated by the Derivative Works, if and 120 | wherever such third-party notices normally appear. The contents 121 | of the NOTICE file are for informational purposes only and do 122 | not modify the License. You may add Your own attribution notices 123 | within Derivative Works that You distribute, alongside or as an 124 | addendum to the NOTICE text from the Work, provided that such 125 | additional attribution notices cannot be construed as modifying 126 | the License. 127 | 128 | You may add Your own copyright statement to Your modifications and 129 | may provide additional or different license terms and conditions 130 | for use, reproduction, or distribution of Your modifications, or 131 | for any such Derivative Works as a whole, provided Your use, 132 | reproduction, and distribution of the Work otherwise complies with 133 | the conditions stated in this License. 134 | 135 | 5. Submission of Contributions. Unless You explicitly state otherwise, 136 | any Contribution intentionally submitted for inclusion in the Work 137 | by You to the Licensor shall be under the terms and conditions of 138 | this License, without any additional terms or conditions. 139 | Notwithstanding the above, nothing herein shall supersede or modify 140 | the terms of any separate license agreement you may have executed 141 | with Licensor regarding such Contributions. 142 | 143 | 6. Trademarks. This License does not grant permission to use the trade 144 | names, trademarks, service marks, or product names of the Licensor, 145 | except as required for reasonable and customary use in describing 146 | the origin of the Work and reproducing the content of the NOTICE 147 | file. 148 | 149 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed 150 | to in writing, Licensor provides the Work (and each Contributor 151 | provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES 152 | OR CONDITIONS OF ANY KIND, either express or implied, including, 153 | without limitation, any warranties or conditions of TITLE, 154 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR 155 | PURPOSE. You are solely responsible for determining the 156 | appropriateness of using or redistributing the Work and assume any 157 | risks associated with Your exercise of permissions under this 158 | License. 159 | 160 | 8. Limitation of Liability. In no event and under no legal theory, 161 | whether in tort (including negligence), contract, or otherwise, 162 | unless required by applicable law (such as deliberate and grossly 163 | negligent acts) or agreed to in writing, shall any Contributor be 164 | liable to You for damages, including any direct, indirect, special, 165 | incidental, or consequential damages of any character arising as a 166 | result of this License or out of the use or inability to use the 167 | Work (including but not limited to damages for loss of goodwill, 168 | work stoppage, computer failure or malfunction, or any and all 169 | other commercial damages or losses), even if such Contributor has 170 | been advised of the possibility of such damages. 171 | 172 | 9. Accepting Warranty or Additional Liability. While redistributing 173 | the Work or Derivative Works thereof, You may choose to offer, and 174 | charge a fee for, acceptance of support, warranty, indemnity, or 175 | other liability obligations and/or rights consistent with this 176 | License. However, in accepting such obligations, You may act only 177 | on Your own behalf and on Your sole responsibility, not on behalf 178 | of any other Contributor, and only if You agree to indemnify, 179 | defend, and hold each Contributor harmless for any liability 180 | incurred by, or claims asserted against, such Contributor by reason 181 | of your accepting any such warranty or additional liability. 182 | 183 | END OF TERMS AND CONDITIONS 184 | 185 | APPENDIX: How to apply the Apache License to your work. 186 | 187 | To apply the Apache License to your work, attach the following 188 | boilerplate notice, with the fields enclosed by brackets "[]" 189 | replaced with your own identifying information. (Don't include 190 | the brackets!) The text should be enclosed in the appropriate 191 | comment syntax for the file format. We also recommend that a 192 | file or class name and description of purpose be included on the 193 | same "printed page" as the copyright notice for easier 194 | identification within third-party archives. 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/erlware/relx/workflows/Common%20Test/badge.svg) 2 | ![Cirrus CI - Task and Script Build Status](https://img.shields.io/cirrus/github/erlware/relx?label=OSX%20Tests) 3 | 4 | Relx 5 | ======= 6 | 7 | Relx is a library that assembles Erlang/OTP releases. Given a release 8 | specification and a list of directories in which to search for OTP 9 | applications it will generate a release output. 10 | 11 | It is generally used through the Erlang/OTP build tool 12 | [rebar3](https://www.rebar3.org/) which provides a cli interface. 13 | 14 | Documentation 15 | ----------- 16 | 17 | `relx` is a library used by [rebar3](https://www.rebar3.org/). Documentation on 18 | using `rebar3` for building releases with `relx` can be found on 19 | [rebar3.org](https://rebar3.org/docs/deployment/releases/). 20 | 21 | Also see [Adopting Erlang's Releases 22 | chapter](https://adoptingerlang.org/docs/production/releases/). 23 | 24 | 25 | Building and Testing 26 | -------- 27 | 28 | Common Test suites can be run with `rebar3`: 29 | 30 | ``` shell 31 | $ rebar3 compile 32 | $ rebar3 ct 33 | ``` 34 | 35 | Tests for the start scripts that are generated by `relx` are tested with 36 | [shelltestrunner](https://github.com/simonmichael/shelltestrunner/). 37 | 38 | The script `shelltests/run_tests.sh` will clone `rebar3` main and build it 39 | with the current `relx` as a checkout dependency and then run the tests using 40 | that `rebar3` escript: 41 | 42 | ``` shell 43 | $ shelltests/run_tests.sh 44 | ``` 45 | -------------------------------------------------------------------------------- /pr2relnotes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ -z $1 ] 4 | then 5 | echo "pr2relnotes.sh: prints list of pull requests merged since " 6 | echo " usage: $0 [pull-request-url (default: https://github.com/erlware/relx/pull/)]" 7 | exit 0 8 | fi 9 | export url=${2:-"https://github.com/erlware/relx/pull/"} 10 | 11 | git log --merges --pretty=medium $1..HEAD | \ 12 | awk -v url=$url ' 13 | # first line of a merge commit entry 14 | /^commit / {mode="new"} 15 | 16 | # merge commit default message 17 | / +Merge pull request/ { 18 | page_id=substr($4, 2, length($4)-1); 19 | mode="started"; 20 | next; 21 | } 22 | 23 | # line of content including title 24 | mode=="started" && / [^ ]+/ { 25 | print "- [" substr($0, 5) "](" url page_id ")"; mode="done" 26 | }' 27 | -------------------------------------------------------------------------------- /priv/templates/bin: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | SCRIPT=$(readlink "$0" || true) 6 | if [ -z "$SCRIPT" ]; then 7 | SCRIPT=$0 8 | fi; 9 | SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd -P)" 10 | RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)" 11 | export REL_NAME="{{ rel_name }}" 12 | REL_VSN="{{ rel_vsn }}" 13 | 14 | # export these to match mix release environment variables 15 | export RELEASE_NAME="{{ rel_name }}" 16 | export RELEASE_VSN="{{ rel_vsn }}" 17 | export RELEASE_PROG="${SCRIPT}" 18 | 19 | ERTS_VSN="{{ erts_vsn }}" 20 | REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN" 21 | ERL_OPTS="{{ erl_opts }}" 22 | export ESCRIPT_NAME="${ESCRIPT_NAME-$SCRIPT}" 23 | 24 | find_erts_dir() { 25 | __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN" 26 | if [ -d "$__erts_dir" ]; then 27 | ERTS_DIR="$__erts_dir"; 28 | else 29 | __erl="$(command -v erl)" 30 | code="io:format(\"~s\", [code:root_dir()]), halt()." 31 | __erl_root="$("$__erl" -boot no_dot_erlang -noshell -eval "$code")" 32 | ERTS_DIR="$__erl_root/erts-$ERTS_VSN" 33 | fi 34 | } 35 | 36 | find_sys_config() { 37 | __possible_sys="$REL_DIR/sys.config" 38 | if [ -f "$__possible_sys" ]; then 39 | SYS_CONFIG="$__possible_sys" 40 | else 41 | if [ -L "$__possible_sys".orig ]; then 42 | mv "$__possible_sys".orig "$__possible_sys" 43 | SYS_CONFIG="$__possible_sys" 44 | fi 45 | fi 46 | } 47 | 48 | find_vm_args() { 49 | __possible_vm_args="$REL_DIR/vm.args" 50 | if [ -f "$__possible_vm_args" ]; then 51 | VM_ARGS="$__possible_vm_args" 52 | else 53 | if [ -L "$__possible_vm_args".orig ]; then 54 | mv "$__possible_vm_args".orig "$__possible_vm_args" 55 | VM_ARGS="$__possible_vm_args" 56 | fi 57 | fi 58 | } 59 | 60 | find_erts_dir 61 | find_sys_config 62 | find_vm_args 63 | export ROOTDIR="$RELEASE_ROOT_DIR" 64 | export BINDIR="$ERTS_DIR/bin" 65 | export EMU="beam" 66 | export PROGNAME="erl" 67 | export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH" 68 | SYSTEM_LIB_DIR="$(dirname "$ERTS_DIR")/lib" 69 | [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start 70 | cd "$ROOTDIR" 71 | 72 | {{! Define alternative field separator using ASCII US (unit separator). US is 73 | not expected to appear in any argument. }} 74 | IFS_NORM="$IFS" 75 | IFS_ARGS="$(printf '\x1f')" 76 | 77 | # Save extra arguments 78 | {{! Join extra arguments into a US-delimited string. }} 79 | IFS="$IFS_ARGS" 80 | ARGS="$*" 81 | IFS="$IFS_NORM" 82 | 83 | # Build arguments for erlexec 84 | set -- 85 | [ "$ERL_OPTS" ] && set -- "$@" "$ERL_OPTS" 86 | [ "$SYS_CONFIG" ] && set -- "$@" -config "$SYS_CONFIG" 87 | [ "$VM_ARGS" ] && set -- "$@" -args_file "$VM_ARGS" 88 | set -- "$@" -boot_var SYSTEM_LIB_DIR "$SYSTEM_LIB_DIR" -boot "$REL_DIR/$BOOTFILE" 89 | {{! Split string with extra arguments back into an argument list. }} 90 | IFS="$IFS_ARGS" 91 | # shellcheck disable=SC2086 92 | set -- "$@" $ARGS 93 | IFS="$IFS_NORM" 94 | 95 | exec "$BINDIR/erlexec" "$@" 96 | -------------------------------------------------------------------------------- /priv/templates/bin_windows: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: This is a simple start batch file that runs the release in an Erlang shell 3 | 4 | :: Set variables that describe the release 5 | set rel_name={{ rel_name }} 6 | set rel_vsn={{ rel_vsn }} 7 | set erts_vsn={{ erts_vsn }} 8 | set erl_opts={{ erl_opts }} 9 | 10 | :: export these to match mix release environment variables 11 | set RELEASE_NAME={{ rel_name }} 12 | set RELEASE_VSN={{ rel_vsn }} 13 | set RELEASE_PROG=%~nx0 14 | 15 | :: Set the root release directory based on the location of this batch file 16 | set script_dir=%~dp0 17 | for %%A in ("%script_dir%\..") do ( 18 | set "release_root_dir=%%~fA" 19 | ) 20 | set "rel_dir=%release_root_dir%\releases\%rel_vsn%" 21 | 22 | call :find_erts_dir 23 | call :find_sys_config 24 | call :set_boot_script_var 25 | 26 | set "rootdir=%release_root_dir%" 27 | set "bindir=%erts_dir%\bin" 28 | set progname=erl 29 | set erl=%bindir%\erl 30 | 31 | cd %rootdir% 32 | 33 | :: Write the erl.ini file 34 | set erl_ini=%erts_dir%\bin\erl.ini 35 | set converted_bindir=%bindir:\=\\% 36 | set converted_rootdir=%rootdir:\=\\% 37 | echo [erlang] > "%erl_ini%" 38 | echo Bindir=%converted_bindir% >> "%erl_ini%" 39 | echo Progname=%progname% >> "%erl_ini%" 40 | echo Rootdir=%converted_rootdir% >> "%erl_ini%" 41 | 42 | :: Start the release in an `erl` shell 43 | set boot=-boot "%boot_script%" -boot_var RELEASE_DIR "%release_root_dir%" 44 | "%erl%" %erl_opts% %sys_config% %boot% %* 45 | 46 | goto :eof 47 | 48 | :: Find the ERTS dir 49 | :find_erts_dir 50 | set "erts_dir=%release_root_dir%\erts-%erts_vsn%" 51 | if exist %erts_dir% ( 52 | goto :set_erts_dir_from_default 53 | ) else ( 54 | goto :set_erts_dir_from_erl 55 | ) 56 | goto :eof 57 | 58 | :: Set the ERTS dir from the passed in erts_vsn 59 | :set_erts_dir_from_default 60 | set erts_dir=%erts_dir% 61 | set root_dir=%release_root_dir% 62 | goto :eof 63 | 64 | :: Set the ERTS dir from erl 65 | :set_erts_dir_from_erl 66 | for /f "delims=" %%i in ('where erl') do ( 67 | set erl=%%i 68 | ) 69 | for /f "delims=" %%i in ('call "%erl%" -boot no_dot_erlang -boot_var RELEASE_DIR "%release_root_dir%" -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop') do ( 70 | set erl_root=%%i 71 | ) 72 | set "erts_dir=%erl_root%\erts-%erts_vsn%" 73 | set rootdir=%erl_root% 74 | goto :eof 75 | 76 | :: Find the sys.config file 77 | :find_sys_config 78 | set "possible_sys=%rel_dir%\sys.config" 79 | if exist "%possible_sys%" ( 80 | set sys_config=-config "%possible_sys%" 81 | ) else ( 82 | if exist "%possible_sys%.orig" ( 83 | ren "%possible_sys%.orig" sys.config 84 | set sys_config=-config "%possible_sys%" 85 | ) 86 | ) 87 | 88 | :: Find the vm.args file 89 | :find_vm_args 90 | set "possible_vm_args=%rel_dir%\vm.args" 91 | if exist "%possible_vm_args%" ( 92 | set vm_args="%possible_vm_args%" 93 | ) else ( 94 | if exist "%possible_vm_args%.orig" ( 95 | ren "%possible_vm_args%.orig" vm.args 96 | set vm_args="%possible_vm_args%" 97 | ) 98 | ) 99 | goto :eof 100 | 101 | :: set boot_script variable 102 | :set_boot_script_var 103 | if exist "%rel_dir%\%rel_name%.boot" ( 104 | set "boot_script=%rel_dir%\%rel_name%" 105 | ) else ( 106 | set "boot_script=%rel_dir%\start" 107 | ) 108 | goto :eof 109 | -------------------------------------------------------------------------------- /priv/templates/bin_windows_ps: -------------------------------------------------------------------------------- 1 | #! /usr/bin/pwsh 2 | # This is a simple start script file that runs the release in an Erlang shell 3 | 4 | # Terminate on error 5 | $ErrorActionPreference = "Stop" 6 | 7 | # Set variables that describe the release 8 | $rel_name = '{{ rel_name }}' 9 | $rel_vsn = '{{ rel_vsn }}' 10 | $erts_vsn = '{{ erts_vsn }}' 11 | $erl_opts = '{{ erl_opts }}' 12 | 13 | # export these to match mix release environment variables 14 | $RELEASE_NAME = '{{ rel_name }}' 15 | $RELEASE_VERSION = '{{ rel_vsn }}' 16 | $RELEASE_PROG = $MyInvocation.MyCommand.Name 17 | 18 | # Ensure we have PSScriptRoot 19 | if (!(Test-Path variable:global:PSScriptRoot)) { 20 | # Support for powershell 2.0 21 | $PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition 22 | } 23 | 24 | # Import psutil helper functions 25 | . $PSScriptRoot\psutil.ps1 26 | 27 | # Set the root release directory based on the location of this script 28 | $rootdir = Split-Path -Parent -Path $PSScriptRoot 29 | $rel_dir = "$rootdir\releases\$rel_vsn" 30 | 31 | $erts_root, $erts_dir = Find-ERTS -RelRoot $rootdir -Vsn $erts_vsn 32 | $sys_config = Find-FormatConfig -RelDir $rel_dir -File 'sys.config' 33 | $vm_args = Find-FormatConfig -RelDir $rel_dir -File 'vm.args' 34 | $boot_script = Find-BootScript -RelDir $rel_dir -RelName $rel_name 35 | $werl = "$erts_dir\bin\werl.exe" 36 | 37 | # Set the ERL_LIBS environment variable 38 | $env:ERL_LIBS = "$rootdir\lib" 39 | 40 | # Start the release in an `erl` shell 41 | $params = @($erl_opts, '-boot', $boot_script) 42 | if (![string]::IsNullOrEmpty($sys_config)) { $params += '-config', $sys_config } 43 | if (![string]::IsNullOrEmpty($vm_args)) { $params += '-args_file', $vm_args } 44 | $params += $args 45 | & $werl $params 46 | 47 | # Cleanup 48 | $env:ERL_LIBS = '' 49 | -------------------------------------------------------------------------------- /priv/templates/builtin_hook_pid: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # loop until the VM starts responding to pings 4 | while ! erl_rpc erlang is_alive > /dev/null 5 | do 6 | sleep 1 7 | done 8 | 9 | # get the beam pid and write it to the file passed as 10 | # argument 11 | PID="$(relx_get_pid)" 12 | echo "$PID" > "$1" 13 | -------------------------------------------------------------------------------- /priv/templates/builtin_hook_status: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | erl_eval "application:which_applications()." 4 | -------------------------------------------------------------------------------- /priv/templates/builtin_hook_wait_for_process: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # loop until the VM starts responding to pings 4 | while ! erl_rpc erlang is_alive > /dev/null 5 | do 6 | sleep 1 7 | done 8 | 9 | # loop until the name provided as argument gets 10 | # registered 11 | while true 12 | do 13 | if [ "$(erl_eval "whereis($1).")" != "undefined" ] 14 | then 15 | break 16 | fi 17 | done 18 | -------------------------------------------------------------------------------- /priv/templates/builtin_hook_wait_for_vm_start: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # loop until the VM starts responding to pings 4 | while ! erl_rpc erlang is_alive > /dev/null 5 | do 6 | sleep 1 7 | done 8 | -------------------------------------------------------------------------------- /priv/templates/erl_ini: -------------------------------------------------------------------------------- 1 | [erlang] 2 | Bindir={{ bin_dir }} 3 | Progname=erl 4 | Rootdir={{ output_dir }} 5 | -------------------------------------------------------------------------------- /priv/templates/erl_script: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | SCRIPT_DIR=`dirname $0` 5 | ROOTDIR=`cd $SCRIPT_DIR/../../ && pwd` 6 | BINDIR=$ROOTDIR/erts-{{ erts_vsn }}/bin 7 | EMU=beam 8 | PROGNAME=`echo $0 | sed 's/.*\\///'` 9 | export EMU 10 | export ROOTDIR 11 | export BINDIR 12 | export PROGNAME 13 | exec "$BINDIR/erlexec" ${1+"$@"} 14 | -------------------------------------------------------------------------------- /priv/templates/nodetool: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env escript 2 | %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- 3 | %% ex: ft=erlang ts=4 sw=4 et 4 | %% ------------------------------------------------------------------- 5 | %% 6 | %% nodetool: Helper Script for interacting with live nodes 7 | %% 8 | %% On releases running with OTP-23+ this escript is not used. Instead, 9 | %% the `erl_call' command is used. This escript will be removed from 10 | %% relx when OTP-23 becomes the earliest support version of OTP. 11 | %% 12 | %% ------------------------------------------------------------------- 13 | -mode(interpret). 14 | 15 | main(Args) -> 16 | %% Extract the args 17 | {RestArgs, TargetNode, StartEpmd} = process_args(Args, [], undefined, true), 18 | 19 | ok = start_epmd(StartEpmd), 20 | 21 | %% See if the node is currently running -- if it's not, we'll bail 22 | case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of 23 | {true, pong} -> 24 | ok; 25 | {_, pang} -> 26 | io:format("Node ~p not responding to pings.~n", [TargetNode]), 27 | halt(1) 28 | end, 29 | 30 | Timeout = 31 | case os:getenv("RELX_RPC_TIMEOUT") of 32 | false -> 33 | 60000; 34 | StrVal -> 35 | try 36 | %% RELX_RPC_TIMEOUT is in seconds 37 | list_to_integer(StrVal) * 1000 38 | catch _:_ -> 39 | 60000 40 | end 41 | end, 42 | 43 | case RestArgs of 44 | ["rpc", Module, Function | ArgsAsString] -> 45 | case consult(lists:flatten(ArgsAsString)) of 46 | {error, Reason} -> 47 | io:format("Error parsing arguments `~s`, failed with reason: ~s~n", [ArgsAsString, Reason]); 48 | {ok, ParsedArgs} when is_list(ParsedArgs) -> 49 | case rpc:call(TargetNode, list_to_atom(Module), 50 | list_to_atom(Function), ParsedArgs, Timeout) of 51 | {badrpc, Reason} -> 52 | io:format("RPC to ~p failed: ~p~n", [TargetNode, Reason]), 53 | halt(1); 54 | rpc_ok -> 55 | %% code doesn't want any output 56 | ok; 57 | {rpc_error, Code} when is_integer(Code) -> 58 | %% code failed, halt with a supplied code 59 | halt(Code); 60 | {rpc_error, Code, Output} when is_integer(Code) -> 61 | %% code failed, halt with a supplied code 62 | %% and log output to stderr 63 | io:format(standard_error, "~p~n", [Output]), 64 | halt(Code); 65 | Other -> 66 | io:format("~p~n", [Other]) 67 | end; 68 | {ok, ParsedArgs} -> 69 | io:format("Error: args `~p` not a list.~n" 70 | "Example to call `foo:bar(1,2,3)` pass `foo bar \"[1, 2, 3].\"`~n", [ParsedArgs]) 71 | end; 72 | ["eval" | ListOfArgs] -> 73 | % shells may process args into more than one, and end up stripping 74 | % spaces, so this converts all of that to a single string to parse 75 | String = binary_to_list( 76 | list_to_binary( 77 | join(ListOfArgs," ") 78 | ) 79 | ), 80 | 81 | % then scan and parse the string 82 | {ok, Scanned, _} = erl_scan:string(String), 83 | {ok, Parsed } = erl_parse:parse_exprs(Scanned), 84 | 85 | % and evaluate it on the remote node 86 | case rpc:call(TargetNode, erl_eval, exprs, [Parsed, [] ]) of 87 | {value, Value, _} -> 88 | io:format ("~p~n",[Value]); 89 | {badrpc, Reason} -> 90 | io:format("RPC to ~p failed: ~p~n", [TargetNode, Reason]), 91 | halt(1) 92 | end; 93 | Other -> 94 | io:format("Other: ~p~n", [Other]), 95 | io:format("Usage: nodetool {ping|stop|restart|reboot|rpc|rpcterms|eval [Terms]} [RPC]~n") 96 | end, 97 | net_kernel:stop(). 98 | 99 | process_args([], Acc, TargetNode, StartEpmd) -> 100 | {lists:reverse(Acc), TargetNode, StartEpmd}; 101 | process_args(["-setcookie", Cookie | Rest], Acc, TargetNode, StartEpmd) -> 102 | erlang:set_cookie(node(), list_to_atom(Cookie)), 103 | process_args(Rest, Acc, TargetNode, StartEpmd); 104 | process_args(["-start_epmd", StartEpmd | Rest], Acc, TargetNode, _StartEpmd) -> 105 | process_args(Rest, Acc, TargetNode, list_to_atom(StartEpmd)); 106 | process_args(["-name", TargetName | Rest], Acc, _, StartEpmd) -> 107 | maybe_start_node(TargetName, longnames), 108 | process_args(Rest, Acc, nodename(TargetName), StartEpmd); 109 | process_args(["-sname", TargetName | Rest], Acc, _, StartEpmd) -> 110 | maybe_start_node(TargetName, shortnames), 111 | process_args(Rest, Acc, nodename(TargetName), StartEpmd); 112 | process_args([Arg | Rest], Acc, Opts, StartEpmd) -> 113 | process_args(Rest, [Arg | Acc], Opts, StartEpmd). 114 | 115 | maybe_start_node(TargetName, Names) -> 116 | case erlang:node() of 117 | 'nonode@nohost' -> 118 | ThisNode = append_node_suffix(TargetName, "_maint_"), 119 | {ok, _} = net_kernel:start([ThisNode, Names]); 120 | _ -> 121 | ok 122 | end. 123 | 124 | start_epmd(true) -> 125 | [] = os:cmd("\"" ++ epmd_path() ++ "\" -daemon"), 126 | ok; 127 | start_epmd(_) -> 128 | ok. 129 | 130 | epmd_path() -> 131 | ErtsBinDir = filename:dirname(escript:script_name()), 132 | Name = "epmd", 133 | case os:find_executable(Name, ErtsBinDir) of 134 | false -> 135 | case os:find_executable(Name) of 136 | false -> 137 | io:format("Could not find epmd.~n"), 138 | halt(1); 139 | GlobalEpmd -> 140 | GlobalEpmd 141 | end; 142 | Epmd -> 143 | Epmd 144 | end. 145 | 146 | 147 | nodename(Name) -> 148 | case re:split(Name, "@", [unicode, {return, list}]) of 149 | [_Node, _Host] -> 150 | list_to_atom(Name); 151 | [Node] -> 152 | [_, Host] = re:split(atom_to_list(node()), "@", [{return, list}, unicode]), 153 | list_to_atom(lists:concat([Node, "@", Host])) 154 | end. 155 | 156 | append_node_suffix(Name, Suffix) -> 157 | rand:seed(exsss, os:timestamp()), 158 | case re:split(Name, "@", [{return, list}, unicode]) of 159 | [Node, Host] -> 160 | list_to_atom(lists:concat([Node, Suffix, rand:uniform(1000), "@", Host])); 161 | [Node] -> 162 | list_to_atom(lists:concat([Node, Suffix, rand:uniform(1000)])) 163 | end. 164 | 165 | %% convert string to erlang term 166 | consult([]) -> 167 | {ok, []}; 168 | consult(Bin) when is_binary(Bin)-> 169 | consult(binary_to_list(Bin)); 170 | consult(Str) when is_list(Str) -> 171 | %% add '.' if the string doesn't end in one 172 | Normalized = 173 | case lists:reverse(Str) of 174 | [$. | _] -> Str; 175 | R -> lists:reverse([$. | R]) 176 | end, 177 | 178 | case erl_scan:string(Normalized) of 179 | {ok, Tokens, _} -> 180 | case erl_parse:parse_term(Tokens) of 181 | {ok, Args} -> 182 | {ok, Args}; 183 | {error, {_, _, ErrorDescriptor}} -> 184 | {error, erl_parse:format_error(ErrorDescriptor)} 185 | end; 186 | {error, {_, _, ErrorDescriptor}} -> 187 | {error, erl_scan:format_error(ErrorDescriptor)} 188 | end. 189 | 190 | %% string:join/2 copy; string:join/2 is getting obsoleted 191 | %% and replaced by lists:join/2, but lists:join/2 is too new 192 | %% for version support (only appeared in 19.0) so it cannot be 193 | %% used. Instead we just adopt join/2 locally and hope it works 194 | %% for most unicode use cases anyway. 195 | join([], Sep) when is_list(Sep) -> 196 | []; 197 | join([H|T], Sep) -> 198 | H ++ lists:append([Sep ++ X || X <- T]). 199 | -------------------------------------------------------------------------------- /priv/templates/psutil: -------------------------------------------------------------------------------- 1 | #! /usr/bin/pwsh 2 | # Utility functions for powershell script files 3 | 4 | function Find-ERTS() 5 | { 6 | param ( 7 | [Parameter(Mandatory=$true, Position=0)] 8 | [string] $RelRoot, 9 | [Parameter(Mandatory=$true, Position=1)] 10 | [string] $Vsn 11 | ) 12 | 13 | if (Test-Path "$RelRoot\erts-$Vsn") { 14 | # Set the ERTS dir from the passed in erts_vsn 15 | return @($RelRoot, "$RelRoot\erts-$Vsn") 16 | } 17 | 18 | # Get the ERTS dir from erl 19 | $erl = (Get-Command erl).source 20 | $erl_root = & $erl -boot no_dot_erlang -noshell -eval 'io:format(\"~s\", [filename:nativename(code:root_dir())]), halt().' 21 | if (Test-Path "$erl_root\erts-$Vsn") { 22 | return @($erl_root, "$erl_root\erts-$Vsn") 23 | } 24 | 25 | # Expected $vsn but not found, get ERTS version installed 26 | $erts_vsn = & $erl -boot no_dot_erlang -noshell -eval 'io:format(\"~s\", [erlang:system_info(version)]), halt().' 27 | if (!(Test-Path "$erl_root\erts-$erts_vsn")) { 28 | Write-Error "Can not run the release. There is no ERTS bundled with the release or found on the system." 29 | # Terminates here due to $ErrorActionPreference = "Stop" 30 | } 31 | 32 | Write-Warning "Exact ERTS version ($Vsn) match not found, instead using $erts_vsn}. The release may fail to run." 33 | return @($erl_root, "$erl_root\erts-$erts_vsn") 34 | } 35 | 36 | function Find-BootScript() 37 | { 38 | param ( 39 | [Parameter(Mandatory=$true, Position=0)] 40 | [string] $RelDir, 41 | [Parameter(Mandatory=$true, Position=1)] 42 | [string] $RelName 43 | ) 44 | 45 | if (Test-Path "$RelDir\$RelName.boot") { 46 | return "$RelDir\$RelName" 47 | } 48 | 49 | if (Test-Path "$RelDir\start.boot") { 50 | return "$RelDir\start" 51 | } 52 | 53 | Write-Error "No boot script found in $RelDir" 54 | } 55 | 56 | function Find-FormatConfig() 57 | { 58 | param ( 59 | [Parameter(Mandatory=$true, Position=0)] 60 | [string] $RelDir, 61 | [Parameter(Mandatory=$true, Position=1)] 62 | [string] $File 63 | ) 64 | 65 | $in = $out = "$RelDir\$File" 66 | if (Test-Path "$in.src") { 67 | # apply the environment variable substitution 68 | Format-OSVars "$in.src" $out 69 | } 70 | elseif (Test-Path env:RELX_REPLACE_OS_VARS) { 71 | # If vm.args.orig or sys.config.orig is present then use that 72 | if (Test-Path "$in.orig") { 73 | $in = "$in.orig" 74 | } 75 | # if they are both the same, then ensure that we don't clobber 76 | # the file by saving a backup with the .orig extension 77 | if ($in -eq $out) { 78 | Copy-Item $in "$in.orig" 79 | } 80 | # apply the environment variable substitution 81 | Format-OSVars $in $out 82 | } 83 | else { 84 | # If vm.arg.orig or sys.config.orig is present then use that 85 | if (Test-Path "$in.orig") { 86 | $in = "$in.orig" 87 | } 88 | if ($in -ne $out) { 89 | Copy-Item $in $out 90 | } 91 | } 92 | 93 | return $out 94 | } 95 | 96 | function Format-OSVars() 97 | { 98 | param( 99 | [Parameter(Mandatory=$true, Position=0)] 100 | [string] $In, 101 | [Parameter(Mandatory=$true, Position=1)] 102 | [string] $Out 103 | ) 104 | 105 | $content = Get-Content $In 106 | $matches = ([regex]'[$]{(?[^}]*)}').Matches($content) 107 | foreach ($match in $matches) { 108 | $var = $match.groups['var'].value 109 | $val = Invoke-Expression "`$env:${var}" 110 | $content = $content.replace("`${$var}", $val) 111 | } 112 | Set-Content -Path $Out -Value $content -Encoding ASCII 113 | } 114 | 115 | function Get-NodeAndHost() 116 | { 117 | param( 118 | [string]$vmargs 119 | ) 120 | 121 | $node_type, $node_name = Get-Content $vmargs ` 122 | | Select-String '(-s{0,1}name)\s+([^\s]+)' ` 123 | | ForEach-Object { ` 124 | @($_.matches[0].groups[1].value, ` 125 | $_.matches[0].groups[2].value) ` 126 | } 127 | 128 | if ($node_name -match '@') { 129 | $node_name, $hostname = $node_name -split '@' 130 | } 131 | 132 | # if no hostname is set, attempt to pick one from the env 133 | if ([string]::IsNullOrEmpty($hostname) -and (Test-Path env:COMPUTERNAME)) { 134 | if ($node_type -eq '-sname') { 135 | $hostname = $env:COMPUTERNAME 136 | } 137 | elseif (Test-Path env:USERDNSDOMAIN) { 138 | $hostname = "$env:COMPUTERNAME.$env:USERDNSDOMAIN" 139 | } 140 | } 141 | 142 | # Add @ to hostname if not empty so that we can just concatenate values safely 143 | if (![string]::IsNullOrEmpty($hostname)) { 144 | $hostname = "@$hostname" 145 | } 146 | 147 | # Return to caller 148 | @($node_type, $node_name, $hostname) 149 | } 150 | 151 | function Get-Cookie() 152 | { 153 | param( 154 | [string]$vmargs 155 | ) 156 | 157 | $cookie = Get-Content $vmargs ` 158 | | Select-String '-setcookie\s+([^\s]+)' ` 159 | | ForEach-Object { ` 160 | @($_.matches[0].groups[1].value) ` 161 | } 162 | 163 | if ([string]::IsNullOrEmpty($cookie)) { 164 | $default_cookie_file = "$env:USERPROFILE\.erlang.cookie" 165 | if (Test-Path $default_cookie_file) { 166 | $cookie = Get-Content $default_cookie_file | Select-Object -First 1 167 | } 168 | else { 169 | Write-Warning "No cookie is set or found. This limits the scripts functionality, installing, upgrading, rpc and getting a list of versions will not work." 170 | return $null 171 | } 172 | } 173 | 174 | return $cookie 175 | } -------------------------------------------------------------------------------- /priv/templates/sys_config: -------------------------------------------------------------------------------- 1 | %% Thanks to Ulf Wiger at Ericcson for these comments: 2 | %% 3 | %% This file is identified via the erl command line option -config File. 4 | %% Note that File should have no extension, e.g. 5 | %% erl -config .../sys (if this file is called sys.config) 6 | %% 7 | %% In this file, you can redefine application environment variables. 8 | %% This way, you don't have to modify the .app files of e.g. OTP applications. 9 | []. 10 | -------------------------------------------------------------------------------- /priv/templates/vm_args: -------------------------------------------------------------------------------- 1 | ## Name of the node 2 | -sname {{ rel_name }} 3 | 4 | ## Cookie for distributed erlang 5 | -setcookie {{ rel_name }} 6 | 7 | ## This is now the default as of OTP-26 8 | ## Multi-time warp mode in combination with time correction is the preferred configuration. 9 | ## It is only not the default in Erlang itself because it could break older systems. 10 | +C multi_time_warp 11 | 12 | ## Uncomment the following line if running in a container. 13 | ## +sbwt none 14 | 15 | ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive 16 | ## (Disabled by default..use with caution!) 17 | ##-heart 18 | 19 | ## Increase number of concurrent ports/sockets 20 | ##-env ERL_MAX_PORTS 4096 21 | 22 | ## Tweak GC to run more often 23 | ##-env ERL_FULLSWEEP_AFTER 10 24 | 25 | # +B [c | d | i] 26 | # Option c makes Ctrl-C interrupt the current shell instead of invoking the emulator break 27 | # handler. Option d (same as specifying +B without an extra option) disables the break handler. # Option i makes the emulator ignore any break signal. 28 | # If option c is used with oldshell on Unix, Ctrl-C will restart the shell process rather than 29 | # interrupt it. 30 | # Disable the emulator break handler 31 | # it easy to accidentally type ctrl-c when trying 32 | # to reach for ctrl-d. ctrl-c on a live node can 33 | # have very undesirable results 34 | ##+Bi 35 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- 2 | %% Dependencies ================================================================ 3 | {deps, [{bbmustache, "~>1.10"}]}. 4 | 5 | %% Compiler Options ============================================================ 6 | {erl_opts, [debug_info, warnings_as_errors, inline]}. 7 | 8 | %% Profiles ==================================================================== 9 | 10 | {profiles, [{test, [{erl_opts, [nowarn_export_all]}]}, 11 | {docs, [{edoc_opts, [{preprocess, true}]}]}]}. 12 | 13 | {overrides, [{override, bbmustache, [{deps, []}, {plugins, []}]}]}. 14 | 15 | {ct_opts, [{cover_spec, "cover.spec"}, 16 | {ct_hooks, [cth_surefire]}]}. 17 | 18 | {cover_enabled, true}. 19 | {cover_print_enabled, true}. 20 | {cover_excl_mods, [bin_dtl, erl_script_dtl, extended_bin_dtl, 21 | extended_bin_windows_dtl, erl_ini_dtl, 22 | bin_windows_dtl, nodetool_dtl, psutil_dtl, 23 | bin_windows_ps_dtl, extended_bin_windows_ps_dtl, 24 | install_upgrade_escript_dtl, 25 | sys_config_dtl, vm_args_dtl, relx]}. 26 | 27 | %% ignore warnings about unused exports for functions that are part of 28 | %% the external API for relx. 29 | {xref_ignores, [{relx, release, 3}, 30 | {relx, build_release, 2}, 31 | {relx, build_release, 3}, 32 | {relx, build_tar, 2}, 33 | {relx, build_tar, 3}, 34 | {relx, build_relup, 4}, 35 | {relx, format_error, 1}, 36 | 37 | %% probably will want this format for debug logs later 38 | {rlx_app_info, format, 1}, 39 | {rlx_app_info, format, 2}, 40 | {rlx_state, format, 1}, 41 | {rlx_state, format, 2}, 42 | {rlx_state, dev_mode, 1}, 43 | {rlx_state, filter_xref_warning, 2}, 44 | 45 | %% used in tests 46 | {rlx_app_info, new, 5}, 47 | {rlx_app_info, new, 6}, 48 | {rlx_app_info, new, 7}, 49 | {rlx_file_utils, type, 1}, 50 | {rlx_file_utils, write, 2}, 51 | {rlx_release, applications, 1}, 52 | {rlx_release, app_specs, 1}, 53 | {rlx_state, realized_releases, 1}, 54 | 55 | {rlx_app_info, format_error, 1}, 56 | {rlx_tar, format_error, 1}, 57 | {rlx_assemble, format_error, 1}, 58 | {rlx_config, format_error, 1}, 59 | {rlx_overlay, format_error, 1}, 60 | {rlx_release, format_error, 1}, 61 | {rlx_relup, format_error, 1}, 62 | {rlx_resolve, format_error, 1}, 63 | {rlx_file_utils, format_error, 1}]}. 64 | -------------------------------------------------------------------------------- /rebar.lock: -------------------------------------------------------------------------------- 1 | {"1.2.0", 2 | [{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.10.0">>},0}]}. 3 | [ 4 | {pkg_hash,[ 5 | {<<"bbmustache">>, <<"DDC927463F0E95D66CDAC889153AF08015D609124D6D79006C248AD2DE7F6ECD">>}]}, 6 | {pkg_hash_ext,[ 7 | {<<"bbmustache">>, <<"43EFFA3FD4BB9523157AF5A9E2276C493495B8459FC8737144AA186CB13CE2EE">>}]} 8 | ]. 9 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/README.md: -------------------------------------------------------------------------------- 1 | check_undefined_test 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/apps/check_undefined_test/src/check_undefined_test.app.src: -------------------------------------------------------------------------------- 1 | {application, check_undefined_test, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {check_undefined_test_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/apps/check_undefined_test/src/check_undefined_test_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc check_undefined_test public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(check_undefined_test_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | %% calls to functions that should result in warnings during release building 14 | crypto:start(), 15 | notamodule:dosomething(), 16 | 17 | check_undefined_test_sup:start_link(). 18 | 19 | stop(_State) -> 20 | ok. 21 | 22 | %% internal functions 23 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/apps/check_undefined_test/src/check_undefined_test_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc check_undefined_test top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(check_undefined_test_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/check_undefined_test.test: -------------------------------------------------------------------------------- 1 | $ TERM=dumb rebar3 release 2 | > 3 | ===> Verifying dependencies... 4 | ===> Analyzing applications... 5 | ===> Compiling check_undefined_test 6 | ===> Assembling release check_undefined_test-0.1.0... 7 | ===> There are missing function calls in the release. 8 | ===> Make sure all applications needed at runtime are included in the release. 9 | ===> check_undefined_test_app:start/2 calls undefined function crypto:start/0 10 | ===> check_undefined_test_app:start/2 calls undefined function notamodule:dosomething/0 11 | ===> Release successfully assembled: _build/default/rel/check_undefined_test 12 | >= 0 -------------------------------------------------------------------------------- /shelltests/check_undefined_test/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {check_undefined_test, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname check_undefined_test 2 | 3 | -setcookie check_undefined_test_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/check_undefined_test/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {check_undefined_test, "0.1.0"}, 5 | [check_undefined_test, 6 | sasl]}, 7 | 8 | {mode, dev}, 9 | 10 | %% automatically picked up if the files 11 | %% exist but can be set manually, which 12 | %% is required if the names aren't exactly 13 | %% sys.config and vm.args 14 | {sys_config, "./config/sys.config"}, 15 | {vm_args, "./config/vm.args"} 16 | 17 | %% the .src form of the configuration files do 18 | %% not require setting RELX_REPLACE_OS_VARS 19 | %% {sys_config_src, "./config/sys.config.src"}, 20 | %% {vm_args_src, "./config/vm.args.src"} 21 | ]}. 22 | 23 | {profiles, [{prod, [{relx, 24 | [%% prod is the default mode when prod 25 | %% profile is used, so does not have 26 | %% to be explicitly included like this 27 | {mode, prod} 28 | 29 | %% use minimal mode to exclude ERTS 30 | %% {mode, minimal} 31 | ] 32 | }]}]}. 33 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/README.md: -------------------------------------------------------------------------------- 1 | replace_os_vars_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/config/included.config: -------------------------------------------------------------------------------- 1 | [ 2 | {replace_os_vars_tests, [{var1_included, "${VAR1}"}]} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/config/sys.config: -------------------------------------------------------------------------------- 1 | [{replace_os_vars_tests, [{var1, "${VAR1}"}]}]. 2 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname node1@localhost 2 | -setcookie cookie1 -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/dev_replace_os_vars_tests.test: -------------------------------------------------------------------------------- 1 | $ rebar3 release 2 | > / Release successfully assembled: / 3 | >= 0 4 | 5 | $ RELX_REPLACE_OS_VARS=1 VAR1=101 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 6 | >= 0 7 | 8 | $ sleep 1 9 | >= 0 10 | 11 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 12 | > 13 | pong 14 | >= 0 15 | 16 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 17 | > 18 | "101" 19 | >= 0 20 | 21 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 22 | > 23 | "node1" 24 | >= 0 25 | 26 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 27 | > 28 | cookie1 29 | >= 0 30 | 31 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 32 | >= 0 33 | 34 | # run without RELX_REPLACE_OS_VARS and VAR1 should not be replaced 35 | $ VAR1=201 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 36 | 37 | $ sleep 1 38 | >= 0 39 | 40 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 41 | > 42 | pong 43 | >= 0 44 | 45 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 46 | > 47 | "${VAR1}" 48 | >= 0 49 | 50 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 51 | > 52 | "node1" 53 | >= 0 54 | 55 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 56 | > 57 | cookie1 58 | >= 0 59 | 60 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 61 | >= 0 62 | 63 | $ rebar3 as dev release 64 | > / Release successfully assembled: / 65 | >= 0 66 | 67 | $ file _build/dev/rel/replace_os_vars_tests/releases/0.1.0/sys.config 68 | > / symbolic link / 69 | >= 0 70 | 71 | $ RELX_REPLACE_OS_VARS=1 VAR1=101 ./_build/dev/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 72 | >= 0 73 | 74 | $ sleep 1 75 | >= 0 76 | 77 | $ ./_build/dev/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 78 | > 79 | pong 80 | >= 0 81 | 82 | $ ls _build/dev/rel/replace_os_vars_tests/releases/0.1.0/sys.config.orig 83 | > 84 | _build/dev/rel/replace_os_vars_tests/releases/0.1.0/sys.config.orig 85 | >= 0 86 | 87 | $ ./_build/dev/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 88 | > 89 | "101" 90 | >= 0 91 | 92 | $ ./_build/dev/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 93 | >= 0 94 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {replace_os_vars_tests, "0.1.0"}, 5 | [replace_os_vars_tests]}, 6 | {sys_config, "config/sys.config"}, 7 | {vm_args, "config/vm.args"} 8 | ]}. 9 | 10 | {profiles, [{dev, [{relx, [{dev_mode, true}]}]}]}. 11 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/src/replace_os_vars_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, replace_os_vars_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/dev_replace_os_vars_tests/src/replace_os_vars_tests.erl: -------------------------------------------------------------------------------- 1 | -module(replace_os_vars_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/README.md: -------------------------------------------------------------------------------- 1 | replace_os_vars_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/included.config: -------------------------------------------------------------------------------- 1 | [ 2 | {replace_os_vars_tests, [{var1_included, "${VAR1}"}]} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/pathname_escape.sys.config: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/pathname_escape.vm.args: -------------------------------------------------------------------------------- 1 | -sname node@localhost 2 | -setcookie cookie1 3 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/sys.config: -------------------------------------------------------------------------------- 1 | [{replace_os_vars_tests, [{var1, "${VAR1}"}]}, 2 | "releases/0.1.0/config/included.config"]. 3 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/vm-2.args: -------------------------------------------------------------------------------- 1 | -sname node1@localhost 2 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/vm-4.args: -------------------------------------------------------------------------------- 1 | -args_file /tmp/vm-3.args 2 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/vm-5.args: -------------------------------------------------------------------------------- 1 | -args_file /tmp/vm-6.args -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/vm-6.args: -------------------------------------------------------------------------------- 1 | -args_file /tmp/vm-2.args -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/config/vm.args: -------------------------------------------------------------------------------- 1 | -args_file /tmp/vm-2.args 2 | 3 | -setcookie cookie1 -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/extended_start_script_tests.tests: -------------------------------------------------------------------------------- 1 | # -args_file must be absolute so we copy them to /tmp 2 | # vm-5.args references vm-6.args. We copy it to vm-2.args 3 | # since that is the one included by vm.args and are testing 4 | # that the script catches circular references 5 | $ cp config/vm-5.args /tmp/vm-2.args 6 | >= 0 7 | 8 | # vm-6.args references vm-5.args 9 | $ cp config/vm-6.args /tmp/vm-6.args 10 | >= 0 11 | 12 | $ rebar3 release 13 | > / Release successfully assembled: / 14 | >= 0 15 | 16 | # circular args_file must fail 17 | $ RELX_REPLACE_OS_VARS=1 VAR1=101 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 18 | > 19 | circular reference to /tmp/vm-2.args encountered in /tmp/vm-6.args 20 | >= 5 21 | 22 | $ cp config/vm-4.args /tmp/vm-2.args 23 | >= 0 24 | 25 | # pass args_file that doesn't exist to verify script catches it 26 | $ RELX_REPLACE_OS_VARS=1 VAR1=101 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 27 | > 28 | /tmp/vm-3.args not found 29 | >= 3 30 | 31 | $ cp config/vm-2.args /tmp/vm-2.args 32 | >= 0 33 | 34 | # pass arg directly to verify it also works 35 | $ RELX_REPLACE_OS_VARS=1 VAR1=101 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon -replace_os_vars_tests baz "\"bat zing\"" 36 | >= 0 37 | 38 | $ sleep 1 39 | >= 0 40 | 41 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 42 | > 43 | pong 44 | >= 0 45 | 46 | # check install_upgrade escript through its versions command 47 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests versions 48 | > 49 | Installed versions: 50 | * 0.1.0 permanent 51 | >= 0 52 | 53 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 54 | > 55 | "101" 56 | >= 0 57 | 58 | # rpc works with and without dot at the end of arguments 59 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests rpc application get_env "[replace_os_vars_tests, var1, ok]" 60 | > 61 | "101" 62 | >= 0 63 | 64 | # rpc works with and without dot at the end of arguments 65 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests rpc application get_env "[replace_os_vars_tests, var1, ok]." 66 | > 67 | "101" 68 | >= 0 69 | 70 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, baz), V.' 71 | > 72 | "bat zing" 73 | >= 0 74 | 75 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1_included), V.' 76 | > 77 | "${VAR1}" 78 | >= 0 79 | 80 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 81 | > 82 | "node1" 83 | >= 0 84 | 85 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 86 | > 87 | cookie1 88 | >= 0 89 | 90 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 91 | >= 0 92 | 93 | # run without RELX_REPLACE_OS_VARS and VAR1 should not be replaced 94 | $ VAR1=201 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 95 | 96 | $ sleep 1 97 | >= 0 98 | 99 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 100 | > 101 | pong 102 | >= 0 103 | 104 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 105 | > 106 | "${VAR1}" 107 | >= 0 108 | 109 | 110 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1_included), V.' 111 | > 112 | "${VAR1}" 113 | >= 0 114 | 115 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 116 | > 117 | "node1" 118 | >= 0 119 | 120 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 121 | > 122 | cookie1 123 | >= 0 124 | 125 | # verify NODETOOL_TIMEOUT still works and is converted to an integer 126 | $ NODETOOL_TIMEOUT=1000 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests rpc timer sleep "[2000]." 127 | > 128 | RPC to node1@localhost failed: timeout 129 | >= 1 130 | 131 | # verify RELX_RPC_TIMEOUT variable works 132 | $ RELX_RPC_TIMEOUT=1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests rpc timer sleep "[2000]." 133 | > 134 | RPC to node1@localhost failed: timeout 135 | >= 1 136 | 137 | # fail if NODETOOL_TIMEOUT is not a number 138 | $ NODETOOL_TIMEOUT=foo ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests rpc timer sleep "[2000]." 139 | >2 /Illegal number:/ 140 | >= 2 141 | 142 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 143 | >= 0 144 | 145 | # we run these tests only on 23.1 so we can test that ERL_DIST_PORT causes epmd to not start 146 | $ pkill epmd 147 | 148 | $ ERL_DIST_PORT=8001 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 149 | 150 | $ sleep 1 151 | >= 0 152 | 153 | # verify epmd isn't running 154 | $ pidof epmd 155 | >= 1 156 | 157 | $ ERL_DIST_PORT=8001 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 158 | > 159 | pong 160 | >= 0 161 | 162 | $ ERL_DIST_PORT=8001 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 163 | >= 0 164 | 165 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests start 166 | 167 | $ sleep 1 168 | >= 0 169 | 170 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 171 | > 172 | pong 173 | >= 0 174 | 175 | $ ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 176 | >= 0 177 | 178 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/extended_start_script_tests_pathname_escape.test: -------------------------------------------------------------------------------- 1 | $ rebar3 as pathname_escape tar -n pathname_escape 2 | > / Tarball successfully created: / 3 | >= 0 4 | 5 | # make a file _build/p that contains all bytes 0x01..0x0f except 6 | # 0x00 (NUL) and 0x2f (/) : because those must not be part of a POSIX filename 7 | # 8 | # also exclude 0x22 ("), 0x60 (`) and anything > 0x0f : the extendend_bin 9 | # script can handle it but various parts of the erlang runtime (that exec /bin/sh 10 | # with unsanatized input) would fail. 11 | # 12 | # use the content of the _build/p as filename component of the release ROOTDIR 13 | # 14 | $ for c in $(for x in $(seq 1 33) $(seq 35 46) $(seq 48 95) $(seq 97 127); do printf '%03o\n' $x; done); do printf \\$c ; done > ./_build/p 15 | >= 0 16 | 17 | $ mkdir -p "./_build/test/$(cat ./_build/p)" 18 | >= 0 19 | 20 | $tar -C "./_build/test/$(cat ./_build/p)" -xf ./_build/pathname_escape/rel/pathname_escape/pathname_escape-0.1.0.tar.gz 21 | 22 | $ "./_build/test/$(cat ./_build/p)/bin/pathname_escape" daemon 23 | >= 0 24 | 25 | $ sleep 1 26 | >= 0 27 | 28 | $ "./_build/test/$(cat ./_build/p)/bin/pathname_escape" ping 29 | > 30 | pong 31 | >= 0 32 | 33 | $ "./_build/test/$(cat ./_build/p)/bin/pathname_escape" stop 34 | >= 0 35 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {replace_os_vars_tests, "0.1.0"}, 5 | [replace_os_vars_tests, 6 | sasl]}, 7 | {sys_config, "config/sys.config"}, 8 | {vm_args, "config/vm.args"}, 9 | 10 | {overlay, [ 11 | {mkdir, "releases/{{release_version}}/config"}, 12 | {template, "config/included.config", "releases/{{release_version}}/config/included.config"}]}]}. 13 | 14 | {profiles, [ 15 | {pathname_escape, [ 16 | {relx, [ 17 | {release, {pathname_escape, "0.1.0"}, [sasl]}, 18 | {sys_config, "config/pathname_escape.sys.config"}, 19 | {vm_args, "config/pathname_escape.vm.args"}] 20 | }] 21 | }] 22 | }. 23 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/src/replace_os_vars_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, replace_os_vars_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib, 8 | sasl 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/extended_start_script_tests/src/replace_os_vars_tests.erl: -------------------------------------------------------------------------------- 1 | -module(replace_os_vars_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/extension_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/extension_tests/README.md: -------------------------------------------------------------------------------- 1 | extension_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/extension_tests/bar: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo \{bar, $REL_NAME, \'$NAME\', $COOKIE\}. 3 | exit 0 -------------------------------------------------------------------------------- /shelltests/extension_tests/baz: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo teststring -------------------------------------------------------------------------------- /shelltests/extension_tests/extension_tests.test: -------------------------------------------------------------------------------- 1 | $ rebar3 release 2 | > /===> Release successfully assembled:/ 3 | >= 0 4 | 5 | $ ./_build/default/rel/extension_tests/bin/extension_tests daemon 6 | >= 0 7 | 8 | $ sleep 1 9 | >= 0 10 | 11 | $ ./_build/default/rel/extension_tests/bin/extension_tests ping 12 | > 13 | pong 14 | >= 0 15 | 16 | $ _build/default/rel/extension_tests/bin/extension_tests bar 17 | > /{bar, extension_tests, 'extension_tests@.*', extension_tests}./ 18 | >= 0 19 | 20 | $ _build/default/rel/extension_tests/bin/extension_tests foo 21 | > 22 | teststring 23 | >= 42 24 | 25 | # fail if there is no explicit exit 0 in the extension script 26 | $ _build/default/rel/extension_tests/bin/extension_tests baz 27 | > 28 | teststring 29 | >= 1 30 | 31 | $ ./_build/default/rel/extension_tests/bin/extension_tests stop 32 | >= 0 33 | -------------------------------------------------------------------------------- /shelltests/extension_tests/foo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo teststring 3 | exit 42 -------------------------------------------------------------------------------- /shelltests/extension_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {extension_tests, "0.1.0"}, 5 | [extension_tests]}, 6 | {extended_start_script_extensions, [{bar, "extensions/bar"}, 7 | {foo, "extensions/foo"}, 8 | {baz, "extensions/baz"}]}, 9 | {overlay, [{copy, "./bar", "bin/extensions/bar"}, 10 | {copy, "./foo", "bin/extensions/foo"}, 11 | {copy, "./baz", "bin/extensions/baz"}]} 12 | ]}. 13 | -------------------------------------------------------------------------------- /shelltests/extension_tests/src/extension_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, extension_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/extension_tests/src/extension_tests.erl: -------------------------------------------------------------------------------- 1 | -module(extension_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/README.md: -------------------------------------------------------------------------------- 1 | force_nodetool_tests 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/apps/force_nodetool_tests/src/force_nodetool_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, force_nodetool_tests, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {force_nodetool_tests_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/apps/force_nodetool_tests/src/force_nodetool_tests_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc force_nodetool_tests public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(force_nodetool_tests_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | force_nodetool_tests_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/apps/force_nodetool_tests/src/force_nodetool_tests_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc force_nodetool_tests top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(force_nodetool_tests_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {force_nodetool_tests, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname force_nodetool_tests 2 | 3 | -setcookie force_nodetool_tests_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/force_nodetool_tests.test: -------------------------------------------------------------------------------- 1 | $ TERM=dumb rebar3 release 2 | > /Release successfully assembled:/ 3 | >= 0 4 | 5 | $ ERL_DIST_PORT=8001 ./_build/default/rel/force_nodetool_tests/bin/force_nodetool_tests daemon 6 | 7 | $ sleep 1 8 | >= 0 9 | 10 | # force nodetool so that stdout is printed from rpc calls 11 | $ USE_NODETOOL=true ./_build/default/rel/force_nodetool_tests/bin/force_nodetool_tests rpc io format "[\"hello\\n\"]" 12 | > 13 | hello 14 | ok 15 | >= 0 16 | 17 | # using erl_call instead of nodetool means no stdout from the node 18 | $ ./_build/default/rel/force_nodetool_tests/bin/force_nodetool_tests rpc io format "[\"hello\\n\"]" 19 | > 20 | ok 21 | >= 0 22 | 23 | $ ./_build/default/rel/force_nodetool_tests/bin/force_nodetool_tests stop 24 | >= 0 25 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {force_nodetool_tests, "0.1.0"}, 5 | [force_nodetool_tests, 6 | sasl]}, 7 | 8 | {mode, dev}, 9 | 10 | %% automatically picked up if the files 11 | %% exist but can be set manually, which 12 | %% is required if the names aren't exactly 13 | %% sys.config and vm.args 14 | {sys_config, "./config/sys.config"}, 15 | {vm_args, "./config/vm.args"} 16 | 17 | %% the .src form of the configuration files do 18 | %% not require setting RELX_REPLACE_OS_VARS 19 | %% {sys_config_src, "./config/sys.config.src"}, 20 | %% {vm_args_src, "./config/vm.args.src"} 21 | ]}. 22 | 23 | {profiles, [{prod, [{relx, 24 | [%% prod is the default mode when prod 25 | %% profile is used, so does not have 26 | %% to be explicitly included like this 27 | {mode, prod} 28 | 29 | %% use minimal mode to exclude ERTS 30 | %% {mode, minimal} 31 | ] 32 | }]}]}. 33 | -------------------------------------------------------------------------------- /shelltests/force_nodetool_tests/rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/README.md: -------------------------------------------------------------------------------- 1 | hooks_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname hooks_tests@localhost 2 | 3 | -setcookie hooks_tests -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks/post_start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $* 3 | echo \{post_start, $REL_NAME, \'$NAME\', $COOKIE\}. >> test -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks/post_stop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $* 3 | echo \{post_stop, $REL_NAME, \'$NAME\', $COOKIE\}. >> test -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks/pre_start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $* 3 | echo \{pre_start, $REL_NAME, \'$NAME\', $COOKIE\}. >> test -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks/pre_stop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $* 3 | echo \{pre_stop, $REL_NAME, \'$NAME\', $COOKIE\}. >> test -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks/status: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $* 3 | echo \{status, $REL_NAME, \'$NAME\', $COOKIE\}. -------------------------------------------------------------------------------- /shelltests/hooks_tests/hooks_tests.test: -------------------------------------------------------------------------------- 1 | $ rebar3 release 2 | > / Release successfully assembled: / 3 | >= 0 4 | 5 | $ ./_build/default/rel/hooks_tests/bin/hooks_tests daemon 6 | >= 0 7 | 8 | # no need to sleep because of the wait_for_vm_start hook 9 | 10 | $ ./_build/default/rel/hooks_tests/bin/hooks_tests ping 11 | > 12 | pong 13 | >= 0 14 | 15 | $ ./_build/default/rel/hooks_tests/bin/hooks_tests status 16 | > 17 | {status, hooks_tests, 'hooks_tests@localhost', hooks_tests}. 18 | >= 0 19 | 20 | $ ./_build/default/rel/hooks_tests/bin/hooks_tests stop 21 | >= 0 22 | 23 | $ ls ./_build/default/rel/hooks_tests/foo.pid 24 | > 25 | ./_build/default/rel/hooks_tests/foo.pid 26 | >= 0 27 | 28 | $ cat ./_build/default/rel/hooks_tests/test 29 | > 30 | {pre_start, hooks_tests, 'hooks_tests@localhost', hooks_tests}. 31 | {post_start, hooks_tests, 'hooks_tests@localhost', hooks_tests}. 32 | {pre_stop, hooks_tests, 'hooks_tests@localhost', hooks_tests}. 33 | {post_stop, hooks_tests, 'hooks_tests@localhost', hooks_tests}. 34 | >= 0 35 | 36 | $ rm ./_build/default/rel/hooks_tests/test 37 | > 38 | >= 0 39 | 40 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {hooks_tests, "0.1.0"}, 5 | [hooks_tests]}, 6 | {vm_args, "config/vm.args"}, 7 | {extended_start_script_hooks, [ 8 | {pre_start, [ 9 | {custom, "hooks/pre_start"} 10 | ]}, 11 | {post_start, [ 12 | wait_for_vm_start, 13 | {pid, "foo.pid"}, 14 | wait_for_vm_start, 15 | {custom, "hooks/post_start"} 16 | ]}, 17 | {pre_stop, [ 18 | {custom, "hooks/pre_stop"} 19 | ]}, 20 | {post_stop, [ 21 | {custom, "hooks/post_stop"} 22 | ]}, 23 | {status, [ 24 | {custom, "hooks/status"} 25 | ]} 26 | ]}, 27 | 28 | {overlay, [{copy, "./hooks/status", "bin/hooks/status"}, 29 | {copy, "./hooks/{pre,post}_{start,stop}", "bin/hooks/"}]}]}. 30 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/src/hooks_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, hooks_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/hooks_tests/src/hooks_tests.erl: -------------------------------------------------------------------------------- 1 | -module(hooks_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/README.md: -------------------------------------------------------------------------------- 1 | overlay_error_test 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/apps/overlay_error_test/src/overlay_error_test.app.src: -------------------------------------------------------------------------------- 1 | {application, overlay_error_test, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {overlay_error_test_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/apps/overlay_error_test/src/overlay_error_test_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc overlay_error_test public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(overlay_error_test_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | overlay_error_test_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/apps/overlay_error_test/src/overlay_error_test_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc overlay_error_test top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(overlay_error_test_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {overlay_error_test, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname overlay_error_test 2 | 3 | -setcookie overlay_error_test_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/overlay_error_test.test: -------------------------------------------------------------------------------- 1 | # baseline, no overlay 2 | $ rebar3 as prod release 3 | > / Release successfully assembled: / 4 | >= 0 5 | 6 | # {overlay, [{malformed, foo}]} 7 | $ rebar3 as malformed_error release 8 | > / Overlay section malformed: / 9 | >= 1 10 | 11 | 12 | # {overlay, [{mkdir, "releases/RELEASES"}]} 13 | $ rebar3 as mkdir_error release 14 | > / Unable to make directory / 15 | >= 1 16 | 17 | # {overlay, [{copy, "does_not_exist", "priv/something"}]} 18 | $ rebar3 as copy_error release 19 | > / Unable to copy from / 20 | >= 1 21 | 22 | # {overlay, [{template, "does_not_exist", "something"}]} 23 | $ rebar3 as template_read_error release 24 | > / Unable to read template file / 25 | >= 1 26 | 27 | # {overlay, [{template, "README.md", "releases"}]} 28 | $ rebar3 as template_write_error release 29 | > / Unable to write to / 30 | >= 1 31 | 32 | # {overlay, [{template, "README.md", "releases/RELEASES/foo"}]} 33 | $ rebar3 as template_dir_error release 34 | > / Unable to create enclosing directory for / 35 | >= 1 36 | 37 | # {overlay, [{chmod, "000", "does_not_exist"}]} 38 | $ rebar3 as chmod_error release 39 | > / Unable to chmod / 40 | >= 1 41 | 42 | # {mode, dev}, 43 | # {overlay, [{link, "README.md", "../../../../../../../../../../../../../../../../../../../../../../../../f"}]} 44 | $ rebar3 as link_error release 45 | > / Unable to symlink / 46 | >= 1 47 | -------------------------------------------------------------------------------- /shelltests/overlay_error_test/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {overlay_error_test, "0.1.0"}, 5 | [overlay_error_test, 6 | sasl]}, 7 | 8 | {mode, dev}, 9 | 10 | %% automatically picked up if the files 11 | %% exist but can be set manually, which 12 | %% is required if the names aren't exactly 13 | %% sys.config and vm.args 14 | {sys_config, "./config/sys.config"}, 15 | {vm_args, "./config/vm.args"} 16 | 17 | %% the .src form of the configuration files do 18 | %% not require setting RELX_REPLACE_OS_VARS 19 | %% {sys_config_src, "./config/sys.config.src"}, 20 | %% {vm_args_src, "./config/vm.args.src"} 21 | ]}. 22 | 23 | {profiles, [{prod, [{relx, 24 | [%% prod is the default mode when prod 25 | %% profile is used, so does not have 26 | %% to be explicitly included like this 27 | {mode, prod} 28 | 29 | %% use minimal mode to exclude ERTS 30 | %% {mode, minimal} 31 | ] 32 | }]}, 33 | {malformed_error, [{relx, 34 | [ 35 | {mode, prod}, 36 | {overlay, [{malformed, foo}]} 37 | ]}]}, 38 | {mkdir_error, [{relx, 39 | [ 40 | {mode, prod}, 41 | {overlay, [{mkdir, "releases/RELEASES"}]} 42 | ]}]}, 43 | {copy_error, [{relx, 44 | [ 45 | {mode, prod}, 46 | {overlay, [{copy, "does_not_exist", "something"}]} 47 | ]}]}, 48 | {template_read_error, [{relx, 49 | [ 50 | {mode, prod}, 51 | {overlay, [{template, "does_not_exist", "something"}]} 52 | ]}]}, 53 | {template_write_error, [{relx, 54 | [ 55 | {mode, prod}, 56 | {overlay, [{template, "README.md", "releases"}]} 57 | ]}]}, 58 | {template_dir_error, [{relx, 59 | [ 60 | {mode, prod}, 61 | {overlay, [{template, "README.md", "releases/RELEASES/foo"}]} 62 | ]}]}, 63 | {chmod_error, [{relx, 64 | [ 65 | {mode, prod}, 66 | {overlay, [{chmod, 0, "does_not_exist"}]} 67 | ]}]}, 68 | {link_error, [{relx, 69 | [ 70 | {mode, dev}, 71 | {overlay, [{link, "README.md", "../../../../../../../../../../../../../../../../../../../../../../../../f"}]} 72 | ]}]} 73 | 74 | ]}. 75 | -------------------------------------------------------------------------------- /shelltests/powershell_release/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/powershell_release/README.md: -------------------------------------------------------------------------------- 1 | powershell_release 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/powershell_release/apps/powershell_release/src/powershell_release.app.src: -------------------------------------------------------------------------------- 1 | {application, powershell_release, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {powershell_release_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/powershell_release/apps/powershell_release/src/powershell_release_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc powershell_release public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(powershell_release_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | powershell_release_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/powershell_release/apps/powershell_release/src/powershell_release_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc powershell_release top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(powershell_release_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/powershell_release/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {powershell_release, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/powershell_release/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname powershell_release 2 | 3 | -setcookie powershell_release_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/powershell_release/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {powershell_release, "0.1.0"}, 5 | [powershell_release, sasl]}, 6 | {sys_config, "./config/sys.config"}, 7 | {vm_args, "./config/vm.args"}, 8 | {extended_start_script, true}, 9 | {include_start_scripts_for, [powershell]}] 10 | }. 11 | 12 | {profiles, [{dev, [{relx, [{dev_mode, true}]}]}]}. 13 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/README.md: -------------------------------------------------------------------------------- 1 | extended_script_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname extended_script_tests 2 | 3 | ## Cookie for distributed erlang 4 | -setcookie extended_script_tests 5 | 6 | -heart 7 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {extended_script_tests, "0.1.0"}, 5 | [extended_script_tests]}, 6 | {vm_args, "config/vm.args"}]}. 7 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/reboot_restart_test.test: -------------------------------------------------------------------------------- 1 | $ rebar3 tar 2 | > /===> Tarball successfully created:/ 3 | >= 0 4 | 5 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests daemon 6 | >= 0 7 | 8 | $ sleep 1 9 | >= 0 10 | 11 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests ping 12 | > 13 | pong 14 | >= 0 15 | 16 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests pid > /tmp/est_pid1 17 | >= 0 18 | 19 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests reboot && sleep 1 20 | >= 0 21 | 22 | # takes a little bit for the reboot to complete 23 | $ while ! ./_build/default/rel/extended_script_tests/bin/extended_script_tests ping > /dev/null 2>&1 ; do sleep 1 ; done 24 | >= 0 25 | 26 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests pid > /tmp/est_pid2 27 | >= 0 28 | 29 | # should be different pids. command cmp will error with status code 1 30 | $ cmp -s /tmp/est_pid1 /tmp/est_pid2 31 | >= 1 32 | 33 | # now test restart which does not result in a new pid 34 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests pid > /tmp/est_pid1 35 | >= 0 36 | 37 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests restart 38 | >= 0 39 | 40 | $ ./_build/default/rel/extended_script_tests/bin/extended_script_tests pid > /tmp/est_pid2 41 | >= 0 42 | 43 | # should be different pids. command cmp will error with status code 1 44 | $ cmp -s /tmp/est_pid1 /tmp/est_pid2 45 | >= 0 46 | 47 | # kill heart to stop the release 48 | $ pkill heart 49 | >= 0 50 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/src/extended_script_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, extended_script_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/reboot_restart_test/src/extended_script_tests.erl: -------------------------------------------------------------------------------- 1 | -module(extended_script_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/README.md: -------------------------------------------------------------------------------- 1 | replace_os_vars_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/config/sys.config.src: -------------------------------------------------------------------------------- 1 | [{replace_os_vars_tests, [{var1, ${VAR1}}, 2 | {var2, "${VAR2:-201}"}, 3 | {var3, "${VAR3:-VA:-test3}"}, 4 | {var4, "${VAR4:-VAR4:-test4}"}, 5 | {var5, "${VAR5}"}, 6 | {var6, "${VAR6:-test6:-6}"}, 7 | {var7, "${VAR7:-test7:-7:-7}"}, 8 | {var8, ${VAR8:-888}}, 9 | {var9, "${VAR9}"}]}]. 10 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/config/vm.args.src: -------------------------------------------------------------------------------- 1 | -sname ${NODENAME}@localhost 2 | -setcookie ${COOKIE} -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {replace_os_vars_tests, "0.1.0"}, 5 | [replace_os_vars_tests]}, 6 | {sys_config_src, "config/sys.config.src"}, 7 | {vm_args_src, "config/vm.args.src"}]}. 8 | 9 | {profiles, [{dev, [{relx, [{dev_mode, true}]}]}]}. 10 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/replace_src_vars_tests.test: -------------------------------------------------------------------------------- 1 | $ rebar3 release 2 | > / Release successfully assembled: / 3 | >= 0 4 | 5 | $ RELX_OUT_FILE_PATH=/tmp NODENAME=node1 COOKIE=cookie1 VAR1=101 VAR2=201:-test2-2 VAR3=VA:-test3-2 VAR4=VAR4:-test4-2 VAR5=test5-2 VAR6=test6:-6-2 VAR7=test7:-7:-7-2 VAR9="ab&cd" ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 6 | >= 0 7 | 8 | $ sleep 1 9 | >= 0 10 | 11 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 12 | > 13 | pong 14 | >= 0 15 | 16 | # verify out file path works 17 | $ ls /tmp/sys.config 18 | > 19 | /tmp/sys.config 20 | >= 0 21 | 22 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 23 | > 24 | 101 25 | >= 0 26 | 27 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var2), V.' 28 | > 29 | "201:-test2-2" 30 | >= 0 31 | 32 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var3), V.' 33 | > 34 | "VA:-test3-2" 35 | >= 0 36 | 37 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var4), V.' 38 | > 39 | "VAR4:-test4-2" 40 | >= 0 41 | 42 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var5), V.' 43 | > 44 | "test5-2" 45 | >= 0 46 | 47 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var6), V.' 48 | > 49 | "test6:-6-2" 50 | >= 0 51 | 52 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var7), V.' 53 | > 54 | "test7:-7:-7-2" 55 | >= 0 56 | 57 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var8), V.' 58 | > 59 | 888 60 | >= 0 61 | 62 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, [$a,$b,$&,$c,$d] = V} = application:get_env(replace_os_vars_tests, var9), V.' 63 | > 64 | "ab&cd" 65 | >= 0 66 | 67 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 68 | > 69 | "node1" 70 | >= 0 71 | 72 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 73 | > 74 | cookie1 75 | >= 0 76 | 77 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 78 | >= 0 79 | 80 | # start without defaults being overridden 81 | $ NODENAME=node2 COOKIE=cookie2 VAR1=201 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 82 | 83 | $ sleep 1 84 | >= 0 85 | 86 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests ping 87 | > 88 | pong 89 | >= 0 90 | 91 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var1), V.' 92 | > 93 | 201 94 | >= 0 95 | 96 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var2), V.' 97 | > 98 | "201" 99 | >= 0 100 | 101 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '{ok, V} = application:get_env(replace_os_vars_tests, var6), V.' 102 | > 103 | "test6:-6" 104 | >= 0 105 | 106 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval '[Node,_] = re:split(atom_to_list(node()), "@"),binary_to_list(Node).' 107 | > 108 | "node2" 109 | >= 0 110 | 111 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests eval 'erlang:get_cookie().' 112 | > 113 | cookie2 114 | >= 0 115 | 116 | # fail to shutdown node1 which was already stopped 117 | $ NODENAME=node1 COOKIE=cookie1 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 118 | >= 1 119 | 120 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 121 | >= 0 122 | 123 | # test RELX_MULTI_NODE creates a sys.config with the node in the name 124 | $ RELX_MULTI_NODE=1 NODENAME=node2 COOKIE=cookie2 VAR1=201 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests daemon 125 | >= 0 126 | 127 | $ ls ./_build/default/rel/replace_os_vars_tests/releases/0.1.0/sys.node2@localhost.config 128 | > 129 | ./_build/default/rel/replace_os_vars_tests/releases/0.1.0/sys.node2@localhost.config 130 | >= 0 131 | 132 | $ NODENAME=node2 COOKIE=cookie2 ./_build/default/rel/replace_os_vars_tests/bin/replace_os_vars_tests stop 133 | >= 0 134 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/src/replace_os_vars_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, replace_os_vars_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/replace_src_vars_tests/src/replace_os_vars_tests.erl: -------------------------------------------------------------------------------- 1 | -module(replace_os_vars_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -xe 4 | 5 | cd $(dirname $(realpath $0)) 6 | 7 | export TERM=dumb 8 | 9 | find . -name _build | xargs rm -rf 10 | 11 | current_dir=$(pwd) 12 | rebar3_dir=$(mktemp -d) 13 | 14 | pushd "${rebar3_dir}" 15 | 16 | # clone latest rebar3 and build with relx as a checkout 17 | git clone https://github.com/erlang/rebar3 . 18 | mkdir _checkouts 19 | ln -s "$current_dir/../../relx" _checkouts/relx 20 | sed -i.bak 's_relx\(.*\)build/default/lib/_relx\1checkouts_' rebar.config 21 | rm rebar.config.bak 22 | ./bootstrap 23 | 24 | popd 25 | 26 | PATH="${rebar3_dir}":~/.cabal/bin/:$PATH shelltest -c --diff --all --execdir -- */*.test 27 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/README.md: -------------------------------------------------------------------------------- 1 | shellcheck_test 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/apps/shellcheck_test/src/shellcheck_test.app.src: -------------------------------------------------------------------------------- 1 | {application, shellcheck_test, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {shellcheck_test_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/apps/shellcheck_test/src/shellcheck_test_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc shellcheck_test public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(shellcheck_test_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | shellcheck_test_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/apps/shellcheck_test/src/shellcheck_test_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc shellcheck_test top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(shellcheck_test_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {shellcheck_test, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname shellcheck_test 2 | 3 | -setcookie shellcheck_test_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {shellcheck_test, "0.1.0"}, 5 | [shellcheck_test, 6 | sasl]}, 7 | 8 | {mode, dev}, 9 | 10 | %% automatically picked up if the files 11 | %% exist but can be set manually, which 12 | %% is required if the names aren't exactly 13 | %% sys.config and vm.args 14 | {sys_config, "./config/sys.config"}, 15 | {vm_args, "./config/vm.args"} 16 | 17 | %% the .src form of the configuration files do 18 | %% not require setting RELX_REPLACE_OS_VARS 19 | %% {sys_config_src, "./config/sys.config.src"}, 20 | %% {vm_args_src, "./config/vm.args.src"} 21 | ]}. 22 | 23 | {profiles, [{prod, [{relx, 24 | [%% prod is the default mode when prod 25 | %% profile is used, so does not have 26 | %% to be explicitly included like this 27 | {mode, prod} 28 | 29 | %% use minimal mode to exclude ERTS 30 | %% {mode, minimal} 31 | ] 32 | }]}]}. 33 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /shelltests/shellcheck_test/shellcheck_test.test: -------------------------------------------------------------------------------- 1 | $ TERM=dumb rebar3 release 2 | > /Release successfully assembled:/ 3 | >= 0 4 | 5 | $ shellcheck _build/default/rel/shellcheck_test/bin/shellcheck_test 6 | >= 0 7 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/README.md: -------------------------------------------------------------------------------- 1 | system_libs_tests 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/apps/system_libs_tests/src/system_libs_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, system_libs_tests, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {system_libs_tests_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/apps/system_libs_tests/src/system_libs_tests_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc system_libs_tests public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(system_libs_tests_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | system_libs_tests_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/apps/system_libs_tests/src/system_libs_tests_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc system_libs_tests top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(system_libs_tests_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {system_libs_tests, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname system_libs_tests 2 | 3 | -setcookie system_libs_tests_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {system_libs_tests, "0.1.0"}, 5 | [system_libs_tests]}, 6 | 7 | {system_libs, "system_libs/"}, 8 | 9 | {mode, prod}, 10 | 11 | {sys_config, "./config/sys.config"}, 12 | {vm_args, "./config/vm.args"} 13 | ]}. 14 | 15 | {profiles, [{bad_system_libs, 16 | [%% make it a real dir so it fails in the search 17 | %% instead of the config setup part of relx 18 | {relx, [{system_libs, "config/"}]} 19 | ]}, 20 | {false_system_libs, 21 | [%% make it a real dir so it fails in the search 22 | %% instead of the config setup part of relx 23 | {relx, [{system_libs, false}]} 24 | ]}]}. 25 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/ebin/application.beam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlware/relx/b228c36bd152ecbe779469054693027cd93d2b33/shelltests/system_libs_tests/system_libs/kernel-7.1-test/ebin/application.beam -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/ebin/kernel.app: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1996-2019. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | %% This is an -*- erlang -*- file. 21 | %% 22 | {application, kernel, 23 | [ 24 | {description, "ERTS CXC 138 10"}, 25 | {vsn, "7.1-test"}, 26 | {modules, [application]}, 27 | {registered, [application_controller, 28 | erl_reply, 29 | auth, 30 | boot_server, 31 | code_server, 32 | disk_log_server, 33 | disk_log_sup, 34 | erl_prim_loader, 35 | error_logger, 36 | file_server_2, 37 | fixtable_server, 38 | global_group, 39 | global_name_server, 40 | heart, 41 | init, 42 | kernel_config, 43 | kernel_refc, 44 | kernel_sup, 45 | logger, 46 | logger_handler_watcher, 47 | logger_sup, 48 | net_kernel, 49 | net_sup, 50 | rex, 51 | user, 52 | os_server, 53 | ddll_server, 54 | erl_epmd, 55 | inet_db, 56 | pg, 57 | pg2]}, 58 | {applications, []}, 59 | {env, [{logger_level, notice}, 60 | {logger_sasl_compatible, false}, 61 | {shell_docs_ansi,auto} 62 | ]}, 63 | {mod, {kernel, []}}, 64 | {runtime_dependencies, ["erts-11.0", "stdlib-3.13", "sasl-3.0"]} 65 | ] 66 | }. 67 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/dist.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1999-2018. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | 21 | %% 22 | %% Distribution capabilities flags (corresponds with dist.h). 23 | %% 24 | 25 | -define(DFLAG_PUBLISHED,1). 26 | -define(DFLAG_ATOM_CACHE,2). 27 | -define(DFLAG_EXTENDED_REFERENCES,4). 28 | -define(DFLAG_DIST_MONITOR,8). 29 | -define(DFLAG_FUN_TAGS,16#10). 30 | -define(DFLAG_DIST_MONITOR_NAME,16#20). 31 | -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). 32 | -define(DFLAG_NEW_FUN_TAGS,16#80). 33 | -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). 34 | -define(DFLAG_EXPORT_PTR_TAG,16#200). 35 | -define(DFLAG_BIT_BINARIES,16#400). 36 | -define(DFLAG_NEW_FLOATS,16#800). 37 | -define(DFLAG_UNICODE_IO,16#1000). 38 | -define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000). 39 | -define(DFLAG_SMALL_ATOM_TAGS, 16#4000). 40 | -define(DFLAG_UTF8_ATOMS, 16#10000). 41 | -define(DFLAG_MAP_TAG, 16#20000). 42 | -define(DFLAG_BIG_CREATION, 16#40000). 43 | -define(DFLAG_SEND_SENDER, 16#80000). 44 | -define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000). 45 | %% -define(DFLAG_NO_MAGIC, 16#200000). %% Used internally only 46 | -define(DFLAG_EXIT_PAYLOAD, 16#400000). 47 | -define(DFLAG_FRAGMENTS, 16#00800000). 48 | -define(DFLAG_HANDSHAKE_23, 16#01000000). 49 | -define(DFLAG_RESERVED, 16#fe000000). 50 | -define(DFLAG_SPAWN, 16#100000000). 51 | -define(DFLAG_NAME_ME, 16#200000000). 52 | 53 | %% Also update dflag2str() in ../src/dist_util.erl 54 | %% when adding flags... 55 | 56 | 57 | -define(ERL_DIST_VER_5, 5). % OTP-22 or (much) older 58 | -define(ERL_DIST_VER_6, 6). % OTP-23 (or maybe newer?) 59 | 60 | -define(ERL_DIST_VER_LOW, ?ERL_DIST_VER_5). 61 | -define(ERL_DIST_VER_HIGH, ?ERL_DIST_VER_6). 62 | 63 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/dist_util.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1999-2018. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | %% uncomment this if tracing of handshake etc is wanted 21 | %%-define(dist_trace, true). 22 | %%-define(dist_debug, true). 23 | 24 | 25 | -ifdef(dist_debug). 26 | -define(debug(Term), erlang:display(Term)). 27 | -else. 28 | -define(debug(Term), ok). 29 | -endif. 30 | 31 | -ifdef(dist_trace). 32 | -define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:convert_time_unit(erlang:monotonic_time()-erlang:system_info(start_time), native, microsecond),node(),lists:flatten(io_lib:format(Fmt, Args))])). 33 | % Use the one below for config-file (early boot) connection tracing 34 | %-define(trace(Fmt,Args), erlang:display([erlang:convert_time_unit(erlang:monotonic_time()-erlang:system_info(start_time), native, microsecond),node(),lists:flatten(io_lib:format(Fmt, Args))])). 35 | -define(trace_factor,8). 36 | -else. 37 | -define(trace(Fmt,Args), ok). 38 | -define(trace_factor,1). 39 | -endif. 40 | 41 | -define(shutdown(Data), dist_util:shutdown(?MODULE, ?LINE, Data)). 42 | -define(shutdown2(Data, Reason), dist_util:shutdown(?MODULE, ?LINE, Data, Reason)). 43 | 44 | %% Handshake state structure 45 | -record(hs_data, { 46 | kernel_pid, %% Pid of net_kernel 47 | other_node, %% Name of peer 48 | this_node, %% my nodename 49 | socket, %% The connection "socket" 50 | timer, %% The setup timer 51 | %% (stream_dist_handshake:start_timer) 52 | this_flags, %% Flags my node should use 53 | allowed, %% Allowed nodes list 54 | other_version, %% The other nodes distribution version 55 | other_flags, %% The other nodes flags. 56 | other_started, %% True if the other node initiated. 57 | f_send, %% Fun that behaves like gen_tcp:send 58 | f_recv, %% Fun that behaves like gen_tcp:recv 59 | f_setopts_pre_nodeup, %% Sets "socket" options before 60 | %% nodeup is delivered to net_kernel 61 | f_setopts_post_nodeup, %% Sets "socket" options after 62 | %% nodeup is delivered 63 | f_getll, %% Get low level port or pid. 64 | f_address, %% The address of the "socket", 65 | %% generated from Socket,Node 66 | %% These three are used in the tick loop, 67 | %% so they are not fun's to avoid holding old code. 68 | mf_tick, %% Takes the socket as parameters and 69 | %% sends a tick, this is no fun, it 70 | %% is a tuple {M,F}. 71 | %% Is should place {tcp_closed, Socket} 72 | %% in the message queue on failure. 73 | mf_getstat, %% Returns 74 | %% {ok, RecvCnt, SendCnt, SendPend} for 75 | %% a given socket. This is a {M,F}, 76 | %% returning {error, Reason on failure} 77 | request_type = normal, 78 | 79 | %% New in kernel-5.1 (OTP 19.1): 80 | mf_setopts, %% netkernel:setopts on active connection 81 | mf_getopts, %% netkernel:getopts on active connection 82 | 83 | %% New in kernel-6.0 (OTP 21.0) 84 | f_handshake_complete, %% Notify handshake complete 85 | add_flags, %% dflags to add 86 | reject_flags, %% dflags not to use (not all can be rejected) 87 | require_flags, %% dflags that are required 88 | 89 | %% New in kernel-@master@ (OTP-23.0) 90 | this_creation, 91 | other_creation 92 | }). 93 | 94 | 95 | %% The following should be filled in upon enter of... 96 | %% - handshake_we_started: 97 | %% kernel_pid, other_node, this_node, socket, timer, 98 | %% this_flags, other_version, All fun's/mf's. 99 | %% - handshake_other_started: 100 | %% kernel_pid, this_node, socket, timer, 101 | %% this_flags, allowed, All fun's/mf's. 102 | 103 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/eep48.hrl: -------------------------------------------------------------------------------- 1 | -define(NATIVE_FORMAT,<<"application/erlang+html">>). 2 | -define(CURR_DOC_VERSION, {1,0,0}). 3 | -record(docs_v1, {anno, 4 | beam_language = erlang, 5 | format = ?NATIVE_FORMAT, 6 | module_doc, 7 | metadata = #{ otp_doc_vsn => ?CURR_DOC_VERSION }, 8 | docs}). 9 | 10 | -record(docs_v1_entry, {kind_name_arity, 11 | anno, 12 | signature, 13 | doc, 14 | metadata}). 15 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/file.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1997-2015. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | 21 | -ifndef(FILE_HRL_). 22 | -define(FILE_HRL_, 1). 23 | %%-------------------------------------------------------------------------- 24 | 25 | -record(file_info, 26 | {size :: non_neg_integer() | 'undefined', % Size of file in bytes. 27 | type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink' 28 | | 'undefined', 29 | access :: 'read' | 'write' | 'read_write' | 'none' | 'undefined', 30 | atime :: file:date_time() | non_neg_integer() | 'undefined', 31 | % The local time the file was last read: 32 | % {{Year, Mon, Day}, {Hour, Min, Sec}}. 33 | % atime, ctime, mtime may also be unix epochs() 34 | mtime :: file:date_time() | non_neg_integer() | 'undefined', 35 | % The local time the file was last written. 36 | ctime :: file:date_time() | non_neg_integer() | 'undefined', 37 | % The interpretation of this time field 38 | % is dependent on operating system. 39 | % On Unix it is the last time the file 40 | % or the inode was changed. On Windows, 41 | % it is the creation time. 42 | mode :: non_neg_integer() | 'undefined', 43 | % File permissions. On Windows, 44 | % the owner permissions will be 45 | % duplicated for group and user. 46 | links :: non_neg_integer() | 'undefined', 47 | % Number of links to the file (1 if the 48 | % filesystem doesn't support links). 49 | major_device :: non_neg_integer() | 'undefined', 50 | % Identifies the file system (Unix), 51 | % or the drive number (A: = 0, B: = 1) 52 | % (Windows). 53 | %% The following are Unix specific. 54 | %% They are set to zero on other operating systems. 55 | minor_device :: non_neg_integer() | 'undefined', 56 | % Only valid for devices. 57 | inode :: non_neg_integer() | 'undefined', % Inode number for file. 58 | uid :: non_neg_integer() | 'undefined', % User id for owner. 59 | gid :: non_neg_integer() | 'undefined'}). % Group id for owner. 60 | 61 | 62 | -record(file_descriptor, 63 | {module :: module(), % Module that handles this kind of file 64 | data :: term()}). % Module dependent data 65 | 66 | %%-------------------------------------------------------------------------- 67 | -endif. 68 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/inet.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1997-2017. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | %% This record is returned by inet:gethostbyaddr/2 and inet:gethostbyname/2. 21 | 22 | 23 | -record(hostent, 24 | { 25 | h_name :: inet:hostname(), %% official name of host 26 | h_aliases = [] :: [inet:hostname()], %% alias list 27 | h_addrtype :: 'inet' | 'inet6', %% host address type 28 | h_length :: non_neg_integer(), %% length of address 29 | h_addr_list = [] :: [inet:ip_address()]%% list of addresses from name server 30 | }). 31 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/inet_sctp.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 2007-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | %% SCTP protocol contribution by Leonid Timochouk and Serge Aleynikov. 21 | %% See also: $ERL_TOP/lib/kernel/AUTHORS 22 | %% 23 | 24 | %% 25 | %% SCTP-related records. 26 | %% 27 | 28 | %% sctp_initmsg: For creating a new association (send*) and 29 | %% SCTP_OPT_INITMSG setsockopt: 30 | -record(sctp_initmsg, 31 | { 32 | num_ostreams, % 0 Use endpoint default 33 | max_instreams, % 0 Use endpoint default 34 | max_attempts, % 0 Use endpoint default 35 | max_init_timeo % 0 Use endpoint default 36 | }). 37 | 38 | %% sctp_sndrcvinfo: Possible "flags": Atoms, as below. Used 39 | %% in "send*" and SCTP_OPT_DEFAULT_SEND_PARAM setsockopt: 40 | -record(sctp_sndrcvinfo, 41 | { 42 | stream, % 0 Streams numbered from 0 (XXX?) 43 | ssn, % 0, Ignored for send 44 | flags, % [unordered, 45 | %% addr_over, 46 | %% abort, 47 | %% eof] 48 | ppid, % 0, Passed to the remote end 49 | context, % 0, Passed to the user on error 50 | timetolive, % 0, In msec; 0 -> no expiration 51 | tsn, % 0, Recv only: TSN of one of the chunks 52 | cumtsn, % 0, Only for unordered recv 53 | assoc_id % 0 IMPORTANT! 54 | }). 55 | 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 | %% 58 | %% SCTP Notification Events: 59 | %% 60 | 61 | %% sctp_assoc_change: Possible valid "state" values include: 62 | %% comm_up, comm_lost, restart, 63 | %% shutdown_comp, cant_assoc 64 | -record(sctp_assoc_change, 65 | { 66 | state = cant_assoc, 67 | error = 0, 68 | outbound_streams = 0, 69 | inbound_streams = 0, 70 | assoc_id = 0 71 | }). 72 | 73 | %% sctp_paddr_change: Peer address is a list. Possible "state" values: 74 | %% addr_available, addr_unreachable, 75 | %% addr_removed, addr_added, 76 | %% addr_made_prim 77 | -record(sctp_paddr_change, 78 | { 79 | addr = [0,0,0,0], 80 | state = addr_available, 81 | error = 0, 82 | assoc_id = 0 83 | }). 84 | 85 | %% sctp_remote_error: Possible "data" elements are Error Causes (Atoms 86 | %% (extending the info provided by "error" field). 87 | -record(sctp_remote_error, 88 | { 89 | error = 0, 90 | assoc_id = 0, 91 | data = [] 92 | }). 93 | 94 | %% sctp_send_failed: The "flags" is a Boolean specifying whether the 95 | %% data have actually been transmitted over the wire. 96 | %% "error" is similar to in #sctp_remote_error{} above. 97 | %% "info" is the orig "*sndrcvinfo", and "data" is 98 | %% the whole orig data chunk we attempted to send: 99 | -record(sctp_send_failed, 100 | { 101 | flags = false, 102 | error = 0, 103 | info = #sctp_sndrcvinfo{}, 104 | assoc_id = 0, 105 | data = <<>> 106 | }). 107 | 108 | %% sctp_shutdown_event: In this case, shut-down occurs on a particular 109 | %% association, not on the whole socket. 110 | -record(sctp_shutdown_event, 111 | { 112 | assoc_id = 0 113 | }). 114 | 115 | %% sctp_adaptation_event: "adaptation_ind" is opaque user-specified data: 116 | -record(sctp_adaptation_event, 117 | { 118 | adaptation_ind = 0, 119 | assoc_id = 0 120 | }). 121 | 122 | %% sctp_partial_delivery_event: XXX: Not clear whether it is delivered to 123 | %% the Sender or to the Recipient (probably the 124 | %% former). Currently, there is only 1 possible 125 | %% value for "indication": 126 | -record(sctp_pdapi_event, 127 | { 128 | indication = partial_delivery_aborted, 129 | assoc_id = 0 130 | }). 131 | 132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 133 | %% 134 | %% SCTP Socket Options: 135 | %% 136 | 137 | -record(sctp_rtoinfo, % For SCTP_OPT_RTOINFO 138 | { 139 | assoc_id, 140 | initial, % 0 141 | max, % 0 142 | min % 0 143 | }). 144 | 145 | -record(sctp_assocparams, % For SCTP_OPT_ASSOCINFO 146 | { 147 | assoc_id, 148 | asocmaxrxt, % 0 149 | number_peer_destinations, % 0 150 | peer_rwnd, % 0 151 | local_rwnd, % 0 152 | cookie_life % 0 153 | }). 154 | 155 | % #sctp_initmsg{} and #sctp_sndrcvinfo{}, declared above, can also be options. 156 | 157 | -record(sctp_prim, % For SCTP_OPT_SET_PRIMARY_ADDR and 158 | { 159 | assoc_id, 160 | addr % When set: {IP, Port} 161 | }). 162 | 163 | -record(sctp_setpeerprim, % For SCTP_OPT_SET_PEER_PRIMARY_ADDR 164 | { 165 | assoc_id, 166 | addr % When set: { IP, Port} 167 | }). 168 | 169 | -record(sctp_setadaptation, % For SCTP_OPT_ADAPTATION_LAYER 170 | { 171 | adaptation_ind % 0 172 | }). 173 | 174 | -record(sctp_paddrparams, % For SCTP_OPT_PEER_ADDR_PARAMS 175 | { 176 | assoc_id, 177 | address, % When set: {IP, Port} 178 | hbinterval, % 0 179 | pathmaxrxt, % 0 180 | pathmtu, % 0 181 | sackdelay, % 0 182 | flags % [hb_enable, 183 | %% hb_disable 184 | %% hb_demand, 185 | %% pmtud_enable, 186 | %% pmtud_disable, 187 | %% sackdelay_enable, 188 | %% sackdelay_disable] 189 | }). 190 | 191 | 192 | % SCTP events which will be subscribed by default upon opening the socket. 193 | % NB: "data_io_event" controls delivery of #sctp_sndrcvinfo{} ancilary 194 | % data, not events (which are normal data) in fact; it may be needed in 195 | % order to get the AssocID of data just received: 196 | % 197 | -record(sctp_event_subscribe, 198 | { 199 | data_io_event, % true, % Used by gen_sctp 200 | association_event, % true, % Used by gen_sctp 201 | address_event, % true, % Unlikely to happen... 202 | send_failure_event, % true, % Delivered as an ERROR 203 | peer_error_event, % true, % Delivered as an ERROR 204 | shutdown_event, % true, % Used by gen_sctp 205 | partial_delivery_event, % true, % Unlikely to happen... 206 | adaptation_layer_event, % false % Probably not needed... 207 | authentication_event % false % Not implemented yet... 208 | }). 209 | 210 | -record(sctp_assoc_value, % For SCTP_OPT_DELAYED_ACK_TIME 211 | { 212 | assoc_id, 213 | assoc_value % 0 214 | }). 215 | 216 | 217 | 218 | % sctp_paddrinfo and sctp_status are records for read-only options: 219 | -record(sctp_paddrinfo, 220 | { 221 | assoc_id, 222 | address, % When set: {IP, Port} 223 | state, % 'inactive', Or 'active' 224 | cwnd, % 0 225 | srtt, % 0, 226 | rto, % 0 227 | mtu % 0 228 | }). 229 | 230 | -record(sctp_status, 231 | { 232 | assoc_id, 233 | state, % empty, 234 | % Other possible states: 235 | % closed, cookie_wait, 236 | % cookie_echoed, established, 237 | % shutdown_pending, shutdow_sent, 238 | % shutdown_received, shutdown_ack_sent; 239 | % NOT YET IMPLEMENTED: 240 | % bound, listen 241 | rwnd, % 0 242 | unackdata, % 0, 243 | penddata, % 0, 244 | instrms, % 0, 245 | outstrms, % 0, 246 | fragmentation_point, % 0, 247 | primary % When set: an #sctp_paddrinfo{} record 248 | }). 249 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/logger.hrl: -------------------------------------------------------------------------------- 1 | -ifndef(LOGGER_HRL). 2 | -define(LOGGER_HRL,true). 3 | -define(LOG_EMERGENCY(A),?DO_LOG(emergency,[A])). 4 | -define(LOG_EMERGENCY(A,B),?DO_LOG(emergency,[A,B])). 5 | -define(LOG_EMERGENCY(A,B,C),?DO_LOG(emergency,[A,B,C])). 6 | 7 | -define(LOG_ALERT(A),?DO_LOG(alert,[A])). 8 | -define(LOG_ALERT(A,B),?DO_LOG(alert,[A,B])). 9 | -define(LOG_ALERT(A,B,C),?DO_LOG(alert,[A,B,C])). 10 | 11 | -define(LOG_CRITICAL(A),?DO_LOG(critical,[A])). 12 | -define(LOG_CRITICAL(A,B),?DO_LOG(critical,[A,B])). 13 | -define(LOG_CRITICAL(A,B,C),?DO_LOG(critical,[A,B,C])). 14 | 15 | -define(LOG_ERROR(A),?DO_LOG(error,[A])). 16 | -define(LOG_ERROR(A,B),?DO_LOG(error,[A,B])). 17 | -define(LOG_ERROR(A,B,C),?DO_LOG(error,[A,B,C])). 18 | 19 | -define(LOG_WARNING(A),?DO_LOG(warning,[A])). 20 | -define(LOG_WARNING(A,B),?DO_LOG(warning,[A,B])). 21 | -define(LOG_WARNING(A,B,C),?DO_LOG(warning,[A,B,C])). 22 | 23 | -define(LOG_NOTICE(A),?DO_LOG(notice,[A])). 24 | -define(LOG_NOTICE(A,B),?DO_LOG(notice,[A,B])). 25 | -define(LOG_NOTICE(A,B,C),?DO_LOG(notice,[A,B,C])). 26 | 27 | -define(LOG_INFO(A),?DO_LOG(info,[A])). 28 | -define(LOG_INFO(A,B),?DO_LOG(info,[A,B])). 29 | -define(LOG_INFO(A,B,C),?DO_LOG(info,[A,B,C])). 30 | 31 | -define(LOG_DEBUG(A),?DO_LOG(debug,[A])). 32 | -define(LOG_DEBUG(A,B),?DO_LOG(debug,[A,B])). 33 | -define(LOG_DEBUG(A,B,C),?DO_LOG(debug,[A,B,C])). 34 | 35 | -define(LOG(L,A),?DO_LOG(L,[A])). 36 | -define(LOG(L,A,B),?DO_LOG(L,[A,B])). 37 | -define(LOG(L,A,B,C),?DO_LOG(L,[A,B,C])). 38 | 39 | -define(LOCATION,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY}, 40 | line=>?LINE, 41 | file=>?FILE}). 42 | 43 | %%%----------------------------------------------------------------- 44 | %%% Internal, i.e. not intended for direct use in code - use above 45 | %%% macros instead! 46 | -define(DO_LOG(Level,Args), 47 | case logger:allow(Level,?MODULE) of 48 | true -> 49 | apply(logger,macro_log,[?LOCATION,Level|Args]); 50 | false -> 51 | ok 52 | end). 53 | -endif. 54 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/kernel-7.1-test/include/net_address.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1997-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | 21 | %% Generic address format 22 | 23 | -record(net_address, 24 | { 25 | address, %% opaque address 26 | host, %% host name 27 | protocol, %% protocol 28 | family %% address family 29 | }). 30 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/ebin/array.beam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlware/relx/b228c36bd152ecbe779469054693027cd93d2b33/shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/ebin/array.beam -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/ebin/stdlib.app: -------------------------------------------------------------------------------- 1 | %% This is an -*- erlang -*- file. 2 | %% 3 | %% %CopyrightBegin% 4 | %% 5 | %% Copyright Ericsson AB 1996-2020. All Rights Reserved. 6 | %% 7 | %% Licensed under the Apache License, Version 2.0 (the "License"); 8 | %% you may not use this file except in compliance with the License. 9 | %% You may obtain a copy of the License at 10 | %% 11 | %% http://www.apache.org/licenses/LICENSE-2.0 12 | %% 13 | %% Unless required by applicable law or agreed to in writing, software 14 | %% distributed under the License is distributed on an "AS IS" BASIS, 15 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | %% See the License for the specific language governing permissions and 17 | %% limitations under the License. 18 | %% 19 | %% %CopyrightEnd% 20 | %% 21 | {application, stdlib, 22 | [{description, "ERTS CXC 138 10"}, 23 | {vsn, "3.13.2-test"}, 24 | {modules, [array]}, 25 | {registered,[timer_server,rsh_starter,take_over_monitor,pool_master, 26 | dets]}, 27 | {applications, [kernel]}, 28 | {env, []}, 29 | {runtime_dependencies, ["sasl-3.0","kernel-7.0","erts-11.0","crypto-3.3", 30 | "compiler-5.0"]} 31 | ]}. 32 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/include/erl_bits.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1999-2015. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | %% This is an -*- erlang -*- file. 21 | %% Generic compiler options, passed from the erl_compile module. 22 | 23 | -type bt_endian():: 'big' | 'little' | 'native'. 24 | -type bt_sign() :: 'signed' | 'unsigned'. 25 | -type bt_type() :: 'integer' | 'float' | 'binary' | 'utf8' | 'utf16' | 'utf32'. 26 | -type bt_unit() :: 1..256. 27 | 28 | -record(bittype, { 29 | type :: bt_type() | 'undefined', 30 | unit :: bt_unit() | 'undefined', %% element unit 31 | sign :: bt_sign() | 'undefined', 32 | endian :: bt_endian() | 'undefined' 33 | }). 34 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/include/erl_compile.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 1997-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | 21 | %% Generic compiler options, passed from the erl_compile module. 22 | 23 | -record(options, 24 | {includes=[] :: [file:filename()], % Include paths (list of 25 | % absolute directory names). 26 | outdir="." :: file:filename(), % Directory for result 27 | % (absolute path). 28 | output_type=undefined :: atom(), % Type of output file. 29 | defines=[] :: [atom() | {atom(),_}], % Preprocessor defines. Each 30 | % element is an atom 31 | % (the name to define), or 32 | % a {Name, Value} tuple. 33 | warning=1 :: non_neg_integer(), % Warning level (0 - no 34 | % warnings, 1 - standard level, 35 | % 2, 3, ... - more warnings). 36 | verbose=false :: boolean(), % Verbose (true/false). 37 | optimize=999, % Optimize options. 38 | specific=[] :: [_], % Compiler specific options. 39 | outfile="" :: file:filename(), % Name of output file (internal 40 | % use in erl_compile.erl). 41 | cwd :: file:filename() % Current working directory 42 | % for erlc. 43 | }). 44 | 45 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/include/ms_transform.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 2002-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | -compile({parse_transform,ms_transform}). 21 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/include/qlc.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 2004-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | -compile({parse_transform,qlc}). 21 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs/stdlib-3.13.2-test/include/zip.hrl: -------------------------------------------------------------------------------- 1 | %% 2 | %% %CopyrightBegin% 3 | %% 4 | %% Copyright Ericsson AB 2006-2016. All Rights Reserved. 5 | %% 6 | %% Licensed under the Apache License, Version 2.0 (the "License"); 7 | %% you may not use this file except in compliance with the License. 8 | %% You may obtain a copy of the License at 9 | %% 10 | %% http://www.apache.org/licenses/LICENSE-2.0 11 | %% 12 | %% Unless required by applicable law or agreed to in writing, software 13 | %% distributed under the License is distributed on an "AS IS" BASIS, 14 | %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | %% See the License for the specific language governing permissions and 16 | %% limitations under the License. 17 | %% 18 | %% %CopyrightEnd% 19 | %% 20 | 21 | -record(zip_file, { 22 | name :: string(), % file name 23 | info :: file:file_info(), 24 | comment :: string(), % zip file comment 25 | offset :: non_neg_integer(), % offset of file's local header in archive 26 | comp_size :: non_neg_integer() % compressed size 27 | }). 28 | 29 | -record(zip_comment, { 30 | comment :: string() % zip archive comment 31 | }). 32 | 33 | -------------------------------------------------------------------------------- /shelltests/system_libs_tests/system_libs_tests.test: -------------------------------------------------------------------------------- 1 | $ TERM=dumb rebar3 release 2 | > /Release successfully assembled:/ 3 | >= 0 4 | 5 | $ TERM=dumb rebar3 tar 6 | > /Release successfully assembled:/ 7 | >= 0 8 | 9 | $ ls _build/default/rel/system_libs_tests/lib/kernel-7.1-test 10 | > /ebin/ 11 | >= 0 12 | 13 | $ ls _build/default/rel/system_libs_tests/lib/stdlib-3.13.2-test 14 | > /ebin/ 15 | >= 0 16 | 17 | $ TERM=dumb rebar3 as bad_system_libs release 18 | > /Application needed for release not found: kernel/ 19 | >= 1 20 | 21 | $ TERM=dumb rebar3 as false_system_libs release 22 | > /Release successfully assembled:/ 23 | >= 0 24 | 25 | $ ls _build/false_system_libs/rel/system_libs_tests/lib/kernel* 26 | >2 /cannot access/ 27 | >= 2 28 | 29 | $ TERM=dumb rebar3 as false_system_libs tar 30 | > /Release successfully assembled:/ 31 | >= 0 32 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/README.md: -------------------------------------------------------------------------------- 1 | upgrade_test 2 | ===== 3 | 4 | An OTP application 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps/upgrade_test/ebin/upgrade_test.appup: -------------------------------------------------------------------------------- 1 | {"0.1.0", 2 | [{<<".*">>, [{restart_application, upgrade_test}]}], 3 | [{<<".*">>, [{restart_application, upgrade_test}]}]}. 4 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps/upgrade_test/src/upgrade_test.app.src: -------------------------------------------------------------------------------- 1 | {application, upgrade_test, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, {upgrade_test_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps/upgrade_test/src/upgrade_test_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc upgrade_test public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(upgrade_test_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | upgrade_test_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps/upgrade_test/src/upgrade_test_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc upgrade_test top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(upgrade_test_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps011/upgrade_test/ebin/upgrade_test.appup: -------------------------------------------------------------------------------- 1 | {"0.1.1", 2 | [{<<".*">>, [{restart_application, upgrade_test}]}], 3 | [{<<".*">>, [{restart_application, upgrade_test}]}]}. 4 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps011/upgrade_test/src/upgrade_test.app.src: -------------------------------------------------------------------------------- 1 | {application, upgrade_test, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.1"}, 4 | {registered, []}, 5 | {mod, {upgrade_test_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib 9 | ]}, 10 | {env,[]}, 11 | {modules, []}, 12 | 13 | {licenses, ["Apache 2.0"]}, 14 | {links, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps011/upgrade_test/src/upgrade_test_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc upgrade_test public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(upgrade_test_app). 7 | 8 | -behaviour(application). 9 | 10 | -export([start/2, stop/1]). 11 | 12 | start(_StartType, _StartArgs) -> 13 | upgrade_test_sup:start_link(). 14 | 15 | stop(_State) -> 16 | ok. 17 | 18 | %% internal functions 19 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/apps011/upgrade_test/src/upgrade_test_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc upgrade_test top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(upgrade_test_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | -export([start_link/0]). 11 | 12 | -export([init/1]). 13 | 14 | -define(SERVER, ?MODULE). 15 | 16 | start_link() -> 17 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 18 | 19 | %% sup_flags() = #{strategy => strategy(), % optional 20 | %% intensity => non_neg_integer(), % optional 21 | %% period => pos_integer()} % optional 22 | %% child_spec() = #{id => child_id(), % mandatory 23 | %% start => mfargs(), % mandatory 24 | %% restart => restart(), % optional 25 | %% shutdown => shutdown(), % optional 26 | %% type => worker(), % optional 27 | %% modules => modules()} % optional 28 | init([]) -> 29 | SupFlags = #{strategy => one_for_all, 30 | intensity => 0, 31 | period => 1}, 32 | ChildSpecs = [], 33 | {ok, {SupFlags, ChildSpecs}}. 34 | 35 | %% internal functions 36 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | {upgrade_test, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname upgrade_test 2 | 3 | -setcookie upgrade_test_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [{release, {upgrade_test, "0.1.0"}, 5 | [upgrade_test, 6 | sasl]}, 7 | 8 | {mode, dev}, 9 | 10 | %% automatically picked up if the files 11 | %% exist but can be set manually, which 12 | %% is required if the names aren't exactly 13 | %% sys.config and vm.args 14 | {sys_config, "./config/sys.config"}, 15 | {vm_args, "./config/vm.args"} 16 | 17 | %% the .src form of the configuration files do 18 | %% not require setting RELX_REPLACE_OS_VARS 19 | %% {sys_config_src, "./config/sys.config.src"}, 20 | %% {vm_args_src, "./config/vm.args.src"} 21 | ]}. 22 | 23 | {profiles, [{prod, [{relx, 24 | [%% prod is the default mode when prod 25 | %% profile is used, so does not have 26 | %% to be explicitly included like this 27 | {mode, prod} 28 | 29 | %% use minimal mode to exclude ERTS 30 | %% {mode, minimal} 31 | ] 32 | }]}]}. 33 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/rebar.config011: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {project_app_dirs, ["apps011/*"]}. 5 | 6 | 7 | {relx, [{release, {upgrade_test, "0.1.0"}, 8 | [upgrade_test, 9 | sasl]}, 10 | {release, {upgrade_test, "0.1.1"}, 11 | [upgrade_test, 12 | sasl]}, 13 | 14 | {mode, dev}, 15 | 16 | %% automatically picked up if the files 17 | %% exist but can be set manually, which 18 | %% is required if the names aren't exactly 19 | %% sys.config and vm.args 20 | {sys_config, "./config/sys.config"}, 21 | {vm_args, "./config/vm.args"} 22 | 23 | %% the .src form of the configuration files do 24 | %% not require setting RELX_REPLACE_OS_VARS 25 | %% {sys_config_src, "./config/sys.config.src"}, 26 | %% {vm_args_src, "./config/vm.args.src"} 27 | ]}. 28 | 29 | {profiles, [{prod, [{relx, 30 | [%% prod is the default mode when prod 31 | %% profile is used, so does not have 32 | %% to be explicitly included like this 33 | {mode, prod} 34 | 35 | %% use minimal mode to exclude ERTS 36 | %% {mode, minimal} 37 | ] 38 | }]}]}. 39 | -------------------------------------------------------------------------------- /shelltests/upgrade_test/upgrade_test.test: -------------------------------------------------------------------------------- 1 | # create 0.1.0 tar archive and then the 0.1.1 tar 2 | # 3 | # 4 | $ rebar3 as prod tar 5 | > / Release successfully assembled: / 6 | >= 0 7 | 8 | $ REBAR_CONFIG=rebar.config011 rebar3 as prod release -v 0.1.1 9 | > / Release successfully assembled: / 10 | >= 0 11 | 12 | $ REBAR_CONFIG=rebar.config011 rebar3 as prod relup -n upgrade_test -v 0.1.1 -u 0.1.0 13 | > / Release successfully assembled: / 14 | >= 0 15 | 16 | $ REBAR_CONFIG=rebar.config011 rebar3 as prod tar -v 0.1.1 17 | > / Release successfully assembled: / 18 | >= 0 19 | 20 | 21 | # 22 | # extract 0.1.0 into _build/n, start node and check versions 23 | # 24 | 25 | $ mkdir -p _build/n 26 | >= 0 27 | 28 | $ tar -C _build/n -xf ./_build/prod/rel/upgrade_test/upgrade_test-0.1.0.tar.gz 29 | >= 0 30 | 31 | $ _build/n/bin/upgrade_test daemon 32 | >= 0 33 | 34 | $ sleep 1 35 | >= 0 36 | 37 | $ _build/n/bin/upgrade_test versions 38 | > 39 | Installed versions: 40 | * 0.1.0 permanent 41 | >= 0 42 | 43 | # 44 | # unpack 0.1.1 and check versions 45 | # 46 | 47 | $ cp _build/prod/rel/upgrade_test/upgrade_test-0.1.1.tar.gz _build/n/releases/ 48 | >= 0 49 | 50 | $ _build/n/bin/upgrade_test unpack 0.1.1 51 | > 52 | Release 0.1.1 not found, attempting to unpack releases/upgrade_test-0.1.1.tar.gz 53 | Unpacked successfully: "0.1.1" 54 | >= 0 55 | 56 | $ _build/n/bin/upgrade_test versions 57 | > 58 | Installed versions: 59 | * 0.1.1 unpacked 60 | * 0.1.0 permanent 61 | >= 0 62 | 63 | # 64 | # upgrade to 0.1.1 and check versions 65 | # 66 | $ _build/n/bin/upgrade_test upgrade 0.1.1 67 | > 68 | Release 0.1.1 is already unpacked, now installing. 69 | Installed Release: 0.1.1 70 | Made release permanent: "0.1.1" 71 | >= 72 | 73 | $ _build/n/bin/upgrade_test versions 74 | > 75 | Installed versions: 76 | * 0.1.1 permanent 77 | * 0.1.0 old 78 | >= 0 79 | 80 | # 81 | # stop node and remove _build/n 82 | # 83 | $ _build/n/bin/upgrade_test stop 84 | >=0 85 | 86 | $ sleep 2 87 | >=0 88 | 89 | $ rm -rf _build/n 90 | >=0 91 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | _build 16 | .idea 17 | *.iml 18 | rebar3.crashdump 19 | *~ 20 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/README.md: -------------------------------------------------------------------------------- 1 | vm_args_inclusion_tests 2 | ===== 3 | 4 | An OTP library 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/config/sys.config.src: -------------------------------------------------------------------------------- 1 | [{vm_args_inclusion_tests, [ 2 | %% SASL config 3 | {sasl, [ 4 | {sasl_error_logger, {file, "error.log"}}, 5 | {errlog_type, error}, 6 | {error_logger_mf_dir, "sasl"}, % Log directory 7 | {error_logger_mf_maxbytes, 10485760}, % 10 MB max file size 8 | {error_logger_mf_maxfiles, 5} % 5 files max 9 | ]} 10 | ]}]. 11 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/config/vm.args.src: -------------------------------------------------------------------------------- 1 | -sname ${NODENAME}@localhost 2 | 3 | -setcookie cookie1 4 | -args_file releases/{{release_version}}/vm.extended.args 5 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/config/vm.extended.args: -------------------------------------------------------------------------------- 1 | # Sets default scheduler hint for port parallelism. 2 | # erlang:system_info(port_parallelism) gives us this value 3 | +spp true 4 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {relx, [ 5 | {release, {vm_args_inclusion_tests, "0.1.0"}, 6 | [vm_args_inclusion_tests]}, 7 | {sys_config_src, "config/sys.config.src"}, 8 | {vm_args_src, "config/vm.args.src"}, 9 | 10 | {overlay, [ 11 | {template, "config/vm.args.src", "releases/{{release_version}}/vm.args.src"}, 12 | {copy, "config/vm.extended.args", "releases/{{release_version}}/vm.extended.args"} 13 | ]} 14 | ]}. 15 | 16 | {profiles, [{dev, [{relx, [{dev_mode, true}]}]}]}. 17 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/src/vm_args_inclusion_tests.app.src: -------------------------------------------------------------------------------- 1 | {application, vm_args_inclusion_tests, 2 | [{description, "An OTP library"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {applications, 6 | [kernel, 7 | stdlib 8 | ]}, 9 | {env,[]}, 10 | {modules, []}, 11 | 12 | {licenses, ["Apache 2.0"]}, 13 | {links, []} 14 | ]}. 15 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/src/vm_args_inclusion_tests.erl: -------------------------------------------------------------------------------- 1 | -module(vm_args_inclusion_tests). 2 | 3 | -export([]). 4 | -------------------------------------------------------------------------------- /shelltests/vm_args_inclusion_tests/vm_args_inclusion_tests.test: -------------------------------------------------------------------------------- 1 | $ rebar3 release 2 | > / Release successfully assembled: / 3 | >= 0 4 | 5 | $ RELX_OUT_FILE_PATH=/tmp NODENAME=node1 ./_build/default/rel/vm_args_inclusion_tests/bin/vm_args_inclusion_tests daemon 6 | >= 0 7 | 8 | $ sleep 1 9 | >= 0 10 | 11 | $ NODENAME=node1 ./_build/default/rel/vm_args_inclusion_tests/bin/vm_args_inclusion_tests ping 12 | > 13 | pong 14 | >= 0 15 | 16 | $ NODENAME=node1 ./_build/default/rel/vm_args_inclusion_tests/bin/vm_args_inclusion_tests eval 'erlang:system_info(port_parallelism).' 17 | > 18 | true 19 | >= 0 20 | 21 | $ NODENAME=node1 ./_build/default/rel/vm_args_inclusion_tests/bin/vm_args_inclusion_tests stop 22 | >= 0 23 | 24 | -------------------------------------------------------------------------------- /shelltests/wintest.ps1: -------------------------------------------------------------------------------- 1 | #! /usr/bin/pwsh 2 | # Test build, install, start, ping, stop, uninstall of powershell_release 3 | $release = "powershell_release" 4 | 5 | # Terminate on error 6 | $ErrorActionPreference = "Stop" 7 | 8 | # CD to script location (shelltests) 9 | Set-Location $PSScriptRoot 10 | 11 | # Clean all builds (continue on error) 12 | "*** Clean" 13 | Get-ChildItem -Path . -Filter _build -Recurse | ForEach-Object { 14 | "Remove $($_.FullName).." 15 | Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue 16 | } 17 | "" 18 | 19 | # Create temporary build folder for rebar3 20 | "*** Build rebar3" 21 | $rebar3_dir = "$PSScriptRoot\$(([System.Guid]::NewGuid()).Guid)" 22 | mkdir $rebar3_dir | Out-Null 23 | 24 | # Clone latest rebar3 and build with relx as a checkout 25 | Push-Location $rebar3_dir 26 | & git clone "https://github.com/erlang/rebar3" . 27 | mkdir _checkouts | Out-Null 28 | New-Item -ItemType SymbolicLink -Path "_checkouts\relx" -Target "$PSScriptRoot\..\..\relx" | Out-Null 29 | (Get-Content rebar.config) -replace 'relx(.*)build/default/lib/', 'relx$1checkouts' | Set-Content rebar.config -Encoding ASCII 30 | cmd /c bootstrap.bat 31 | Pop-Location 32 | "" 33 | 34 | # Function to run rebar3 35 | function Rebar() { 36 | & escript.exe "$rebar3_dir\rebar3" @args 37 | if ($LASTEXITCODE -ne 0) { 38 | Write-Error "rebar3 ${args} exited with status $LASTEXITCODE" 39 | } 40 | } 41 | 42 | # Our release source 43 | Set-Location ".\$release\" 44 | 45 | "*** Build release" 46 | Rebar release 47 | "" 48 | 49 | "*** Rebuild dev release (test for symlink issues)" 50 | Rebar as dev release 51 | Rebar as dev release 52 | "" 53 | 54 | # Go to release 55 | Set-Location "_build\default\rel\$release\bin" 56 | 57 | "*** Install service" 58 | & ".\$release.ps1" install 59 | if ($LASTEXITCODE -ne 0) { 60 | Write-Error "Failed to install service" 61 | } 62 | "" 63 | 64 | "*** Start service" 65 | & ".\$release.ps1" start 66 | if ($LASTEXITCODE -ne 0) { 67 | Write-Error "Failed to start service" 68 | } 69 | "" 70 | 71 | "*** Ping service" 72 | & ".\$release.ps1" ping 73 | if ($LASTEXITCODE -ne 0) { 74 | Write-Error "Failed to ping service" 75 | } 76 | "" 77 | 78 | "*** Stop service" 79 | & ".\$release.ps1" stop 80 | if ($LASTEXITCODE -ne 0) { 81 | Write-Error "Failed to stop service" 82 | } 83 | "" 84 | 85 | "*** Uninstall service" 86 | & ".\$release.ps1" uninstall 87 | if ($LASTEXITCODE -ne 0) { 88 | Write-Error "Failed to uninstall service" 89 | } 90 | "" 91 | -------------------------------------------------------------------------------- /src/relx.app.src: -------------------------------------------------------------------------------- 1 | {application, relx, 2 | [{description, "Release assembler for Erlang/OTP Releases"}, 3 | {vsn, "git"}, 4 | {modules, []}, 5 | {registered, []}, 6 | {applications, [kernel, 7 | stdlib, 8 | bbmustache, 9 | sasl, 10 | tools]}, 11 | {licenses, ["Apache-2.0"]}, 12 | {links, [{"Github", "https://github.com/erlware/relx"}]}]}. 13 | -------------------------------------------------------------------------------- /src/relx.erl: -------------------------------------------------------------------------------- 1 | %% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- 2 | %%% Copyright 2012 Erlware, LLC. All Rights Reserved. 3 | %%% 4 | %%% This file is provided to you under the Apache License, 5 | %%% Version 2.0 (the "License"); you may not use this file 6 | %%% except in compliance with the License. You may obtain 7 | %%% a copy of the License at 8 | %%% 9 | %%% http://www.apache.org/licenses/LICENSE-2.0 10 | %%% 11 | %%% Unless required by applicable law or agreed to in writing, 12 | %%% software distributed under the License is distributed on an 13 | %%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | %%% KIND, either express or implied. See the License for the 15 | %%% specific language governing permissions and limitations 16 | %%% under the License. 17 | %%%--------------------------------------------------------------------------- 18 | %%% @author Tristan Sloughter 19 | %%% @author Eric Merritt 20 | %%% @copyright (C) 2012 Erlware, LLC. 21 | %%% @doc 22 | -module(relx). 23 | 24 | -export([release/3, 25 | build_release/2, 26 | build_release/3, 27 | 28 | build_tar/2, 29 | build_tar/3, 30 | 31 | build_relup/4, 32 | format_error/1]). 33 | 34 | -include("relx.hrl"). 35 | 36 | -type error() :: {error, {Module::module(), Reason::term()}}. 37 | -type goal() :: rlx_release:name() | 38 | {rlx_release:name(), rlx_release:vsn() | rlx_release:type()} | 39 | {rlx_release:name(), rlx_release:vsn(), rlx_release:type() | rlx_release:incl_apps()} | 40 | {rlx_release:name(), rlx_release:vsn(), rlx_release:type(), rlx_release:incl_apps()}. 41 | 42 | -export_type([goal/0, 43 | error/0]). 44 | 45 | -type release() :: #{name := atom(), 46 | vsn := string(), 47 | 48 | %% top level application list to include in release 49 | %% referred to as goals because it is not the complete 50 | %% list of applications. 51 | goals := [goal()], 52 | 53 | relfile_path := file:filename_all() | undefined}. 54 | 55 | -spec release(rlx_release:name(), rlx_release:vsn(), [goal()]) -> release(). 56 | release(Name, Vsn, Goals) -> 57 | #{name => Name, 58 | vsn => Vsn, 59 | goals => Goals, 60 | relfile_path => undefined}. 61 | 62 | -spec build_release(Release, Config) -> {ok, rlx_state:t()} | {error, term()} when 63 | Release :: atom() | {atom(), string()} | release(), 64 | Config :: rlx_config:t(). 65 | build_release(Release, Config) -> 66 | {ok, State} = rlx_config:to_state(Config), 67 | build_release(Release, #{}, State). 68 | 69 | -spec build_release(Release, Apps, State) -> {ok, rlx_state:t()} | {error, term()} when 70 | Release :: atom() | {atom(), string()} | release() | undefined, 71 | Apps :: #{atom() => rlx_app_info:t()}, 72 | State :: rlx_state:t(). 73 | build_release(RelNameOrUndefined, Apps, State) when is_atom(RelNameOrUndefined) -> 74 | {RelName, RelVsn} = pick_release_version(RelNameOrUndefined, State), 75 | Release = #{name => RelName, 76 | vsn => RelVsn}, 77 | RealizedRelease = build_release_(Release, Apps, State), 78 | {ok, rlx_state:add_realized_release(State, RealizedRelease)}; 79 | build_release({RelName, RelVsn}, Apps, State) when is_atom(RelName) , 80 | is_list(RelVsn) -> 81 | Release = #{name => RelName, 82 | vsn => RelVsn}, 83 | RealizedRelease = build_release_(Release, Apps, State), 84 | {ok, rlx_state:add_realized_release(State, RealizedRelease)}; 85 | build_release(Release=#{name := _RelName, 86 | vsn := _RelVsn}, Apps, State) -> 87 | RealizedRelease = build_release_(Release, Apps, State), 88 | {ok, rlx_state:add_realized_release(State, RealizedRelease)}; 89 | build_release(Release, _, _) -> 90 | ?RLX_ERROR({unrecognized_release, Release}). 91 | 92 | -spec build_tar(Release, Config) -> {ok, rlx_release:t()} when 93 | Release :: atom() | {atom(), string()} | release() | undefined, 94 | Config :: rlx_config:t(). 95 | build_tar(Release, Config) when is_list(Config) -> 96 | {ok, State} = rlx_config:to_state(Config), 97 | build_tar(Release, #{}, State). 98 | 99 | -spec build_tar(Release, Apps, State) -> {ok, rlx_release:t()} when 100 | Release :: atom() | {atom(), string()} | release() | undefined, 101 | Apps :: #{atom() => rlx_app_info:t()}, 102 | State :: rlx_state:t(). 103 | build_tar(undefined, Apps, State) -> 104 | {RelName, RelVsn} = pick_release(State), 105 | Release = #{name => RelName, 106 | vsn => RelVsn}, 107 | RealizedRelease = build_release_(Release, Apps, State), 108 | build_tar_(RealizedRelease, State), 109 | {ok, RealizedRelease}; 110 | build_tar(Release=#{name := RelName, 111 | vsn := RelVsn}, Apps, State) when is_atom(RelName) , 112 | is_list(RelVsn) -> 113 | RealizedRelease = build_release_(Release, Apps, State), 114 | build_tar_(RealizedRelease, State), 115 | {ok, RealizedRelease}; 116 | build_tar({RelName, RelVsn}, Apps, State) when is_atom(RelName) -> 117 | Release = #{name => RelName, 118 | vsn => RelVsn}, 119 | RealizedRelease = build_release_(Release, Apps, State), 120 | build_tar_(RealizedRelease, State), 121 | {ok, RealizedRelease}; 122 | build_tar(RelName, Apps, State) when is_atom(RelName) -> 123 | {RelName, RelVsn} = pick_release_version(RelName, State), 124 | Release = #{name => RelName, 125 | vsn => RelVsn}, 126 | RealizedRelease = build_release_(Release, Apps, State), 127 | build_tar_(RealizedRelease, State), 128 | {ok, RealizedRelease}. 129 | 130 | -spec build_relup(rlx_release:name(), rlx_release:vsn(), rlx_release:vsn(), rlx_config:t() | rlx_state:t()) 131 | -> {ok, rlx_state:t()} | {error, term()}. 132 | build_relup(RelName, ToVsn, UpFromVsn, Config) when is_list(Config) -> 133 | {ok, State} = rlx_config:to_state(Config), 134 | build_relup(RelName, ToVsn, UpFromVsn, State); 135 | build_relup(RelName, ToVsn, UpFromVsn, State) -> 136 | {RelName, ToVsn} = pick_release_version(RelName, State), 137 | rlx_relup:do(RelName, ToVsn, UpFromVsn, State). 138 | 139 | -spec format_error(Reason::term()) -> string(). 140 | format_error({unrecognized_release, Release}) -> 141 | io_lib:format("Could not understand release argument ~p~n", [Release]); 142 | format_error({error, {relx, Reason}}) -> 143 | format_error(Reason); 144 | format_error({no_release_name, Vsn}) -> 145 | io_lib:format("A target release version was specified (~s) but no name", [Vsn]); 146 | format_error({invalid_release_info, Info}) -> 147 | io_lib:format("Target release information is in an invalid format ~p", [Info]); 148 | format_error({multiple_release_names, _, _}) -> 149 | "Must specify the name of the release to build when there are multiple releases in the config"; 150 | format_error(no_releases_in_system) -> 151 | "No releases have been specified in the system!"; 152 | format_error({no_releases_for, RelName}) -> 153 | io_lib:format("No releases exist in the system for ~s!", [RelName]); 154 | format_error({release_not_found, {RelName, RelVsn}}) -> 155 | io_lib:format("No releases exist in the system for ~p:~s!", [RelName, RelVsn]); 156 | format_error({error, {Module, Reason}}) -> 157 | io_lib:format("~s~n", [Module:format_error(Reason)]). 158 | 159 | %% 160 | 161 | build_tar_(RealizedRelease, State) -> 162 | OutputDir = filename:join(rlx_state:base_output_dir(State), 163 | rlx_release:name(RealizedRelease)), 164 | rlx_tar:make_tar(RealizedRelease, OutputDir, State). 165 | 166 | build_release_(#{name := RelName, 167 | vsn := RelVsn}, Apps, State) -> 168 | Release = rlx_state:get_configured_release(State, RelName, RelVsn), 169 | {ok, RealizedRelease, State1} = 170 | rlx_resolve:solve_release(Release, rlx_state:available_apps(State, Apps)), 171 | {ok, State2} = rlx_assemble:do(RealizedRelease, State1), 172 | _ = rlx_overlay:render(RealizedRelease, State2), 173 | RealizedRelease. 174 | 175 | pick_release(State) -> 176 | %% Here we will just get the highest versioned release and run that. 177 | case lists:sort(fun release_sort/2, maps:to_list(rlx_state:configured_releases(State))) of 178 | [{{RelName, RelVsn}, _} | _] -> 179 | {RelName, RelVsn}; 180 | [] -> 181 | erlang:error(?RLX_ERROR(no_releases_in_system)) 182 | end. 183 | 184 | pick_release_version(undefined, State) -> 185 | pick_release(State); 186 | pick_release_version(RelName, State) -> 187 | %% Here we will just get the latest version for name RelName and run that. 188 | AllReleases = maps:to_list(rlx_state:configured_releases(State)), 189 | SpecificReleases = [Rel || Rel={{PossibleRelName, _}, _} <- AllReleases, PossibleRelName =:= RelName], 190 | case lists:sort(fun release_sort/2, SpecificReleases) of 191 | [{{RelName, RelVsn}, _} | _] -> 192 | {RelName, RelVsn}; 193 | [] -> 194 | erlang:error(?RLX_ERROR({no_releases_for, RelName})) 195 | end. 196 | 197 | -spec release_sort({{rlx_release:name(),rlx_release:vsn()}, term()}, 198 | {{rlx_release:name(),rlx_release:vsn()}, term()}) -> 199 | boolean(). 200 | release_sort({{RelName, RelVsnA}, _}, 201 | {{RelName, RelVsnB}, _}) -> 202 | rlx_util:parsed_vsn_lte(rlx_util:parse_vsn(RelVsnB), rlx_util:parse_vsn(RelVsnA)); 203 | release_sort({{RelA, _}, _}, {{RelB, _}, _}) -> 204 | %% The release names are different. When the releases are named differently 205 | %% we can not just take the latest version. You *must* provide a default 206 | %% release name at least. So we throw an error here that the top can catch 207 | %% and return 208 | error(?RLX_ERROR({multiple_release_names, RelA, RelB})). 209 | -------------------------------------------------------------------------------- /src/relx.hrl: -------------------------------------------------------------------------------- 1 | %% Copyright 2012 Erlware, LLC. All Rights Reserved. 2 | %% 3 | %% This file is provided to you under the Apache License, 4 | %% Version 2.0 (the "License"); you may not use this file 5 | %% except in compliance with the License. You may obtain 6 | %% a copy of the License at 7 | %% 8 | %% http://www.apache.org/licenses/LICENSE-2.0 9 | %% 10 | %% Unless required by applicable law or agreed to in writing, 11 | %% software distributed under the License is distributed on an 12 | %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | %% KIND, either express or implied. See the License for the 14 | %% specific language governing permissions and limitations 15 | %% under the License. 16 | %% 17 | 18 | %% This is the default form of error messages for the Relx 19 | %% system. It is expected that everything that returns an error use 20 | %% this and that they all expose a format_error/1 message that returns 21 | %% an iolist. 22 | -define(RLX_ERROR(Reason), {error, {?MODULE, Reason}}). 23 | 24 | -ifdef(OTP_RELEASE). 25 | -define(WITH_STACKTRACE(T, R, S), T:R:S ->). 26 | -else. 27 | -define(WITH_STACKTRACE(T, R, S), T:R -> S = erlang:get_stacktrace(),). 28 | -endif. 29 | -------------------------------------------------------------------------------- /src/rlx_app_info.erl: -------------------------------------------------------------------------------- 1 | %% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- 2 | %%% Copyright 2012 Erlware, LLC. All Rights Reserved. 3 | %%% 4 | %%% This file is provided to you under the Apache License, 5 | %%% Version 2.0 (the "License"); you may not use this file 6 | %%% except in compliance with the License. You may obtain 7 | %%% a copy of the License at 8 | %%% 9 | %%% http://www.apache.org/licenses/LICENSE-2.0 10 | %%% 11 | %%% Unless required by applicable law or agreed to in writing, 12 | %%% software distributed under the License is distributed on an 13 | %%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | %%% KIND, either express or implied. See the License for the 15 | %%% specific language governing permissions and limitations 16 | %%% under the License. 17 | %%%--------------------------------------------------------------------------- 18 | %%% @author Eric Merritt 19 | %%% @copyright (C) 2012 Erlware, LLC. 20 | %%% 21 | %%% @doc This module represents useful, relevant information about an 22 | %%% application. The relevant information is. 23 | %%% 24 | %%%
    25 | %%%
  • `name' - The application name as an atom.
  • 26 | %%%
  • `vsn' - The application version as a list.
  • 27 | %%%
  • `dir' - The root directory of the application. The directory that contains the 28 | %%% ebin/src/priv
  • 29 | %%%
  • `link' - Whether to symlink or copy the application directory.
  • 30 | %%%
  • `applications' - The `application' dependencies of the OTP 31 | %%% App. That is the things in the `applications' property of the application 32 | %%% metadata
  • 33 | %%%
  • `included_applications' - The apps in the `included_applications' property 34 | %%% of the application metadata.
  • 35 | %%%
36 | %%% 37 | -module(rlx_app_info). 38 | 39 | -export([new/5, 40 | new/6, 41 | new/7, 42 | name/1, 43 | vsn/1, 44 | dir/1, 45 | applications/1, 46 | included_applications/1, 47 | optional_applications/1, 48 | link/1, 49 | link/2, 50 | format_error/1, 51 | format/2, 52 | format/1]). 53 | 54 | -include("relx.hrl"). 55 | 56 | -type app_type() :: project | dep | checkout | system. 57 | -type t() :: #{name := atom() | undefined, 58 | vsn := string() | undefined, 59 | 60 | applications := [atom()], 61 | included_applications := [atom()], 62 | optional_applications := [atom()], 63 | 64 | dir := file:name() | undefined, 65 | link := boolean() | undefined, 66 | 67 | %% `project' app is one the user is actively developing on 68 | %% `dep' is dependency fetched by rebar3 69 | %% `checkout' is a dependency linked to from the _checkouts dir 70 | %% and treated like a project app 71 | %% `system' applications are dependencies from Erlang/OTP 72 | app_type := app_type()}. 73 | 74 | -export_type([t/0, 75 | app_type/0]). 76 | 77 | -spec new(atom(), string(), file:name(), [atom()], [atom()]) -> t(). 78 | new(Name, Vsn, Dir, Applications, IncludedApplications) -> 79 | new(Name, Vsn, Dir, Applications, IncludedApplications, [], dep). 80 | 81 | -spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()] | atom()) -> t(). 82 | new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications) 83 | when is_list(OptionalApplications) -> 84 | new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, dep); 85 | new(Name, Vsn, Dir, Applications, IncludedApplications, AppType) when is_atom(AppType) -> 86 | new(Name, Vsn, Dir, Applications, IncludedApplications, [], AppType). 87 | 88 | -spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()], app_type()) -> t(). 89 | new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, AppType) -> 90 | #{name => Name, 91 | vsn => Vsn, 92 | 93 | applications => Applications, 94 | included_applications => IncludedApplications, 95 | optional_applications => OptionalApplications, 96 | 97 | dir => Dir, 98 | link => false, 99 | 100 | app_type => AppType}. 101 | 102 | -spec name(t()) -> atom(). 103 | name(#{name := Name}) -> 104 | Name. 105 | 106 | -spec vsn(t()) -> string(). 107 | vsn(#{vsn := Vsn}) -> 108 | Vsn. 109 | 110 | -spec dir(t()) -> binary(). 111 | dir(#{dir := Dir}) -> 112 | Dir. 113 | 114 | -spec applications(t()) -> [atom()]. 115 | applications(#{applications := Deps}) -> 116 | Deps. 117 | 118 | -spec included_applications(t()) -> [atom()]. 119 | included_applications(#{included_applications := Deps}) -> 120 | Deps. 121 | 122 | -spec optional_applications(t()) -> [atom()]. 123 | optional_applications(#{optional_applications := Deps}) -> 124 | Deps. 125 | 126 | -spec link(t()) -> boolean(). 127 | link(#{link := Link}) -> 128 | Link. 129 | 130 | -spec link(t(), boolean()) -> t(). 131 | link(AppInfo, NewLink) -> 132 | AppInfo#{link => NewLink}. 133 | 134 | -spec format_error(Reason::term()) -> iolist(). 135 | format_error(Error) -> 136 | io_lib:format("~p", [Error]). 137 | 138 | -spec format(t()) -> iolist(). 139 | format(AppInfo) -> 140 | format(0, AppInfo). 141 | 142 | -spec format(non_neg_integer(), t()) -> iolist(). 143 | format(Indent, #{name := Name, 144 | vsn := Vsn, 145 | dir := Dir, 146 | applications := Deps, 147 | included_applications := IncDeps, 148 | link := Link}) -> 149 | [rlx_util:indent(Indent), erlang:atom_to_list(Name), "-", Vsn, ": ", Dir, "\n", 150 | rlx_util:indent(Indent + 1), "Symlink: ", erlang:atom_to_list(Link), "\n", 151 | rlx_util:indent(Indent + 1), "Applications:\n", 152 | [[rlx_util:indent(Indent + 2), erlang:atom_to_list(Dep), "\n"] || Dep <- Deps], 153 | rlx_util:indent(Indent + 1), "Included Applications:\n", 154 | [[rlx_util:indent(Indent + 2), erlang:atom_to_list(IncDep), "\n"] || IncDep <- IncDeps]]. 155 | -------------------------------------------------------------------------------- /src/rlx_log.erl: -------------------------------------------------------------------------------- 1 | -module(rlx_log). 2 | 3 | -export([log/3]). 4 | 5 | -spec log(atom(), atom() | string() | binary(), [term()]) -> ok. 6 | log(_Level, Msg, Args) -> 7 | io:format(Msg, Args). 8 | -------------------------------------------------------------------------------- /src/rlx_log.hrl: -------------------------------------------------------------------------------- 1 | -ifndef(RLX_LOG). 2 | -define(RLX_LOG, rlx_log). 3 | -endif. 4 | 5 | %% logging macros 6 | -define(log_debug(Msg), ?RLX_LOG:log(debug, Msg, [])). 7 | -define(log_warn(Msg), ?RLX_LOG:log(warn, Msg, [])). 8 | -define(log_error(Msg), ?RLX_LOG:log(error, Msg, [])). 9 | -define(log_info(Msg), ?RLX_LOG:log(info, Msg, [])). 10 | 11 | -define(log_debug(Msg, Args), ?RLX_LOG:log(debug, Msg, Args)). 12 | -define(log_warn(Msg, Args), ?RLX_LOG:log(warn, Msg, Args)). 13 | -define(log_error(Msg, Args), ?RLX_LOG:log(error, Msg, Args)). 14 | -define(log_info(Msg, Args), ?RLX_LOG:log(info, Msg, Args)). 15 | -------------------------------------------------------------------------------- /src/rlx_relup.erl: -------------------------------------------------------------------------------- 1 | -module(rlx_relup). 2 | 3 | -export([do/4, 4 | format_error/1]). 5 | 6 | -include("relx.hrl"). 7 | -include("rlx_log.hrl"). 8 | 9 | -spec do(atom(), string(), string() | undefined, rlx_state:t()) -> {ok, rlx_state:t()} | relx:error(). 10 | do(RelName, ToVsn, undefined, State) -> 11 | OutputDir = rlx_state:base_output_dir(State), 12 | ReleasesDir = filename:join([OutputDir, RelName, "releases"]), 13 | LastRelVsn = get_version_before(RelName, ToVsn, ReleasesDir), 14 | make_upfrom_script(RelName, ToVsn, LastRelVsn, State); 15 | do(RelName, ToVsn, UpFromVsn, State) -> 16 | make_upfrom_script(RelName, ToVsn, UpFromVsn, State). 17 | 18 | format_error({relfile_not_found, {Name, Vsn}}) -> 19 | io_lib:format("Release ~p-~s not found", [Name, Vsn]); 20 | format_error({bad_rel_tuple, Release}) -> 21 | io_lib:format("Release format ~p not recognized. Should be of the form {Name, Vsn}.", [Release]); 22 | format_error({relup_generation_error, CurrentName, UpFromName}) -> 23 | io_lib:format("Unknown internal release error generating the relup from ~s to ~s", 24 | [UpFromName, CurrentName]); 25 | format_error({no_upfrom_release_found, undefined}) -> 26 | io_lib:format("No earlier release for relup found", []); 27 | format_error({no_upfrom_release_found, Vsn}) -> 28 | io_lib:format("Upfrom release version (~s) for relup not found", [Vsn]); 29 | format_error({relup_script_generation_error, systools_relup, {missing_sasl, _}}) -> 30 | "Unfortunately, due to requirements in systools, you need to have the sasl application " 31 | "in both the current release and the release to upgrade from."; 32 | format_error({relup_script_generation_error, Module, Error}) -> 33 | ["Error generating relup: \n", rlx_util:indent(2), Module:format_error(Error)]. 34 | 35 | %% 36 | 37 | make_upfrom_script(Name, ToVsn, UpFromVsn, State) -> 38 | OutputDir = rlx_state:base_output_dir(State), 39 | OutDir = filename:join([OutputDir, atom_to_list(Name), "releases", ToVsn]), 40 | WarningsAsErrors = rlx_state:warnings_as_errors(State), 41 | Options = [{outdir, OutDir}, 42 | {path, [filename:join([OutputDir, "*", "lib", "*", "ebin"])]}, 43 | {silent, true} | case WarningsAsErrors of 44 | true -> [warnings_as_errors]; 45 | false -> [] 46 | end], 47 | CurrentRel = strip_dot_rel(find_rel_file(Name, ToVsn, OutputDir)), 48 | UpFromRel = strip_dot_rel(find_rel_file(Name, UpFromVsn, OutputDir)), 49 | ?log_debug("systools:make_relup(~p, ~p, ~p, ~p)", [CurrentRel, UpFromRel, UpFromRel, Options]), 50 | case systools:make_relup(CurrentRel, [UpFromRel], [UpFromRel], [no_warn_sasl | Options]) of 51 | ok -> 52 | ?log_info("relup from ~s to ~s successfully created!", [UpFromRel, CurrentRel]), 53 | {ok, State}; 54 | error -> 55 | erlang:error(?RLX_ERROR({relup_generation_error, CurrentRel, UpFromRel})); 56 | {ok, _RelUp, _, []} -> 57 | ?log_info("relup successfully created!"), 58 | {ok, State}; 59 | {ok, _RelUp, Module, Warnings} -> 60 | ?log_warn("Warnings generating relup:~n~s", [[Module:format_warning(W) || W <- Warnings]]), 61 | {ok, State}; 62 | 63 | {error, Module, Error} -> 64 | erlang:error(?RLX_ERROR({relup_script_generation_error, Module, Error})) 65 | end. 66 | 67 | %% return path to rel file without the .rel extension as a string (not binary) 68 | strip_dot_rel(Name) -> 69 | rlx_util:to_string(filename:join(filename:dirname(Name), 70 | filename:basename(Name, ".rel"))). 71 | 72 | find_rel_file(Name, Vsn, Dir) when is_atom(Name) , 73 | is_list(Vsn) -> 74 | RelFile = filename:join([Dir, atom_to_list(Name), "releases", Vsn, atom_to_list(Name) ++ ".rel"]), 75 | case filelib:is_regular(RelFile) of 76 | true -> 77 | RelFile; 78 | _ -> 79 | erlang:error(?RLX_ERROR({relfile_not_found, {Name, Vsn}})) 80 | end; 81 | find_rel_file(Name, Vsn, _) -> 82 | erlang:error(?RLX_ERROR({bad_rel_tuple, {Name, Vsn}})). 83 | 84 | get_version_before(Name, Vsn, ReleasesDir) -> 85 | %% Given directory where all releases for `Name' are find all versions of the release. 86 | %% Since the releases directory will have other files like `RELEASES', use the wildcard 87 | %% `*/Name.rel' to find all version directories and then trim down to just the version 88 | %% string with `filename:dirname/1' 89 | Vsns = [begin 90 | V = filename:dirname(R), 91 | {rlx_util:parse_vsn(V), V} 92 | end || R <- filelib:wildcard(filename:join("*", [Name, ".rel"]), ReleasesDir)], 93 | 94 | %% sort all the versions 95 | SortedVsns = lists:sort(fun vsn_lte/2, Vsns), 96 | 97 | %% take the last element of a list that has every element up to the `Vsn' we are building 98 | %% the relup for. This will be the most recent version of the same release found. 99 | case lists:reverse(lists:takewhile(fun({_, X}) -> X =/= Vsn end, SortedVsns)) of 100 | [{_, LastVersion} | _] -> 101 | LastVersion; 102 | _ -> 103 | erlang:error(?RLX_ERROR({no_upfrom_release_found, Vsn})) 104 | end. 105 | 106 | vsn_lte({VsnA, _}, {VsnB, _}) -> 107 | rlx_util:parsed_vsn_lte(VsnA, VsnB). 108 | -------------------------------------------------------------------------------- /src/rlx_string.erl: -------------------------------------------------------------------------------- 1 | %% Compatibility module for the string API changes between 2 | %% OTP-19 and OTP-21, where Unicode support means the deprecation 3 | %% of a lot of string functions. 4 | -module(rlx_string). 5 | -export([concat/2, lexemes/2, join/2, trim/3, to_list/1]). 6 | 7 | -ifdef(unicode_str). 8 | concat(Str1, Str2) -> unicode:characters_to_list([Str1,Str2]). 9 | lexemes(Str, Separators) -> string:lexemes(Str, Separators). 10 | trim(Str, Direction, Cluster=[_]) -> string:trim(Str, Direction, Cluster). 11 | -else. 12 | concat(Str1, Str2) -> string:concat(Str1, Str2). 13 | lexemes(Str, Separators) -> string:tokens(Str, Separators). 14 | trim(Str, Direction, [Char]) -> 15 | Dir = case Direction of 16 | both -> both; 17 | leading -> left; 18 | trailing -> right 19 | end, 20 | string:strip(Str, Dir, Char). 21 | -endif. 22 | 23 | %% string:join/2 copy; string:join/2 is getting obsoleted 24 | %% and replaced by lists:join/2, but lists:join/2 is too new 25 | %% for version support (only appeared in 19.0) so it cannot be 26 | %% used. Instead we just adopt join/2 locally and hope it works 27 | %% for most unicode use cases anyway. 28 | join([], Sep) when is_list(Sep) -> 29 | []; 30 | join([H|T], Sep) -> 31 | H ++ lists:append([Sep ++ X || X <- T]). 32 | 33 | -spec to_list(binary() | list()) -> list(). 34 | to_list(String) when is_binary(String) -> 35 | binary_to_list(String); 36 | to_list(String) when is_list(String) -> 37 | String. 38 | -------------------------------------------------------------------------------- /test/rlx_dscv_util.erl: -------------------------------------------------------------------------------- 1 | %% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- 2 | %%% Copyright 2012 Erlware, LLC. All Rights Reserved. 3 | %%% 4 | %%% This file is provided to you under the Apache License, 5 | %%% Version 2.0 (the "License"); you may not use this file 6 | %%% except in compliance with the License. You may obtain 7 | %%% a copy of the License at 8 | %%% 9 | %%% http://www.apache.org/licenses/LICENSE-2.0 10 | %%% 11 | %%% Unless required by applicable law or agreed to in writing, 12 | %%% software distributed under the License is distributed on an 13 | %%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | %%% KIND, either express or implied. See the License for the 15 | %%% specific language governing permissions and limitations 16 | %%% under the License. 17 | %%%--------------------------------------------------------------------------- 18 | %%% @author Eric Merritt 19 | %%% @copyright (C) 2012 Erlware, LLC. 20 | -module(rlx_dscv_util). 21 | 22 | -export([do/2, 23 | format_error/1]). 24 | 25 | -include("relx.hrl"). 26 | 27 | %%============================================================================ 28 | %% Types 29 | %%============================================================================ 30 | 31 | -type process_fun(Result) :: fun((file:name(), file | directory) -> 32 | {ok, Result} | 33 | {error, term()} | 34 | {ok, Result, Recurse::boolean()} | 35 | {noresult, Recurse::boolean()} | 36 | {error, term()}). 37 | 38 | %%============================================================================ 39 | %% API 40 | %%============================================================================ 41 | 42 | %% @doc recursively dig down into the library directories specified in the state 43 | %% looking for OTP Applications 44 | -spec do(process_fun([term()] | term()), [file:name()]) -> 45 | [term() | {error, term()}]. 46 | do(ProcessDir, LibDirs) -> 47 | lists:flatten(lists:map(fun(LibDir) -> 48 | discover_dir(ProcessDir, LibDir, 49 | rlx_file_utils:type(LibDir)) 50 | end, LibDirs)). 51 | 52 | -spec format_error([ErrorDetail::term()]) -> iolist(). 53 | format_error(ErrorDetails) 54 | when erlang:is_list(ErrorDetails) -> 55 | [[format_detail(ErrorDetail), "\n"] || ErrorDetail <- ErrorDetails]. 56 | 57 | %%%=================================================================== 58 | %%% Internal Functions 59 | %%%=================================================================== 60 | -spec format_detail(ErrorDetail::term()) -> iolist(). 61 | format_detail({accessing, File, eaccess}) -> 62 | io_lib:format("permission denied accessing file ~s", [File]); 63 | format_detail({accessing, File, Type}) -> 64 | io_lib:format("error (~p) accessing file ~s", [Type, File]); 65 | format_detail({not_a_directory, EbinDir}) -> 66 | io_lib:format("~s is not a directory when it should be a directory", [EbinDir]). 67 | 68 | -spec discover_dir(process_fun([term()] | term()), 69 | file:name(), 70 | directory | file | symlink | undefined) -> 71 | [{ok, term()} 72 | | {error, Reason::term()}] 73 | | [] 74 | | {ok, term()} 75 | | {error, Reason::term()}. 76 | discover_dir(_ProcessDir, _File, undefined) -> 77 | []; 78 | discover_dir(ProcessDir, File, directory) -> 79 | case ProcessDir(File, directory) of 80 | {ok, Result, true} -> 81 | [{ok, Result} | recurse(ProcessDir, File)]; 82 | {noresult, true} -> 83 | recurse(ProcessDir, File); 84 | {ok, Result, _} -> 85 | [{ok, Result}]; 86 | {noresult, _} -> 87 | []; 88 | Err = {error, _} -> 89 | [Err] 90 | end; 91 | discover_dir(ProcessDir, File, file) -> 92 | case ProcessDir(File, file) of 93 | {ok, Result} -> 94 | [{ok, Result}]; 95 | {noresult, _} -> 96 | []; 97 | Warn = {warning, _} -> 98 | [Warn]; 99 | Err = {error, _} -> 100 | [Err] 101 | end; 102 | discover_dir(ProcessDir, File, symlink) -> 103 | case filelib:is_dir(File) of 104 | false -> 105 | discover_dir(ProcessDir, File, file); 106 | true -> 107 | discover_real_symlink_dir(ProcessDir, File) 108 | end. 109 | 110 | discover_real_symlink_dir(ProcessDir, File) -> 111 | {ok, ActualRealDir} = file:read_link(File), 112 | case lists:prefix(filename:split(iolist_to_list(filename:absname(ActualRealDir))), 113 | filename:split(iolist_to_list(filename:absname(File)))) of 114 | true -> 115 | %% Ignore cycles 116 | []; 117 | false -> 118 | case ProcessDir(File, directory) of 119 | {ok, Result, true} -> 120 | [{ok, Result} | recurse(ProcessDir, File)]; 121 | {noresult, true} -> 122 | recurse(ProcessDir, File); 123 | {ok, Result, _} -> 124 | [{ok, Result}]; 125 | {noresult, _} -> 126 | []; 127 | Err = {error, _} -> 128 | [Err] 129 | end 130 | end. 131 | 132 | recurse(ProcessDir, File) -> 133 | case file:list_dir(File) of 134 | {error, Reason} -> 135 | {error, {accessing, File, Reason}}; 136 | {ok, List} -> 137 | lists:map(fun(LibDir) -> 138 | discover_dir(ProcessDir, LibDir, rlx_file_utils:type(LibDir)) 139 | end, [filename:join([File, Dir]) || Dir <- List]) 140 | end. 141 | 142 | iolist_to_list(IoList) -> 143 | erlang:binary_to_list(erlang:iolist_to_binary(IoList)). 144 | -------------------------------------------------------------------------------- /test/rlx_relup_SUITE.erl: -------------------------------------------------------------------------------- 1 | -module(rlx_relup_SUITE). 2 | 3 | -compile([export_all]). 4 | 5 | -include_lib("common_test/include/ct.hrl"). 6 | -include_lib("eunit/include/eunit.hrl"). 7 | 8 | all() -> 9 | [make_relup_release, make_relup_release2, no_upfrom_release]. 10 | 11 | suite() -> 12 | []. 13 | 14 | init_per_suite(Config) -> 15 | Config. 16 | 17 | end_per_suite(_Config) -> 18 | ok. 19 | 20 | init_per_testcase(_, Config) -> 21 | DataDir = filename:join(proplists:get_value(priv_dir, Config), ?MODULE), 22 | LibDir1 = filename:join([DataDir, rlx_test_utils:create_random_name("lib_dir1_")]), 23 | ok = rlx_file_utils:mkdir_p(LibDir1), 24 | [{lib_dir, LibDir1} | Config]. 25 | 26 | make_relup_release(Config) -> 27 | LibDir1 = ?config(lib_dir, Config), 28 | 29 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [stdlib,kernel,non_goal_1], []), 30 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.2", [stdlib,kernel,non_goal_1], []), 31 | GA1 = rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.3", [stdlib,kernel,non_goal_1], []), 32 | rlx_test_utils:create_app(LibDir1, "lib_dep_1", "0.0.1", [stdlib,kernel], []), 33 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.1", [stdlib,kernel,goal_app_1,non_goal_2], []), 34 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.2", [stdlib,kernel,goal_app_1,non_goal_2], []), 35 | GA2 = rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.3", [stdlib,kernel,goal_app_1,non_goal_2], []), 36 | rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [stdlib,kernel], [lib_dep_1]), 37 | rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", [stdlib,kernel], []), 38 | 39 | rlx_test_utils:write_appup_file(GA1, "0.0.2"), 40 | rlx_test_utils:write_appup_file(GA2, "0.0.2"), 41 | 42 | RelxConfig = [{release, {foo, "0.0.1"}, 43 | [sasl, 44 | {goal_app_1, "0.0.1"}, 45 | {goal_app_2, "0.0.1"}]}, 46 | {release, {foo, "0.0.2"}, 47 | [sasl, 48 | {goal_app_1, "0.0.2"}, 49 | {goal_app_2, "0.0.2"}]}, 50 | {release, {foo, "0.0.3"}, 51 | [sasl, 52 | {goal_app_1, "0.0.3"}, 53 | {goal_app_2, "0.0.3"}]}], 54 | OutputDir = filename:join([?config(priv_dir, Config), 55 | rlx_test_utils:create_random_name("relx-output")]), 56 | 57 | {ok, _State} = relx:build_release({foo, "0.0.1"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 58 | {output_dir, OutputDir} | RelxConfig]), 59 | 60 | {ok, _State1} = relx:build_release({foo, "0.0.2"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 61 | {output_dir, OutputDir} | RelxConfig]), 62 | 63 | %% Goal apps are removed to simulate a users dev environment where the apps 64 | %% being used in an appup/relup are likely only under _rel//lib/ 65 | rlx_file_utils:remove(filename:join(LibDir1, "goal_app_1-0.0.1"), [recursive]), 66 | rlx_file_utils:remove(filename:join(LibDir1, "goal_app_1-0.0.2"), [recursive]), 67 | 68 | {ok, State2} = relx:build_release({foo, "0.0.3"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 69 | {output_dir, OutputDir} | RelxConfig]), 70 | 71 | %% `undefined' means automatically find last release version 72 | %% in this case `0.0.2' 73 | {ok, _State3} = relx:build_relup(foo, "0.0.3", undefined, 74 | [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 75 | {output_dir, OutputDir} | RelxConfig]), 76 | 77 | ?assertMatch({ok, [{"0.0.3", 78 | [{"0.0.2",[],[point_of_no_return]}], 79 | [{"0.0.2",[],[point_of_no_return]}]}]}, 80 | file:consult(filename:join([OutputDir, foo, "releases", "0.0.3", "relup"]))), 81 | 82 | [{{foo, "0.0.3"}, Release}] = maps:to_list(rlx_state:realized_releases(State2)), 83 | 84 | AppSpecs = rlx_release:app_specs(Release), 85 | ?assert(lists:keymember(stdlib, 1, AppSpecs)), 86 | ?assert(lists:keymember(kernel, 1, AppSpecs)), 87 | ?assert(lists:member({non_goal_1, "0.0.1"}, AppSpecs)), 88 | ?assert(lists:member({non_goal_2, "0.0.1"}, AppSpecs)), 89 | ?assert(lists:member({goal_app_1, "0.0.3"}, AppSpecs)), 90 | ?assert(lists:member({goal_app_2, "0.0.3"}, AppSpecs)), 91 | ?assert(lists:member({lib_dep_1, "0.0.1", load}, AppSpecs)). 92 | 93 | 94 | make_relup_release2(Config) -> 95 | LibDir1 = ?config(lib_dir, Config), 96 | 97 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [stdlib,kernel,non_goal_1], []), 98 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.2", [stdlib,kernel,non_goal_1], []), 99 | GA1 = rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.3", [stdlib,kernel,non_goal_1], []), 100 | rlx_test_utils:create_app(LibDir1, "lib_dep_1", "0.0.1", [stdlib,kernel], []), 101 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.1", [stdlib,kernel,goal_app_1,non_goal_2], []), 102 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.2", [stdlib,kernel,goal_app_1,non_goal_2], []), 103 | GA2 = rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.3", [stdlib,kernel,goal_app_1,non_goal_2], []), 104 | rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [stdlib,kernel], [lib_dep_1]), 105 | rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", [stdlib,kernel], []), 106 | 107 | rlx_test_utils:write_appup_file(GA1, "0.0.1"), 108 | rlx_test_utils:write_appup_file(GA2, "0.0.1"), 109 | 110 | RelxConfig = [{release, {foo, "0.0.1"}, 111 | [sasl, 112 | {goal_app_1, "0.0.1"}, 113 | {goal_app_2, "0.0.1"}]}, 114 | {release, {foo, "0.0.2"}, 115 | [sasl, 116 | {goal_app_1, "0.0.2"}, 117 | {goal_app_2, "0.0.2"}]}, 118 | {release, {foo, "0.0.3"}, 119 | [sasl, 120 | {goal_app_1, "0.0.3"}, 121 | {goal_app_2, "0.0.3"}]}], 122 | OutputDir = filename:join([proplists:get_value(priv_dir, Config), 123 | rlx_test_utils:create_random_name("relx-output")]), 124 | 125 | {ok, _} = relx:build_release({foo, "0.0.1"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 126 | {output_dir, OutputDir} | RelxConfig]), 127 | 128 | {ok, _} = relx:build_release({foo, "0.0.2"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 129 | {output_dir, OutputDir} | RelxConfig]), 130 | 131 | {ok, State2} = relx:build_release({foo, "0.0.3"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 132 | {output_dir, OutputDir} | RelxConfig]), 133 | 134 | {ok, _State3} = relx:build_relup(foo, "0.0.3", "0.0.1", 135 | [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 136 | {output_dir, OutputDir} | RelxConfig]), 137 | 138 | ?assertMatch({ok, [{"0.0.3", 139 | [{"0.0.1",[],[point_of_no_return]}], 140 | [{"0.0.1",[],[point_of_no_return]}]}]}, 141 | file:consult(filename:join([OutputDir, foo, "releases", "0.0.3", "relup"]))), 142 | 143 | [{{foo, "0.0.3"}, Release}] = maps:to_list(rlx_state:realized_releases(State2)), 144 | ?assertMatch(foo, rlx_release:name(Release)), 145 | ?assertMatch("0.0.3", rlx_release:vsn(Release)), 146 | AppSpecs = rlx_release:app_specs(Release), 147 | ?assert(lists:keymember(stdlib, 1, AppSpecs)), 148 | ?assert(lists:keymember(kernel, 1, AppSpecs)), 149 | ?assert(lists:member({non_goal_1, "0.0.1"}, AppSpecs)), 150 | ?assert(lists:member({non_goal_2, "0.0.1"}, AppSpecs)), 151 | ?assert(lists:member({goal_app_1, "0.0.3"}, AppSpecs)), 152 | ?assert(lists:member({goal_app_2, "0.0.3"}, AppSpecs)), 153 | ?assert(lists:member({lib_dep_1, "0.0.1", load}, AppSpecs)). 154 | 155 | no_upfrom_release(Config) -> 156 | LibDir1 = ?config(lib_dir, Config), 157 | 158 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [stdlib,kernel,non_goal_1], []), 159 | rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.2", [stdlib,kernel,non_goal_1], []), 160 | GA1 = rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.3", [stdlib,kernel,non_goal_1], []), 161 | rlx_test_utils:create_app(LibDir1, "lib_dep_1", "0.0.1", [stdlib,kernel], []), 162 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.1", [stdlib,kernel,goal_app_1,non_goal_2], []), 163 | rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.2", [stdlib,kernel,goal_app_1,non_goal_2], []), 164 | GA2 = rlx_test_utils:create_app(LibDir1, "goal_app_2", "0.0.3", [stdlib,kernel,goal_app_1,non_goal_2], []), 165 | rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [stdlib,kernel], [lib_dep_1]), 166 | rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", [stdlib,kernel], []), 167 | 168 | rlx_test_utils:write_appup_file(GA1, "0.0.2"), 169 | rlx_test_utils:write_appup_file(GA2, "0.0.2"), 170 | 171 | RelxConfig = [{release, {foo, "0.0.1"}, 172 | [sasl, 173 | {goal_app_1, "0.0.1"}, 174 | {goal_app_2, "0.0.1"}]}, 175 | {release, {foo, "0.0.2"}, 176 | [sasl, 177 | {goal_app_1, "0.0.2"}, 178 | {goal_app_2, "0.0.2"}]}, 179 | {release, {foo, "0.0.3"}, 180 | [sasl, 181 | {goal_app_1, "0.0.3"}, 182 | {goal_app_2, "0.0.3"}]}], 183 | OutputDir = filename:join([?config(priv_dir, Config), 184 | rlx_test_utils:create_random_name("relx-output")]), 185 | 186 | {ok, _} = relx:build_release({foo, "0.0.3"}, [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 187 | {output_dir, OutputDir} | RelxConfig]), 188 | 189 | %% no release to build relup from leads to an error 190 | ?assertError({error, {rlx_relup, {no_upfrom_release_found, "0.0.3"}}}, 191 | relx:build_relup(foo, "0.0.3", undefined, 192 | [{root_dir, LibDir1}, {lib_dirs, [LibDir1]}, 193 | {output_dir, OutputDir} | RelxConfig])). 194 | --------------------------------------------------------------------------------