Files
2026-07-13 13:00:08 +08:00

134 lines
3.0 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"reasonix/internal/config"
"reasonix/internal/fileutil"
)
// upsertDotEnv stores KEY=value in Reasonix's global .env and applies it to the
// running process so a rebuild picks it up without a restart.
func upsertDotEnv(key, value string) error {
_, err := config.SetCredential(key, value)
return err
}
func removeDotEnv(key string) error {
return config.RemoveCredential(key)
}
// upsertEnvFile merges KEY=value into a KEY=value file at path, preserving
// comments and unrelated lines, writing atomically via a sibling temp + rename.
func upsertEnvFile(path, key, value string) error {
key = strings.TrimSpace(key)
if key == "" {
return nil
}
var lines []string
if b, err := readFileUTF8(path); err == nil {
lines = strings.Split(strings.TrimRight(string(b), "\n"), "\n")
}
replaced := false
for i, ln := range lines {
t := strings.TrimSpace(ln)
if t == "" || strings.HasPrefix(t, "#") {
continue
}
if k, _, ok := strings.Cut(t, "="); ok && strings.TrimSpace(k) == key {
lines[i] = key + "=" + value
replaced = true
break
}
}
if !replaced {
lines = append(lines, key+"="+value)
}
out := strings.Join(lines, "\n") + "\n"
dir := filepath.Dir(path)
if dir != "" && dir != "." {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
}
tmp, err := os.CreateTemp(dir, "credentials.*.tmp")
if err != nil {
return err
}
tmpPath := tmp.Name()
if _, err := tmp.WriteString(out); err != nil {
tmp.Close()
os.Remove(tmpPath)
return err
}
if err := tmp.Close(); err != nil {
os.Remove(tmpPath)
return err
}
if err := fileutil.ReplaceFile(tmpPath, path); err != nil {
os.Remove(tmpPath)
return err
}
return os.Setenv(key, value)
}
func removeEnvFile(path, key string) error {
key = strings.TrimSpace(key)
if key == "" {
return nil
}
data, err := readFileUTF8(path)
if err != nil {
if os.IsNotExist(err) {
return os.Unsetenv(key)
}
return err
}
lines := strings.Split(strings.TrimRight(string(data), "\n"), "\n")
outLines := make([]string, 0, len(lines))
for _, ln := range lines {
t := strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(ln), "export "))
if t == "" || strings.HasPrefix(t, "#") {
outLines = append(outLines, ln)
continue
}
if k, _, ok := strings.Cut(t, "="); ok && strings.TrimSpace(k) == key {
continue
}
outLines = append(outLines, ln)
}
out := ""
if len(outLines) > 0 {
out = strings.Join(outLines, "\n") + "\n"
}
dir := filepath.Dir(path)
if dir != "" && dir != "." {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
}
tmp, err := os.CreateTemp(dir, "credentials.*.tmp")
if err != nil {
return err
}
tmpPath := tmp.Name()
if _, err := tmp.WriteString(out); err != nil {
tmp.Close()
os.Remove(tmpPath)
return err
}
if err := tmp.Close(); err != nil {
os.Remove(tmpPath)
return err
}
if err := fileutil.ReplaceFile(tmpPath, path); err != nil {
os.Remove(tmpPath)
return err
}
return os.Unsetenv(key)
}