Finish output directory follow-up work
This commit is contained in:
@@ -67,14 +67,54 @@ func resolveOutputDir(workingDir, override string) (string, error) {
|
||||
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)
|
||||
if err := preflightOutputDirectory(directory); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return directory, nil
|
||||
}
|
||||
|
||||
func preflightOutputDirectory(directory string) error {
|
||||
info, err := os.Stat(directory)
|
||||
if err == nil {
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("output directory %q is not a directory", directory)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("inspect output directory %q: %w", directory, err)
|
||||
}
|
||||
|
||||
// A missing directory is valid, but os.Stat also reports ErrNotExist for a
|
||||
// dangling symlink. Walk to the first existing component so invalid links
|
||||
// fail preflight instead of being discovered only during publication.
|
||||
for component := directory; ; component = filepath.Dir(component) {
|
||||
componentInfo, componentErr := os.Lstat(component)
|
||||
if componentErr == nil {
|
||||
if componentInfo.Mode()&os.ModeSymlink != 0 {
|
||||
targetInfo, targetErr := os.Stat(component)
|
||||
if targetErr != nil {
|
||||
return fmt.Errorf("inspect output directory %q at %q: %w", directory, component, targetErr)
|
||||
}
|
||||
if !targetInfo.IsDir() {
|
||||
return fmt.Errorf("output directory %q has non-directory path component %q", directory, component)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !componentInfo.IsDir() {
|
||||
return fmt.Errorf("output directory %q has non-directory path component %q", directory, component)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(componentErr) {
|
||||
return fmt.Errorf("inspect output directory %q at %q: %w", directory, component, componentErr)
|
||||
}
|
||||
if filepath.Dir(component) == component {
|
||||
return fmt.Errorf("inspect output directory %q: no existing directory ancestor", directory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func resolveOutputPath(workingDir, override, defaultName string) (string, error) {
|
||||
workingDir, err := validateWorkingDir(workingDir)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user