Skip to content

Commit

Permalink
feat: Expand Environment Variables
Browse files Browse the repository at this point in the history
The path-helper now expands environment variables used in the files on
the directories it processes.
  • Loading branch information
otaviof committed Feb 10, 2024
1 parent f97906f commit 6acd047
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Unit and E2E Tests
name: test

on:
push:
Expand Down
18 changes: 16 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,24 @@ PKG ?= ./pkg/$(APP)/...
GOFLAGS ?= -v -a
CGO_LDFLAGS ?= -s -w

GOFLAGS_TEST ?= -failfast -race -coverprofile=coverage.txt -covermode=atomic -cover -v
GOFLAGS_TEST ?= \
-v \
-failfast \
-race \
-cover \
-coverprofile=coverage.txt \
-covermode=atomic

BATS_CORE ?= test/e2e/bats/core/bin/bats
E2E_DIR ?= test/e2e
E2E_TEST_GLOB ?= *.bats
E2E_TESTS = $(E2E_DIR)/$(E2E_TEST_GLOB)

# Expanded during path files evaluation, to assert environment variables support.
PATH_HELPER_TEST_DIR = "/test"

LOWER_OSTYPE ?= $(shell uname -s |tr '[:upper:]' '[:lower:]')
CPUTYPE ?= $(shell uname -m)
INSTALL_DIR ?= /usr/local/bin

ARGS ?=
Expand All @@ -24,6 +35,7 @@ ARGS ?=

default: build

.PHONY: $(BIN)
$(BIN):
go build -o $(BIN) $(CMD)

Expand Down Expand Up @@ -62,7 +74,9 @@ snapshot-local:
goreleaser --clean --snapshot --skip-publish --debug

snapshot-install: snapshot-local
install -m 755 build/dist/darwin_darwin_amd64/$(APP) "$(GOPATH)/bin/$(APP)"
install -m 755 \
${OUTPUT_DIR}/dist/$(APP)_$(LOWER_OSTYPE)_$(CPUTYPE)/$(APP) \
$(INSTALL_DIR)/$(APP)

release:
git tag $(VERSION)
Expand Down
44 changes: 27 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@

# `path-helper`

Command-line application to generate `PATH` and `MANPATH` environment variables based in a
configuration directory, the same approach used in Mac OS. By default, `PATH` is genarated based in
`/etc/paths.d`, while `MANPATH` is based on `/etc/manpaths.d`.
Command-line application to generate `PATH` and `MANPATH` environment variables based on a configuration directory, the same approach used in MacOS.

Inside those base directories the order of the files is kept, and each line in a file corresponds to
a directory in the file-system that should become part of `PATH` or `MANPATH`. Please consider the
local example of [`paths.d`](./test/paths.d).
By default, `PATH` is genarated based in `/etc/paths.d` directory, while `MANPATH` is based on `/etc/manpaths.d`, you can configure these locations.

Files created on these directories are listed alphabetically, each line in a file corresponds to a another directory that should become part of `PATH` and `MANPATH`.

Configuration files may as well contain environment variables which will be expanded during execution.

Please consider the local example of [`paths.d`](./test/paths.d).

In short, the usage of `path-helper` is:

Expand All @@ -28,16 +30,24 @@ eval `path-helper`

## Install

To install `path-helper` you can simply `go install`, as per:
The most convenient way would be:

```bash
go install github.com/otaviof/path-helper/cmd/path-helper@latest
```sh
curl -sL https://raw.githubusercontent.com/otaviof/path-helper/main/hack/install-lastest-release.sh | sh
```

Alternatively, you can run the following target in the project folder, `sudo` might be required for completion.
This process is [automated by this script](./hack/install-lastest-release.sh), you should consider running on your repository clone, i.e.:

```bash
make install INSTALL_DIR="/usr/local/bin"
```sh
hack/install-lastest-release.sh
```

To install `path-helper` consider the [release page][releaseURL] and download pre-compiled binaries for your platform. Once the tarball is downloaded, you need to extract and install on the desired location, like the example snippet below

```sh
cd /tmp
tar -zxvpf path-helper-ostype-arch.tar.gz path-helper
install -m 0755 path-helper /usr/local/bin/path-helper
```

## Usage Examples
Expand All @@ -62,18 +72,18 @@ path-helper -d

### Shell Configuration Example

Evaluate `path-helper` output in order to export `PATH` and `MANPATH` environment variables. The
following example checks if `path-helper` is present in default location, and later runs `eval`
against:
Evaluate `path-helper` output in order to export `PATH` and `MANPATH` environment variables. The following example checks if `path-helper` is present in default location, and later runs `eval` against:

```bash
[ -x ${GOPATH}/bin/path-helper ] && \
[[ -x ${GOPATH}/bin/path-helper ]] &&
eval `${GOPATH}/bin/path-helper`
```

Running `path-helper` without `eval`, would return:
Running `path-helper` without `eval`, would print out the Shell script snippet it generateds. For instance:

```
$ path-helper
PATH="..." ; MANPATH="..." ; export PATH MANPATH ;
```

[releaseURL]: https://github.com/otaviof/path-helper/releases/tag/0.1.1
38 changes: 18 additions & 20 deletions cmd/path-helper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,44 @@ func fatal(err error) {
}

// commandLineParser handle command line flags, display help message.
func commandLineParser(config *pathhelper.Config) {
func commandLineParser() *pathhelper.Config {
flag.Usage = func() {
fmt.Printf(`## path-helper
Helper command-line application to compose "PATH" expression based in a "paths.d"
directory, respecting order of files and adding toggles to skip entries.
Helper command-line application to compose "PATH" and "MANPATH" based in a
"paths.d" directory, respecting order of its files and toggles to skip entries.
To export new "PATH" to your shell instance, run "eval" against "path-helper"
output. Examples below.
Environment variables may be used inside the path-files, and these will be
expanded before rendering the final "PATH" and "MANPATH".
Usage:
To export new "PATH" and "MANPATH" to your shell current instance, run "eval"
against "path-helper" output.
# Usage:
$ path-helper [-h|--help|flags]
Examples:
# Examples:
$ path-helper -v
$ path-helper -v -s=false -d=false
Shell-Export:
# Shell-Export:
$ eval "$(path-helper -s=false -d=false)"
$ echo $PATH
$ echo ${PATH}
$ echo ${MANPATH}
Command-Line Options:
# Command-Line Options:
`)
flag.PrintDefaults()
}

flag.StringVar(&config.PathBaseDir, "p", "/etc/paths.d", "Paths directory")
flag.StringVar(&config.ManBaseDir, "m", "/etc/manpaths.d", "Man pages directory")
flag.BoolVar(&config.SkipNotFound, "d", true, "Skip not found directories")
flag.BoolVar(&config.SkipDuplicates, "s", true, "Skip duplicated entries")
flag.BoolVar(&config.Verbose, "v", false, "Verbose")

cfg := pathhelper.NewConfigFromFlags()
flag.Parse()
return cfg
}

func main() {
config := &pathhelper.Config{}
commandLineParser(config)

p := pathhelper.NewPathHelper(config)
cfg := commandLineParser()
p := pathhelper.NewPathHelper(cfg)
expr, err := p.RenderExpression()
if err != nil {
fatal(err)
Expand Down
22 changes: 22 additions & 0 deletions pkg/path-helper/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package pathhelper

import "flag"

// Config all configuration entries supported by this application.
type Config struct {
PathBaseDir string // paths.d directory path
Expand All @@ -8,3 +10,23 @@ type Config struct {
SkipDuplicates bool // skip duplicated entries to compose PATH
Verbose bool // make output verbose
}

func NewConfig() *Config {
return &Config{
PathBaseDir: "/etc/paths.d",
ManBaseDir: "/etc/manpaths.d",
SkipNotFound: true,
SkipDuplicates: true,
Verbose: false,
}
}

func NewConfigFromFlags() *Config {
cfg := NewConfig()
flag.StringVar(&cfg.PathBaseDir, "p", cfg.PathBaseDir, "Paths directory")
flag.StringVar(&cfg.ManBaseDir, "m", cfg.ManBaseDir, "Man pages directory")
flag.BoolVar(&cfg.SkipNotFound, "d", cfg.SkipNotFound, "Skip not found directories")
flag.BoolVar(&cfg.SkipDuplicates, "s", cfg.SkipDuplicates, "Skip duplicated entries")
flag.BoolVar(&cfg.Verbose, "v", cfg.Verbose, "Verbose")
return cfg
}
12 changes: 8 additions & 4 deletions pkg/path-helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pathhelper

import (
"fmt"
"os"
"path"
"path/filepath"
"strings"
Expand Down Expand Up @@ -49,8 +50,9 @@ func (p *PathHelper) globPathFiles(baseDir string) ([]string, error) {
return files, nil
}

// inspectPathDirectories based in path files, read and inspect direcotories listed in those. Can
// return errors related to reading files.
// inspectPathDirectories based in path files, read and inspect direcotories
// listed, and it also expands environment variables. Can return errors related to
// reading files.
func (p *PathHelper) inspectPathDirectories(files []string) ([]string, error) {
directories := []string{}
for _, file := range files {
Expand All @@ -61,12 +63,14 @@ func (p *PathHelper) inspectPathDirectories(files []string) ([]string, error) {
}

for _, directory := range lines {
p.logger("\t- '%s'", directory)
if strings.HasPrefix(directory, "#") {
continue
}
directory = os.ExpandEnv(directory)
p.logger("\t- '%s'", directory)
if p.config.SkipNotFound && !dirExists(directory) {
p.logger("[WARN] Directory '%s' (%s) is not found! Skipping.", directory, file)
p.logger("[WARN] Directory '%s' (%s) is not found! Skipping.",
directory, file)
continue
}
directories = p.append(directories, directory)
Expand Down
11 changes: 9 additions & 2 deletions pkg/path-helper/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pathhelper

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -16,8 +17,14 @@ func TestPathHelper(t *testing.T) {
ManBaseDir: "../../test/paths.d",
PathBaseDir: "../../test/paths.d",
}
expectedJoinedPaths := "/a/a/a:/b/b/b:/c/c/c:/d/d/d"
expectedJoinedPathsDuplicated := "/a/a/a:/b/b/b:/c/c/c:/d/d/d:/d/d/d"
testDirEnv := os.Getenv("PATH_HELPER_TEST_DIR")
expectedJoinedPaths := fmt.Sprintf(
"/a/a/a:/b/b/b:/c/c/c:/d/d/d:%s/bin", testDirEnv,
)
expectedJoinedPathsDuplicated := fmt.Sprintf(
"/a/a/a:/b/b/b:/c/c/c:/d/d/d:/d/d/d:%s/bin",
testDirEnv,
)

t.Run("without-duplicates-and-without-not-founds", func(t *testing.T) {
t.Run("inspecting-directories-and-files", func(t *testing.T) {
Expand Down
13 changes: 7 additions & 6 deletions test/e2e/path-helper.bats
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ declare -r BIN="${BIN:-}"
BASE_DIR="${PWD}/test/paths.d"
PATH_HELPER="${BIN} -p ${BASE_DIR} -m ${BASE_DIR}"

PATHS="/a/a/a:/b/b/b:/c/c/c:/d/d/d"
PATHS_DUP="/a/a/a:/b/b/b:/c/c/c:/d/d/d:/d/d/d"
PATHS="/a/a/a:/b/b/b:/c/c/c:/d/d/d:${PATH_HELPER_TEST_DIR}/bin"
PATHS_DUP="/a/a/a:/b/b/b:/c/c/c:/d/d/d:/d/d/d:${PATH_HELPER_TEST_DIR}/bin"

EXPR="PATH=\"${PATHS}\" ; MANPATH=\"${PATHS}\" ; export PATH MANPATH ;"
EXPR_DUP="PATH=\"${PATHS_DUP}\" ; MANPATH=\"${PATHS_DUP}\" ; export PATH MANPATH ;"

@test "without-duplicates-and-witout-not-founds" {
[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]
echo ${BIN}
[[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]]

run ${PATH_HELPER}

Expand All @@ -21,7 +22,7 @@ EXPR_DUP="PATH=\"${PATHS_DUP}\" ; MANPATH=\"${PATHS_DUP}\" ; export PATH MANPATH
}

@test "with-duplicates" {
[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]
[[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]]

run ${PATH_HELPER} -s=false

Expand All @@ -30,7 +31,7 @@ EXPR_DUP="PATH=\"${PATHS_DUP}\" ; MANPATH=\"${PATHS_DUP}\" ; export PATH MANPATH
}

@test "with-not-founds" {
[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]
[[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]]

run ${PATH_HELPER} -d=false

Expand All @@ -39,7 +40,7 @@ EXPR_DUP="PATH=\"${PATHS_DUP}\" ; MANPATH=\"${PATHS_DUP}\" ; export PATH MANPATH
}

@test "with-duplicates-and-with-not-founds" {
[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]
[[ -f "${BIN}" && -n "${PATH_HELPER}" && -d "${BASE_DIR}" ]]

run ${PATH_HELPER} -s=false -d=false

Expand Down
1 change: 1 addition & 0 deletions test/paths.d/04-env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
${PATH_HELPER_TEST_DIR}/bin

0 comments on commit 6acd047

Please sign in to comment.