matugen: give dry runs their own config file

fixes #3279
port 1.6

(cherry picked from commit d57e32c5cb)
This commit is contained in:
bbedward
2026-09-04 14:37:56 +00:00
committed by dms-ci[bot]
parent f2114c1a01
commit fdf8722818
2 changed files with 115 additions and 15 deletions
+42 -15
View File
@@ -500,23 +500,25 @@ func buildImportData(dank16JSON, image string) string {
return fmt.Sprintf(`{"dank16": %s, "image": %s}`, dank16JSON, path)
}
func userConfigSection(opts *Options) string {
if !opts.RunUserTemplates || opts.ConfigDir == "" {
return "[config]\n\n"
}
data, err := os.ReadFile(filepath.Join(opts.ConfigDir, "matugen", "config.toml"))
if err != nil {
return "[config]\n\n"
}
section := extractTOMLSection(string(data), "[config]", "[templates]")
if section == "" {
return "[config]\n\n"
}
return section + "\n"
}
func buildMergedConfig(opts *Options, cfgFile *os.File, tmpDir string) error {
userConfigPath := filepath.Join(opts.ConfigDir, "matugen", "config.toml")
wroteConfig := false
if opts.RunUserTemplates {
if data, err := os.ReadFile(userConfigPath); err == nil {
configSection := extractTOMLSection(string(data), "[config]", "[templates]")
if configSection != "" {
cfgFile.WriteString(configSection)
cfgFile.WriteString("\n")
wroteConfig = true
}
}
}
if !wroteConfig {
cfgFile.WriteString("[config]\n\n")
}
cfgFile.WriteString(userConfigSection(opts))
baseConfigPath := filepath.Join(opts.ShellDir, "matugen", "configs", "base.toml")
if data, err := os.ReadFile(baseConfigPath); err == nil {
@@ -983,7 +985,32 @@ func runMatugenDryRun(opts *Options) (string, error) {
return execDryRun(opts, newFlags)
}
// matugen aborts on a config file it cannot deserialize, and without -c it
// reads the user's own ~/.config/matugen/config.toml, so a dry run gets a
// config of its own instead of inheriting whatever is there.
func writeDryRunConfig(opts *Options) (string, error) {
cfgFile, err := os.CreateTemp("", "matugen-dryrun-*.toml")
if err != nil {
return "", fmt.Errorf("failed to create dry-run config: %w", err)
}
defer cfgFile.Close()
section := userConfigSection(opts)
if idx := strings.Index(section, "\n[templates"); idx != -1 {
section = section[:idx+1]
}
cfgFile.WriteString(section)
cfgFile.WriteString("[templates]\n")
return cfgFile.Name(), nil
}
func execDryRun(opts *Options, flags matugenFlags) (string, error) {
cfgPath, err := writeDryRunConfig(opts)
if err != nil {
return "", err
}
defer os.Remove(cfgPath)
var baseArgs []string
switch opts.Kind {
case "hex":
@@ -991,7 +1018,7 @@ func execDryRun(opts *Options, flags matugenFlags) (string, error) {
default:
baseArgs = []string{opts.Kind, opts.Value}
}
baseArgs = append(baseArgs, "-m", string(opts.Mode), "-t", opts.MatugenType, "--json", "hex", "--dry-run")
baseArgs = append(baseArgs, "-m", string(opts.Mode), "-t", opts.MatugenType, "-c", cfgPath, "--json", "hex", "--dry-run")
baseArgs = appendContrastArg(baseArgs, opts.Contrast)
if flags.isV4 {
baseArgs = append(baseArgs, sourceSelectionArgs(opts.SourceMode, flags.supportsPrefer)...)
+73
View File
@@ -1327,3 +1327,76 @@ func TestResolveSmartMode(t *testing.T) {
})
}
}
func writeUserMatugenConfig(t *testing.T, configDir, content string) {
t.Helper()
dir := filepath.Join(configDir, "matugen")
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatalf("failed to create matugen config dir: %v", err)
}
if err := os.WriteFile(filepath.Join(dir, "config.toml"), []byte(content), 0o644); err != nil {
t.Fatalf("failed to write user config: %v", err)
}
}
func TestWriteDryRunConfigAlwaysDeclaresConfigAndTemplates(t *testing.T) {
tests := []struct {
name string
userConfig string
runUserTemplates bool
wantContains []string
wantNotContains []string
}{
{
name: "comment only user config",
userConfig: "# nothing here\n",
runUserTemplates: true,
wantNotContains: []string{"# nothing here"},
},
{
name: "user config section is carried over",
userConfig: "[config]\nfallback_color = \"#ff0000\"\n\n[templates.mine]\ninput_path = 'in'\noutput_path = 'out'\n",
runUserTemplates: true,
wantContains: []string{"fallback_color = \"#ff0000\""},
wantNotContains: []string{"[templates.mine]"},
},
{
name: "user templates disabled",
userConfig: "[config]\nfallback_color = \"#ff0000\"\n",
wantNotContains: []string{"fallback_color"},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
configDir := filepath.Join(t.TempDir(), "config")
writeUserMatugenConfig(t, configDir, tc.userConfig)
opts := &Options{ConfigDir: configDir, RunUserTemplates: tc.runUserTemplates}
cfgPath, err := writeDryRunConfig(opts)
if err != nil {
t.Fatalf("writeDryRunConfig failed: %v", err)
}
defer os.Remove(cfgPath)
data, err := os.ReadFile(cfgPath)
if err != nil {
t.Fatalf("failed to read dry-run config: %v", err)
}
content := string(data)
assert.Contains(t, content, "[config]")
assert.Contains(t, content, "[templates]")
for _, want := range tc.wantContains {
assert.Contains(t, content, want)
}
for _, unwanted := range tc.wantNotContains {
assert.NotContains(t, content, unwanted)
}
})
}
}
func TestUserConfigSectionWithoutConfigDir(t *testing.T) {
assert.Equal(t, "[config]\n\n", userConfigSection(&Options{RunUserTemplates: true}))
}