├── share └── elixir-build │ ├── master │ └── dev ├── install.sh ├── LICENSE ├── bin ├── exenv-uninstall ├── exenv-install ├── json └── elixir-build └── README.md /share/elixir-build/master: -------------------------------------------------------------------------------- 1 | install_git "elixir-master" "https://github.com/elixir-lang/elixir.git" "master" 2 | -------------------------------------------------------------------------------- /share/elixir-build/dev: -------------------------------------------------------------------------------- 1 | install_git_with_history "elixir-dev" "https://github.com/elixir-lang/elixir.git" "master" 2 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ -z "${PREFIX}" ]; then 6 | PREFIX="/usr/local" 7 | fi 8 | 9 | BIN_PATH="${PREFIX}/bin" 10 | SHARE_PATH="${PREFIX}/share/elixir-build" 11 | 12 | mkdir -p "${BIN_PATH}" 13 | mkdir -p "${SHARE_PATH}" 14 | 15 | for file in bin/*; do 16 | cp "${file}" "${BIN_PATH}" 17 | done 18 | 19 | for file in share/elixir-build/*; do 20 | cp "${file}" "${SHARE_PATH}" 21 | done 22 | 23 | echo "Installed elixir-build at ${PREFIX}" 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Sam Stephenson, Yuki Ito 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /bin/exenv-uninstall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Provide exenv completions 5 | if [ "$1" = "--complete" ]; then 6 | exec exenv versions --bare 7 | fi 8 | 9 | if [ -z "$EXENV_ROOT" ]; then 10 | EXENV_ROOT="${HOME}/.exenv" 11 | fi 12 | 13 | unset FORCE 14 | if [ "$1" = "-f" ]; then 15 | FORCE=true 16 | shift 17 | fi 18 | 19 | DEFINITION="$1" 20 | case "$DEFINITION" in 21 | "" | -* ) 22 | { echo "usage: exenv uninstall [-f] VERSION" 23 | echo 24 | echo " -f Attempt to remove the specified version without prompting" 25 | echo " for confirmation. If the version does not exist, do not" 26 | echo " display an error message." 27 | echo 28 | echo "Installed versions:" 29 | exenv versions --bare | sed 's/^/ /' 30 | echo 31 | } >&2 32 | exit 1 33 | ;; 34 | esac 35 | 36 | VERSION_NAME="${DEFINITION##*/}" 37 | PREFIX="${EXENV_ROOT}/versions/${VERSION_NAME}" 38 | 39 | if [ -z "$FORCE" ]; then 40 | if [ ! -d "$PREFIX" ]; then 41 | echo "exenv: version \`$VERSION_NAME' not installed" >&2 42 | exit 1 43 | fi 44 | 45 | read -p "exenv: remove $PREFIX? " 46 | case "$REPLY" in 47 | y* | Y* ) ;; 48 | * ) exit 1 ;; 49 | esac 50 | fi 51 | 52 | if [ -d "$PREFIX" ]; then 53 | rm -rf "$PREFIX" 54 | exenv rehash 55 | fi 56 | -------------------------------------------------------------------------------- /bin/exenv-install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | [ -n "$EXENV_DEBUG" ] && set -x 4 | 5 | # Provide exenv completions 6 | if [ "$1" = "--complete" ]; then 7 | exec elixir-build --definitions 8 | fi 9 | 10 | if [ -z "$EXENV_ROOT" ]; then 11 | EXENV_ROOT="${HOME}/.exenv" 12 | fi 13 | 14 | # Load shared library functions 15 | eval "$(elixir-build --lib)" 16 | 17 | usage() { 18 | { echo "usage: exenv install [-k|--keep] [-v|--verbose] VERSION" 19 | echo " exenv install [-k|--keep] [-v|--verbose] /path/to/definition" 20 | echo " exenv install -l|--list" 21 | echo " exenv install -a|-add VERSION" 22 | echo 23 | echo " -l/--list List all available versions" 24 | echo " -k/--keep Keep source tree in \$EXENV_BUILD_ROOT after installation" 25 | echo " (defaults to ${EXENV_ROOT}/sources)" 26 | echo " -v/--verbose Verbose mode: print compilation status to stdout" 27 | echo " -a/--add Adds version with given sha into list of available versions" 28 | echo 29 | } >&2 30 | 31 | [ -z "$1" ] || exit "$1" 32 | } 33 | 34 | unset KEEP 35 | unset VERBOSE 36 | 37 | parse_options "$@" 38 | for option in "${OPTIONS[@]}"; do 39 | case "$option" in 40 | "h" | "help" ) 41 | usage 0 42 | ;; 43 | "l" | "list" ) 44 | echo "Available versions:" 45 | elixir-build --definitions | sed 's/^/ /' 46 | exit 47 | ;; 48 | "a" | "add" ) 49 | version="${ARGUMENTS[0]}" 50 | [ -z $version ] && usage 0 51 | elixir-build --add-definition "${version}" 52 | exit 53 | ;; 54 | "k" | "keep" ) 55 | [ -n "${EXENV_BUILD_ROOT}" ] || EXENV_BUILD_ROOT="${EXENV_ROOT}/sources" 56 | ;; 57 | "v" | "verbose" ) 58 | VERBOSE="-v" 59 | ;; 60 | "version" ) 61 | exec elixir-build --version 62 | ;; 63 | * ) 64 | usage 1 65 | ;; 66 | esac 67 | done 68 | 69 | DEFINITION="${ARGUMENTS[0]}" 70 | [ -n "$DEFINITION" ] || usage 1 71 | 72 | for script in $(exenv-hooks install); do 73 | source "$script" 74 | done 75 | 76 | VERSION_NAME="${DEFINITION##*/}" 77 | PREFIX="${EXENV_ROOT}/versions/${VERSION_NAME}" 78 | 79 | # If EXENV_BUILD_ROOT is set, then always pass keep options to elixir-build 80 | if [ -n "${EXENV_BUILD_ROOT}" ]; then 81 | export ELIXIR_BUILD_BUILD_PATH="${EXENV_BUILD_ROOT}/${VERSION_NAME}" 82 | KEEP="-k" 83 | fi 84 | 85 | elixir-build $KEEP $VERBOSE "$DEFINITION" "$PREFIX" 86 | exenv rehash 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This repository is archived** 2 | 3 | --- 4 | 5 | # elixir-build 6 | 7 | elixir-build is an [exenv](https://github.com/mururu/exenv) plugin 8 | that provides an `exenv install` command to compile and install 9 | different versions of Elixir on UNIX-like systems. 10 | 11 | You can also use elixir-build without exenv in environments where you 12 | need precise control over Elixir version installation. 13 | 14 | elixir-build is the Elixir version of ruby-build. Thanks to @sstephenson! 15 | 16 | ### Prerequisite 17 | 18 | Erlang, version R16B or later. 19 | 20 | ## Installation 21 | 22 | ### Installing as an exenv plugin (recommended) 23 | 24 | Installing elixir-build as an exenv plugin will give you access to the 25 | `exenv install` command. 26 | 27 | git clone git://github.com/mururu/elixir-build.git ~/.exenv/plugins/elixir-build 28 | 29 | This will install the latest development version of elixir-build into 30 | the `~/.exenv/plugins/elixir-build` directory. From that directory, you 31 | can check out a specific release tag. To update elixir-build, run `git 32 | pull` to download the latest changes. 33 | 34 | ### Installing as a standalone program (advanced) 35 | 36 | Installing elixir-build as a standalone program will give you access to 37 | the `elixir-build` command for precise control over Elixir version 38 | installation. If you have exenv installed, you will also be able to 39 | use the `exenv install` command. 40 | 41 | git clone git://github.com/mururu/elixir-build.git 42 | cd elixir-build 43 | ./install.sh 44 | 45 | This will install elixir-build into `/usr/local`. If you do not have 46 | write permission to `/usr/local`, you will need to run `sudo 47 | ./install.sh` instead. You can install to a different prefix by 48 | setting the `PREFIX` environment variable. 49 | 50 | To update elixir-build after it has been installed, run `git pull` in 51 | your cloned copy of the repository, then re-run the install script. 52 | 53 | ## Usage 54 | 55 | ### Using `exenv install` with exenv 56 | 57 | To install a Elixir version for use with exenv, run `exenv install` with 58 | the exact name of the version you want to install. For example, 59 | 60 | exenv install 0.7.0 61 | 62 | Elixir versions will be installed into a directory of the same name 63 | under `~/.exenv/versions`. 64 | 65 | To see a list of all available Elixir versions, run `exenv install --list`. 66 | You may also tab-complete available Elixir 67 | versions if your exenv installation is properly configured. 68 | 69 | ### Using `elixir-build` standalone 70 | 71 | If you have installed elixir-build as a standalone program, you can use 72 | the `elixir-build` command to compile and install Elixir versions into 73 | specific locations. 74 | 75 | Run the `elixir-build` command with the exact name of the version you 76 | want to install and the full path where you want to install it. For 77 | example, 78 | 79 | elixir-build 0.6.0 ~/local/0.6.0 80 | 81 | To see a list of all available Elixir versions, run `elixir-build 82 | --definitions`. 83 | 84 | Pass the `-v` or `--verbose` flag to `elixir-build` as the first 85 | argument to see what's happening under the hood. 86 | 87 | ### Keeping the build directory after installation 88 | 89 | Both `elixir-build` and `exenv install` accept the `-k` or `--keep` 90 | flag, which tells elixir-build to keep the downloaded source after 91 | installation. 92 | 93 | Source code will be kept in a parallel directory tree 94 | `~/.exenv/sources` when using `--keep` with the `exenv install` 95 | command. 96 | 97 | ### Installing Elixir of specified revision (Advanced) 98 | 99 | You can install Elixir of specified revision by specifying the sha1. 100 | For example, 101 | 102 | ``` 103 | exenv install --add v0.9.3-9-g7d22146 104 | exenv install v0.9.3-9-g7d22146 105 | ``` 106 | 107 | ## Version History 108 | 109 | #### 20130921 110 | 111 | * Add --add option (@khia) 112 | 113 | #### 20130609 114 | 115 | * Add install_git_sha1 116 | 117 | #### 20121120 118 | 119 | * fork [ruby-build](https://github.com/sstephenson/ruby-build) 120 | 121 | ### License 122 | 123 | (The MIT License) 124 | 125 | Copyright (c) 2011 Sam Stephenson, Yuki Ito 126 | 127 | Permission is hereby granted, free of charge, to any person obtaining 128 | a copy of this software and associated documentation files (the 129 | "Software"), to deal in the Software without restriction, including 130 | without limitation the rights to use, copy, modify, merge, publish, 131 | distribute, sublicense, and/or sell copies of the Software, and to 132 | permit persons to whom the Software is furnished to do so, subject to 133 | the following conditions: 134 | 135 | The above copyright notice and this permission notice shall be 136 | included in all copies or substantial portions of the Software. 137 | 138 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 139 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 140 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 141 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 142 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 143 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 144 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 145 | -------------------------------------------------------------------------------- /bin/json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # The MIT License 4 | 5 | # Copyright (c) 2011 Dominic Tarr 6 | 7 | # Permission is hereby granted, free of charge, 8 | # to any person obtaining a copy of this software and 9 | # associated documentation files (the "Software"), to 10 | # deal in the Software without restriction, including 11 | # without limitation the rights to use, copy, modify, 12 | # merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom 14 | # the Software is furnished to do so, 15 | # subject to the following conditions: 16 | 17 | # The above copyright notice and this permission notice 18 | # shall be included in all copies or substantial portions of the Software. 19 | 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 24 | # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | throw () { 29 | echo "$*" >&2 30 | exit 1 31 | } 32 | 33 | BRIEF=0 34 | LEAFONLY=0 35 | PRUNE=0 36 | 37 | usage() { 38 | echo 39 | echo "Usage: JSON.sh [-b] [-l] [-p] [-h]" 40 | echo 41 | echo "-p - Prune empty. Exclude fields with empty values." 42 | echo "-l - Leaf only. Only show leaf nodes, which stops data duplication." 43 | echo "-b - Brief. Combines 'Leaf only' and 'Prune empty' options." 44 | echo "-h - This help text." 45 | echo 46 | } 47 | 48 | parse_options() { 49 | set -- "$@" 50 | local ARGN=$# 51 | while [ $ARGN -ne 0 ] 52 | do 53 | case $1 in 54 | -h) usage 55 | exit 0 56 | ;; 57 | -b) BRIEF=1 58 | LEAFONLY=1 59 | PRUNE=1 60 | ;; 61 | -l) LEAFONLY=1 62 | ;; 63 | -p) PRUNE=1 64 | ;; 65 | ?*) echo "ERROR: Unknown option." 66 | usage 67 | exit 0 68 | ;; 69 | esac 70 | shift 1 71 | ARGN=$((ARGN-1)) 72 | done 73 | } 74 | 75 | awk_egrep () { 76 | local pattern_string=$1 77 | 78 | gawk '{ 79 | while ($0) { 80 | start=match($0, pattern); 81 | token=substr($0, start, RLENGTH); 82 | print token; 83 | $0=substr($0, start+RLENGTH); 84 | } 85 | }' pattern=$pattern_string 86 | } 87 | 88 | tokenize () { 89 | local GREP 90 | local ESCAPE 91 | local CHAR 92 | 93 | if echo "test string" | egrep -ao --color=never "test" &>/dev/null 94 | then 95 | GREP='egrep -ao --color=never' 96 | else 97 | GREP='egrep -ao' 98 | fi 99 | 100 | if echo "test string" | egrep -o "test" &>/dev/null 101 | then 102 | ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' 103 | CHAR='[^[:cntrl:]"\\]' 104 | else 105 | GREP=awk_egrep 106 | ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' 107 | CHAR='[^[:cntrl:]"\\\\]' 108 | fi 109 | 110 | local STRING="\"$CHAR*($ESCAPE$CHAR*)*\"" 111 | local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' 112 | local KEYWORD='null|false|true' 113 | local SPACE='[[:space:]]+' 114 | 115 | $GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$" 116 | } 117 | 118 | parse_array () { 119 | local index=0 120 | local ary='' 121 | read -r token 122 | case "$token" in 123 | ']') ;; 124 | *) 125 | while : 126 | do 127 | parse_value "$1" "$index" 128 | index=$((index+1)) 129 | ary="$ary""$value" 130 | read -r token 131 | case "$token" in 132 | ']') break ;; 133 | ',') ary="$ary," ;; 134 | *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;; 135 | esac 136 | read -r token 137 | done 138 | ;; 139 | esac 140 | [ "$BRIEF" -eq 0 ] && value=`printf '[%s]' "$ary"` || value= 141 | : 142 | } 143 | 144 | parse_object () { 145 | local key 146 | local obj='' 147 | read -r token 148 | case "$token" in 149 | '}') ;; 150 | *) 151 | while : 152 | do 153 | case "$token" in 154 | '"'*'"') key=$token ;; 155 | *) throw "EXPECTED string GOT ${token:-EOF}" ;; 156 | esac 157 | read -r token 158 | case "$token" in 159 | ':') ;; 160 | *) throw "EXPECTED : GOT ${token:-EOF}" ;; 161 | esac 162 | read -r token 163 | parse_value "$1" "$key" 164 | obj="$obj$key:$value" 165 | read -r token 166 | case "$token" in 167 | '}') break ;; 168 | ',') obj="$obj," ;; 169 | *) throw "EXPECTED , or } GOT ${token:-EOF}" ;; 170 | esac 171 | read -r token 172 | done 173 | ;; 174 | esac 175 | [ "$BRIEF" -eq 0 ] && value=`printf '{%s}' "$obj"` || value= 176 | : 177 | } 178 | 179 | parse_value () { 180 | local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0 181 | case "$token" in 182 | '{') parse_object "$jpath" ;; 183 | '[') parse_array "$jpath" ;; 184 | # At this point, the only valid single-character tokens are digits. 185 | ''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;; 186 | *) value=$token 187 | isleaf=1 188 | [ "$value" = '""' ] && isempty=1 189 | ;; 190 | esac 191 | [ "$value" = '' ] && return 192 | [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 0 ] && print=1 193 | [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && [ $PRUNE -eq 0 ] && print=1 194 | [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 1 ] && [ "$isempty" -eq 0 ] && print=1 195 | [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && \ 196 | [ $PRUNE -eq 1 ] && [ $isempty -eq 0 ] && print=1 197 | [ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value" 198 | : 199 | } 200 | 201 | parse () { 202 | read -r token 203 | parse_value 204 | read -r token 205 | case "$token" in 206 | '') ;; 207 | *) throw "EXPECTED EOF GOT $token" ;; 208 | esac 209 | } 210 | 211 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 212 | then 213 | parse_options "$@" 214 | tokenize | parse 215 | fi 216 | -------------------------------------------------------------------------------- /bin/elixir-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ELIXIR_BUILD_VERSION="20141001" 4 | 5 | set -E 6 | exec 3<&2 # preserve original stderr at fd 3 7 | 8 | 9 | lib() { 10 | parse_options() { 11 | OPTIONS=() 12 | ARGUMENTS=() 13 | local arg option index 14 | 15 | for arg in "$@"; do 16 | if [ "${arg:0:1}" = "-" ]; then 17 | if [ "${arg:1:1}" = "-" ]; then 18 | OPTIONS[${#OPTIONS[*]}]="${arg:2}" 19 | else 20 | index=1 21 | while option="${arg:$index:1}"; do 22 | [ -n "$option" ] || break 23 | OPTIONS[${#OPTIONS[*]}]="$option" 24 | index=$(($index+1)) 25 | done 26 | fi 27 | else 28 | ARGUMENTS[${#ARGUMENTS[*]}]="$arg" 29 | fi 30 | done 31 | } 32 | 33 | if [ "$1" == "--$FUNCNAME" ]; then 34 | declare -f "$FUNCNAME" 35 | echo "$FUNCNAME \"\$1\";" 36 | exit 37 | fi 38 | } 39 | lib "$1" 40 | 41 | 42 | resolve_link() { 43 | $(type -p greadlink readlink | head -1) "$1" 44 | } 45 | 46 | abs_dirname() { 47 | local cwd="$(pwd)" 48 | local path="$1" 49 | 50 | while [ -n "$path" ]; do 51 | cd "${path%/*}" 52 | local name="${path##*/}" 53 | path="$(resolve_link "$name" || true)" 54 | done 55 | 56 | pwd 57 | cd "$cwd" 58 | } 59 | 60 | build_failed() { 61 | { echo 62 | echo "BUILD FAILED" 63 | echo 64 | 65 | if ! rmdir "${BUILD_PATH}" 2>/dev/null; then 66 | echo "Inspect or clean up the working tree at ${BUILD_PATH}" 67 | 68 | if file_is_not_empty "$LOG_PATH"; then 69 | echo "Results logged to ${LOG_PATH}" 70 | echo 71 | echo "Last 10 log lines:" 72 | tail -n 10 "$LOG_PATH" 73 | fi 74 | fi 75 | } >&3 76 | exit 1 77 | } 78 | 79 | file_is_not_empty() { 80 | local filename="$1" 81 | local line_count="$(wc -l "$filename" 2>/dev/null || true)" 82 | 83 | if [ -n "$line_count" ]; then 84 | words=( $line_count ) 85 | [ "${words[0]}" -gt 0 ] 86 | else 87 | return 1 88 | fi 89 | } 90 | 91 | install_package() { 92 | install_package_using "tarball" 1 $* 93 | } 94 | 95 | install_git() { 96 | install_package_using "git" 2 $* 97 | } 98 | 99 | install_git_with_history() { 100 | install_package_using "git_with_history" 2 $* 101 | } 102 | 103 | install_git_sha1() { 104 | install_package_using "git_sha1" 2 $* 105 | } 106 | 107 | install_package_using() { 108 | local package_type="$1" 109 | local package_type_nargs="$2" 110 | local package_name="$3" 111 | shift 3 112 | 113 | pushd "$BUILD_PATH" >&4 114 | "fetch_${package_type}" "$package_name" $* 115 | shift $(($package_type_nargs)) 116 | make_package "$package_name" $* 117 | popd >&4 118 | 119 | echo "Installed ${package_name} to ${PREFIX_PATH}" >&2 120 | } 121 | 122 | make_package() { 123 | local package_name="$1" 124 | shift 125 | 126 | pushd "$package_name" >&4 127 | before_install_package "$package_name" 128 | build_package "$package_name" $* 129 | after_install_package "$package_name" 130 | fix_directory_permissions 131 | popd >&4 132 | } 133 | 134 | fetch_url() { 135 | if type curl &>/dev/null; then 136 | curl -L "$@" 137 | elif type wget &>/dev/null; then 138 | wget -O- "$@" 139 | else 140 | echo "error: please install \`curl\` or \`wget\` and try again" >&2 141 | exit 1 142 | fi 143 | } 144 | 145 | fetch_tarball() { 146 | local package_name="$1" 147 | local package_url="$2" 148 | 149 | echo "Downloading ${package_url}..." >&2 150 | { fetch_url "$package_url" > "${package_name}.tar.gz" 151 | tar xzvf "${package_name}.tar.gz" 152 | # Handle the case where we fetch a tarball from GitHub, and 153 | # it contains an innner package with the SHA1 of the release commit 154 | if test -n "$(find "$BUILD_PATH" -maxdepth 1 -name 'elixir-lang-elixir-*' -print -quit)"; then 155 | ls -la "$BUILD_PATH" 156 | mv elixir-lang-elixir-* "$package_name" 157 | fi 158 | } >&4 2>&1 159 | } 160 | 161 | fetch_git() { 162 | local package_name="$1" 163 | local git_url="$2" 164 | local git_ref="$3" 165 | 166 | echo "Cloning ${git_url}..." >&2 167 | 168 | if type git &>/dev/null; then 169 | git clone --depth 1 --branch "$git_ref" "$git_url" "${package_name}" >&4 2>&1 170 | else 171 | echo "error: please install \`git\` and try again" >&2 172 | exit 1 173 | fi 174 | } 175 | 176 | fetch_git_with_history() { 177 | local package_name="$1" 178 | local git_url="$2" 179 | local git_ref="$3" 180 | 181 | echo "Cloning ${git_url}..." >&2 182 | 183 | if type git &>/dev/null; then 184 | git clone --branch "$git_ref" "$git_url" "${package_name}" >&4 2>&1 185 | else 186 | echo "error: please install \`git\` and try again" >&2 187 | exit 1 188 | fi 189 | } 190 | 191 | fetch_git_sha1() { 192 | local package_name="$1" 193 | local git_url="$2" 194 | local git_ref="$3" 195 | 196 | echo "Cloning ${git_url}..." >&2 197 | 198 | if type git &>/dev/null; then 199 | git clone --branch master "$git_url" "${package_name}" >&4 2>&1 200 | pushd "$package_name" >&4 201 | if git checkout "$git_ref" >&4 2>&1; then 202 | popd >&4 203 | else 204 | echo "error: unknown sha1 $git_ref" 205 | exit 1 206 | fi 207 | else 208 | echo "error: please install \`git\` and try again" >&2 209 | exit 1 210 | fi 211 | } 212 | 213 | build_package() { 214 | local package_name="$1" 215 | shift 216 | 217 | if [ "$#" -eq 0 ]; then 218 | local commands="standard" 219 | else 220 | local commands="$*" 221 | fi 222 | 223 | echo "Installing ${package_name}..." >&2 224 | 225 | for command in $commands; do 226 | "build_package_${command}" 227 | done 228 | } 229 | 230 | build_package_standard() { 231 | local package_name="$1" 232 | 233 | if [ "${MAKEOPTS+defined}" ]; then 234 | MAKE_OPTS="$MAKEOPTS" 235 | elif [ -z "${MAKE_OPTS+defined}" ]; then 236 | MAKE_OPTS="-j 2" 237 | fi 238 | 239 | { make 240 | } >&4 2>&1 241 | 242 | mkdir -p "$PREFIX_PATH" 243 | cp -R . "$PREFIX_PATH" 244 | } 245 | 246 | before_install_package() { 247 | local stub=1 248 | } 249 | 250 | after_install_package() { 251 | local stub=1 252 | } 253 | 254 | fix_directory_permissions() { 255 | # Ensure installed directories are not world-writable to avoid Bundler warnings 256 | find "$PREFIX_PATH" -type d -exec chmod go-w {} \; 257 | } 258 | version() { 259 | echo "elixir-build ${ELIXIR_BUILD_VERSION}" 260 | } 261 | 262 | usage() { 263 | { version 264 | echo "usage: elixir-build [-k|--keep] [-v|--verbose] definition prefix" 265 | echo " elixir-build --definitions" 266 | echo " elixir-build --add-definition VERSION" 267 | } >&2 268 | 269 | if [ -z "$1" ]; then 270 | exit 1 271 | fi 272 | } 273 | 274 | list_custom_definitions() { 275 | { for definition in "${ELIXIR_BUILD_ROOT}/share/elixir-build/"*; do 276 | echo "${definition##*/}" 277 | done 278 | } | sort 279 | } 280 | 281 | list_definitions() { 282 | { 283 | local items=() 284 | for i in $(curl -s https://api.github.com/repos/elixir-lang/elixir/releases | ${ELIXIR_BUILD_ROOT}/bin/json | egrep '\[[0-9]+,"assets",[0-9]+,"browser_download_url"\]' | tr "\t" "\n"); do 285 | items+=($i) 286 | done 287 | 288 | items_len=${#items[@]} 289 | for ((i=1;i<=$items_len;i+=2)); do 290 | local release_url=$(echo ${items[i]} | sed 's/\"//g') 291 | echo "$(parse_release_version "$release_url")" 292 | done 293 | } | sort -r 294 | } 295 | 296 | parse_release_version() { 297 | local release_url="$1" 298 | echo "$(echo "$release_url" | sed 's/https\:\/\/github\.com\/elixir\-lang\/elixir\/releases\/download\/v//' | sed 's/\/Precompiled\.zip$//')" 299 | } 300 | 301 | is_defined() { 302 | local version="$1" 303 | for def in $(list_definitions); do 304 | if [ "$def" == "$version" ]; then 305 | return 0 306 | fi 307 | done 308 | return 1 309 | } 310 | 311 | add_definition() { 312 | local version="$1" 313 | echo "Adding version: ${version}" 314 | echo "install_git_sha1 \"${version}\" \"https://github.com/elixir-lang/elixir.git\" \"${version}\"" > "${ELIXIR_BUILD_ROOT}/share/elixir-build/${version}" 315 | } 316 | 317 | 318 | unset VERBOSE 319 | unset KEEP_BUILD_PATH 320 | ELIXIR_BUILD_ROOT="$(abs_dirname "$0")/.." 321 | 322 | parse_options "$@" 323 | 324 | for option in "${OPTIONS[@]}"; do 325 | case "$option" in 326 | "h" | "help" ) 327 | usage without_exiting 328 | { echo 329 | echo " -k/--keep Do not remove source tree after installation" 330 | echo " -v/--verbose Verbose mode: print compilation status to stdout" 331 | echo " --definitions List all built-in definitions" 332 | echo " --add-definition VERSION Adds version with given sha into list of available versions" 333 | echo 334 | } >&2 335 | exit 0 336 | ;; 337 | "definitions" ) 338 | list_definitions 339 | list_custom_definitions 340 | exit 0 341 | ;; 342 | "add-definition" ) 343 | [ -z "${ARGUMENTS[0]}" ] && usage 344 | add_definition "${ARGUMENTS[0]}" 345 | exit 0 346 | ;; 347 | "k" | "keep" ) 348 | KEEP_BUILD_PATH=true 349 | ;; 350 | "v" | "verbose" ) 351 | VERBOSE=true 352 | ;; 353 | "version" ) 354 | version 355 | exit 0 356 | ;; 357 | esac 358 | done 359 | 360 | IS_REMOTE_DEFINITION=0 361 | DEFINITION_PATH="${ARGUMENTS[0]}" 362 | if [ -z "$DEFINITION_PATH" ]; then 363 | usage 364 | elif [ ! -e "$DEFINITION_PATH" ]; then 365 | BUILTIN_DEFINITION_PATH="${ELIXIR_BUILD_ROOT}/share/elixir-build/${DEFINITION_PATH}" 366 | if [ -e "$BUILTIN_DEFINITION_PATH" ]; then 367 | DEFINITION_PATH="$BUILTIN_DEFINITION_PATH" 368 | else 369 | # Check if there is a release with this definition 370 | is_defined $DEFINITION_PATH 371 | case $? in 372 | 0) 373 | IS_REMOTE_DEFINITION=1 374 | ;; 375 | *) 376 | echo "elixir-build: definition not found: ${DEFINITION_PATH}" >&2 377 | exit 1 378 | ;; 379 | esac 380 | fi 381 | fi 382 | 383 | PREFIX_PATH="${ARGUMENTS[1]}" 384 | if [ -z "$PREFIX_PATH" ]; then 385 | usage 386 | fi 387 | 388 | if [ -z "$TMPDIR" ]; then 389 | TMP="/tmp" 390 | else 391 | TMP="${TMPDIR%/}" 392 | fi 393 | 394 | SEED="$(date "+%Y%m%d%H%M%S").$$" 395 | LOG_PATH="${TMP}/elixir-build.${SEED}.log" 396 | ELIXIR_BIN="${PREFIX_PATH}/bin/elixir" 397 | CWD="$(pwd)" 398 | 399 | if [ -z $ELIXIR_BUILD_BUILD_PATH ]; then 400 | BUILD_PATH="${TMP}/elixir-build.${SEED}" 401 | else 402 | BUILD_PATH=$ELIXIR_BUILD_BUILD_PATH 403 | fi 404 | 405 | exec 4<> "$LOG_PATH" # open the log file at fd 4 406 | if [ -n "$VERBOSE" ]; then 407 | tail -f "$LOG_PATH" & 408 | trap "kill 0" SIGINT SIGTERM EXIT 409 | fi 410 | 411 | unset ELIXIROPT 412 | unset ELIXIRLIB 413 | 414 | trap build_failed ERR 415 | if [ $IS_REMOTE_DEFINITION -eq 1 ]; then 416 | mkdir -p "$BUILD_PATH" 417 | DEFINITION_NAME="${DEFINITION_PATH##*/}" 418 | install_package "elixir-${DEFINITION_NAME}" "https://api.github.com/repos/elixir-lang/elixir/tarball/v${DEFINITION_NAME}" 419 | else 420 | mkdir -p "$BUILD_PATH" 421 | source "$DEFINITION_PATH" 422 | fi 423 | [ -z "${KEEP_BUILD_PATH}" ] && rm -fr "$BUILD_PATH" 424 | trap - ERR 425 | --------------------------------------------------------------------------------