124 lines
3.4 KiB
Go
124 lines
3.4 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
|
)
|
|
|
|
func plannedBatchOutputPath(outputDir string, planned plannedBatchReport) (string, error) {
|
|
outputName, err := planned.Resolved.OutputName()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return validateOutputPath(filepath.Join(outputDir, outputName))
|
|
}
|
|
|
|
func prepareBatchOutputs(outputDir string, plannedReports []plannedBatchReport) error {
|
|
for index := range plannedReports {
|
|
outputPath, err := plannedBatchOutputPath(outputDir, plannedReports[index])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
plannedReports[index].OutputPath = outputPath
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func resolveReportOutputPath(workingDir, override, configuredDir string, resolved report.Resolved) (string, error) {
|
|
outputName, err := resolved.OutputName()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if override != "" {
|
|
return resolveOutputPath(workingDir, override, outputName)
|
|
}
|
|
outputDir, err := resolveOutputDir(workingDir, configuredDir)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return validateOutputPath(filepath.Join(outputDir, outputName))
|
|
}
|
|
|
|
func resolveOutputDirWithConfigured(workingDir, override, configuredDir string) (string, error) {
|
|
directory := configuredDir
|
|
if override != "" {
|
|
directory = override
|
|
}
|
|
return resolveOutputDir(workingDir, directory)
|
|
}
|
|
|
|
func resolveOutputDir(workingDir, override string) (string, error) {
|
|
workingDir, err := validateWorkingDir(workingDir)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if override == "" {
|
|
return workingDir, nil
|
|
}
|
|
if strings.TrimSpace(override) == "" {
|
|
return "", fmt.Errorf("output directory is required")
|
|
}
|
|
directory := override
|
|
if !filepath.IsAbs(directory) {
|
|
directory = filepath.Join(workingDir, directory)
|
|
}
|
|
directory = filepath.Clean(directory)
|
|
if info, err := os.Stat(directory); err == nil && !info.IsDir() {
|
|
return "", fmt.Errorf("output directory %q is not a directory", directory)
|
|
} else if err != nil && !os.IsNotExist(err) {
|
|
return "", fmt.Errorf("inspect output directory %q: %w", directory, err)
|
|
}
|
|
return directory, nil
|
|
}
|
|
|
|
func resolveOutputPath(workingDir, override, defaultName string) (string, error) {
|
|
workingDir, err := validateWorkingDir(workingDir)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
path := override
|
|
if path == "" {
|
|
path = defaultName
|
|
}
|
|
if strings.TrimSpace(path) == "" {
|
|
return "", fmt.Errorf("final output path is required")
|
|
}
|
|
if !filepath.IsAbs(path) {
|
|
path = filepath.Join(workingDir, path)
|
|
}
|
|
return validateOutputPath(path)
|
|
}
|
|
|
|
func validateWorkingDir(workingDir string) (string, error) {
|
|
if strings.TrimSpace(workingDir) == "" {
|
|
return "", fmt.Errorf("working directory is required")
|
|
}
|
|
if !filepath.IsAbs(workingDir) {
|
|
return "", fmt.Errorf("working directory %q must be absolute", workingDir)
|
|
}
|
|
return filepath.Clean(workingDir), nil
|
|
}
|
|
|
|
func validateOutputPath(path string) (string, error) {
|
|
if strings.TrimSpace(path) == "" {
|
|
return "", fmt.Errorf("final output path is required")
|
|
}
|
|
path = filepath.Clean(path)
|
|
if !filepath.IsAbs(path) {
|
|
return "", fmt.Errorf("final output path %q must be absolute", path)
|
|
}
|
|
if filepath.Dir(path) == path {
|
|
return "", fmt.Errorf("final output path %q must not be a filesystem root", path)
|
|
}
|
|
if info, err := os.Stat(path); err == nil && info.IsDir() {
|
|
return "", fmt.Errorf("final output path %q is a directory", path)
|
|
} else if err != nil && !os.IsNotExist(err) {
|
|
return "", fmt.Errorf("inspect final output path %q: %w", path, err)
|
|
}
|
|
return path, nil
|
|
}
|