aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/migrate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty/src/migrate.rs')
-rw-r--r--alacritty/src/migrate.rs274
1 files changed, 0 insertions, 274 deletions
diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs
deleted file mode 100644
index 39779ba2..00000000
--- a/alacritty/src/migrate.rs
+++ /dev/null
@@ -1,274 +0,0 @@
-//! Configuration file migration.
-
-use std::fs;
-use std::path::Path;
-
-use toml::map::Entry;
-use toml::{Table, Value};
-
-use crate::cli::MigrateOptions;
-use crate::config;
-
-/// Handle migration.
-pub fn migrate(options: MigrateOptions) {
- // Find configuration file path.
- let config_path = options
- .config_file
- .clone()
- .or_else(|| config::installed_config("toml"))
- .or_else(|| config::installed_config("yml"));
-
- // Abort if system has no installed configuration.
- let config_path = match config_path {
- Some(config_path) => config_path,
- None => {
- eprintln!("No configuration file found");
- std::process::exit(1);
- },
- };
-
- // If we're doing a wet run, perform a dry run first for safety.
- if !options.dry_run {
- #[allow(clippy::redundant_clone)]
- let mut options = options.clone();
- options.silent = true;
- options.dry_run = true;
- if let Err(err) = migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) {
- eprintln!("Configuration file migration failed:");
- eprintln!(" {config_path:?}: {err}");
- std::process::exit(1);
- }
- }
-
- // 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, path, recursion_limit)?;
- }
-
- // Migrate deprecated field names to their new location.
- if !options.skip_renames {
- migrate_renames(&mut config)?;
- }
-
- // Convert to TOML format.
- let toml = toml::to_string(&config).map_err(|err| format!("conversion error: {err}"))?;
- let new_path = format!("{prefix}.toml");
-
- if options.dry_run && !options.silent {
- // Output new content to STDOUT.
- println!(
- "\nv-----Start TOML for {path:?}-----v\n\n{toml}\n^-----End TOML for {path:?}-----^\n"
- );
- } else if !options.dry_run {
- // Write the new toml configuration.
- fs::write(&new_path, toml).map_err(|err| format!("filesystem error: {err}"))?;
- }
-
- Ok(new_path)
-}
-
-/// Migrate the imports of a config.
-fn migrate_imports(
- options: &MigrateOptions,
- config: &mut Value,
- base_path: &Path,
- recursion_limit: usize,
-) -> Result<(), String> {
- let imports = match config::imports(config, base_path, recursion_limit) {
- Ok(imports) => imports,
- Err(err) => return Err(format!("import error: {err}")),
- };
-
- // Migrate the individual imports.
- let mut new_imports = Vec::new();
- for import in imports {
- let import = match import {
- Ok(import) => import,
- Err(err) => return Err(format!("import error: {err}")),
- };
-
- // Keep yaml import if path does not exist.
- if !import.exists() {
- if options.dry_run {
- eprintln!("Keeping yaml config for nonexistent import: {import:?}");
- }
- new_imports.push(Value::String(import.to_string_lossy().into()));
- continue;
- }
-
- let new_path = migrate_config(options, &import, recursion_limit - 1)?;
-
- // Print new import path.
- if options.dry_run {
- println!("Successfully migrated import {import:?} to {new_path:?}");
- }
-
- new_imports.push(Value::String(new_path));
- }
-
- // Update the imports field.
- if let Some(import) = config.get_mut("import") {
- *import = Value::Array(new_imports);
- }
-
- Ok(())
-}
-
-/// Migrate deprecated fields.
-fn migrate_renames(config: &mut Value) -> Result<(), String> {
- let config_table = match config.as_table_mut() {
- Some(config_table) => config_table,
- None => return Ok(()),
- };
-
- // draw_bold_text_with_bright_colors -> colors.draw_bold_text_with_bright_colors
- move_value(config_table, &["draw_bold_text_with_bright_colors"], &[
- "colors",
- "draw_bold_text_with_bright_colors",
- ])?;
-
- // key_bindings -> keyboard.bindings
- move_value(config_table, &["key_bindings"], &["keyboard", "bindings"])?;
-
- // mouse_bindings -> mouse.bindings
- move_value(config_table, &["mouse_bindings"], &["mouse", "bindings"])?;
-
- // Avoid warnings due to introduction of the new `general` section.
- move_value(config_table, &["live_config_reload"], &["general", "live_config_reload"])?;
- move_value(config_table, &["working_directory"], &["general", "working_directory"])?;
- move_value(config_table, &["ipc_socket"], &["general", "ipc_socket"])?;
- move_value(config_table, &["import"], &["general", "import"])?;
- move_value(config_table, &["shell"], &["terminal", "shell"])?;
-
- Ok(())
-}
-
-/// Move a toml value from one map to another.
-fn move_value(config_table: &mut Table, origin: &[&str], target: &[&str]) -> Result<(), String> {
- if let Some(value) = remove_node(config_table, origin)? {
- if !insert_node_if_empty(config_table, target, value)? {
- return Err(format!(
- "conflict: both `{}` and `{}` are set",
- origin.join("."),
- target.join(".")
- ));
- }
- }
-
- Ok(())
-}
-
-/// Remove a node from a tree of tables.
-fn remove_node(table: &mut Table, path: &[&str]) -> Result<Option<Value>, String> {
- if path.len() == 1 {
- Ok(table.remove(path[0]))
- } else {
- let next_table_value = match table.get_mut(path[0]) {
- Some(next_table_value) => next_table_value,
- None => return Ok(None),
- };
-
- let next_table = match next_table_value.as_table_mut() {
- Some(next_table) => next_table,
- None => return Err(format!("invalid `{}` table", path[0])),
- };
-
- remove_node(next_table, &path[1..])
- }
-}
-
-/// Try to insert a node into a tree of tables.
-///
-/// Returns `false` if the node already exists.
-fn insert_node_if_empty(table: &mut Table, path: &[&str], node: Value) -> Result<bool, String> {
- if path.len() == 1 {
- match table.entry(path[0]) {
- Entry::Vacant(vacant_entry) => {
- vacant_entry.insert(node);
- Ok(true)
- },
- Entry::Occupied(_) => Ok(false),
- }
- } else {
- let next_table_value = table.entry(path[0]).or_insert_with(|| Value::Table(Table::new()));
-
- let next_table = match next_table_value.as_table_mut() {
- Some(next_table) => next_table,
- None => return Err(format!("invalid `{}` table", path[0])),
- };
-
- insert_node_if_empty(next_table, &path[1..], node)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn move_values() {
- let input = r#"
-root_value = 3
-
-[table]
-table_value = 5
-
-[preexisting]
-not_moved = 9
- "#;
-
- let mut value: Value = toml::from_str(input).unwrap();
- let table = value.as_table_mut().unwrap();
-
- move_value(table, &["root_value"], &["new_table", "root_value"]).unwrap();
- move_value(table, &["table", "table_value"], &["preexisting", "subtable", "new_name"])
- .unwrap();
-
- let output = toml::to_string(table).unwrap();
-
- assert_eq!(
- output,
- "[new_table]\nroot_value = 3\n\n[preexisting]\nnot_moved = \
- 9\n\n[preexisting.subtable]\nnew_name = 5\n\n[table]\n"
- );
- }
-}