From 12d3b948f5b3bd31faf53801f34dafaa6cfc7a5c Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 15 Apr 2023 17:53:25 +1200 Subject: [PATCH 01/54] Post release --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index 2a877c45..e7a21084 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.1.0" +VERSION="v9.1.1-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index c023a551..b543983d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.1.0", + "version": "9.1.1-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d9fb4cff..1976ffb1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.1.0", + "version": "9.1.1-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 5d0002e9cce05e8fe45eccb483e1145fc4a333d4 Mon Sep 17 00:00:00 2001 From: Mark Dorison Date: Wed, 16 Aug 2023 02:14:44 -0400 Subject: [PATCH 02/54] Update path to Homebrew formula. (#777) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1d10604..e13c109b 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ to install `n` to `bin/n` of the directory specified in the environment variable ### Third Party Installers -On macOS with [Homebrew](https://brew.sh/) you can install the [n formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/n.rb). +On macOS with [Homebrew](https://brew.sh/) you can install the [n formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/n/n.rb). brew install n From 0f4997415fc4f4a3170cc9138dbc6e57a958603e Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 15 Oct 2023 17:28:48 +1300 Subject: [PATCH 03/54] Add --offline (#785) --- bin/n | 59 +++++++++++++++++++++++++++++++++++++++++ test/tests/offline.bats | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 test/tests/offline.bats diff --git a/bin/n b/bin/n index e7a21084..fcd06a28 100755 --- a/bin/n +++ b/bin/n @@ -135,6 +135,7 @@ g_target_node= DOWNLOAD=false # set to opt-out of activate (install), and opt-in to download (run, exec) ARCH= SHOW_VERBOSE_LOG="true" +OFFLINE=false # ANSI escape codes # https://en.wikipedia.org/wiki/ANSI_escape_code @@ -393,6 +394,7 @@ Options: -q, --quiet Disable curl output. Disable log messages processing "auto" and "engine" labels. -d, --download Download if necessary, and don't make active -a, --arch Override system architecture + --offline Resolve target version against cached downloads instead of internet lookup --all ls-remote displays all matches instead of last 20 --insecure Turn off certificate checking for https requests (may be needed from behind a proxy server) --use-xz/--no-use-xz Override automatic detection of xz support and enable/disable use of xz compressed node downloads. @@ -784,6 +786,9 @@ install() { exit fi fi + if [[ "$OFFLINE" == "true" ]]; then + abort "version unavailable offline" + fi log installing "${g_mirror_folder_name}-v$version" @@ -1103,6 +1108,7 @@ function get_package_engine_version() { verbose_log "target" "${version}" else command -v npx &> /dev/null || abort "an active version of npx is required to use complex 'engine' ranges from package.json" + [[ "$OFFLINE" != "true" ]] || abort "offline: an internet connection is required for looking up complex 'engine' ranges from package.json" verbose_log "resolving" "${range}" local version_per_line="$(n lsr --all)" local versions_one_line=$(echo "${version_per_line}" | tr '\n' ' ') @@ -1199,6 +1205,8 @@ function get_latest_resolved_version() { # Just numbers, already resolved, no need to lookup first. simple_version="${simple_version#v}" g_target_node="${simple_version}" + elif [[ "$OFFLINE" == "true" ]]; then + g_target_node=$(display_local_versions "${version}") else # Complicated recognising exact version, KISS and lookup. g_target_node=$(N_MAX_REMOTE_MATCHES=1 display_remote_versions "$version") @@ -1232,6 +1240,56 @@ function display_match_limit(){ fi } +# +# Synopsis: display_local_versions version +# + +function display_local_versions() { + local version="$1" + local match='.' + verbose_log "offline" "matching cached versions" + + # Transform some labels before processing further. + if is_node_support_version "${version}"; then + version="$(display_latest_node_support_alias "${version}")" + match_count=1 + elif [[ "${version}" = "auto" ]]; then + # suppress stdout logging so lsr layout same as usual for scripting + get_auto_version || return 2 + version="${g_target_node}" + elif [[ "${version}" = "engine" ]]; then + # suppress stdout logging so lsr layout same as usual for scripting + get_engine_version || return 2 + version="${g_target_node}" + fi + + if [[ "${version}" = "latest" || "${version}" = "current" ]]; then + match='^node/.' + elif is_exact_numeric_version "${version}"; then + # Quote any dots in version so they are literal for expression + match="^node/${version//\./\.}" + elif is_numeric_version "${version}"; then + version="${version#v}" + # Quote any dots in version so they are literal for expression + match="${version//\./\.}" + # Avoid 1.2 matching 1.23 + match="^node/${match}[^0-9]" + # elif is_lts_codename "${version}"; then + # see if demand + elif is_download_folder "${version}"; then + match="^${version}/" + # elif is_download_version "${version}"; then + # see if demand + else + abort "invalid version '$1' for offline matching" + fi + + display_versions_paths \ + | n_grep -E "${match}" \ + | tail -n 1 \ + | sed 's|node/||' +} + # # Synopsis: display_remote_versions version # @@ -1577,6 +1635,7 @@ while [[ $# -ne 0 ]]; do -h|--help|help) display_help; exit ;; -q|--quiet) set_quiet ;; -d|--download) DOWNLOAD="true" ;; + --offline) OFFLINE="true" ;; --insecure) set_insecure ;; -p|--preserve) N_PRESERVE_NPM="true" N_PRESERVE_COREPACK="true" ;; --no-preserve) N_PRESERVE_NPM="" N_PRESERVE_COREPACK="" ;; diff --git a/test/tests/offline.bats b/test/tests/offline.bats new file mode 100644 index 00000000..64aa844e --- /dev/null +++ b/test/tests/offline.bats @@ -0,0 +1,52 @@ +#!/usr/bin/env bats + +load shared-functions +load '../../node_modules/bats-support/load' +load '../../node_modules/bats-assert/load' + +function setup_file() { + unset_n_env + setup_tmp_prefix + # Note, NOT latest version of 16. + n --download 16.19.0 + export N_NODE_MIRROR="https://no.internet.available" +} + +function teardown_file() { + rm -rf "${TMP_PREFIX_DIR}" +} + +function setup() { + hash -r +} + +@test "n --offline 16" { + n --offline 16 + hash -r + output="$(node --version)" + assert_equal "${output}" "v16.19.0" + rm "${TMP_PREFIX_DIR}/bin/node" +} + +@test "n --offline latest" { + n --offline latest + hash -r + output="$(node --version)" + assert_equal "${output}" "v16.19.0" + rm "${TMP_PREFIX_DIR}/bin/node" +} + +@test "n --offline run 16..." { + output="$(n --offline run 16 --version)" + assert_equal "${output}" "v16.19.0" +} + +@test "n --offline exec 16..." { + output="$(n --offline exec 16 node --version)" + assert_equal "${output}" "v16.19.0" +} + +@test "n --offline which 16..." { + output="$(n --offline which 16)" + assert_equal "${output}" "${TMP_PREFIX_DIR}/n/versions/node/16.19.0/bin/node" +} From 3fd9dcae1110fa08e27276754f3e9c3198eb6f3c Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 15 Oct 2023 17:33:28 +1300 Subject: [PATCH 04/54] Prepare for release --- CHANGELOG.md | 8 ++++++++ bin/n | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4af90e3..2ab91fa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (date goes here) +## [9.2.0] (2023-10-15) + +### Added + +- `--offline` for resolving target version against cached downloads instead of internet lookup ([#785]) + ## [9.1.0] (2023-04-15) ### Added @@ -479,10 +485,12 @@ Only minor functional changes, but technically could break scripts relying on sp [#745]: https://github.com/tj/n/pull/745 [#746]: https://github.com/tj/n/pull/746 [#764]: https://github.com/tj/n/pull/764 +[#785]: https://github.com/tj/n/pull/785 [Unreleased]: https://github.com/tj/n/compare/master...develop +[9.2.0]: https://github.com/tj/n/compare/v9.1.0...v9.2.0 [9.1.0]: https://github.com/tj/n/compare/v9.0.1...v9.1.0 [9.0.1]: https://github.com/tj/n/compare/v9.0.0...v9.0.1 [9.0.0]: https://github.com/tj/n/compare/v8.2.0...v9.0.0 diff --git a/bin/n b/bin/n index fcd06a28..eb276a2f 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.1.1-0" +VERSION="v9.2.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From d5240ace6caf4410b24b8db51c5516934972688f Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 15 Oct 2023 17:34:34 +1300 Subject: [PATCH 05/54] 9.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b543983d..18a1dc48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.1.1-0", + "version": "9.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1976ffb1..fcfd41a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.1.1-0", + "version": "9.2.0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 9561800fd3e9b9e709d67134145a3cd4d038e39f Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 15 Oct 2023 17:35:22 +1300 Subject: [PATCH 06/54] Post-release --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index eb276a2f..548916bf 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.0" +VERSION="v9.2.1-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index 18a1dc48..7350fb4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.0", + "version": "9.2.1-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fcfd41a0..7152668c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.0", + "version": "9.2.1-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From ea87a51027c5d2b1d3d618e89d1fd49d5df67e80 Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 27 Nov 2023 20:52:40 +1300 Subject: [PATCH 07/54] Add --offline to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e13c109b..51df25a7 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,10 @@ List downloaded versions in cache: n ls +Use `n` to access cached versions (already downloaded) without internet available. + + n --offline 12 + Display diagnostics to help resolve problems: n doctor From 127506d021d1aea44b6ec3a704ea449654fb8e45 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 20 Jan 2024 09:56:52 +1300 Subject: [PATCH 08/54] Expand permissions issues coverage (#790) --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 51df25a7..cc113f8d 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,15 @@ If you already have Node.js installed, an easy way to install `n` is using `npm` npm install -g n -The `n` command downloads and installs to `/usr/local` by default, but you may override this location by defining `N_PREFIX`. +The default root location used when running `n` is `/usr/local` where a normal user does not have write permission. You may strike the same sort of permission error when using npm to install global modules, like the above command. You have three main options: + +1) change the ownership of the relevant directories to yourself (see below) +2) tell `n` to use a custom location where you do have write permissions (see `N_PREFIX`) +3) put `sudo` in front of the command to run it as super user + `n` caches Node.js versions in subdirectory `n/versions`. The _active_ Node.js version is installed in subdirectories `bin`, `include`, `lib`, and `share`. -To avoid requiring `sudo` for `n` and `npm` global installs, it is suggested you either install to your home directory using `N_PREFIX`, or take ownership of the system directories: +To take ownership of the system directories (option 1): # make cache folder (if missing) and take ownership sudo mkdir -p /usr/local/n From 8bb34aaa4425f85135c866242862cabe55862692 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 20 Jan 2024 09:57:39 +1300 Subject: [PATCH 09/54] Condense make instructions (#792) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc113f8d..b9310a74 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Alternatively, you can clone this repo and make install -to install `n` to `bin/n` of the directory specified in the environment variable `$PREFIX`, which defaults to `/usr/local` (note that you will likely need to use `sudo`). To install `n` in a custom location (such as `$CUSTOM_LOCATION/bin/n`), run `PREFIX=$CUSTOM_LOCATION make install`. +which defaults to `/usr/local/bin/n`. To install `n` in a custom location such as `$CUSTOM_LOCATION/bin/n`, run `PREFIX=$CUSTOM_LOCATION make install`. ### Third Party Installers From ebfd77d6352b54b7462f199d1272e1bac30cf4dd Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 20 Jan 2024 10:04:49 +1300 Subject: [PATCH 10/54] Restore release version for a documentation-only update --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index 548916bf..41e3d62f 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.1-0" +VERSION="v9.2.1" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index 7350fb4c..e2bf1bff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.1-0", + "version": "9.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7152668c..019307a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.1-0", + "version": "9.2.1", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 0af211c189be5820ea972a116aeb9e8eb9d6280b Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 20 Jan 2024 10:06:06 +1300 Subject: [PATCH 11/54] Restore release version for a documentation-only update --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index 41e3d62f..eb276a2f 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.1" +VERSION="v9.2.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index e2bf1bff..18a1dc48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.1", + "version": "9.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 019307a9..fcfd41a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.1", + "version": "9.2.0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From a06293e2e9833cbcf493061de25c7e3af52831c4 Mon Sep 17 00:00:00 2001 From: John Gee Date: Wed, 7 Feb 2024 13:54:45 +1300 Subject: [PATCH 12/54] Add sudo tip to proxy docs --- docs/proxy-server.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/proxy-server.md b/docs/proxy-server.md index e02dafac..40702adf 100644 --- a/docs/proxy-server.md +++ b/docs/proxy-server.md @@ -14,6 +14,10 @@ If your proxy requires authentication you can add the [url-encoded](https://urle If you have defined a custom node mirror which uses http, then you would define `http_proxy` rather than `https_proxy`. +If you use `sudo` to run `n`, you need to do something extra to make the environment variables available. A simple way is to use `-E` (`--preserve-env`): + + sudo -E n lts + ## Certificate Checks Your proxy server may supply its own ssl certificates for remote sites (as a man-in-the-middle). If you can not arrange to trust the proxy in this role, you can turn off (all) certificate checking with `--insecure`. e.g. From 8fc8778384d721c8f50d3dcbe5cc64e6fc8e8e02 Mon Sep 17 00:00:00 2001 From: John Gee Date: Tue, 13 Feb 2024 19:54:55 +1300 Subject: [PATCH 13/54] Add security and funding (#794) --- .github/FUNDING.yml | 2 ++ SECURITY.md | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 SECURITY.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..da36760e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [tj, shadowspawn] +tidelift: npm/n diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..1ff8adba --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +The latest two major versions get security updates. + +Pull Requests for security issues will be considered for older versions. + +## Reporting a Vulnerability + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. From eb8f127c3409ee5d30468f634a079cb2e482d897 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 25 Feb 2024 16:24:58 +1300 Subject: [PATCH 14/54] Rework doctor checks to support custom cache prefix (#796) --- bin/n | 71 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/bin/n b/bin/n index eb276a2f..1a5510f2 100755 --- a/bin/n +++ b/bin/n @@ -1425,7 +1425,11 @@ uninstall_installed() { function show_permission_suggestions() { echo "Suggestions:" echo "- run n with sudo, or" - echo "- define N_PREFIX to a writeable location, or" + if [[ "${N_CACHE_PREFIX}" == "${N_PREFIX}" ]]; then + echo "- define N_PREFIX to a writeable location, or" + else + echo "- define N_PREFIX and N_CACHE_PREFIX to writeable locations, or" + fi } # @@ -1556,34 +1560,42 @@ function show_diagnostics() { fi fi - printf "\nChecking permissions for cache folder...\n" - # Most likely problem is ownership rather than than permissions as such. - local cache_root="${N_PREFIX}/n" - if [[ -e "${N_PREFIX}" && ! -w "${N_PREFIX}" && ! -e "${cache_root}" ]]; then - echo_red "You do not have write permission to create: ${cache_root}" - show_permission_suggestions - echo "- make a folder you own:" - echo " sudo mkdir -p \"${cache_root}\"" - echo " sudo chown $(whoami) \"${cache_root}\"" - elif [[ -e "${cache_root}" && ! -w "${cache_root}" ]]; then - echo_red "You do not have write permission to: ${cache_root}" - show_permission_suggestions - echo "- change folder ownership to yourself:" - echo " sudo chown -R $(whoami) \"${cache_root}\"" - elif [[ ! -e "${cache_root}" ]]; then - echo "Cache folder does not exist: ${cache_root}" - echo "This is normal if you have not done an install yet, as cache is only created when needed." - elif [[ -e "${CACHE_DIR}" && ! -w "${CACHE_DIR}" ]]; then - echo_red "You do not have write permission to: ${CACHE_DIR}" - show_permission_suggestions - echo "- change folder ownership to yourself:" - echo " sudo chown -R $(whoami) \"${CACHE_DIR}\"" - else + printf "\nChecking prefix folders...\n" + if [[ ! -e "${N_PREFIX}" ]]; then + echo "Folder does not exist: ${N_PREFIX}" + echo "- This folder will be created when you do an install." + fi + if [[ "${N_PREFIX}" != "${N_CACHE_PREFIX}" && ! -e "${N_CACHE_PREFIX}" ]]; then + echo "Folder does not exist: ${N_CACHE_PREFIX}" + echo "- This folder will be created when you do an install." + fi + if [[ -e "${N_PREFIX}" && -e "${N_CACHE_PREFIX}" ]]; then echo "good" fi + if [[ -e "${N_CACHE_PREFIX}" ]]; then + printf "\nChecking permissions for cache folder...\n" + # Using knowledge cache path ends in /n/versions in following check. + if [[ ! -e "${CACHE_DIR}" && (( -e "${N_CACHE_PREFIX}/n" && ! -w "${N_CACHE_PREFIX}/n" ) || ( ! -e "${N_CACHE_PREFIX}/n" && ! -w "${N_CACHE_PREFIX}" )) ]]; then + echo_red "You do not have write permission to create: ${CACHE_DIR}" + show_permission_suggestions + echo "- make a folder you own:" + echo " sudo mkdir -p \"${CACHE_DIR}\"" + echo " sudo chown $(whoami) \"${CACHE_DIR}\"" + elif [[ ! -e "${CACHE_DIR}" ]]; then + echo "Cache folder does not exist: ${CACHE_DIR}" + echo "- This is normal if you have not done an install yet, as cache is only created when needed." + elif [[ ! -w "${CACHE_DIR}" ]]; then + echo_red "You do not have write permission to: ${CACHE_DIR}" + show_permission_suggestions + echo "- change folder ownership to yourself:" + echo " sudo chown -R $(whoami) \"${CACHE_DIR}\"" + else + echo "good" + fi + fi + if [[ -e "${N_PREFIX}" ]]; then - # Most likely problem is ownership rather than than permissions as such. printf "\nChecking permissions for install folders...\n" local install_writeable="true" for subdir in bin lib include share; do @@ -1592,13 +1604,20 @@ function show_diagnostics() { echo_red "You do not have write permission to: ${N_PREFIX}/${subdir}" break fi + if [[ ! -e "${N_PREFIX}/${subdir}" && ! -w "${N_PREFIX}" ]]; then + install_writeable="false" + echo_red "You do not have write permission to create: ${N_PREFIX}/${subdir}" + break + fi done if [[ "${install_writeable}" = "true" ]]; then echo "good" else show_permission_suggestions echo "- change folder ownerships to yourself:" - echo " (cd \"${N_PREFIX}\" && sudo chown -R $(whoami) bin lib include share)" + echo " cd \"${N_PREFIX}\"" + echo " sudo mkdir -p bin lib include share" + echo " sudo chown -R $(whoami) bin lib include share" fi fi From 1a825416696d28d7734ac38a6c339f01447b09d7 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 25 Feb 2024 16:35:46 +1300 Subject: [PATCH 15/54] Prepare for release --- CHANGELOG.md | 13 +++++++++++-- bin/dev/release | 2 +- bin/n | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ab91fa3..19c6e3e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [Unreleased] (date goes here) +## [9.2.1] (2024-02-25) + +### Fixed + +- `n doctor` works with custom `N_CACHE_PREFIX` + +### Added + +- expand tests in `n doctor` for folder existence and permissions ## [9.2.0] (2023-10-15) @@ -23,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.0.1] (2022-11-04) -### Fixes +### Fixed - `Makefile` compatible with more flavours of `make` ([#745]) - quote paths in `Makefile` in case `PREFIX` contains spaces ([#746]) @@ -490,6 +498,7 @@ Only minor functional changes, but technically could break scripts relying on sp [Unreleased]: https://github.com/tj/n/compare/master...develop +[9.2.1]: https://github.com/tj/n/compare/v9.2.0...v9.2.1 [9.2.0]: https://github.com/tj/n/compare/v9.1.0...v9.2.0 [9.1.0]: https://github.com/tj/n/compare/v9.0.1...v9.1.0 [9.0.1]: https://github.com/tj/n/compare/v9.0.0...v9.0.1 diff --git a/bin/dev/release b/bin/dev/release index b3814669..643ab144 100755 --- a/bin/dev/release +++ b/bin/dev/release @@ -18,7 +18,7 @@ function confirm { } -readonly N_VERSION="$(n --version)" +readonly N_VERSION="$(./bin/n --version)" if [[ "${N_VERSION}" =~ ^[0-9.]+-[0-9]+$ ]]; then echo "Error: internal version number still prerelease, set it to desired version first." exit 2 diff --git a/bin/n b/bin/n index 1a5510f2..7628972c 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.0" +VERSION="v9.2.1" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From 0ce85771fdff8f4b3e09ade700461b4f58a64444 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 25 Feb 2024 16:36:38 +1300 Subject: [PATCH 16/54] 9.2.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 18a1dc48..e2bf1bff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.0", + "version": "9.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fcfd41a0..019307a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.0", + "version": "9.2.1", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From d1ae8080671cd0e20dcfeb5a88e9d4e1ec21e567 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 25 Feb 2024 16:38:12 +1300 Subject: [PATCH 17/54] Post-release --- CHANGELOG.md | 2 ++ bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c6e3e4..aa8b7a20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## [Unreleased] (date goes here) + ## [9.2.1] (2024-02-25) ### Fixed diff --git a/bin/n b/bin/n index 7628972c..a9bfc9fc 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.1" +VERSION="v9.2.2-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index e2bf1bff..2c9e5405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.1", + "version": "9.2.2-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 019307a9..b9793197 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.1", + "version": "9.2.2-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 059b39d5f8aa4c8c0f6fa4796d6b961f927e247d Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:24:25 +1200 Subject: [PATCH 18/54] 9.2.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2c9e5405..28f7c3b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.2-0", + "version": "9.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b9793197..952c0f48 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.2-0", + "version": "9.2.2", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 723bfcded118c73cfb3c67407bb3da6129c95faf Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:28:50 +1200 Subject: [PATCH 19/54] Post-release --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index a9bfc9fc..a402faef 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.2-0" +VERSION="v9.2.3-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index 28f7c3b6..836f4898 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.2", + "version": "9.2.3-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 952c0f48..56212622 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.2", + "version": "9.2.3-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From f9ee486b784761f8e77e6f48f26227bc1c0e6f6a Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:29:18 +1200 Subject: [PATCH 20/54] Remove use of curl --compressed due to a bug in 8.7.1 (#801) --- CHANGELOG.md | 7 ++++++- bin/n | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa8b7a20..355e4601 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [Unreleased] (date goes here) +## [9.2.2] (2024-04-21) + +### Fixed + +- avoid problems with `curl` 8.7.1 and `--compressed` by removing option until fixed ## [9.2.1] (2024-02-25) @@ -500,6 +504,7 @@ Only minor functional changes, but technically could break scripts relying on sp [Unreleased]: https://github.com/tj/n/compare/master...develop +[9.2.2]: https://github.com/tj/n/compare/v9.2.1...v9.2.2 [9.2.1]: https://github.com/tj/n/compare/v9.2.0...v9.2.1 [9.2.0]: https://github.com/tj/n/compare/v9.1.0...v9.2.0 [9.1.0]: https://github.com/tj/n/compare/v9.0.1...v9.1.0 diff --git a/bin/n b/bin/n index a9bfc9fc..3e5e2167 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.2-0" +VERSION="v9.2.2" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} @@ -853,7 +853,7 @@ function do_get() { function do_get_index() { if command -v curl &> /dev/null; then # --silent to suppress progress et al - curl --silent --compressed "${CURL_OPTIONS[@]}" "$@" + curl --silent "${CURL_OPTIONS[@]}" "$@" elif command -v wget &> /dev/null; then wget "${WGET_OPTIONS[@]}" "$@" else From 010f060b7bf3d386441fdcb4e6a01167134d57d4 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:33:23 +1200 Subject: [PATCH 21/54] Prepare for release --- CHANGELOG.md | 7 ++++++- bin/n | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 355e4601..f9f84669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [9.2.2] (2024-04-21) +## [9.2.3] (2024-04-21) ### Fixed - avoid problems with `curl` 8.7.1 and `--compressed` by removing option until fixed +## [9.2.2] (2024-04-21) + +(No changes.) + ## [9.2.1] (2024-02-25) ### Fixed @@ -504,6 +508,7 @@ Only minor functional changes, but technically could break scripts relying on sp [Unreleased]: https://github.com/tj/n/compare/master...develop +[9.2.3]: https://github.com/tj/n/compare/v9.2.2...v9.2.3 [9.2.2]: https://github.com/tj/n/compare/v9.2.1...v9.2.2 [9.2.1]: https://github.com/tj/n/compare/v9.2.0...v9.2.1 [9.2.0]: https://github.com/tj/n/compare/v9.1.0...v9.2.0 diff --git a/bin/n b/bin/n index f43a5494..86b6a0fa 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.3-0" +VERSION="v9.2.3" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From 371affba8a21ec95ca1cab784ef409c879e6ce83 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:34:04 +1200 Subject: [PATCH 22/54] 9.2.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 836f4898..3bfe6ada 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.3-0", + "version": "9.2.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 56212622..8bd787c2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.3-0", + "version": "9.2.3", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 010c596cc9c9629fc0cd52a3bcd0cc75502e4171 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 21 Apr 2024 12:35:24 +1200 Subject: [PATCH 23/54] Post-release --- CHANGELOG.md | 2 ++ bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f84669..b370c813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## [Unreleased] (date goes here) + ## [9.2.3] (2024-04-21) ### Fixed diff --git a/bin/n b/bin/n index 86b6a0fa..e4aae8d9 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.3" +VERSION="v9.2.4-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index 3bfe6ada..fbaf2abb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.3", + "version": "9.2.4-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8bd787c2..add090c1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.3", + "version": "9.2.4-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 7e56c67a3ae1661b81659f888db8923620ac48bf Mon Sep 17 00:00:00 2001 From: John Gee Date: Thu, 9 May 2024 19:46:14 +1200 Subject: [PATCH 24/54] Docs for switching node directory (#802) --- README.md | 13 ++++ docs/changing-node-location.md | 115 +++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 docs/changing-node-location.md diff --git a/README.md b/README.md index b9310a74..2487d17e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Node.js version management: no subshells, no profile setup, no convoluted API, j - [Supported Platforms](#supported-platforms) - [Installation](#installation) - [Third Party Installers](#third-party-installers) + - [Replacing a previous node install](#replacing-a-previous-node-install) - [Installing Node.js Versions](#installing-nodejs-versions) - [Specifying Node.js Versions](#specifying-nodejs-versions) - [Removing Versions](#removing-versions) @@ -87,6 +88,18 @@ n-install sets both `PREFIX` and `N_PREFIX` to `$HOME/n`, installs `n` to `$HOME As a result, both `n` itself and all Node.js versions it manages are hosted inside a single, optionally configurable directory, which you can later remove with the included `n-uninstall` script. `n-update` updates `n` itself to the latest version. See the [n-install repo](https://github.com/mklement0/n-install) for more details. +### Replacing a previous node install + +Changing from a previous Node.js installed to a different location may involve a few extra steps. See docs for [changing node location]((./docs/changing-node-location.md)) for a walk-through example of switching from using Homebrew to using `n` to manage Node.js. + +You have a problem with multiple versions if after installing node you see the "installed" and "active" locations are different: +```console +% n lts + copying : node/20.12.2 + installed : v20.12.2 to /usr/local/bin/node + active : v21.7.3 at /opt/homebrew/bin/node +``` + ## Installing Node.js Versions Simply execute `n ` to download and install a version of Node.js. If `` has already been downloaded, `n` will install from its cache. diff --git a/docs/changing-node-location.md b/docs/changing-node-location.md new file mode 100644 index 00000000..ef333db1 --- /dev/null +++ b/docs/changing-node-location.md @@ -0,0 +1,115 @@ +# Switching To `n` Managed Node.js + +If you already have Node.js installed to a different root than `n` uses, you can easily end up with multiple copies of node (and npm, and npx, and globally installed packages!). Some common situations are you already had Node.js installed using your Linux package manager, or using another node version manager, or using say Homebrew. The two main ways you might resolve this are: + +- uninstall from the old directory and reinstall to the new directory +- put the `bin` directory that `n` uses early in the `PATH` environment variable, so the `n` installed node is found first + +The simplest setup to understand is the first one. Just have one version of `node` installed. + +Let's walk-through the process of switching over from using Homebrew as an example. Let's start off with Node.js installed, `npm` updated, and an example global npm package. The key point is there are two install prefixes involved: + +- old: `/opt/homebrew` +- new: `/usr/local` + +```console +% brew install node +% npm install --global npm@latest +% npm install --global @shadowspawn/forest-arborist +% brew list node +/opt/homebrew/Cellar/node/21.7.3/bin/node +/opt/homebrew/Cellar/node/21.7.3/bin/npm +/opt/homebrew/Cellar/node/21.7.3/bin/npx +/opt/homebrew/Cellar/node/21.7.3/etc/bash_completion.d/npm +/opt/homebrew/Cellar/node/21.7.3/include/node/ (107 files) +/opt/homebrew/Cellar/node/21.7.3/libexec/bin/ (2 files) +/opt/homebrew/Cellar/node/21.7.3/libexec/lib/ (2012 files) +/opt/homebrew/Cellar/node/21.7.3/share/doc/ (2 files) +/opt/homebrew/Cellar/node/21.7.3/share/man/man1/node.1 +% command -v node +/opt/homebrew/bin/node +% command -v npm +/opt/homebrew/bin/npm +% npm prefix --global +/opt/homebrew +``` + +Before we start transferring, list the global npm packages in the "old" location. We will refer back to this list. + +```console +% npm list --global +/opt/homebrew/lib +├── @shadowspawn/forest-arborist@12.0.0 +└── npm@10.5.0 +``` + +We could clean out the old location first, but let's install `n` and another copy of node and see what that looks like. We end up with two versions of node, and the active one is still the Homebrew managed version. + +```console +% brew install n +% n lts + installing : node-v20.12.2 + mkdir : /usr/local/n/versions/node/20.12.2 + fetch : https://nodejs.org/dist/v20.12.2/node-v20.12.2-darwin-arm64.tar.xz + copying : node/20.12.2 + installed : v20.12.2 to /usr/local/bin/node + active : v21.7.3 at /opt/homebrew/bin/node +% command -v node +/opt/homebrew/bin/node +% which -a node +/opt/homebrew/bin/node +/usr/local/bin/node +% command -v npm +/opt/homebrew/bin/npm +% command -v npx +/opt/homebrew/bin/npx +% n doctor +<...> + +CHECKS + +Checking n install destination is in PATH... +good + +Checking n install destination priority in PATH... +⚠️ There is a version of node installed which will be found in PATH before the n installed version. + +Checking npm install destination... +⚠️ There is an active version of npm shadowing the version installed by n. Check order of entries in PATH. + installed : /usr/local/bin/npm + active : /opt/homebrew/bin/npm + +<...> +``` + +Now let's switch over. Delete everything from the old location. Delete all the global npm packages _except_ npm itself, then delete npm, then delete node. + +```console +npm uninstall --global @shadowspawn/forest-arborist + +npm uninstall --global npm + +brew uninstall node +``` + +Check the active binaries are now the ones installed by `n`: +```console +% command -v node +/usr/local/bin/node +% command -v npm +/usr/local/bin/npm +% command -v npx +/usr/local/bin/npx +``` + +And lastly, reinstall the global npm packages you started with: +``` +% npm prefix --global +/usr/local +% npm install --global npm@latest +% npm install --global @shadowspawn/forest-arborist +% npm list -g +/usr/local/lib +├── @shadowspawn/forest-arborist@12.0.0 +└── npm@10.5.0 +``` From a07ed85c6aaa126f4cbba90f84c774b289de485f Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 11 May 2024 16:18:53 +1200 Subject: [PATCH 25/54] Docs for switching node directory (#802) --- README.md | 13 ++++ docs/changing-node-location.md | 115 +++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 docs/changing-node-location.md diff --git a/README.md b/README.md index b9310a74..2487d17e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Node.js version management: no subshells, no profile setup, no convoluted API, j - [Supported Platforms](#supported-platforms) - [Installation](#installation) - [Third Party Installers](#third-party-installers) + - [Replacing a previous node install](#replacing-a-previous-node-install) - [Installing Node.js Versions](#installing-nodejs-versions) - [Specifying Node.js Versions](#specifying-nodejs-versions) - [Removing Versions](#removing-versions) @@ -87,6 +88,18 @@ n-install sets both `PREFIX` and `N_PREFIX` to `$HOME/n`, installs `n` to `$HOME As a result, both `n` itself and all Node.js versions it manages are hosted inside a single, optionally configurable directory, which you can later remove with the included `n-uninstall` script. `n-update` updates `n` itself to the latest version. See the [n-install repo](https://github.com/mklement0/n-install) for more details. +### Replacing a previous node install + +Changing from a previous Node.js installed to a different location may involve a few extra steps. See docs for [changing node location]((./docs/changing-node-location.md)) for a walk-through example of switching from using Homebrew to using `n` to manage Node.js. + +You have a problem with multiple versions if after installing node you see the "installed" and "active" locations are different: +```console +% n lts + copying : node/20.12.2 + installed : v20.12.2 to /usr/local/bin/node + active : v21.7.3 at /opt/homebrew/bin/node +``` + ## Installing Node.js Versions Simply execute `n ` to download and install a version of Node.js. If `` has already been downloaded, `n` will install from its cache. diff --git a/docs/changing-node-location.md b/docs/changing-node-location.md new file mode 100644 index 00000000..ef333db1 --- /dev/null +++ b/docs/changing-node-location.md @@ -0,0 +1,115 @@ +# Switching To `n` Managed Node.js + +If you already have Node.js installed to a different root than `n` uses, you can easily end up with multiple copies of node (and npm, and npx, and globally installed packages!). Some common situations are you already had Node.js installed using your Linux package manager, or using another node version manager, or using say Homebrew. The two main ways you might resolve this are: + +- uninstall from the old directory and reinstall to the new directory +- put the `bin` directory that `n` uses early in the `PATH` environment variable, so the `n` installed node is found first + +The simplest setup to understand is the first one. Just have one version of `node` installed. + +Let's walk-through the process of switching over from using Homebrew as an example. Let's start off with Node.js installed, `npm` updated, and an example global npm package. The key point is there are two install prefixes involved: + +- old: `/opt/homebrew` +- new: `/usr/local` + +```console +% brew install node +% npm install --global npm@latest +% npm install --global @shadowspawn/forest-arborist +% brew list node +/opt/homebrew/Cellar/node/21.7.3/bin/node +/opt/homebrew/Cellar/node/21.7.3/bin/npm +/opt/homebrew/Cellar/node/21.7.3/bin/npx +/opt/homebrew/Cellar/node/21.7.3/etc/bash_completion.d/npm +/opt/homebrew/Cellar/node/21.7.3/include/node/ (107 files) +/opt/homebrew/Cellar/node/21.7.3/libexec/bin/ (2 files) +/opt/homebrew/Cellar/node/21.7.3/libexec/lib/ (2012 files) +/opt/homebrew/Cellar/node/21.7.3/share/doc/ (2 files) +/opt/homebrew/Cellar/node/21.7.3/share/man/man1/node.1 +% command -v node +/opt/homebrew/bin/node +% command -v npm +/opt/homebrew/bin/npm +% npm prefix --global +/opt/homebrew +``` + +Before we start transferring, list the global npm packages in the "old" location. We will refer back to this list. + +```console +% npm list --global +/opt/homebrew/lib +├── @shadowspawn/forest-arborist@12.0.0 +└── npm@10.5.0 +``` + +We could clean out the old location first, but let's install `n` and another copy of node and see what that looks like. We end up with two versions of node, and the active one is still the Homebrew managed version. + +```console +% brew install n +% n lts + installing : node-v20.12.2 + mkdir : /usr/local/n/versions/node/20.12.2 + fetch : https://nodejs.org/dist/v20.12.2/node-v20.12.2-darwin-arm64.tar.xz + copying : node/20.12.2 + installed : v20.12.2 to /usr/local/bin/node + active : v21.7.3 at /opt/homebrew/bin/node +% command -v node +/opt/homebrew/bin/node +% which -a node +/opt/homebrew/bin/node +/usr/local/bin/node +% command -v npm +/opt/homebrew/bin/npm +% command -v npx +/opt/homebrew/bin/npx +% n doctor +<...> + +CHECKS + +Checking n install destination is in PATH... +good + +Checking n install destination priority in PATH... +⚠️ There is a version of node installed which will be found in PATH before the n installed version. + +Checking npm install destination... +⚠️ There is an active version of npm shadowing the version installed by n. Check order of entries in PATH. + installed : /usr/local/bin/npm + active : /opt/homebrew/bin/npm + +<...> +``` + +Now let's switch over. Delete everything from the old location. Delete all the global npm packages _except_ npm itself, then delete npm, then delete node. + +```console +npm uninstall --global @shadowspawn/forest-arborist + +npm uninstall --global npm + +brew uninstall node +``` + +Check the active binaries are now the ones installed by `n`: +```console +% command -v node +/usr/local/bin/node +% command -v npm +/usr/local/bin/npm +% command -v npx +/usr/local/bin/npx +``` + +And lastly, reinstall the global npm packages you started with: +``` +% npm prefix --global +/usr/local +% npm install --global npm@latest +% npm install --global @shadowspawn/forest-arborist +% npm list -g +/usr/local/lib +├── @shadowspawn/forest-arborist@12.0.0 +└── npm@10.5.0 +``` From 76d6b9870c619d9393ba5c2e3e35fdda171e9773 Mon Sep 17 00:00:00 2001 From: Helber Belmiro Date: Wed, 29 May 2024 17:50:34 -0300 Subject: [PATCH 26/54] Fixed broken link (#803) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2487d17e..c7dbff9d 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ As a result, both `n` itself and all Node.js versions it manages are hosted insi ### Replacing a previous node install -Changing from a previous Node.js installed to a different location may involve a few extra steps. See docs for [changing node location]((./docs/changing-node-location.md)) for a walk-through example of switching from using Homebrew to using `n` to manage Node.js. +Changing from a previous Node.js installed to a different location may involve a few extra steps. See docs for [changing node location](./docs/changing-node-location.md) for a walk-through example of switching from using Homebrew to using `n` to manage Node.js. You have a problem with multiple versions if after installing node you see the "installed" and "active" locations are different: ```console From b496b82ef360b1c3c00866900965c4561f8a63f0 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 16 Aug 2024 00:13:52 -0400 Subject: [PATCH 27/54] If `jq` is installed, use it to get values from package.json (#810) `jq` is a popular choice for being installed, especially on CI machines, and using it to read engines from package.json is faster than running node. --- bin/n | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bin/n b/bin/n index e4aae8d9..94de453e 100755 --- a/bin/n +++ b/bin/n @@ -1084,9 +1084,14 @@ function get_package_engine_version() { g_target_node= local filepath="$1" verbose_log "found" "${filepath}" - command -v node &> /dev/null || abort "an active version of node is required to read 'engines' from package.json" local range - range="$(node -e "package = require('${filepath}'); if (package && package.engines && package.engines.node) console.log(package.engines.node)")" + if command -v jq &> /dev/null; then + range="$(jq -r '.engines.node // ""' < "${filepath}")" + elif command -v node &> /dev/null; then + range="$(node -e "package = require('${filepath}'); if (package && package.engines && package.engines.node) console.log(package.engines.node)")" + else + abort "either jq or an active version of node is required to read 'engines' from package.json" + fi verbose_log "read" "${range}" [[ -n "${range}" ]] || return 2 if [[ "*" == "${range}" ]]; then @@ -1474,6 +1479,13 @@ function show_diagnostics() { echo_red "Neither curl nor wget found. Need one of them for downloads." fi + printf "\njq\n" + if command -v jq &> /dev/null; then + command -v jq && jq --version + else + echo "jq not found, can be used to get package.json values faster than node" + fi + printf "\nuname\n" uname -a From d75cfc6c9f91befc6b4cf48a91254f26a366ddd8 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 16 Aug 2024 16:17:59 +1200 Subject: [PATCH 28/54] Remove redundant checks for commands --- bin/n | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/n b/bin/n index 94de453e..54661018 100755 --- a/bin/n +++ b/bin/n @@ -1456,7 +1456,7 @@ function show_diagnostics() { printf "\nnode\n" if command -v node &> /dev/null; then - command -v node && node --version + node --version node -e 'if (process.versions.v8) console.log("JavaScript engine: v8");' printf "\nnpm\n" @@ -1465,23 +1465,23 @@ function show_diagnostics() { printf "\ntar\n" if command -v tar &> /dev/null; then - command -v tar && tar --version + tar --version else echo_red "tar not found. Needed for extracting downloads." fi printf "\ncurl or wget\n" if command -v curl &> /dev/null; then - command -v curl && curl --version + curl --version elif command -v wget &> /dev/null; then - command -v wget && wget --version + wget --version else echo_red "Neither curl nor wget found. Need one of them for downloads." fi printf "\njq\n" if command -v jq &> /dev/null; then - command -v jq && jq --version + jq --version else echo "jq not found, can be used to get package.json values faster than node" fi From acf6b5c639c03b65ad6a3a5d0e939052aebef0e9 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 16 Aug 2024 16:32:28 +1200 Subject: [PATCH 29/54] Simplify doctor info for jq, in line with other diagnostics --- bin/n | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bin/n b/bin/n index 54661018..c5cc1995 100755 --- a/bin/n +++ b/bin/n @@ -1480,11 +1480,7 @@ function show_diagnostics() { fi printf "\njq\n" - if command -v jq &> /dev/null; then - jq --version - else - echo "jq not found, can be used to get package.json values faster than node" - fi + command -v jq && jq --version printf "\nuname\n" uname -a From 273a485c9e20db875e982f56de8d1c8c910105aa Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 16 Aug 2024 16:37:02 +1200 Subject: [PATCH 30/54] Add use of jq to README and CHANGELOG --- CHANGELOG.md | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b370c813..300160b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (date goes here) +### Changed + +- if `jq` is available, use `jq` for reading `engines` from `package.json` instead of using `node` ([#810]) + ## [9.2.3] (2024-04-21) ### Fixed @@ -506,6 +510,7 @@ Only minor functional changes, but technically could break scripts relying on sp [#746]: https://github.com/tj/n/pull/746 [#764]: https://github.com/tj/n/pull/764 [#785]: https://github.com/tj/n/pull/785 +[#810]: https://github.com/tj/n/pull/810 diff --git a/README.md b/README.md index c7dbff9d..725c5cdc 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ There is an `auto` label to read the target version from a file in the current d - `.nvmrc`: version on single line. Used by `nvm`. - if no version file found, look for `engine` as below. -The `engine` label looks for a `package.json` file and reads the `engines` field to determine compatible Node.js. Requires an installed version of `node`, and uses `npx semver` to resolve complex ranges. +The `engine` label looks for a `package.json` file and reads the `engines` field to determine compatible Node.js. Requires an installed version of `jq` or `node`, and uses `npx semver` to resolve complex ranges. There is support for the named release streams: From 426952cf48614aafa750ba13a232bed9f3d215e4 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 6 Sep 2024 14:07:51 +1200 Subject: [PATCH 31/54] Fast track exact auto (#813) --- bin/n | 14 ++++++++++---- test/bin/run-all-tests | 2 +- test/docker-compose.yml | 1 - test/tests.md | 10 +++++----- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/bin/n b/bin/n index c5cc1995..007f9b63 100755 --- a/bin/n +++ b/bin/n @@ -1205,6 +1205,16 @@ function get_auto_version() { function get_latest_resolved_version() { g_target_node= local version=${1} + + # Transform some labels before processing further to allow fast-track for exact numeric versions. + if [[ "${version}" = "auto" ]]; then + get_auto_version || return 2 + version="${g_target_node}" + elif [[ "${version}" = "engine" ]]; then + get_engine_version || return 2 + version="${g_target_node}" + fi + simple_version=${version#node/} # Only place supporting node/ [sic] if is_exact_numeric_version "${simple_version}"; then # Just numbers, already resolved, no need to lookup first. @@ -1259,11 +1269,9 @@ function display_local_versions() { version="$(display_latest_node_support_alias "${version}")" match_count=1 elif [[ "${version}" = "auto" ]]; then - # suppress stdout logging so lsr layout same as usual for scripting get_auto_version || return 2 version="${g_target_node}" elif [[ "${version}" = "engine" ]]; then - # suppress stdout logging so lsr layout same as usual for scripting get_engine_version || return 2 version="${g_target_node}" fi @@ -1310,11 +1318,9 @@ function display_remote_versions() { version="$(display_latest_node_support_alias "${version}")" match_count=1 elif [[ "${version}" = "auto" ]]; then - # suppress stdout logging so lsr layout same as usual for scripting get_auto_version || return 2 version="${g_target_node}" elif [[ "${version}" = "engine" ]]; then - # suppress stdout logging so lsr layout same as usual for scripting get_engine_version || return 2 version="${g_target_node}" fi diff --git a/test/bin/run-all-tests b/test/bin/run-all-tests index dabaeab7..b41aee8d 100755 --- a/test/bin/run-all-tests +++ b/test/bin/run-all-tests @@ -7,7 +7,7 @@ services=( fedora-curl ubuntu-wget ) cd "$(dirname "${BIN_DIRECTORY}")" || exit 2 for service in "${services[@]}" ; do echo "${service}" - docker-compose run --rm "${service}" "bats" "/mnt/test/tests" + docker compose run --rm "${service}" "bats" "/mnt/test/tests" echo "" done diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 458a9efe..79bf2512 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -1,4 +1,3 @@ -version: '2' services: ubuntu-curl: extends: diff --git a/test/tests.md b/test/tests.md index 8b9f2b85..1d5e3d9d 100644 --- a/test/tests.md +++ b/test/tests.md @@ -20,17 +20,17 @@ Run all the tests on a single system: cd test npx bats tests - docker-compose run ubuntu-curl bats /mnt/test/tests + docker compose run ubuntu-curl bats /mnt/test/tests Run single test on a single system:: cd test npx bats tests/install-contents.bats - docker-compose run ubuntu-curl bats /mnt/test/tests/install-contents.bats + docker compose run ubuntu-curl bats /mnt/test/tests/install-contents.bats ## Docker Tips -Using `docker-compose` in addition to `docker` for convenient mounting of `n` script and the tests into the container. Changes to the tests or to `n` itself are reflected immediately without needing to rebuild the containers. +Using `docker compose` in addition to `docker` for convenient mounting of `n` script and the tests into the container. Changes to the tests or to `n` itself are reflected immediately without needing to rebuild the containers. `bats` is being mounted directly out of `node_modules` into the container as a manual install based on its own install script. This is a bit of a hack, but avoids needing to install `git` or `npm` for a full remote install of `bats`, and means everything on the same version of `bats`. @@ -38,7 +38,7 @@ The containers each have: * either curl or wget (or both) installed -Using `docker-compose` to run the container adds: +Using `docker compose` to run the container adds: * specified `n` script mounted to `/usr/local/bin/n` * `test/tests` mounted to `/mnt/test/tests` @@ -48,7 +48,7 @@ Using `docker-compose` to run the container adds: So for example: cd test - docker-compose run ubuntu-curl + docker compose run ubuntu-curl # in container n --version bats /mnt/test/tests From 69bc40686e5e97ddb86e1b3fa160a577a2e02876 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 6 Sep 2024 14:28:25 +1200 Subject: [PATCH 32/54] Prepare for release --- CHANGELOG.md | 7 ++++++- bin/n | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 300160b5..06447c6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 -## [Unreleased] (date goes here) +## [10.0.0] (2024-09-06) + +The major version bump is due to using `jq` in preference to `node` for reading `package.json`. ### Changed - if `jq` is available, use `jq` for reading `engines` from `package.json` instead of using `node` ([#810]) +- avoid a network lookup if auto or engine find a fully specified numeric version. ([#813]) ## [9.2.3] (2024-04-21) @@ -511,10 +514,12 @@ Only minor functional changes, but technically could break scripts relying on sp [#764]: https://github.com/tj/n/pull/764 [#785]: https://github.com/tj/n/pull/785 [#810]: https://github.com/tj/n/pull/810 +[#813]: https://github.com/tj/n/pull/813 [Unreleased]: https://github.com/tj/n/compare/master...develop +[10.0.0]: https://github.com/tj/n/compare/v9.2.3...v10.0.0 [9.2.3]: https://github.com/tj/n/compare/v9.2.2...v9.2.3 [9.2.2]: https://github.com/tj/n/compare/v9.2.1...v9.2.2 [9.2.1]: https://github.com/tj/n/compare/v9.2.0...v9.2.1 diff --git a/bin/n b/bin/n index 007f9b63..60ad0508 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v9.2.4-0" +VERSION="v10.0.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From ca23bc2b2d16e509264b1f223a14d2f32416fdd1 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 6 Sep 2024 14:29:49 +1200 Subject: [PATCH 33/54] 10.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index fbaf2abb..ff07ebc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "9.2.4-0", + "version": "10.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index add090c1..0f739e53 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "9.2.4-0", + "version": "10.0.0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 6051073a6aba8e2885a9613aed39ab5cfe781425 Mon Sep 17 00:00:00 2001 From: John Gee Date: Fri, 6 Sep 2024 14:31:49 +1200 Subject: [PATCH 34/54] Post-release --- CHANGELOG.md | 2 ++ bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06447c6a..096d68e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## [Unreleased] (date goes here) + ## [10.0.0] (2024-09-06) The major version bump is due to using `jq` in preference to `node` for reading `package.json`. diff --git a/bin/n b/bin/n index 60ad0508..67157f2e 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v10.0.0" +VERSION="v10.0.1-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index ff07ebc2..bb15caa0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "10.0.0", + "version": "10.0.1-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0f739e53..d0f8cb0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "10.0.0", + "version": "10.0.1-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From cf40ac5e0a23d3a188e87dec1aa0c137b58b6422 Mon Sep 17 00:00:00 2001 From: jinxiao Date: Fri, 4 Oct 2024 06:07:21 +0800 Subject: [PATCH 35/54] mask download url when there is a password (#815) --- bin/n | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bin/n b/bin/n index 67157f2e..44daebf8 100755 --- a/bin/n +++ b/bin/n @@ -197,6 +197,10 @@ display_major_version() { echo "${version}" } +display_masked_url() { + echo "$1" | sed -r 's/(https?:\/\/[^:]+):([^@]+)@/\1:****@/' +} + # # Synopsis: update_mirror_settings_for_version version # e.g. means using download mirror and folder is nightly @@ -793,7 +797,7 @@ install() { log installing "${g_mirror_folder_name}-v$version" local url="$(tarball_url "$version")" - is_ok "${url}" || abort "download preflight failed for '$version' (${url})" + is_ok "${url}" || abort "download preflight failed for '$version' ($(display_masked_url "${url}"))" log mkdir "$dir" mkdir -p "$dir" || abort "sudo required (or change ownership, or define N_PREFIX)" @@ -801,7 +805,7 @@ install() { cd "${dir}" || abort "Failed to cd to ${dir}" - log fetch "$url" + log fetch "$(display_masked_url "${url}")" do_get "${url}" | tar "$tarflag" --strip-components=1 --no-same-owner -f - pipe_results=( "${PIPESTATUS[@]}" ) if [[ "${pipe_results[0]}" -ne 0 ]]; then @@ -1241,7 +1245,7 @@ display_remote_index() { do_get_index "${index_url}" | tail -n +2 | cut -f 1,3,10 if [[ "${PIPESTATUS[0]}" -ne 0 ]]; then # Reminder: abort will only exit subshell, but consistent error display - abort "failed to download version index (${index_url})" + abort "failed to download version index ($(display_masked_url "${index_url}"))" fi } @@ -1494,8 +1498,8 @@ function show_diagnostics() { printf "\n\nSETTINGS\n" printf "\nn\n" - echo "node mirror: ${N_NODE_MIRROR}" - echo "node downloads mirror: ${N_NODE_DOWNLOAD_MIRROR}" + echo "node mirror: $(display_masked_url "${N_NODE_MIRROR}")" + echo "node downloads mirror: $(display_masked_url "${N_NODE_DOWNLOAD_MIRROR}")" echo "install destination: ${N_PREFIX}" [[ -n "${N_PREFIX}" ]] && echo "PATH: ${PATH}" echo "ls-remote max matches: ${N_MAX_REMOTE_MATCHES}" From 65bd2fe237f81c5b59f28b797190dfc41086c3ab Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 20 Oct 2024 11:05:12 +1300 Subject: [PATCH 36/54] Add --cleanup (#818) --- README.md | 14 +++++++++++++- bin/n | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 725c5cdc..60670d6a 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ To take ownership of the system directories (option 1): If `npm` is not yet available, one way to bootstrap an install is to download and run `n` directly. To install the `lts` version of Node.js: - curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s lts + curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s install lts # If you want n installed, you can use npm now. npm install -g n @@ -237,6 +237,18 @@ Use `n` to access cached versions (already downloaded) without internet availabl n --offline 12 +Remove the cache version after installing using `--cleanup`. This is particularly useful for a one-shot install, like in a docker container. + + curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s install --cleanup lts + +The `--download` option can be used in two ways, to download a version into cache but not make active: + + n --download lts + +or to download a possibly missing version for `n run`, `n exec`, and `n which`: + + n --download run 18.3 my-script.js + Display diagnostics to help resolve problems: n doctor diff --git a/bin/n b/bin/n index 44daebf8..203fe196 100755 --- a/bin/n +++ b/bin/n @@ -133,6 +133,7 @@ g_active_node= g_target_node= DOWNLOAD=false # set to opt-out of activate (install), and opt-in to download (run, exec) +CLEANUP=false # remove cached download after install ARCH= SHOW_VERBOSE_LOG="true" OFFLINE=false @@ -397,6 +398,7 @@ Options: -p, --preserve Preserve npm and npx during install of Node.js -q, --quiet Disable curl output. Disable log messages processing "auto" and "engine" labels. -d, --download Download if necessary, and don't make active + --cleanup Remove cached version after install -a, --arch Override system architecture --offline Resolve target version against cached downloads instead of internet lookup --all ls-remote displays all matches instead of last 20 @@ -757,6 +759,12 @@ activate() { printf 'If "node --version" shows the old version then start a new shell, or reset the location hash with:\nhash -r (for bash, zsh, ash, dash, and ksh)\nrehash (for csh and tcsh)\n' fi fi + + if [[ "$CLEANUP" == "true" ]]; then + log "cleanup" "removing cached $version" + remove_versions "$version" + fi + } # @@ -1672,6 +1680,7 @@ while [[ $# -ne 0 ]]; do -h|--help|help) display_help; exit ;; -q|--quiet) set_quiet ;; -d|--download) DOWNLOAD="true" ;; + --cleanup) CLEANUP="true" ;; --offline) OFFLINE="true" ;; --insecure) set_insecure ;; -p|--preserve) N_PRESERVE_NPM="true" N_PRESERVE_COREPACK="true" ;; From e5c51e8d6722ee93d5635766ed03e990adcd8f05 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 20 Oct 2024 11:05:41 +1300 Subject: [PATCH 37/54] Remove stale while loop (#817) --- bin/n | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/bin/n b/bin/n index 203fe196..56f2bcbe 100755 --- a/bin/n +++ b/bin/n @@ -1717,24 +1717,21 @@ if test $# -eq 0; then test -z "$(display_versions_paths)" && err_no_installed_print_help menu_select_cache_versions else - while test $# -ne 0; do - case "$1" in - bin|which) display_bin_path_for_version "$2"; exit ;; - run|as|use) shift; run_with_version "$@"; exit ;; - exec) shift; exec_with_version "$@"; exit ;; - doctor) show_diagnostics; exit ;; - rm|-) shift; remove_versions "$@"; exit ;; - prune) prune_cache; exit ;; - latest) install latest; exit ;; - stable) install stable; exit ;; - lts) install lts; exit ;; - ls|list) display_versions_paths; exit ;; - lsr|ls-remote|list-remote) shift; display_remote_versions "$1"; exit ;; - uninstall) uninstall_installed; exit ;; - i|install) shift; install "$1"; exit ;; - N_TEST_DISPLAY_LATEST_RESOLVED_VERSION) shift; get_latest_resolved_version "$1" > /dev/null || exit 2; echo "${g_target_node}"; exit ;; - *) install "$1"; exit ;; - esac - shift - done + case "$1" in + bin|which) display_bin_path_for_version "$2"; exit ;; + run|as|use) shift; run_with_version "$@"; exit ;; + exec) shift; exec_with_version "$@"; exit ;; + doctor) show_diagnostics; exit ;; + rm|-) shift; remove_versions "$@"; exit ;; + prune) prune_cache; exit ;; + latest) install latest; exit ;; + stable) install stable; exit ;; + lts) install lts; exit ;; + ls|list) display_versions_paths; exit ;; + lsr|ls-remote|list-remote) shift; display_remote_versions "$1"; exit ;; + uninstall) uninstall_installed; exit ;; + i|install) shift; install "$1"; exit ;; + N_TEST_DISPLAY_LATEST_RESOLVED_VERSION) shift; get_latest_resolved_version "$1" > /dev/null || exit 2; echo "${g_target_node}"; exit ;; + *) install "$1"; exit ;; + esac fi From 859efc6a14a5f2446107af808a68f7cfeba1ac67 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sun, 20 Oct 2024 11:11:52 +1300 Subject: [PATCH 38/54] Prepare for release --- CHANGELOG.md | 14 ++++++++++++++ bin/n | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 096d68e1..87d1f8ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (date goes here) +## [10.1.0] (2024-10-20) + +### Added + +- `--cleanup` removes cached version after install ([#818]) +- mention of `--download` in README + +### Changed + +- removed stale code ([#817]) + ## [10.0.0] (2024-09-06) The major version bump is due to using `jq` in preference to `node` for reading `package.json`. @@ -517,10 +528,13 @@ Only minor functional changes, but technically could break scripts relying on sp [#785]: https://github.com/tj/n/pull/785 [#810]: https://github.com/tj/n/pull/810 [#813]: https://github.com/tj/n/pull/813 +[#817]: https://github.com/tj/n/pull/817 +[#818]: https://github.com/tj/n/pull/818 [Unreleased]: https://github.com/tj/n/compare/master...develop +[10.1.0]: https://github.com/tj/n/compare/v10.0.0...v10.1.0 [10.0.0]: https://github.com/tj/n/compare/v9.2.3...v10.0.0 [9.2.3]: https://github.com/tj/n/compare/v9.2.2...v9.2.3 [9.2.2]: https://github.com/tj/n/compare/v9.2.1...v9.2.2 diff --git a/bin/n b/bin/n index 44daebf8..d5e9643b 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v10.0.1-0" +VERSION="v10.1.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From 9d9e58a1df289fda18a4aa20d43e5fffe2ca57e1 Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 28 Oct 2024 10:05:44 +1300 Subject: [PATCH 39/54] Documentation updates --- CHANGELOG.md | 2 +- README.md | 11 ++++------- bin/n | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87d1f8ea..1b2729e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `--cleanup` removes cached version after install ([#818]) -- mention of `--download` in README +- document using `--download` with run/exec/which in README ### Changed diff --git a/README.md b/README.md index 60670d6a..0ed94869 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ As a result, both `n` itself and all Node.js versions it manages are hosted insi Changing from a previous Node.js installed to a different location may involve a few extra steps. See docs for [changing node location](./docs/changing-node-location.md) for a walk-through example of switching from using Homebrew to using `n` to manage Node.js. You have a problem with multiple versions if after installing node you see the "installed" and "active" locations are different: + ```console % n lts copying : node/20.12.2 @@ -241,11 +242,7 @@ Remove the cache version after installing using `--cleanup`. This is particularl curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s install --cleanup lts -The `--download` option can be used in two ways, to download a version into cache but not make active: - - n --download lts - -or to download a possibly missing version for `n run`, `n exec`, and `n which`: +Normally `n run`, `n exec`, and `n which` will fail if the target version is not already in the cache. You can add `--download` to use the cache if available or download first if required: n --download run 18.3 my-script.js @@ -290,8 +287,8 @@ To change the location to say `$HOME/.n`, add lines like the following to your s export N_PREFIX=$HOME/.n export PATH=$N_PREFIX/bin:$PATH -If you want to store the downloads under a different location, use `N_CACHE_PREFIX`. This does *not* affect the currently active -node version. +If you want to store the downloads under a different location, use `N_CACHE_PREFIX`. This does _not_ affect where the active +node version is installed. `n` defaults to using xz compressed Node.js tarballs for the download if it is likely tar on the system supports xz decompression. You can override the automatic choice by setting an environment variable to zero or non-zero: diff --git a/bin/n b/bin/n index 3b59076c..fb686f42 100755 --- a/bin/n +++ b/bin/n @@ -397,7 +397,7 @@ Options: -h, --help Display help information -p, --preserve Preserve npm and npx during install of Node.js -q, --quiet Disable curl output. Disable log messages processing "auto" and "engine" labels. - -d, --download Download if necessary, and don't make active + -d, --download Download if necessary. Used with run/exec/which. --cleanup Remove cached version after install -a, --arch Override system architecture --offline Resolve target version against cached downloads instead of internet lookup From 7128e837f3e1eb6e1051eae7921ee4d2edda72f9 Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 28 Oct 2024 14:12:13 +1300 Subject: [PATCH 40/54] Add more codenames, out to 2026 --- bin/n | 2 +- test/tests/install-options.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/n b/bin/n index fb686f42..675b88c6 100755 --- a/bin/n +++ b/bin/n @@ -262,7 +262,7 @@ function update_arch_settings_for_version() { function is_lts_codename() { # https://github.com/nodejs/Release/blob/master/CODENAMES.md # e.g. argon, Boron - [[ "$1" =~ ^([Aa]rgon|[Bb]oron|[Cc]arbon|[Dd]ubnium|[Ee]rbium|[Ff]ermium|[Gg]allium|[Hh]ydrogen|[Ii]ron|[Jj]od)$ ]] + [[ "$1" =~ ^([Aa]rgon|[Bb]oron|[Cc]arbon|[Dd]ubnium|[Ee]rbium|[Ff]ermium|[Gg]allium|[Hh]ydrogen|[Ii]ron|[Jj]od|[Kk]rypton|[Ll]ithium)$ ]] } # diff --git a/test/tests/install-options.bats b/test/tests/install-options.bats index 2dcdc95f..f30da48b 100644 --- a/test/tests/install-options.bats +++ b/test/tests/install-options.bats @@ -19,7 +19,7 @@ function teardown() { @test "n --download 4.9.1" { n --download 4.9.1 [ -d "${N_PREFIX}/n/versions/node/4.9.1" ] - # Remember, we installed a dumy node so do have a bin/node + # Remember, we installed a dummy node so do have a bin/node [ ! -f "${N_PREFIX}/bin/npm" ] [ ! -d "${N_PREFIX}/include" ] [ ! -d "${N_PREFIX}/lib" ] From 1a1b61967b0c5f010c77722456568a195f48794b Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 28 Oct 2024 14:54:27 +1300 Subject: [PATCH 41/54] Minor reword --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ed94869..fb879d3e 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ Remove the cache version after installing using `--cleanup`. This is particularl curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s install --cleanup lts -Normally `n run`, `n exec`, and `n which` will fail if the target version is not already in the cache. You can add `--download` to use the cache if available or download first if required: +Normally `n run`, `n exec`, and `n which` will fail if the target version is not already in the cache. You can add `--download` to use the cache if available or download if required: n --download run 18.3 my-script.js From eea2a555331a1c5c488f5af392b01a87a9641e65 Mon Sep 17 00:00:00 2001 From: John Gee Date: Mon, 28 Oct 2024 14:58:34 +1300 Subject: [PATCH 42/54] Add support for trailing comment in .nvmrc (#820) --- bin/n | 2 ++ test/tests/version-resolve-auto-nvmrc.bats | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/bin/n b/bin/n index 675b88c6..cd31052b 100755 --- a/bin/n +++ b/bin/n @@ -1147,6 +1147,8 @@ function get_nvmrc_version() { verbose_log "found" "${filepath}" local version <"${filepath}" read -r version + # remove trailing comment, after # + version="$(echo "${version}" | sed 's/[[:space:]]*#.*//')" verbose_log "read" "${version}" # Translate from nvm aliases case "${version}" in diff --git a/test/tests/version-resolve-auto-nvmrc.bats b/test/tests/version-resolve-auto-nvmrc.bats index a99c7fa4..fbe72b7c 100644 --- a/test/tests/version-resolve-auto-nvmrc.bats +++ b/test/tests/version-resolve-auto-nvmrc.bats @@ -68,3 +68,11 @@ function setup() { output="$(n N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto)" assert_equal "${output}" "8.11.1" } + +@test "auto .nvmrc, trailing comment" { + local TARGET_VERSION="8.10.0" + cd "${MY_DIR}" + printf "${TARGET_VERSION} # comment" > .nvmrc + output="$(n N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto)" + assert_equal "${output}" "${TARGET_VERSION}" +} From cbde6e2b0142a0ba577c2ee51aeb5325f1c6d4d7 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 11:42:51 +1300 Subject: [PATCH 43/54] Add download command (#821) --- README.md | 4 ++++ bin/n | 10 +++++++++- test/tests/install-options.bats | 23 ++++++++++++++++++++++- test/tests/offline.bats | 2 +- test/tests/run-which.bats | 4 ++-- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb879d3e..858cb6a5 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,10 @@ List downloaded versions in cache: n ls +Download version into cache: + + n download 22 + Use `n` to access cached versions (already downloaded) without internet available. n --offline 12 diff --git a/bin/n b/bin/n index cd31052b..ac2c961d 100755 --- a/bin/n +++ b/bin/n @@ -390,6 +390,7 @@ Commands: n ls Output downloaded versions n ls-remote [version] Output matching versions available for download n uninstall Remove the installed Node.js + n download Download Node.js into cache Options: @@ -794,6 +795,8 @@ install() { if [[ ! -e "$dir/n.lock" ]] ; then if [[ "$DOWNLOAD" == "false" ]] ; then activate "${g_mirror_folder_name}/${version}" + else + log downloaded "${g_mirror_folder_name}/${version} already in cache" fi exit fi @@ -802,7 +805,11 @@ install() { abort "version unavailable offline" fi - log installing "${g_mirror_folder_name}-v$version" + if [[ "$DOWNLOAD" == "false" ]]; then + log installing "${g_mirror_folder_name}-v$version" + else + log download "${g_mirror_folder_name}-v$version" + fi local url="$(tarball_url "$version")" is_ok "${url}" || abort "download preflight failed for '$version' ($(display_masked_url "${url}"))" @@ -1733,6 +1740,7 @@ else lsr|ls-remote|list-remote) shift; display_remote_versions "$1"; exit ;; uninstall) uninstall_installed; exit ;; i|install) shift; install "$1"; exit ;; + download) shift; DOWNLOAD="true"; install "$1"; exit ;; N_TEST_DISPLAY_LATEST_RESOLVED_VERSION) shift; get_latest_resolved_version "$1" > /dev/null || exit 2; echo "${g_target_node}"; exit ;; *) install "$1"; exit ;; esac diff --git a/test/tests/install-options.bats b/test/tests/install-options.bats index f30da48b..74e5c37c 100644 --- a/test/tests/install-options.bats +++ b/test/tests/install-options.bats @@ -17,9 +17,22 @@ function teardown() { @test "n --download 4.9.1" { + # deprecated use of --download, replaced by download command n --download 4.9.1 [ -d "${N_PREFIX}/n/versions/node/4.9.1" ] - # Remember, we installed a dummy node so do have a bin/node + [ ! -f "${N_PREFIX}/bin/node" ] + [ ! -f "${N_PREFIX}/bin/npm" ] + [ ! -d "${N_PREFIX}/include" ] + [ ! -d "${N_PREFIX}/lib" ] + [ ! -d "${N_PREFIX}/shared" ] +} + + +@test "n download 4.9.1" { + # not an option, but keep with --download so stays in sync + n download 4.9.1 + [ -d "${N_PREFIX}/n/versions/node/4.9.1" ] + [ ! -f "${N_PREFIX}/bin/node" ] [ ! -f "${N_PREFIX}/bin/npm" ] [ ! -d "${N_PREFIX}/include" ] [ ! -d "${N_PREFIX}/lib" ] @@ -35,6 +48,14 @@ function teardown() { } +@test "n --cleanup 4.9.1" { + n install --cleanup 4.9.1 + output="$(node --version)" + assert_equal "${output}" "v4.9.1" + [ ! -d "${N_PREFIX}/n/versions/node/4.9.1" ] +} + + # mostly --preserve, but also variations with i/install and lts/numeric @test "--preserve variations # (4 installs)" { local ARGON_VERSION="v4.9.1" diff --git a/test/tests/offline.bats b/test/tests/offline.bats index 64aa844e..06c62e44 100644 --- a/test/tests/offline.bats +++ b/test/tests/offline.bats @@ -8,7 +8,7 @@ function setup_file() { unset_n_env setup_tmp_prefix # Note, NOT latest version of 16. - n --download 16.19.0 + n download 16.19.0 export N_NODE_MIRROR="https://no.internet.available" } diff --git a/test/tests/run-which.bats b/test/tests/run-which.bats index 99bb6fe7..be8d6d7d 100644 --- a/test/tests/run-which.bats +++ b/test/tests/run-which.bats @@ -9,8 +9,8 @@ function setup_file() { # fixed directory so can reuse the two installs tmpdir="${TMPDIR:-/tmp}" export N_PREFIX="${tmpdir}/n/test/run-which" - n --download 4.9.1 - n --download lts + n download 4.9.1 + n download lts # using "latest" for download tests with run and exec } From fe3c3da5affc3c988ace292583bc5dfbd1226516 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 11:43:28 +1300 Subject: [PATCH 44/54] Add manual install instructions and remove probably rarely used make instruction (#822) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 858cb6a5..9d09198c 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,11 @@ If `npm` is not yet available, one way to bootstrap an install is to download an # If you want n installed, you can use npm now. npm install -g n -Alternatively, you can clone this repo and +If you don't need support for updates to `n` itself you can just save the download: - make install - -which defaults to `/usr/local/bin/n`. To install `n` in a custom location such as `$CUSTOM_LOCATION/bin/n`, run `PREFIX=$CUSTOM_LOCATION make install`. + curl -fsSL -o /usr/local/bin/n https://raw.githubusercontent.com/tj/n/master/bin/n + chmod 0755 /usr/local/bin/n + n install lts ### Third Party Installers From 058fd9a52ea9c9cde2413bc16686dd9fd50aa17d Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 11:57:34 +1300 Subject: [PATCH 45/54] Add unofficial builds as example mirror (#823) --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d09198c..5dd92b4a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Node.js version management: no subshells, no profile setup, no convoluted API, j - [Using Downloaded Node.js Versions Without Reinstalling](#using-downloaded-nodejs-versions-without-reinstalling) - [Preserving npm](#preserving-npm) - [Miscellaneous](#miscellaneous) - - [Custom Source](#custom-source) + - [Custom Mirror](#custom-mirror) - [Custom Architecture](#custom-architecture) - [Optional Environment Variables](#optional-environment-variables) - [How It Works](#how-it-works) @@ -254,13 +254,24 @@ Display diagnostics to help resolve problems: n doctor -## Custom Source +## Custom Mirror If you would like to use a different Node.js mirror which has the same layout as the default , you can define `N_NODE_MIRROR`. -The most common example is from users in China who can define: + +One example is for users in China who can define: export N_NODE_MIRROR=https://npmmirror.com/mirrors/node +Another example is the Node.js [unofficial-builds project](https://github.com/nodejs/unofficial-builds/) which has downloads for some platforms not made available officially, such as armv6l (Raspberry Pi) and 32-bit x86. + + export N_NODE_MIRROR=https://unofficial-builds.nodejs.org/download/release + +You may need to specify the architecture explicitly if not autodetected by `n`, such as using `musl` `libc` on Alpine: + + export N_NODE_MIRROR=https://unofficial-builds.nodejs.org/download/release + apk add bash curl libstdc++ + n --arch x64-musl install lts + If the custom mirror requires authentication you can add the [url-encoded](https://urlencode.org) username and password into the URL. e.g. export N_NODE_MIRROR=https://encoded-username:encoded-password@host:port/path From c66dc02048d72923cd1e919504a2ce8f4e84c006 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 12:08:54 +1300 Subject: [PATCH 46/54] Update CHANGELOG for 10.1.0 --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b2729e8..511b4248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (date goes here) -## [10.1.0] (2024-10-20) +## [10.1.0] (2024-11-09) ### Added -- `--cleanup` removes cached version after install ([#818]) +- `--cleanup` option to delete cached version after install for a one-shot install ([#818]) +- `download` command to download Node.js version into cache ([#821]) - document using `--download` with run/exec/which in README +- support trailing comments in `.nvmrc` file ([#820]) +- mask password in download URL when displayed ([#815]) ### Changed @@ -528,8 +531,11 @@ Only minor functional changes, but technically could break scripts relying on sp [#785]: https://github.com/tj/n/pull/785 [#810]: https://github.com/tj/n/pull/810 [#813]: https://github.com/tj/n/pull/813 +[#815]: https://github.com/tj/n/pull/815 [#817]: https://github.com/tj/n/pull/817 [#818]: https://github.com/tj/n/pull/818 +[#820]: https://github.com/tj/n/pull/820 +[#821]: https://github.com/tj/n/pull/821 From 76213105b7879cf8dad72cf15b01f9146a88560f Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 12:15:23 +1300 Subject: [PATCH 47/54] 10.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb15caa0..ef1d9d8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "10.0.1-0", + "version": "10.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d0f8cb0b..bf3744fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "10.0.1-0", + "version": "10.1.0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From 76d0a47f286737aff892364f11ae59e3c58c4605 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 9 Nov 2024 12:16:25 +1300 Subject: [PATCH 48/54] Bump version post-release --- bin/n | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/n b/bin/n index ac2c961d..6148e4af 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="v10.1.0" +VERSION="10.1.1-0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index ef1d9d8f..0b5cbd52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "10.1.0", + "version": "10.1.1-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index bf3744fc..f6f32b67 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "10.1.0", + "version": "10.1.1-0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues", From c817c143db833341bd05b50d7b01219d22493718 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Tue, 11 Feb 2025 00:47:58 -0500 Subject: [PATCH 49/54] Add `$N_ARCH` as a default architecture (#832) --- README.md | 6 ++++-- bin/n | 36 +++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 5dd92b4a..b16fa162 100644 --- a/README.md +++ b/README.md @@ -266,11 +266,13 @@ Another example is the Node.js [unofficial-builds project](https://github.com/no export N_NODE_MIRROR=https://unofficial-builds.nodejs.org/download/release -You may need to specify the architecture explicitly if not autodetected by `n`, such as using `musl` `libc` on Alpine: +You may need to specify the architecture explicitly if not autodetected by `n`, such as using `musl` `libc` on Alpine. You can do that with `N_ARCH` or `--arch`: export N_NODE_MIRROR=https://unofficial-builds.nodejs.org/download/release + export N_ARCH=x64-musl apk add bash curl libstdc++ - n --arch x64-musl install lts + n install lts + n --arch x64-musl install lts # using a flag If the custom mirror requires authentication you can add the [url-encoded](https://urlencode.org) username and password into the URL. e.g. diff --git a/bin/n b/bin/n index 6148e4af..2147c401 100755 --- a/bin/n +++ b/bin/n @@ -134,7 +134,7 @@ g_target_node= DOWNLOAD=false # set to opt-out of activate (install), and opt-in to download (run, exec) CLEANUP=false # remove cached download after install -ARCH= +ARCH="${N_ARCH-}" SHOW_VERBOSE_LOG="true" OFFLINE=false @@ -1030,20 +1030,25 @@ function display_tarball_platform() { MINGW*) >&2 echo_red "Git BASH (MSYS) is not supported by n" ;; esac - local arch="unexpected_arch" - local uname_m="$(uname -m)" - case "${uname_m}" in - x86_64) arch=x64 ;; - i386 | i686) arch="x86" ;; - aarch64) arch=arm64 ;; - armv8l) arch=arm64 ;; # armv8l probably supports arm64, and there is no specific armv8l build so give it a go - *) - # e.g. armv6l, armv7l, arm64 - arch="${uname_m}" - ;; - esac - # Override from command line, or version specific adjustment. - [ -n "$ARCH" ] && arch="$ARCH" + # architecture might already be known from (priority order): + # * --arch flag on the command line, + # * otherwise, from $N_ARCH + # * otherwise from version specific adjustment (if applicable, see update_arch_settings_for_version) + local arch="$ARCH" + if [[ -z "$arch" ]]; then + arch="unexpected_arch" + local uname_m="$(uname -m)" + case "${uname_m}" in + x86_64) arch=x64 ;; + i386 | i686) arch="x86" ;; + aarch64) arch=arm64 ;; + armv8l) arch=arm64 ;; # armv8l probably supports arm64, and there is no specific armv8l build so give it a go + *) + # e.g. armv6l, armv7l, arm64 + arch="${uname_m}" + ;; + esac + fi echo "${os}-${arch}" } @@ -1519,6 +1524,7 @@ function show_diagnostics() { echo "node downloads mirror: $(display_masked_url "${N_NODE_DOWNLOAD_MIRROR}")" echo "install destination: ${N_PREFIX}" [[ -n "${N_PREFIX}" ]] && echo "PATH: ${PATH}" + [[ -n "$N_ARCH" ]] && echo "default arch: $N_ARCH" echo "ls-remote max matches: ${N_MAX_REMOTE_MATCHES}" [[ -n "${N_PRESERVE_NPM}" ]] && echo "installs preserve npm by default" [[ -n "${N_PRESERVE_COREPACK}" ]] && echo "installs preserve corepack by default" From 61d838af2cc9a7758c8fb843e0507b2bdc263b87 Mon Sep 17 00:00:00 2001 From: John Gee Date: Tue, 11 Feb 2025 19:23:30 +1300 Subject: [PATCH 50/54] Add more N_ARCH documentation to README --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b16fa162..e9744b42 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,6 @@ You may need to specify the architecture explicitly if not autodetected by `n`, export N_ARCH=x64-musl apk add bash curl libstdc++ n install lts - n --arch x64-musl install lts # using a flag If the custom mirror requires authentication you can add the [url-encoded](https://urlencode.org) username and password into the URL. e.g. @@ -289,7 +288,7 @@ On a Mac with Apple silicon: - for Node.js 16 and higher, `n` defaults to arm64 binaries which run natively - for older versions of Node.js, `n` defaults to x64 binaries which run in Rosetta 2 -You can override the default architecture by using the `-a` or `--arch` option. +You can override the default architecture by using the `-a` or `--arch` option, or set `N_ARCH` environment variable. e.g. reinstall latest version of Node.js with x64 binaries: @@ -320,12 +319,13 @@ You can be explicit to get the desired behaviour whatever the environment variab In brief: -- `N_NODE_MIRROR`: See [Custom source](#custom-source) -- `N_NODE_DOWNLOAD_MIRROR`: See [Custom source](#custom-source) +- `N_NODE_MIRROR`: see [Custom Mirror](#custom-mirror) +- `N_NODE_DOWNLOAD_MIRROR`: see [Custom Mirror](#custom-mirror) - support for [NO_COLOR](https://no-color.org) and [CLICOLOR=0](https://bixense.com/clicolors) for controlling use of ANSI color codes - `N_MAX_REMOTE_MATCHES` to change the default `ls-remote` maximum of 20 matching versions -- `N_PRESERVE_NPM`: See [Preserving npm](#preserving-npm) -- `N_PRESERVE_COREPACK`: See [Preserving npm](#preserving-npm) +- `N_PRESERVE_NPM`: see [Preserving npm](#preserving-npm) +- `N_PRESERVE_COREPACK`: see [Preserving npm](#preserving-npm) +- `N_ARCH`: see [Custom Architecture](#custom-architecture) ## How It Works From 8c73780adf9d94703948a50aeb35d53721245313 Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 15 Feb 2025 20:18:52 +1300 Subject: [PATCH 51/54] Better link for Homebrew --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e9744b42..ea20f2f0 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ If you don't need support for updates to `n` itself you can just save the downlo ### Third Party Installers -On macOS with [Homebrew](https://brew.sh/) you can install the [n formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/n/n.rb). +On macOS with [Homebrew](https://brew.sh/) you can install the [n formula](https://formulae.brew.sh/formula/n). brew install n From 429ca00374b31a999a10f49ce5190ab8510d9dd3 Mon Sep 17 00:00:00 2001 From: John Gee Date: Wed, 21 May 2025 15:08:57 +1200 Subject: [PATCH 52/54] Add logo (#836) --- assets/logo.svg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 assets/logo.svg diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 00000000..217ca002 --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,9 @@ + + + + + + + $n + + From 584a61658e75b70ad40dd16e2c92c7f32ec0da0e Mon Sep 17 00:00:00 2001 From: John Gee Date: Wed, 21 May 2025 15:42:28 +1200 Subject: [PATCH 53/54] Prepare for release --- CHANGELOG.md | 8 ++++++++ bin/n | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 511b4248..af7fc167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (date goes here) +## [10.2.0] (2025-05-21) + +### Added + +- environment variable `N_ARCH` to set architecture for download, like using `--arch` ([#832]) + ## [10.1.0] (2024-11-09) ### Added @@ -536,10 +542,12 @@ Only minor functional changes, but technically could break scripts relying on sp [#818]: https://github.com/tj/n/pull/818 [#820]: https://github.com/tj/n/pull/820 [#821]: https://github.com/tj/n/pull/821 +[#832]: https://github.com/tj/n/pull/832 [Unreleased]: https://github.com/tj/n/compare/master...develop +[10.2.0]: https://github.com/tj/n/compare/v10.1.0...v10.2.0 [10.1.0]: https://github.com/tj/n/compare/v10.0.0...v10.1.0 [10.0.0]: https://github.com/tj/n/compare/v9.2.3...v10.0.0 [9.2.3]: https://github.com/tj/n/compare/v9.2.2...v9.2.3 diff --git a/bin/n b/bin/n index 2147c401..6b227595 100755 --- a/bin/n +++ b/bin/n @@ -61,7 +61,7 @@ function n_grep() { # Setup and state # -VERSION="10.1.1-0" +VERSION="10.2.0" N_PREFIX="${N_PREFIX-/usr/local}" N_PREFIX=${N_PREFIX%/} From f52d2172f12cd76f0efe9524690723f52ab74f40 Mon Sep 17 00:00:00 2001 From: John Gee Date: Wed, 21 May 2025 15:43:28 +1200 Subject: [PATCH 54/54] 10.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b5cbd52..d9d9d520 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "n", - "version": "10.1.1-0", + "version": "10.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f6f32b67..ec8dfa05 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "n", "description": "Interactively Manage All Your Node Versions", - "version": "10.1.1-0", + "version": "10.2.0", "author": "TJ Holowaychuk ", "homepage": "https://github.com/tj/n", "bugs": "https://github.com/tj/n/issues",