Repository: alacritty/alacritty
File: alacritty/src/migrate.rs (Rust)

Code before:
            eprintln!("    {config_path:?}: {err}");
            std::process::exit(1);
        }
    }

    // Migrate the root config.
    match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT, true) {
        Ok(new_path) => {
            if !options.silent {
                println!("Successfully migrated {config_path:?} to {new_path:?}");
            }
        },
        Err(err) => {
            eprintln!("Configuration file migration failed:");
            eprintln!("    {config_path:?}: {err}");
            std::process::exit(1);
        },
    }
}

/// Migrate a specific configuration file.
fn migrate_config(
    options: &MigrateOptions,
    path: &Path,
    recursion_limit: usize,
    warn_pruned: bool,
) -> Result<String, String> {
    // Ensure configuration file has an extension.
    let path_str = path.to_string_lossy();
    let (prefix, suffix) = match path_str.rsplit_once('.') {
        Some((prefix, suffix)) => (prefix, suffix),
        None => return Err("missing file extension".to_string()),
    };

    // Abort if config is already toml.
    if suffix == "toml" {
        return Err("already in TOML format".to_string());
    }

    // Try to parse the configuration file.
    let mut config = match config::deserialize_config(path, warn_pruned) {
        Ok(config) => config,
        Err(err) => return Err(format!("parsing error: {err}")),
    };

    // Migrate config imports.
    if !options.skip_imports {
        migrate_imports(options, &mut config, recursion_limit, warn_pruned)?;
    }

    // Migrate deprecated field names to their new location.

Review comment (bug):
Rather than adding another option here, we should probably just use the `options.dry_run` option to ensure consistency with other code. That way we also make sure to **always** warn on the dry run, which ensures that even on failure everything is logged.

Code after:
        }
    }

    // Migrate the root config.
    match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) {
        Ok(new_path) => {
            if !options.silent {
                println!("Successfully migrated {config_path:?} to {new_path:?}");
            }
        },
        Err(err) => {
            eprintln!("Configuration file migration failed:");
            eprintln!("    {config_path:?}: {err}");
            std::process::exit(1);
        },
    }
}

/// Migrate a specific configuration file.
fn migrate_config(
    options: &MigrateOptions,
    path: &Path,
    recursion_limit: usize,
) -> Result<String, String> {
    // Ensure configuration file has an extension.
    let path_str = path.to_string_lossy();
    let (prefix, suffix) = match path_str.rsplit_once('.') {
        Some((prefix, suffix)) => (prefix, suffix),
        None => return Err("missing file extension".to_string()),
    };

    // Abort if config is already toml.
    if suffix == "toml" {
        return Err("already in TOML format".to_string());
    }

    // Try to parse the configuration file.
    let mut config = match config::deserialize_config(path, !options.dry_run) {
        Ok(config) => config,
        Err(err) => return Err(format!("parsing error: {err}")),
    };

    // Migrate config imports.
    if !options.skip_imports {
        migrate_imports(options, &mut config, recursion_limit)?;
    }

    // Migrate deprecated field names to their new location.
    if !options.skip_renames {
        migrate_renames(&mut config)?;
    }