Skip to content

Commit

Permalink
Merge pull request #27 from nodenv/xdg-file
Browse files Browse the repository at this point in the history
Respect XDG basedir spec
  • Loading branch information
jasonkarns authored Sep 2, 2019
2 parents d30f98b + 4308b6d commit 0d3159e
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 39 deletions.
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@

[![Build Status](https://travis-ci.org/nodenv/nodenv-default-packages.svg)](https://travis-ci.org/nodenv/nodenv-default-packages)

This nodenv plugin hooks into the `nodenv install` command to automatically
install `npm` packages every time you install a new version of Node. It
requires the `node-build` plugin to be installed.
This nodenv plugin hooks into the `nodenv install` command to automatically install `npm` packages every time you install a new version of Node.
It requires the `node-build` plugin to be installed.

Forked from the excellent [`rbenv-default-gems`][rbenv-default-gems] plugin from
[sstephenson][sstephenson].
Forked from the excellent [`rbenv-default-gems`][rbenv-default-gems] plugin from [sstephenson][sstephenson].

<!-- toc -->

- [Installation](#installation)
* [Installing as a nodenv plugin](#installing-as-a-nodenv-plugin)
* [Installing with Homebrew (for OS X users)](#installing-with-homebrew-for-os-x-users)
- [Usage](#usage)
* [default-packages Files](#default-packages-files)
* [Updating Default Packages](#updating-default-packages)
- [Credits](#credits)

Expand All @@ -30,11 +29,9 @@ Make sure you have the latest nodenv and node-build versions, then run:

### Installing with Homebrew (for OS X users)

Mac OS X users can install nodenv-default-packages with the
[Homebrew](http://brew.sh) package manager.
Mac OS X users can install nodenv-default-packages with the [Homebrew](http://brew.sh) package manager.

*This is the recommended method of installation if you installed nodenv
with Homebrew.*
*This is the recommended method of installation if you installed nodenv with Homebrew.*

```
$ brew install nodenv/nodenv/nodenv-default-packages
Expand All @@ -48,25 +45,28 @@ $ brew install --HEAD nodenv/nodenv/nodenv-default-packages

## Usage

nodenv-default-packages automatically installs the packages listed in the
`$(nodenv root)/default-packages` file every time you successfully install a new
version of Node with `nodenv install`.
nodenv-default-packages automatically installs the packages listed in the [default-packages file(s)](#default-packages-files) file every time you successfully install a new version of Node with `nodenv install`.

Specify packages in `$(nodenv root)/default-packages` by name, one per line. You may
optionally specify a semver version spec after the name. For example:
Specify packages in `default-packages` by name, one per line.
You may optionally specify a semver version spec after the name. For example:

grunt-cli
jshint ~2.6.3
csslint >= 0.9.0 < 0.10.0

Blank lines and lines beginning with a `#` are ignored.

### default-packages Files

nodenv-default-packages reads from `$(nodenv root)/default-packages` as well as `nodenv/default-packages` under all [XDG config directories][xdg].
The XDG config directories searched are `$XDG_CONFIG_HOME` (`$HOME/.config` if unset/empty) and all colon-separated `$XDG_CONFIG_DIRS` (`/etc/xdg` if unset/empty).

### Updating Default Packages

if you update your `$(nodenv root)/default-packages` and want to refresh some or all of
your existing node installations you can use commands like this:
if you update your `$(nodenv root)/default-packages` and want to refresh some or all of your existing node installations you can use commands like this:

nodenv default-packages install 8.8.1 # Reinstall default packages on Node version 8.8.1

nodenv default-packages install --all # Reinstall default packages on _all_ installed Node versions

*NOTE:* This may take some time.
Expand All @@ -79,3 +79,4 @@ Forked from [Sam Stephenson][sstephenson]'s [rbenv-default-gems][] by [Josh Hagi
[rbenv-default-gems]: https://github.com/rbenv/rbenv-default-gems
[jawshooah]: https://github.com/jawshooah
[nodenv]: https://github.com/nodenv/nodenv
[xdg]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
36 changes: 25 additions & 11 deletions bin/nodenv-default-packages
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
# Usage:
# nodenv default-packages list
# nodenv default-packages install [ --all | <version>...]
# nodenv default-packages files
#

set -eo pipefail
[ -n "$NODENV_DEBUG" ] && set -x

# Provide nodenv completions
if [ "$1" = --complete ]; then
echo files
echo install
echo list
echo --all
Expand All @@ -39,16 +41,9 @@ for_versions() {

# Read package names and versions from $NODENV_ROOT/default-packages
list_default_packages() {
[ -r "${NODENV_ROOT}/default-packages" ] || {
echo "No default-package file found" >&2
exit 1
}

local pkg_name pkg_version

# strip comments and empty lines
sed -e 's/#.*$//g' -e '/^[[:space:]]*$/d' "${NODENV_ROOT}/default-packages" |

default_packages_files |
tr '\n' '\0' | # replace newlines with nullchar so we can use xargs
xargs -0 sed -e 's/#.*$//g' -e '/^[[:space:]]*$/d' | # strip comments and empty lines
while IFS=" " read -r pkg_name pkg_version; do
echo "${pkg_name}${pkg_version:+@$pkg_version}"
done
Expand Down Expand Up @@ -78,14 +73,33 @@ install_default_packages() {
}
}

default_packages_files() {
local file_found

IFS=: read -ra xdg_dirs <<< "${XDG_CONFIG_HOME:-$HOME/.config}:${XDG_CONFIG_DIRS:-/etc/xdg}"

for dir in "$NODENV_ROOT" "${xdg_dirs[@]/%//nodenv}"; do
if test -r "$dir/default-packages"; then
echo "$_" && file_found=true
fi
done

if [ -z "${file_found:-}" ]; then
echo "nodenv: default-packages file not found" >&2
return 1
fi
}

unset cmd

case "$1" in
install ) for_versions install_default_packages "${@:2}" ;;

list ) list_default_packages ;;

-h | --help ) nodenv-help; exit ;;
files ) default_packages_files ;;

-h | --help ) nodenv-help ;;

*) nodenv-help --usage default-packages; exit 1 ;;
esac
68 changes: 68 additions & 0 deletions test/files.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bats

load test_helper

@test "file errors if file not found" {
run nodenv default-packages files

assert_failure
assert_output "nodenv: default-packages file not found"
}

@test "file finds default-packages in NODENV_ROOT" {
with_file "$NODENV_ROOT/default-packages" <<<""

run nodenv default-packages files

assert_success
assert_output "$NODENV_ROOT/default-packages"
}

@test "file finds default-packages in default XDG_CONFIG_HOME" {
with_file "$HOME/.config/nodenv/default-packages" <<<""

run nodenv default-packages files

assert_success
assert_output "$HOME/.config/nodenv/default-packages"
}

@test "file finds default-packages in configured XDG_CONFIG_HOME" {
XDG_CONFIG_HOME=$HOME/myconfig
with_file "$XDG_CONFIG_HOME/nodenv/default-packages" <<<""

XDG_CONFIG_HOME="$XDG_CONFIG_HOME" run nodenv default-packages files

assert_success
assert_output "$XDG_CONFIG_HOME/nodenv/default-packages"
}

@test "file finds default-packages in configured XDG_CONFIG_DIRS" {
with_file "$HOME/myconfig/nodenv/default-packages" <<<""

XDG_CONFIG_DIRS="$HOME/myconfig:other" run nodenv default-packages files

assert_success
assert_output "$HOME/myconfig/nodenv/default-packages"
}

@test "file finds default-packages in default XDG_CONFIG_DIRS" {
skip "can't fake /etc/xdg"
}

@test "file finds multiple files" {
with_file "$NODENV_ROOT/default-packages" <<<""
with_file "$HOME/.config/nodenv/default-packages" <<<""
with_file "$HOME/myconfig/nodenv/default-packages" <<<""
with_file "$HOME/theirconfig/nodenv/default-packages" <<<""

XDG_CONFIG_DIRS="$HOME/myconfig:$HOME/theirconfig" run nodenv default-packages files

assert_success
assert_output - <<-OUT
$NODENV_ROOT/default-packages
$HOME/.config/nodenv/default-packages
$HOME/myconfig/nodenv/default-packages
$HOME/theirconfig/nodenv/default-packages
OUT
}
2 changes: 1 addition & 1 deletion test/hook.bats
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
load test_helper

@test "nodenv-install hook auto installs packages" {
with_default_packages_file <<< fake-package
with_file "$NODENV_ROOT/default-packages" <<< fake-package

run nodenv install 0.10.36

Expand Down
36 changes: 32 additions & 4 deletions test/install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ load test_helper
run nodenv default-packages install 1.2.3

assert_failure
refute_output "No default-packages file found"
assert_output "nodenv: default-packages file not found"
}

@test "install, without a version, installs to current node version" {
nodenv install --no-hooks 10.0.0
with_default_packages_file <<< fake-package
with_file "$NODENV_ROOT/default-packages" <<< fake-package

NODENV_VERSION=10.0.0 run nodenv default-packages install

Expand All @@ -21,7 +21,7 @@ load test_helper

@test "install accepts node version to which to install" {
nodenv install --no-hooks 10.0.0
with_default_packages_file <<< fake-package
with_file "$NODENV_ROOT/default-packages" <<< fake-package

run nodenv default-packages install 10.0.0

Expand All @@ -31,10 +31,38 @@ load test_helper

@test "install npm-installs single package" {
nodenv install --no-hooks 10.0.0
with_default_packages_file <<< fake-package
with_file "$NODENV_ROOT/default-packages" <<< fake-package

run nodenv default-packages install 10.0.0

assert_success
assert_output -p "npm invoked with: 'install -g fake-package'"
}

@test "install combines all default-packages files" {
nodenv install --no-hooks 10.0.0
with_file "$NODENV_ROOT/default-packages" <<< pkg-from-nodenv-root
with_file "$HOME/.config/nodenv/default-packages" <<< pkg-from-config-home
with_file "$HOME/myconfig/nodenv/default-packages" <<< pkg-from-config-dirs1
with_file "$HOME/theirconfig/nodenv/default-packages" <<< pkg-from-config-dirs2

XDG_CONFIG_DIRS="$HOME/myconfig:$HOME/theirconfig" NODENV_VERSION=10.0.0 run nodenv default-packages install

assert_success
assert_output -p "npm invoked with: 'install -g pkg-from-nodenv-root'"
assert_output -p "npm invoked with: 'install -g pkg-from-config-home'"
assert_output -p "npm invoked with: 'install -g pkg-from-config-dirs1'"
assert_output -p "npm invoked with: 'install -g pkg-from-config-dirs2'"
}

@test "install handles filenames with spaces" {
nodenv install --no-hooks 10.0.0
with_file "$HOME/my config/nodenv/default-packages" <<< pkg-from-config-dirs1
with_file "$HOME/their config/nodenv/default-packages" <<< pkg-from-config-dirs2

XDG_CONFIG_DIRS="$HOME/my config:$HOME/their config" NODENV_VERSION=10.0.0 run nodenv default-packages install

assert_success
assert_output -p "npm invoked with: 'install -g pkg-from-config-dirs1'"
assert_output -p "npm invoked with: 'install -g pkg-from-config-dirs2'"
}
3 changes: 1 addition & 2 deletions test/installer.bats
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ load test_helper

@test "overwrites old installation" {
cd "$BATS_TMPDIR"
mkdir -p etc/nodenv.d/install
touch etc/nodenv.d/install/default-packages.bash
with_file etc/nodenv.d/install/default-packages.bash <<<""

PREFIX="$PWD" run "${BATS_TEST_DIRNAME}/../install.sh"
assert_success
Expand Down
4 changes: 2 additions & 2 deletions test/list.bats
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ load test_helper
}

@test "list default-packages" {
with_default_packages_file <<< fake-package
with_file "$NODENV_ROOT/default-packages" <<< fake-package

run nodenv default-packages list

Expand All @@ -19,7 +19,7 @@ load test_helper
}

@test "list skips comments and empty lines" {
with_default_packages_file <<-PKGS
with_file "$NODENV_ROOT/default-packages" <<-PKGS
fake-package
# comment
Expand Down
16 changes: 13 additions & 3 deletions test/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ setup() {
unset "$nodenv_var"
done

# unset all XDG_ vars
local xdg_var
for xdg_var in $(env 2>/dev/null | grep '^XDG_' | cut -d= -f1); do
unset "$xdg_var"
done

# set a restricted PATH (test bin, app bin, and node bin, no homebrew)
local test_bin="$BATS_TEST_DIRNAME/bin"
local package_bin="$BATS_TEST_DIRNAME/../bin"
Expand All @@ -26,17 +32,21 @@ setup() {

mkdir -p "$BATS_TMPDIR"
testdir=$(mktemp -d "$BATS_TMPDIR/$BATS_TEST_NAME.XXX") || exit 1

export NODENV_ROOT=$testdir/nodenv_root
mkdir -p "$NODENV_ROOT"

export HOME=$testdir/home
mkdir -p "$HOME/.config/nodenv"

export NODENV_HOOK_PATH="$BATS_TEST_DIRNAME/../etc/nodenv.d"
}

teardown() {
rm -rf "$BATS_TMPDIR" # same as BATS_MOCK_TMPDIR
}

with_default_packages_file() {
touch "$NODENV_ROOT/default-packages"
cat - >> "$NODENV_ROOT/default-packages"
with_file() {
mkdir -p "$(dirname "$1")"
cat - > "$1"
}

0 comments on commit 0d3159e

Please sign in to comment.