2023-05-16 21:56:57 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"golang.org/x/exp/maps"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
args := os.Args[1:]
|
|
|
|
|
|
|
|
if len(args) != 6 {
|
|
|
|
fmt.Println("Usage: expand_template <template> <out> <substitutions_json> <volatile_status_file> <stable_status_file> <executable>")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
executable := args[5] == "true" || args[5] == "1"
|
|
|
|
|
|
|
|
substitutions := map[string]string{}
|
|
|
|
substitutionJson, err := os.ReadFile(args[2])
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to read substitutions file: %w", err))
|
|
|
|
}
|
|
|
|
if err := json.Unmarshal(substitutionJson, &substitutions); err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to parse substitutions file: %w", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
volatileStatus, err := parseStatusFile(args[3])
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to parse volatile status file: %w", err))
|
|
|
|
}
|
|
|
|
stableStatus, err := parseStatusFile(args[4])
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to parse stable status file: %w", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
statuses := map[string]string{}
|
|
|
|
maps.Copy(statuses, volatileStatus)
|
|
|
|
maps.Copy(statuses, stableStatus)
|
|
|
|
|
|
|
|
for key, value := range substitutions {
|
|
|
|
for token, replacement := range statuses {
|
|
|
|
value = strings.ReplaceAll(value, fmt.Sprintf("{{%s}}", token), replacement)
|
|
|
|
}
|
|
|
|
substitutions[key] = value
|
|
|
|
}
|
|
|
|
|
|
|
|
contentBytes, err := os.ReadFile(args[0])
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to read the template file: %w", err))
|
|
|
|
}
|
|
|
|
content := string(contentBytes)
|
|
|
|
|
|
|
|
for key, value := range substitutions {
|
|
|
|
content = strings.ReplaceAll(content, key, value)
|
|
|
|
}
|
|
|
|
|
2023-09-06 23:20:27 +00:00
|
|
|
var mode os.FileMode = 0666
|
2023-05-16 21:56:57 +00:00
|
|
|
if executable {
|
2023-09-06 23:20:27 +00:00
|
|
|
mode = 0777
|
2023-05-16 21:56:57 +00:00
|
|
|
}
|
|
|
|
err = os.WriteFile(args[1], []byte(content), mode)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(fmt.Errorf("failed to write output file: %w", err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// captures every `KEY VALUE` line in the status file.
|
2024-05-06 20:29:56 +00:00
|
|
|
// for explanation see: https://regex101.com/r/cr6wX1/1
|
|
|
|
var STATUS_REGEX = regexp.MustCompile(`(?m)^([^\s]+)[[:blank:]]+([^\n]*)$`)
|
2023-05-16 21:56:57 +00:00
|
|
|
|
|
|
|
func parseStatusFile(statusFilePath string) (map[string]string, error) {
|
|
|
|
statusFile, err := os.ReadFile(statusFilePath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
matches := STATUS_REGEX.FindAllStringSubmatch(string(statusFile), -1)
|
|
|
|
|
|
|
|
results := map[string]string{}
|
|
|
|
|
|
|
|
for _, match := range matches {
|
|
|
|
results[match[1]] = match[2]
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, nil
|
|
|
|
|
|
|
|
}
|