merge_tools: extract external merge tool functions

This commit is contained in:
Waleed Khan 2023-08-13 13:15:42 -07:00
parent 4bb40bbf10
commit b837e88757

View file

@ -21,7 +21,7 @@ use std::sync::Arc;
use config::ConfigError;
use itertools::Itertools;
use jj_lib::backend::{TreeId, TreeValue};
use jj_lib::backend::{FileId, TreeId, TreeValue};
use jj_lib::conflicts;
use jj_lib::conflicts::{extract_as_single_hunk, materialize_merge_result};
use jj_lib::gitignore::GitIgnoreFile;
@ -261,6 +261,22 @@ pub fn run_mergetool(
let content = extract_as_single_hunk(&file_merge, tree.store(), repo_path);
let editor = get_merge_tool_from_settings(ui, settings)?;
match editor {
MergeTool::Internal => unimplemented!("run_mergetool with internal mergetool"),
MergeTool::External(editor) => {
run_mergetool_external(&editor, file_merge, content, repo_path, conflict, tree)
}
}
}
fn run_mergetool_external(
editor: &ExternalMergeTool,
file_merge: Merge<Option<FileId>>,
content: jj_lib::merge::Merge<jj_lib::files::ContentHunk>,
repo_path: &RepoPath,
conflict: jj_lib::merge::Merge<Option<TreeValue>>,
tree: &Tree,
) -> Result<TreeId, ConflictResolveError> {
let initial_output_content: Vec<u8> = if editor.merge_tool_edits_conflict_markers {
let mut materialized_conflict = vec![];
materialize_merge_result(&content, &mut materialized_conflict)
@ -381,6 +397,29 @@ pub fn edit_diff(
instructions: &str,
base_ignores: Arc<GitIgnoreFile>,
settings: &UserSettings,
) -> Result<TreeId, DiffEditError> {
// Start a diff editor on the two directories.
let editor = get_diff_editor_from_settings(ui, settings)?;
match editor {
MergeTool::Internal => unimplemented!("run_mergetool with internal mergetool"),
MergeTool::External(editor) => edit_diff_external(
editor,
left_tree,
right_tree,
instructions,
base_ignores,
settings,
),
}
}
fn edit_diff_external(
editor: ExternalMergeTool,
left_tree: &Tree,
right_tree: &Tree,
instructions: &str,
base_ignores: Arc<GitIgnoreFile>,
settings: &UserSettings,
) -> Result<TreeId, DiffEditError> {
let store = left_tree.store();
let diff_wc = check_out_trees(store, left_tree, right_tree, &EverythingMatcher)?;
@ -399,8 +438,6 @@ pub fn edit_diff(
.map_err(ExternalToolError::SetUpDir)?;
}
// Start a diff editor on the two directories.
let editor = get_diff_editor_from_settings(ui, settings)?;
let patterns = diff_wc.to_command_variables();
let mut cmd = Command::new(&editor.program);
cmd.args(interpolate_variables(&editor.edit_args, &patterns));
@ -472,6 +509,7 @@ pub fn generate_diff(
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum MergeTool {
Internal,
External(ExternalMergeTool),
}
@ -590,17 +628,17 @@ pub fn get_tool_config_from_args(
fn get_diff_editor_from_settings(
ui: &Ui,
settings: &UserSettings,
) -> Result<ExternalMergeTool, ExternalToolError> {
) -> Result<MergeTool, ExternalToolError> {
let args = editor_args_from_settings(ui, settings, "ui.diff-editor")?;
let editor = get_tool_config_from_args(settings, &args)?
.unwrap_or_else(|| ExternalMergeTool::with_edit_args(&args));
Ok(editor)
Ok(MergeTool::External(editor))
}
fn get_merge_tool_from_settings(
ui: &Ui,
settings: &UserSettings,
) -> Result<ExternalMergeTool, ExternalToolError> {
) -> Result<MergeTool, ExternalToolError> {
let args = editor_args_from_settings(ui, settings, "ui.merge-editor")?;
let editor = get_tool_config_from_args(settings, &args)?
.unwrap_or_else(|| ExternalMergeTool::with_merge_args(&args));
@ -609,7 +647,7 @@ fn get_merge_tool_from_settings(
tool_name: args.to_string(),
})
} else {
Ok(editor)
Ok(MergeTool::External(editor))
}
}
@ -669,6 +707,7 @@ mod tests {
// Default
insta::assert_debug_snapshot!(get("").unwrap(), @r###"
External(
ExternalMergeTool {
program: "meld",
diff_args: [
@ -688,11 +727,13 @@ mod tests {
"--auto-merge",
],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Just program name, edit_args are filled by default
insta::assert_debug_snapshot!(get(r#"ui.diff-editor = "my-diff""#).unwrap(), @r###"
External(
ExternalMergeTool {
program: "my-diff",
diff_args: [
@ -705,12 +746,14 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// String args (with interpolation variables)
insta::assert_debug_snapshot!(
get(r#"ui.diff-editor = "my-diff -l $left -r $right""#).unwrap(), @r###"
External(
ExternalMergeTool {
program: "my-diff",
diff_args: [
@ -725,12 +768,14 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// List args (with interpolation variables)
insta::assert_debug_snapshot!(
get(r#"ui.diff-editor = ["my-diff", "--diff", "$left", "$right"]"#).unwrap(), @r###"
External(
ExternalMergeTool {
program: "my-diff",
diff_args: [
@ -744,7 +789,8 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Pick from merge-tools
@ -755,6 +801,7 @@ mod tests {
edit-args = ["--edit", "args", "$left", "$right"]
"#,
).unwrap(), @r###"
External(
ExternalMergeTool {
program: "foo bar",
diff_args: [
@ -769,7 +816,8 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Pick from merge-tools, but no edit-args specified
@ -780,6 +828,7 @@ mod tests {
program = "MyDiff"
"#,
).unwrap(), @r###"
External(
ExternalMergeTool {
program: "MyDiff",
diff_args: [
@ -792,11 +841,13 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// List args should never be a merge-tools key, edit_args are filled by default
insta::assert_debug_snapshot!(get(r#"ui.diff-editor = ["meld"]"#).unwrap(), @r###"
External(
ExternalMergeTool {
program: "meld",
diff_args: [
@ -809,7 +860,8 @@ mod tests {
],
merge_args: [],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Invalid type
@ -827,6 +879,7 @@ mod tests {
// Default
insta::assert_debug_snapshot!(get("").unwrap(), @r###"
External(
ExternalMergeTool {
program: "meld",
diff_args: [
@ -846,7 +899,8 @@ mod tests {
"--auto-merge",
],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Just program name
@ -859,6 +913,7 @@ mod tests {
// String args
insta::assert_debug_snapshot!(
get(r#"ui.merge-editor = "my-merge $left $base $right $output""#).unwrap(), @r###"
External(
ExternalMergeTool {
program: "my-merge",
diff_args: [
@ -876,7 +931,8 @@ mod tests {
"$output",
],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// List args
@ -884,6 +940,7 @@ mod tests {
get(
r#"ui.merge-editor = ["my-merge", "$left", "$base", "$right", "$output"]"#,
).unwrap(), @r###"
External(
ExternalMergeTool {
program: "my-merge",
diff_args: [
@ -901,7 +958,8 @@ mod tests {
"$output",
],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// Pick from merge-tools
@ -912,6 +970,7 @@ mod tests {
merge-args = ["$base", "$left", "$right", "$output"]
"#,
).unwrap(), @r###"
External(
ExternalMergeTool {
program: "foo bar",
diff_args: [
@ -929,7 +988,8 @@ mod tests {
"$output",
],
merge_tool_edits_conflict_markers: false,
}
},
)
"###);
// List args should never be a merge-tools key