summaryrefslogtreecommitdiff
path: root/utils/lib_nvm.sh
blob: aaea5cd31080c2e5e7dc31ee1e8edca717455c21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env bash
# -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Tools to install and maintain NVM versions manager for Node.js
#
# [1] https://github.com/nvm-sh/nvm

# https://github.com/koalaman/shellcheck/issues/356#issuecomment-853515285
# shellcheck source=utils/lib.sh
. /dev/null

declare main_cmd

# configure nvm environment
# -------------------------

NVM_LOCAL_FOLDER=.nvm

[[ -z "${NVM_GIT_URL}" ]] &&  NVM_GIT_URL="https://github.com/nvm-sh/nvm.git"
[[ -z "${NVM_MIN_NODE_VER}" ]] && NVM_MIN_NODE_VER="16.13.0"

# initialize nvm environment
# -------------------------

nvm.env() {
    source "${NVM_DIR}/nvm.sh"
    source "${NVM_DIR}/bash_completion"
    [ "$VERBOSE" = "1" ] && info_msg "sourced NVM environment from ${NVM_DIR}"
    return 0
}

nvm.is_installed() {
    # is true if NVM is installed / in $HOME or even in <repo-root>/.nvm
    [[ -f "${NVM_DIR}/nvm.sh" ]]
}

if [[ -z "${NVM_DIR}" ]]; then
    # nvm is not pre-intalled in $HOME.  Prepare for using nvm from <repo-root>
    NVM_DIR="$(git rev-parse --show-toplevel)/${NVM_LOCAL_FOLDER}"
fi
export NVM_DIR

if nvm.is_installed; then
    nvm.env
else
    # if nvm is not installed, use this function as a wrapper
    nvm() {
        nvm.ensure
        nvm "$@"
    }
fi

# implement nvm functions
# -----------------------

nvm.is_local() {
    # is true if NVM is installed in <repo-root>/.nvm
    [ "${NVM_DIR}" = "$(git rev-parse --show-toplevel)/${NVM_LOCAL_FOLDER}" ]
}

nvm.min_node() {

    # usage:  nvm.min_node 16.3.0
    #
    # Is true if minimal Node.js version is installed.

    local min_v
    local node_v
    local higher_v

    if ! command -v node >/dev/null; then
        warn_msg "Node.js is not yet installed"
        return 42
    fi

    min_v="${1}"
    node_v="$(node --version)"
    node_v="${node_v:1}" # remove 'v' from 'v16.3.0'
    if ! [ "${min_v}" = "${node_v}" ]; then
        higher_v="$(echo -e "$min_v\n${node_v}" | sort -Vr | head -1)"
        if [ "${min_v}" = "${higher_v}" ]; then
            return 42
        fi
    fi
}

# implement nvm command line
# --------------------------

nvm.help() {
    cat <<EOF
nvm.: use nvm (without dot) to execute nvm commands directly
  install   : install NVM locally at $(git rev-parse --show-toplevel)/${NVM_LOCAL_FOLDER}
  clean     : remove NVM installation
  status    : prompt some status informations about nvm & node
  nodejs    : install Node.js latest LTS
  cmd ...   : run command ... in NVM environment
  bash      : start bash interpreter with NVM environment sourced
EOF
}

nvm.install() {
    local NVM_VERSION_TAG
    info_msg "install (update) NVM at ${NVM_DIR}"
    if nvm.is_installed; then
        info_msg "already cloned at: ${NVM_DIR}"
        pushd "${NVM_DIR}" &> /dev/null
        git fetch --all | prefix_stdout "  ${_Yellow}||${_creset} "
    else
        # delete any leftovers from previos installations
        if nvm.is_local; then
            rm -rf "${NVM_DIR}"
        fi
        info_msg "clone: ${NVM_GIT_URL}"
        git clone "${NVM_GIT_URL}" "${NVM_DIR}" 2>&1 | prefix_stdout "  ${_Yellow}||${_creset} "
        pushd "${NVM_DIR}" &> /dev/null
        git config --local advice.detachedHead false
    fi
    NVM_VERSION_TAG="$(git rev-list --tags --max-count=1)"
    NVM_VERSION_TAG="$(git describe --abbrev=0 --tags --match "v[0-9]*" "${NVM_VERSION_TAG}")"
    info_msg "checkout ${NVM_VERSION_TAG}"
    git checkout "${NVM_VERSION_TAG}" 2>&1 | prefix_stdout "  ${_Yellow}||${_creset} "
    popd &> /dev/null
    if [ -f "${REPO_ROOT}/.nvm_packages" ]; then
        cp "${REPO_ROOT}/.nvm_packages" "${NVM_DIR}/default-packages"
    fi
    nvm.env
}

nvm.clean() {
    if ! nvm.is_installed; then
        build_msg CLEAN "[NVM] not installed"
        return
    fi
    if ! nvm.is_local; then
        build_msg CLEAN "[NVM] can't remove nvm from ${NVM_DIR}"
        return
    fi
    if [ -n "${NVM_DIR}" ]; then
        build_msg CLEAN "[NVM] drop $(realpath --relative-to=. "${NVM_DIR}")/"
        rm -rf "${NVM_DIR}"
    fi
}

nvm.status() {
    if command -v node >/dev/null; then
        info_msg "Node.js is installed at $(command -v node)"
        info_msg "Node.js is version $(node --version)"
        if ! nvm.min_node "${NVM_MIN_NODE_VER}"; then
            warn_msg "minimal Node.js version is ${NVM_MIN_NODE_VER}"
        fi
    else
        warn_msg "Node.js is mot installed"
    fi
    if command -v npm >/dev/null; then
        info_msg "npm is installed at $(command -v npm)"
        info_msg "npm is version $(npm --version)"
    else
        warn_msg "npm is not installed"
    fi
    if nvm.is_installed; then
        info_msg "NVM is installed at ${NVM_DIR}"
    else
        warn_msg "NVM is not installed"
        info_msg "to install NVM and Node.js (LTS) use: ${main_cmd} nvm.nodejs"
    fi
}

nvm.nodejs() {
    nvm install
    nvm.status
}

nvm.bash() {
    nvm.ensure
    bash --init-file <(cat "${NVM_DIR}/nvm.sh" "${NVM_DIR}/bash_completion")
}

nvm.cmd() {
    nvm.ensure
    "$@"
}

nvm.ensure() {
    if ! nvm.is_installed; then
        nvm.install
    fi
}