<commit_before>package types

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/BurntSushi/toml"
	cfg "github.com/containers/storage/pkg/config"
	"github.com/containers/storage/pkg/idtools"
	"github.com/sirupsen/logrus"
)

// TOML-friendly explicit tables used for conversions.
type TomlConfig struct {
	Storage struct {
		Driver              string            `toml:"driver,omitempty"`
		RunRoot             string            `toml:"runroot,omitempty"`
		GraphRoot           string            `toml:"graphroot,omitempty"`
		RootlessStoragePath string            `toml:"rootless_storage_path,omitempty"`
		Options             cfg.OptionsConfig `toml:"options,omitempty"`
	} `toml:"storage"`
}

const (
	overlayDriver  = "overlay"
	overlay2       = "overlay2"
	storageConfEnv = "CONTAINERS_STORAGE_CONF"
)

var (
	defaultStoreOptionsOnce    sync.Once
	loadDefaultStoreOptionsErr error
)

func loadDefaultStoreOptions() {
	defaultStoreOptions.RunRoot = defaultRunRoot
	defaultStoreOptions.GraphRoot = defaultGraphRoot
	defaultStoreOptions.GraphDriverName = ""

	if path, ok := os.LookupEnv(storageConfEnv); ok {
		defaultOverrideConfigFile = path
		if err := ReloadConfigurationFileIfNeeded(path, &defaultStoreOptions); err != nil {
			loadDefaultStoreOptionsErr = err
			return
		}
	} else if path, ok := os.LookupEnv("XDG_CONFIG_HOME"); ok {
		defaultOverrideConfigFile = filepath.Join(path, "containers", "storage.conf")
		if err := ReloadConfigurationFileIfNeeded(defaultOverrideConfigFile, &defaultStoreOptions); err != nil {
			loadDefaultStoreOptionsErr = err
			return
		}
	} else if _, err := os.Stat(defaultOverrideConfigFile); err == nil {
		// The DefaultConfigFile(rootless) function returns the path
		// of the used storage.conf file, by returning defaultConfigFile
		// If override exists containers/storage uses it by default.
		defaultConfigFile = defaultOverrideConfigFile
		if err := ReloadConfigurationFileIfNeeded(defaultOverrideConfigFile, &defaultStoreOptions); err != nil {
			loadDefaultStoreOptionsErr = err
			return
		}
	} else {
		if !os.IsNotExist(err) {
			logrus.Warningf("Attempting to use %s, %v", defaultConfigFile, err)
		}
		if err := ReloadConfigurationFileIfNeeded(defaultConfigFile, &defaultStoreOptions); err != nil && !errors.Is(err, os.ErrNotExist) {
			loadDefaultStoreOptionsErr = err
			return
		}
	}
	// reload could set values to empty for run and graph root if config does not contains anything
	if defaultStoreOptions.RunRoot == "" {
		defaultStoreOptions.RunRoot = defaultRunRoot
	}
	if defaultStoreOptions.GraphRoot == "" {
		defaultStoreOptions.GraphRoot = defaultGraphRoot
	}
}

// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing.
// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function.
func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) {
	var (
		defaultRootlessRunRoot   string
		defaultRootlessGraphRoot string
		err                      error
	)
	defaultStoreOptionsOnce.Do(loadDefaultStoreOptions)
	if loadDefaultStoreOptionsErr != nil {
		return StoreOptions{}, loadDefaultStoreOptionsErr
	}
	storageOpts := defaultStoreOptions
	if rootless && rootlessUID != 0 {
		storageOpts, err = getRootlessStorageOpts(rootlessUID, storageOpts)
		if err != nil {
			return storageOpts, err
		}
	}
	_, err = os.Stat(storageConf)
	if err != nil && !os.IsNotExist(err) {
		return storageOpts, err
	}
	if err == nil && !defaultConfigFileSet {<commit_msg>Use system defaults if storage.conf does not exist in XDG_CONFIG_HOME<commit_after>package types

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/BurntSushi/toml"
	cfg "github.com/containers/storage/pkg/config"
	"github.com/containers/storage/pkg/idtools"
	"github.com/sirupsen/logrus"
)

// TOML-friendly explicit tables used for conversions.
type TomlConfig struct {
	Storage struct {
		Driver              string            `toml:"driver,omitempty"`
		RunRoot             string            `toml:"runroot,omitempty"`
		GraphRoot           string            `toml:"graphroot,omitempty"`
		RootlessStoragePath string            `toml:"rootless_storage_path,omitempty"`
		Options             cfg.OptionsConfig `toml:"options,omitempty"`
	} `toml:"storage"`
}

const (
	overlayDriver  = "overlay"
	overlay2       = "overlay2"
	storageConfEnv = "CONTAINERS_STORAGE_CONF"
)

var (
	defaultStoreOptionsOnce    sync.Once
	loadDefaultStoreOptionsErr error
)

func loadDefaultStoreOptions() {
	defaultStoreOptions.GraphDriverName = ""

	setDefaults := func() {
		// reload could set values to empty for run and graph root if config does not contains anything
		if defaultStoreOptions.RunRoot == "" {
			defaultStoreOptions.RunRoot = defaultRunRoot
		}
		if defaultStoreOptions.GraphRoot == "" {
			defaultStoreOptions.GraphRoot = defaultGraphRoot
		}
	}
	setDefaults()

	if path, ok := os.LookupEnv(storageConfEnv); ok {
		defaultOverrideConfigFile = path
		if err := ReloadConfigurationFileIfNeeded(path, &defaultStoreOptions); err != nil {
			loadDefaultStoreOptionsErr = err
			return
		}
		setDefaults()
		return
	}

	if path, ok := os.LookupEnv("XDG_CONFIG_HOME"); ok {
		homeConfigFile := filepath.Join(path, "containers", "storage.conf")
		if _, err := os.Stat(homeConfigFile); err == nil {
			// user storage.conf in XDG_CONFIG_HOME if it exists
			defaultOverrideConfigFile = homeConfigFile
		} else {
			if !os.IsNotExist(err) {
				loadDefaultStoreOptionsErr = err
				return
			}
		}
	}

	_, err := os.Stat(defaultOverrideConfigFile)
	if err == nil {
		// The DefaultConfigFile(rootless) function returns the path
		// of the used storage.conf file, by returning defaultConfigFile
		// If override exists containers/storage uses it by default.
		defaultConfigFile = defaultOverrideConfigFile
		if err := ReloadConfigurationFileIfNeeded(defaultOverrideConfigFile, &defaultStoreOptions); err != nil {
			loadDefaultStoreOptionsErr = err
			return
		}
		setDefaults()
		return
	}

	if !os.IsNotExist(err) {
		logrus.Warningf("Attempting to use %s, %v", defaultConfigFile, err)
	}
	if err := ReloadConfigurationFileIfNeeded(defaultConfigFile, &defaultStoreOptions); err != nil && !errors.Is(err, os.ErrNotExist) {
		loadDefaultStoreOptionsErr = err
		return
	}
	setDefaults()
}

// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing.
// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function.
func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) {
	var (
		defaultRootlessRunRoot   string
		defaultRootlessGraphRoot string
		err                      error
	)
	defaultStoreOptionsOnce.Do(loadDefaultStoreOptions)
	if loadDefaultStoreOptionsErr != nil {
		return StoreOptions{}, loadDefaultStoreOptionsErr
	}
	storageOpts := defaultStoreOptions
	if rootless && rootlessUID != 0 {
		storageOpts, err = getRootlessStorageOpts(rootlessUID, storageOpts)
		if err != nil {
			return storageOpts, err
		}
	}
	_, err = os.Stat(storageConf)
	if err != nil && !os.IsNotExist(err) {
		return storageOpts, err
	}
	if err == nil && !defaultConfigFileSet {
{'fraction_non_alphanumeric': 0.09305177111716621, 'fraction_numerical': 0.0008174386920980927, 'mean_word_length': 4.1335664335664335, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2799889', 'n_tokens_mistral': 2322, 'n_tokens_neox': 2181, 'n_words': 539}