merge_tools: introduce Diff/MergeEditor newtypes

I'm going to make them be loaded by caller, and these newtypes will provide
extra compile-time safety (plus nicer API to be added later.) The error types
will be cleaned up later patches.
This commit is contained in:
Yuya Nishihara 2024-02-29 18:33:44 +09:00
parent 529acb3d16
commit 863a26440e

View file

@ -115,7 +115,7 @@ pub fn run_mergetool(
}; };
let content = extract_as_single_hunk(&file_merge, tree.store(), repo_path).block_on(); let content = extract_as_single_hunk(&file_merge, tree.store(), repo_path).block_on();
let editor = get_merge_tool_from_settings(ui, settings)?; let editor = MergeEditor::from_settings(ui, settings)?.tool;
match editor { match editor {
MergeTool::Builtin => { MergeTool::Builtin => {
let tree_id = edit_merge_builtin(tree, repo_path, content).map_err(Box::new)?; let tree_id = edit_merge_builtin(tree, repo_path, content).map_err(Box::new)?;
@ -137,7 +137,7 @@ pub fn edit_diff(
settings: &UserSettings, settings: &UserSettings,
) -> Result<MergedTreeId, DiffEditError> { ) -> Result<MergedTreeId, DiffEditError> {
// Start a diff editor on the two directories. // Start a diff editor on the two directories.
let editor = get_diff_editor_from_settings(ui, settings)?; let editor = DiffEditor::from_settings(ui, settings)?.tool;
match editor { match editor {
MergeTool::Builtin => { MergeTool::Builtin => {
let tree_id = edit_diff_builtin(left_tree, right_tree, matcher).map_err(Box::new)?; let tree_id = edit_diff_builtin(left_tree, right_tree, matcher).map_err(Box::new)?;
@ -215,38 +215,51 @@ pub fn get_external_tool_config(
} }
} }
fn get_diff_editor_from_settings( /// Configured diff editor.
ui: &Ui, #[derive(Clone, Debug)]
settings: &UserSettings, pub struct DiffEditor {
) -> Result<MergeTool, ExternalToolError> { tool: MergeTool,
}
impl DiffEditor {
/// Loads the default diff editor from the settings.
// TODO: extract tool configuration error from DiffEditError
pub fn from_settings(ui: &Ui, settings: &UserSettings) -> Result<Self, DiffEditError> {
let args = editor_args_from_settings(ui, settings, "ui.diff-editor")?; let args = editor_args_from_settings(ui, settings, "ui.diff-editor")?;
let editor = if let CommandNameAndArgs::String(name) = &args { let tool = if let CommandNameAndArgs::String(name) = &args {
get_tool_config(settings, name)? get_tool_config(settings, name).map_err(ExternalToolError::Config)?
} else { } else {
None None
} }
.unwrap_or_else(|| MergeTool::External(ExternalMergeTool::with_edit_args(&args))); .unwrap_or_else(|| MergeTool::External(ExternalMergeTool::with_edit_args(&args)));
Ok(editor) Ok(DiffEditor { tool })
}
} }
fn get_merge_tool_from_settings( /// Configured 3-way merge editor.
ui: &Ui, #[derive(Clone, Debug)]
settings: &UserSettings, pub struct MergeEditor {
) -> Result<MergeTool, ExternalToolError> { tool: MergeTool,
}
impl MergeEditor {
/// Loads the default 3-way merge editor from the settings.
// TODO: extract tool configuration error from ConflictResolveError
pub fn from_settings(ui: &Ui, settings: &UserSettings) -> Result<Self, ConflictResolveError> {
let args = editor_args_from_settings(ui, settings, "ui.merge-editor")?; let args = editor_args_from_settings(ui, settings, "ui.merge-editor")?;
let mergetool = if let CommandNameAndArgs::String(name) = &args { let tool = if let CommandNameAndArgs::String(name) = &args {
get_tool_config(settings, name)? get_tool_config(settings, name).map_err(ExternalToolError::Config)?
} else { } else {
None None
} }
.unwrap_or_else(|| MergeTool::External(ExternalMergeTool::with_merge_args(&args))); .unwrap_or_else(|| MergeTool::External(ExternalMergeTool::with_merge_args(&args)));
match mergetool { if matches!(&tool, MergeTool::External(mergetool) if mergetool.merge_args.is_empty()) {
MergeTool::External(mergetool) if mergetool.merge_args.is_empty() => { return Err(ExternalToolError::MergeArgsNotConfigured {
Err(ExternalToolError::MergeArgsNotConfigured {
tool_name: args.to_string(), tool_name: args.to_string(),
})
} }
mergetool => Ok(mergetool), .into());
}
Ok(MergeEditor { tool })
} }
} }
@ -269,7 +282,7 @@ mod tests {
let config = config_from_string(text); let config = config_from_string(text);
let ui = Ui::with_config(&config).unwrap(); let ui = Ui::with_config(&config).unwrap();
let settings = UserSettings::from_config(config); let settings = UserSettings::from_config(config);
get_diff_editor_from_settings(&ui, &settings) DiffEditor::from_settings(&ui, &settings).map(|editor| editor.tool)
}; };
// Default // Default
@ -418,7 +431,7 @@ mod tests {
let config = config_from_string(text); let config = config_from_string(text);
let ui = Ui::with_config(&config).unwrap(); let ui = Ui::with_config(&config).unwrap();
let settings = UserSettings::from_config(config); let settings = UserSettings::from_config(config);
get_merge_tool_from_settings(&ui, &settings) MergeEditor::from_settings(&ui, &settings).map(|editor| editor.tool)
}; };
// Default // Default
@ -426,9 +439,11 @@ mod tests {
// Just program name // Just program name
insta::assert_debug_snapshot!(get(r#"ui.merge-editor = "my-merge""#).unwrap_err(), @r###" insta::assert_debug_snapshot!(get(r#"ui.merge-editor = "my-merge""#).unwrap_err(), @r###"
ExternalTool(
MergeArgsNotConfigured { MergeArgsNotConfigured {
tool_name: "my-merge", tool_name: "my-merge",
} },
)
"###); "###);
// String args // String args
@ -516,9 +531,11 @@ mod tests {
// List args should never be a merge-tools key // List args should never be a merge-tools key
insta::assert_debug_snapshot!( insta::assert_debug_snapshot!(
get(r#"ui.merge-editor = ["meld"]"#).unwrap_err(), @r###" get(r#"ui.merge-editor = ["meld"]"#).unwrap_err(), @r###"
ExternalTool(
MergeArgsNotConfigured { MergeArgsNotConfigured {
tool_name: "meld", tool_name: "meld",
} },
)
"###); "###);
// Invalid type // Invalid type