Repository: jesseduffield/lazygit
File: pkg/config/app_config.go (Go)

Code before:
			if err != nil {
				if os.IsPermission(err) {
					// apparently when people have read-only permissions they prefer us to fail silently
					continue
				}
				return nil, err
			}
			file.Close()
		}

		content, err := os.ReadFile(path)
		if err != nil {
			return nil, err
		}

		content, err = migrateUserConfig(path, content)
		if err != nil {
			return nil, err
		}

		if err := yaml.Unmarshal(content, base); err != nil {
			return nil, fmt.Errorf("The config at `%s` couldn't be parsed, please inspect it before opening up an issue.\n%w", path, err)
		}

		if err := base.Validate(); err != nil {
			return nil, fmt.Errorf("The config at `%s` has validation error.\n%w", path, err)
		}
	}

	return base, nil
}

// Do any backward-compatibility migrations of things that have changed in the
// config over time; examples are renaming a key to a better name, moving a key
// from one container to another, or changing the type of a key (e.g. from bool
// to an enum).
func migrateUserConfig(path string, content []byte) ([]byte, error) {
	changedContent, err := yaml_utils.RenameYamlKey(content, []string{"gui", "skipUnstageLineWarning"},
		"skipDiscardChangeWarning")
	if err != nil {
		return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
	}

	// Add more migrations here...

	// Write config back if changed
	if string(changedContent) != string(content) {
		if err := os.WriteFile(path, changedContent, 0o644); err != nil {
			return nil, fmt.Errorf("Couldn't write migrated config back to `%s`: %s", path, err)
		}
		return changedContent, nil

Review comment (suggestion):
```suggestion
			return nil, fmt.Errorf("The config at `%s` has a validation error.\n%w", path, err)
```

Code after:
				if os.IsPermission(err) {
					// apparently when people have read-only permissions they prefer us to fail silently
					continue
				}
				return nil, err
			}
			file.Close()
		}

		content, err := os.ReadFile(path)
		if err != nil {
			return nil, err
		}

		content, err = migrateUserConfig(path, content)
		if err != nil {
			return nil, err
		}

		if err := yaml.Unmarshal(content, base); err != nil {
			return nil, fmt.Errorf("The config at `%s` couldn't be parsed, please inspect it before opening up an issue.\n%w", path, err)
		}

		if err := base.Validate(); err != nil {
			return nil, fmt.Errorf("The config at `%s` has a validation error.\n%w", path, err)
		}
	}

	return base, nil
}

// Do any backward-compatibility migrations of things that have changed in the
// config over time; examples are renaming a key to a better name, moving a key
// from one container to another, or changing the type of a key (e.g. from bool
// to an enum).
func migrateUserConfig(path string, content []byte) ([]byte, error) {
	changedContent, err := yaml_utils.RenameYamlKey(content, []string{"gui", "skipUnstageLineWarning"},
		"skipDiscardChangeWarning")
	if err != nil {
		return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
	}

	changedContent, err = changeNullKeybindingsToDisabled(changedContent)
	if err != nil {
		return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
	}

	// Add more migrations here...

	// Write config back if changed
	if string(changedContent) != string(content) {