First commit.
This commit is contained in:
commit
e9fbe5535a
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.log
|
||||||
|
.vscode/
|
||||||
8
CHANGELOG.md
Normal file
8
CHANGELOG.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# git.sa-roci.de/oss/go_environment Release notes
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## v. 0.0.1
|
||||||
|
|
||||||
|
- Initial Release.
|
||||||
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Sa Rocí Solutions
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# git.sa-roci.de/oss/go_environment
|
||||||
|
|
||||||
|
A package for extended environment variable usage.
|
||||||
45
envString.go
Normal file
45
envString.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package go_environment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EnvironmentString describes a (readonly) string which is
|
||||||
|
// defined as an environment variable.
|
||||||
|
type EnvironmentString struct {
|
||||||
|
Variable string
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns the JSON encoding of es.
|
||||||
|
func (es EnvironmentString) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(es.Variable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON parses the JSON-encoded data and stores the
|
||||||
|
// result in es.
|
||||||
|
func (es *EnvironmentString) UnmarshalJSON(data []byte) error {
|
||||||
|
return json.Unmarshal(data, &es.Variable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of es.
|
||||||
|
func (es EnvironmentString) String() (value string) {
|
||||||
|
return os.Getenv(es.Variable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the key of the underlying environment
|
||||||
|
// variable of es.
|
||||||
|
func (es EnvironmentString) Key() (value string) {
|
||||||
|
return es.Variable
|
||||||
|
}
|
||||||
|
|
||||||
|
// String determines the validity of the underlying
|
||||||
|
// environment variable of es.
|
||||||
|
func (es EnvironmentString) Valid() (valid bool) {
|
||||||
|
if es.Variable == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var value string
|
||||||
|
value, valid = os.LookupEnv(es.Variable)
|
||||||
|
return valid && (value != "")
|
||||||
|
}
|
||||||
69
envString_test.go
Normal file
69
envString_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package go_environment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
envKey = "ENV_STRING_TEST_VAR"
|
||||||
|
testValue = "dummy"
|
||||||
|
testJSON = `"` + envKey + `"`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnvString(t *testing.T) {
|
||||||
|
os.Setenv(envKey, "")
|
||||||
|
test := EnvironmentString{
|
||||||
|
Variable: envKey,
|
||||||
|
}
|
||||||
|
if test.Key() != envKey {
|
||||||
|
t.Errorf("unexpected environment variable key")
|
||||||
|
}
|
||||||
|
if test.Valid() {
|
||||||
|
t.Errorf("unexpectedly valid environment variable")
|
||||||
|
}
|
||||||
|
if test.String() != "" {
|
||||||
|
t.Errorf("unexpectedly valid environment variable")
|
||||||
|
}
|
||||||
|
os.Setenv(envKey, testValue)
|
||||||
|
if !test.Valid() {
|
||||||
|
t.Errorf("unexpectedly invalid environment variable")
|
||||||
|
}
|
||||||
|
if test.String() != testValue {
|
||||||
|
t.Errorf("unexpectedly valid environment variable")
|
||||||
|
}
|
||||||
|
os.Unsetenv(envKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvStringMarshalling(t *testing.T) {
|
||||||
|
test := EnvironmentString{}
|
||||||
|
if test.UnmarshalJSON([]byte(testJSON)) != nil {
|
||||||
|
t.Errorf("failed to unmarshal")
|
||||||
|
}
|
||||||
|
if test.Key() != envKey {
|
||||||
|
t.Errorf("unexpected environment variable key")
|
||||||
|
}
|
||||||
|
if binary, err := test.MarshalJSON(); err != nil {
|
||||||
|
t.Errorf("failed to marshal")
|
||||||
|
} else if string(binary) != testJSON {
|
||||||
|
t.Errorf("unexpected JSON")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValid(t *testing.T) {
|
||||||
|
os.Setenv(envKey, testValue)
|
||||||
|
test := EnvironmentString{
|
||||||
|
Variable: "",
|
||||||
|
}
|
||||||
|
if test.Valid() {
|
||||||
|
t.Errorf("TestValid: test case 1: unexpectedly valid environment variable")
|
||||||
|
}
|
||||||
|
test.Variable = envKey
|
||||||
|
if !test.Valid() {
|
||||||
|
t.Errorf("TestValid: test case 2: unexpectedly invalid environment variable")
|
||||||
|
}
|
||||||
|
os.Unsetenv(envKey)
|
||||||
|
if test.Valid() {
|
||||||
|
t.Errorf("TestValid: test case 3: unexpectedly valid environment variable")
|
||||||
|
}
|
||||||
|
}
|
||||||
83
environment.go
Normal file
83
environment.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package go_environment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// variableExpression is a regular expression for environment variables
|
||||||
|
//
|
||||||
|
// A match will look like
|
||||||
|
// - %<variableName>% (Windows-Notation)
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
// - $(<variableName>) (Unix-Notation)
|
||||||
|
variableExpression = regexp.MustCompile(`(%([\w]+)%)|(\$\(([\w]+)\))`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReplaceEnvironmentVariablesExt replaces all available
|
||||||
|
// environment variables (defined as %<variableName>%) within
|
||||||
|
// a string possibly also returning an error if necessary.
|
||||||
|
func ReplaceEnvironmentVariablesExt(value string) (string, error) {
|
||||||
|
analysable := value
|
||||||
|
subStrings := variableExpression.FindStringSubmatch(analysable)
|
||||||
|
usedVariables := make(map[string]string)
|
||||||
|
missingVariables := make([]string, 0)
|
||||||
|
var err error
|
||||||
|
if len(subStrings) == 5 {
|
||||||
|
for {
|
||||||
|
if subStrings[2] != "" {
|
||||||
|
variableKey := subStrings[2]
|
||||||
|
|
||||||
|
variableValue, found := os.LookupEnv(variableKey)
|
||||||
|
if found {
|
||||||
|
usedVariables[variableKey] = variableValue
|
||||||
|
analysable = strings.ReplaceAll(analysable, "%"+variableKey+"%", variableValue)
|
||||||
|
} else {
|
||||||
|
missingVariables = append(missingVariables, variableKey)
|
||||||
|
analysable = strings.ReplaceAll(analysable, "%"+variableKey+"%", variableKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if subStrings[4] != "" {
|
||||||
|
variableKey := subStrings[4]
|
||||||
|
|
||||||
|
variableValue, found := os.LookupEnv(variableKey)
|
||||||
|
if found {
|
||||||
|
usedVariables[variableKey] = variableValue
|
||||||
|
analysable = strings.ReplaceAll(analysable, "$("+variableKey+")", variableValue)
|
||||||
|
} else {
|
||||||
|
missingVariables = append(missingVariables, variableKey)
|
||||||
|
analysable = strings.ReplaceAll(analysable, "$("+variableKey+")", variableKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subStrings = variableExpression.FindStringSubmatch(analysable)
|
||||||
|
if len(subStrings) != 5 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result := value
|
||||||
|
for key, value := range usedVariables {
|
||||||
|
result = strings.ReplaceAll(result, "%"+key+"%", value)
|
||||||
|
result = strings.ReplaceAll(result, "$("+key+")", value)
|
||||||
|
}
|
||||||
|
if len(missingVariables) > 0 {
|
||||||
|
if len(missingVariables) == 1 {
|
||||||
|
err = fmt.Errorf("missing environment variable: %s", missingVariables[0])
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("missing environment variables: %s", strings.Join(missingVariables, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceEnvironmentVariablesExt replaces all available
|
||||||
|
// environment variables (defined as %<variableName>%) within
|
||||||
|
// a string.
|
||||||
|
func ReplaceEnvironmentVariables(directoryPath string) string {
|
||||||
|
path, _ := ReplaceEnvironmentVariablesExt(directoryPath)
|
||||||
|
return path
|
||||||
|
}
|
||||||
111
environment_test.go
Normal file
111
environment_test.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package go_environment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReplaceEnvironmentVariables(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input string
|
||||||
|
environment map[string]string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
input: "a",
|
||||||
|
environment: map[string]string{},
|
||||||
|
expected: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar1%",
|
||||||
|
environment: map[string]string{},
|
||||||
|
expected: "%testVar1%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar1%",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar1%&%testVar1%",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b&b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar1%&%testVar2%",
|
||||||
|
environment: map[string]string{},
|
||||||
|
expected: "%testVar1%&%testVar2%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar1%&%testVar2%",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b&%testVar2%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "%testVar2%&%testVar1%",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "%testVar2%&b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar1)",
|
||||||
|
environment: map[string]string{},
|
||||||
|
expected: "$(testVar1)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar1)",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar1)&$(testVar1)",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b&b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar1)&$(testVar2)",
|
||||||
|
environment: map[string]string{},
|
||||||
|
expected: "$(testVar1)&$(testVar2)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar1)&$(testVar2)",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "b&$(testVar2)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "$(testVar2)&$(testVar1)",
|
||||||
|
environment: map[string]string{
|
||||||
|
"testVar1": "b",
|
||||||
|
},
|
||||||
|
expected: "$(testVar2)&b",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
for key, value := range testCase.environment {
|
||||||
|
os.Setenv(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := ReplaceEnvironmentVariables(testCase.input); result != testCase.expected {
|
||||||
|
t.Errorf("TestReplaceEnvironmentVariables: test case %d: expected '%s' but got '%s'", i+1, testCase.expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range testCase.environment {
|
||||||
|
os.Unsetenv(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
go_environment.code-workspace
Normal file
9
go_environment.code-workspace
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"name": "git.sa-roci.de/oss/go_environment",
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user