Publish comparison bundles safely
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/comparison"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
||||
)
|
||||
|
||||
@@ -51,6 +52,35 @@ func resolveOutputDirWithConfigured(workingDir, override, configuredDir string)
|
||||
return resolveOutputDir(workingDir, directory)
|
||||
}
|
||||
|
||||
func resolveComparisonOutputDirectory(workingDir, override, configuredDir, reportOutputName string) (string, error) {
|
||||
workingDir, err := validateWorkingDir(workingDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if override != "" {
|
||||
return resolveComparisonDirectoryPath(workingDir, override)
|
||||
}
|
||||
outputDir, err := resolveOutputDir(workingDir, configuredDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name, err := comparison.DefaultDirectoryName(reportOutputName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(outputDir, name), nil
|
||||
}
|
||||
|
||||
func resolveComparisonDirectoryPath(workingDir, directory string) (string, error) {
|
||||
if strings.TrimSpace(directory) == "" {
|
||||
return "", fmt.Errorf("comparison output directory is required")
|
||||
}
|
||||
if !filepath.IsAbs(directory) {
|
||||
directory = filepath.Join(workingDir, directory)
|
||||
}
|
||||
return filepath.Clean(directory), nil
|
||||
}
|
||||
|
||||
func resolveOutputDir(workingDir, override string) (string, error) {
|
||||
workingDir, err := validateWorkingDir(workingDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,43 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveComparisonOutputDirectory(t *testing.T) {
|
||||
workingDir := t.TempDir()
|
||||
configured := filepath.Join(workingDir, "configured")
|
||||
blocked := filepath.Join(workingDir, "not-a-directory")
|
||||
if err := os.WriteFile(blocked, []byte("blocked"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
override string
|
||||
configuredDir string
|
||||
reportOutputName string
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "working directory default", reportOutputName: "today.md", want: filepath.Join(workingDir, "comparison-today")},
|
||||
{name: "configured relative directory", configuredDir: "configured", reportOutputName: "tomorrow.md", want: filepath.Join(configured, "comparison-tomorrow")},
|
||||
{name: "configured absolute directory", configuredDir: configured, reportOutputName: "hourly.md", want: filepath.Join(configured, "comparison-hourly")},
|
||||
{name: "relative explicit directory", override: "exact", configuredDir: blocked, reportOutputName: "daily-2026-08-24.md", want: filepath.Join(workingDir, "exact")},
|
||||
{name: "absolute explicit directory", override: filepath.Join(workingDir, "absolute"), reportOutputName: "today.md", want: filepath.Join(workingDir, "absolute")},
|
||||
{name: "invalid report suffix", reportOutputName: "today.txt", wantErr: true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := resolveComparisonOutputDirectory(workingDir, test.override, test.configuredDir, test.reportOutputName)
|
||||
if (err != nil) != test.wantErr {
|
||||
t.Fatalf("resolveComparisonOutputDirectory() error = %v, want error %t", err, test.wantErr)
|
||||
}
|
||||
if !test.wantErr && got != test.want {
|
||||
t.Fatalf("resolveComparisonOutputDirectory() = %q, want %q", got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveOutputDirRejectsDanglingSymlinkComponents(t *testing.T) {
|
||||
workingDir := t.TempDir()
|
||||
dangling := filepath.Join(workingDir, "dangling")
|
||||
|
||||
Reference in New Issue
Block a user