Skip to content

Commit ba76946

Browse files
Using godotenv for .env files and new tests.
1 parent 4f13a99 commit ba76946

File tree

4 files changed

+228
-328
lines changed

4 files changed

+228
-328
lines changed

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ go 1.19
44

55
require (
66
github.com/sirupsen/logrus v1.9.0
7+
github.com/stretchr/testify v1.7.0
78
github.com/urfave/cli/v2 v2.23.6
89
)
910

11+
require (
12+
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/pmezard/go-difflib v1.0.0 // indirect
14+
gopkg.in/yaml.v3 v3.0.1 // indirect
15+
)
16+
1017
require (
1118
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
19+
github.com/harness/godotenv/v3 v3.0.1
1220
github.com/russross/blackfriday/v2 v2.1.0 // indirect
1321
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
1422
golang.org/x/sys v0.0.0-20220731174439-a90be440212d // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
33
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
44
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
55
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/harness/godotenv/v3 v3.0.1 h1:7QPEOkpx6SLLrYRRzPBp50d6c0XIxq721iqoFxbz1Bs=
7+
github.com/harness/godotenv/v3 v3.0.1/go.mod h1:UIXXJtTM7NkSYMYknHYOO2d8BfDlAWMYZRuRsXcDDR0=
68
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
79
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
810
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -19,6 +21,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr
1921
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2022
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
2123
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
24+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2225
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2326
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2427
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
28+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

harness/variables.go

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"os"
77
"path/filepath"
88
"strings"
9+
10+
v3 "github.com/harness/godotenv/v3"
911
)
1012

1113
const (
@@ -79,54 +81,80 @@ func SetErrorMetadata(message, code, category string) error {
7981
}
8082

8183
// UpdateOrRemoveKeyValue updates or deletes a key-value pair in the specified file.
82-
func UpdateOrRemoveKeyValue(envVar, key, newValue string, delete bool) error {
83-
// Get the file path from the environment variable
84+
func UpdateOrRemoveKeyValue(envVar, key, newValue string, deleteKey bool) error {
8485
filePath := os.Getenv(envVar)
8586
if filePath == "" {
8687
return fmt.Errorf("environment variable %s is not set", envVar)
8788
}
8889

8990
// Ensure the file exists before reading
9091
if _, err := os.Stat(filePath); os.IsNotExist(err) {
91-
// Create the file if it does not exist
9292
_, err := os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
9393
if err != nil {
9494
return fmt.Errorf("failed to create file: %w", err)
9595
}
9696
}
9797

98-
// Determine the file extension to handle formats
98+
// Trim trailing newline characters from newValue
99+
newValue = strings.TrimRight(newValue, "\n")
100+
99101
ext := strings.ToLower(filepath.Ext(filePath))
100102

101-
// Read the file contents into memory
102-
lines, err := ReadLines(filePath)
103-
if err != nil {
104-
return fmt.Errorf("failed to read file: %w", err)
105-
}
103+
if ext == ".env" {
104+
// Use godotenv for .env files
105+
data, err := v3.Read(filePath)
106+
if err != nil {
107+
return fmt.Errorf("failed to parse .env file: %w", err)
108+
}
106109

107-
// Process lines
108-
var updatedLines []string
109-
found := false
110-
for _, line := range lines {
111-
k, v := ParseKeyValue(line, ext)
112-
if k == key {
113-
found = true
114-
if delete {
115-
continue // Skip the line to delete it
116-
}
117-
updatedLines = append(updatedLines, FormatKeyValue(k, newValue, ext))
110+
if deleteKey {
111+
delete(data, key)
118112
} else {
119-
updatedLines = append(updatedLines, FormatKeyValue(k, v, ext))
113+
data[key] = newValue
120114
}
121-
}
122115

123-
// Append new key-value if not found and not deleting
124-
if !found && !delete {
125-
updatedLines = append(updatedLines, FormatKeyValue(key, newValue, ext))
116+
err = v3.Write(data, filePath)
117+
if err != nil {
118+
return fmt.Errorf("failed to write .env file: %w", err)
119+
}
120+
} else {
121+
// For .out files, process manually
122+
// For .out files, check for multiline values
123+
if strings.Contains(newValue, "\n") {
124+
return fmt.Errorf("multiline values are not allowed for key %s in .out file", key)
125+
}
126+
127+
lines, err := ReadLines(filePath)
128+
if err != nil {
129+
return fmt.Errorf("failed to read file: %w", err)
130+
}
131+
132+
var updatedLines []string
133+
found := false
134+
for _, line := range lines {
135+
k, v := ParseKeyValue(line, ext)
136+
if k == key {
137+
found = true
138+
if deleteKey {
139+
continue
140+
}
141+
updatedLines = append(updatedLines, FormatKeyValue(k, newValue, ext))
142+
} else {
143+
updatedLines = append(updatedLines, FormatKeyValue(k, v, ext))
144+
}
145+
}
146+
147+
if !found && !deleteKey {
148+
updatedLines = append(updatedLines, FormatKeyValue(key, newValue, ext))
149+
}
150+
151+
err = WriteLines(filePath, updatedLines)
152+
if err != nil {
153+
return fmt.Errorf("failed to write file: %w", err)
154+
}
126155
}
127156

128-
// Write updated lines back to the file
129-
return WriteLines(filePath, updatedLines)
157+
return nil
130158
}
131159

132160
// ReadLines reads lines from a file and returns them as a slice of strings.
@@ -164,28 +192,22 @@ func WriteLines(filename string, lines []string) error {
164192

165193
// ParseKeyValue parses a key-value pair from a string and returns the key and value.
166194
func ParseKeyValue(line, ext string) (string, string) {
167-
if ext == ".env" {
168-
parts := strings.SplitN(line, "=", 2)
169-
if len(parts) == 2 {
170-
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
171-
}
172-
return strings.TrimSpace(parts[0]), ""
173-
} else if ext == ".out" {
195+
if ext == ".out" {
174196
parts := strings.Fields(line)
175197
if len(parts) > 1 {
176198
return strings.TrimSpace(parts[0]), strings.TrimSpace(strings.Join(parts[1:], " "))
177199
}
178200
return strings.TrimSpace(parts[0]), ""
179201
}
202+
// .env is handled by godotenv, so this is not used for .env files
180203
return "", ""
181204
}
182205

183-
// FormatKeyValue formats a key-value pair into a string.
206+
// FormatKeyValue handles formatting for .env and .out files.
184207
func FormatKeyValue(key, value, ext string) string {
185-
if ext == ".env" {
186-
return fmt.Sprintf("%s=%s", key, value)
187-
} else if ext == ".out" {
208+
if ext == ".out" {
188209
return fmt.Sprintf("%s %s", key, value)
189210
}
211+
// For .env files, use godotenv directly; this function won't apply
190212
return ""
191213
}

0 commit comments

Comments
 (0)