Finder API
The pkg/finder package provides configuration file discovery functionality across different platforms and directory structures.
Overview
The Finder API is responsible for:
- Locating NuGet configuration files in standard locations
- Supporting platform-specific configuration paths
- Providing flexible search strategies
- Handling project-level and global configuration discovery
Types
ConfigFinder
type ConfigFinder struct {
SearchPaths []string
}The main finder type that handles configuration file discovery.
Fields:
SearchPaths: List of paths to search for configuration files
Constructors
NewConfigFinder
func NewConfigFinder() *ConfigFinderCreates a new configuration finder with default search paths.
Returns:
*ConfigFinder: New finder instance with platform-specific default paths
Example:
finder := finder.NewConfigFinder()
configPath, err := finder.FindConfigFile()
if err != nil {
log.Printf("No configuration file found: %v", err)
} else {
fmt.Printf("Found configuration: %s\n", configPath)
}NewConfigFinderWithPaths
func NewConfigFinderWithPaths(searchPaths []string) *ConfigFinderCreates a new configuration finder with custom search paths.
Parameters:
searchPaths([]string): Custom list of paths to search
Returns:
*ConfigFinder: New finder instance with specified paths
Example:
customPaths := []string{
"/custom/path/NuGet.Config",
"/another/path/NuGet.Config",
}
finder := finder.NewConfigFinderWithPaths(customPaths)Discovery Methods
FindConfigFile
func (f *ConfigFinder) FindConfigFile() (string, error)Finds the first available NuGet configuration file.
Returns:
string: Path to the found configuration fileerror: Error if no configuration file is found
Search Order:
- Current directory (
./NuGet.Config) - Parent directories (walking up the tree)
- User-specific configuration directory
- System-wide configuration directory
Platform-specific paths:
- Windows:
%APPDATA%\NuGet\NuGet.Config,%ProgramData%\NuGet\NuGet.Config - macOS:
~/Library/Application Support/NuGet/NuGet.Config,/Library/Application Support/NuGet/NuGet.Config - Linux:
~/.config/NuGet/NuGet.Config,/etc/NuGet/NuGet.Config
Example:
finder := finder.NewConfigFinder()
configPath, err := finder.FindConfigFile()
if err != nil {
if errors.IsNotFoundError(err) {
fmt.Println("No NuGet configuration file found")
// Create default configuration
} else {
log.Fatalf("Error searching for config: %v", err)
}
} else {
fmt.Printf("Using configuration file: %s\n", configPath)
}FindAllConfigFiles
func (f *ConfigFinder) FindAllConfigFiles() []stringFinds all available NuGet configuration files in the search paths.
Returns:
[]string: List of paths to all found configuration files
Example:
finder := finder.NewConfigFinder()
configFiles := finder.FindAllConfigFiles()
fmt.Printf("Found %d configuration files:\n", len(configFiles))
for i, path := range configFiles {
fmt.Printf("%d. %s\n", i+1, path)
}
// Use the first one or merge multiple configurations
if len(configFiles) > 0 {
primaryConfig := configFiles[0]
fmt.Printf("Using primary config: %s\n", primaryConfig)
}FindProjectConfig
func (f *ConfigFinder) FindProjectConfig(startDir string) (string, error)Finds a project-level configuration file starting from the specified directory.
Parameters:
startDir(string): Starting directory for the search
Returns:
string: Path to the found project configuration fileerror: Error if no project configuration file is found
Search Strategy:
- Starts from
startDir - Looks for
NuGet.Configin current directory - Walks up parent directories until found or reaches root
- Stops at the first configuration file found
Example:
finder := finder.NewConfigFinder()
// Find project config starting from current directory
projectConfig, err := finder.FindProjectConfig(".")
if err != nil {
fmt.Println("No project-specific configuration found")
} else {
fmt.Printf("Project config: %s\n", projectConfig)
}
// Find config for a specific project
projectPath := "/path/to/my/project"
projectConfig, err = finder.FindProjectConfig(projectPath)
if err != nil {
fmt.Printf("No config found for project at %s\n", projectPath)
} else {
fmt.Printf("Project config: %s\n", projectConfig)
}FindGlobalConfig
func (f *ConfigFinder) FindGlobalConfig() (string, error)Finds the global (user-level) configuration file.
Returns:
string: Path to the global configuration fileerror: Error if no global configuration file is found
Example:
finder := finder.NewConfigFinder()
globalConfig, err := finder.FindGlobalConfig()
if err != nil {
fmt.Println("No global configuration found")
} else {
fmt.Printf("Global config: %s\n", globalConfig)
}FindSystemConfig
func (f *ConfigFinder) FindSystemConfig() (string, error)Finds the system-wide configuration file.
Returns:
string: Path to the system configuration fileerror: Error if no system configuration file is found
Example:
finder := finder.NewConfigFinder()
systemConfig, err := finder.FindSystemConfig()
if err != nil {
fmt.Println("No system configuration found")
} else {
fmt.Printf("System config: %s\n", systemConfig)
}Path Management
GetDefaultSearchPaths
func (f *ConfigFinder) GetDefaultSearchPaths() []stringReturns the default search paths for the current platform.
Returns:
[]string: List of default search paths
Example:
finder := finder.NewConfigFinder()
paths := finder.GetDefaultSearchPaths()
fmt.Println("Default search paths:")
for i, path := range paths {
fmt.Printf("%d. %s\n", i+1, path)
}AddSearchPath
func (f *ConfigFinder) AddSearchPath(path string)Adds a custom search path to the finder.
Parameters:
path(string): Path to add to the search list
Example:
finder := finder.NewConfigFinder()
finder.AddSearchPath("/custom/config/location/NuGet.Config")
finder.AddSearchPath("/another/location/NuGet.Config")
// Now search will include custom paths
configPath, err := finder.FindConfigFile()SetSearchPaths
func (f *ConfigFinder) SetSearchPaths(paths []string)Sets the complete list of search paths, replacing existing ones.
Parameters:
paths([]string): New list of search paths
Example:
finder := finder.NewConfigFinder()
customPaths := []string{
"./project.config",
"/etc/nuget/global.config",
"/usr/local/share/nuget/system.config",
}
finder.SetSearchPaths(customPaths)Utility Methods
ConfigExists
func (f *ConfigFinder) ConfigExists(path string) boolChecks if a configuration file exists at the specified path.
Parameters:
path(string): Path to check
Returns:
bool: True if the configuration file exists and is readable
Example:
finder := finder.NewConfigFinder()
configPath := "/path/to/NuGet.Config"
if finder.ConfigExists(configPath) {
fmt.Printf("Configuration exists: %s\n", configPath)
} else {
fmt.Printf("Configuration not found: %s\n", configPath)
}ValidateConfigFile
func (f *ConfigFinder) ValidateConfigFile(path string) errorValidates that a file is a valid NuGet configuration file.
Parameters:
path(string): Path to the configuration file
Returns:
error: Error if the file is not valid
Example:
finder := finder.NewConfigFinder()
configPath := "/path/to/NuGet.Config"
err := finder.ValidateConfigFile(configPath)
if err != nil {
fmt.Printf("Invalid configuration file: %v\n", err)
} else {
fmt.Println("Configuration file is valid")
}Advanced Usage
Custom Search Strategy
// Create a finder with custom search strategy
func createCustomFinder() *finder.ConfigFinder {
finder := finder.NewConfigFinder()
// Add project-specific paths
finder.AddSearchPath("./config/NuGet.Config")
finder.AddSearchPath("./settings/NuGet.Config")
// Add environment-specific paths
if env := os.Getenv("NUGET_CONFIG_PATH"); env != "" {
finder.AddSearchPath(env)
}
return finder
}Hierarchical Configuration Discovery
// Find all configurations in hierarchy
func findConfigHierarchy(projectPath string) ([]string, error) {
finder := finder.NewConfigFinder()
var configs []string
// Project-level config
if projectConfig, err := finder.FindProjectConfig(projectPath); err == nil {
configs = append(configs, projectConfig)
}
// Global config
if globalConfig, err := finder.FindGlobalConfig(); err == nil {
configs = append(configs, globalConfig)
}
// System config
if systemConfig, err := finder.FindSystemConfig(); err == nil {
configs = append(configs, systemConfig)
}
return configs, nil
}Error Handling
The finder uses standard error types from the pkg/errors package:
import "github.com/scagogogo/nuget-config-parser/pkg/errors"
finder := finder.NewConfigFinder()
configPath, err := finder.FindConfigFile()
if err != nil {
if errors.IsNotFoundError(err) {
// No configuration file found
fmt.Println("Creating default configuration...")
// Handle missing configuration
} else {
// Other error occurred
log.Fatalf("Search error: %v", err)
}
}Platform Differences
Windows
- User config:
%APPDATA%\NuGet\NuGet.Config - System config:
%ProgramData%\NuGet\NuGet.Config
macOS
- User config:
~/Library/Application Support/NuGet/NuGet.Config - System config:
/Library/Application Support/NuGet/NuGet.Config
Linux/Unix
- User config:
~/.config/NuGet/NuGet.Config(respectsXDG_CONFIG_HOME) - System config:
/etc/NuGet/NuGet.Config
Best Practices
- Use default finder: Start with
NewConfigFinder()for standard behavior - Handle missing files: Always check for
IsNotFoundErrorand provide fallbacks - Respect hierarchy: Use project configs over global configs when both exist
- Validate paths: Use
ConfigExists()before attempting to parse files - Custom paths: Use
AddSearchPath()for additional locations rather than replacing defaults - Environment variables: Consider environment-specific configuration paths
Thread Safety
The ConfigFinder is thread-safe for read operations but not for modifications. If you need to modify search paths concurrently, provide appropriate synchronization.