Repository: spf13/viper
File: file.go (Go)

Code before:
		}

		finder = locafero.Finder{
			Paths: v.configPaths,
			Names: names,
			Type:  locafero.FileTypeFile,
		}
	}

	if finder != nil {
		return v.findConfigFileWithFinder(finder)
	}

	return v.findConfigFileOld()
}

func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) {
	results, err := finder.Find(v.fs)
	if err != nil {
		return "", err
	}

	if len(results) == 0 {
		return "", ConfigFileNotFoundFromFinderError{
			name: v.configName, locations: fmt.Sprintf("%s", v.configPaths),
		}
	}

	// We call clean on the final result to ensure that the path is in its canonical form.
	// This is mostly for consistent path handling and to make sure tests pass.
	return results[0], nil
}

// Search all configPaths for any config file.
// Returns the first path that exists (and is a config file).
func (v *Viper) findConfigFileOld() (string, error) {
	v.logger.Info("searching for config in paths", "paths", v.configPaths)

	for _, cp := range v.configPaths {
		file := v.searchInPath(cp)
		if file != "" {
			return file, nil
		}
	}
	return "", ConfigFileNotFoundFromFinderError{
		name: v.configName, locations: fmt.Sprintf("%s", v.configPaths),
	}
}

func (v *Viper) searchInPath(in string) (filename string) {
	v.logger.Debug("searching for config in path", "path", in)

Review comment (suggestion):
This is a bit problematic, because it's a breaking change.

Here is what I would do:

- keep `ConfigFileNotFoundError`
- add a deprecated comment to it telling users to use what instead
- pass `ConfigFileNotFoundFromFinderError` to `ConfigFileNotFoundError`
- Implement `Unwrap` on `ConfigFileNotFoundError` (and return the other one) (that way matching with errors.As is going to work)
- Since `ConfigFileNotFoundError` will have access to the underlying error, there is no need to pass the other parameters to it.

Code after:

		finder = locafero.Finder{
			Paths: v.configPaths,
			Names: names,
			Type:  locafero.FileTypeFile,
		}
	}

	if finder != nil {
		return v.findConfigFileWithFinder(finder)
	}

	return v.findConfigFileOld()
}

func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) {
	results, err := finder.Find(v.fs)
	if err != nil {
		return "", err
	}

	if len(results) == 0 {
		return "", ConfigFileNotFoundError{name: v.configName, locations: v.configPaths}
	}

	// We call clean on the final result to ensure that the path is in its canonical form.
	// This is mostly for consistent path handling and to make sure tests pass.
	return results[0], nil
}

// Search all configPaths for any config file.
// Returns the first path that exists (and is a config file).
func (v *Viper) findConfigFileOld() (string, error) {
	v.logger.Info("searching for config in paths", "paths", v.configPaths)

	for _, cp := range v.configPaths {
		file := v.searchInPath(cp)
		if file != "" {
			return file, nil
		}
	}
	return "", ConfigFileNotFoundError{name: v.configName, locations: v.configPaths}
}

func (v *Viper) searchInPath(in string) (filename string) {
	v.logger.Debug("searching for config in path", "path", in)
	for _, ext := range SupportedExts {
		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
			return filepath.Join(in, v.configName+"."+ext)