From 148e076a71908602768a7ceeb7210c60fa342d23 Mon Sep 17 00:00:00 2001 From: Noah Pederson Date: Sun, 31 May 2026 21:05:06 -0500 Subject: [PATCH] Support editor commands in merge conflicts tsk-99 --- src/merge.rs | 33 +++++++++++++++++++++++++++++++-- tests/multi_user.rs | 6 +++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index 71ccca6..ef59dfb 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -29,7 +29,9 @@ use crate::queue::{self, QUEUE_REF_PREFIX, Queue}; use crate::references; use git2::{Commit, IndexEntry, Oid, Repository, Tree}; use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::process::Command; +use std::ffi::OsStr; +use std::path::Path; +use std::process::{Command, ExitStatus}; #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub enum Strategy { @@ -235,7 +237,7 @@ fn edit_conflict_content(initial: String) -> Result> { })?; let path = conflict_temp_path()?; std::fs::write(&path, initial)?; - let status = Command::new(editor).arg(&path).status()?; + let status = run_editor_command(&editor, &path)?; if !status.success() { return Err(crate::errors::Error::Parse( "editor exited unsuccessfully while resolving task body conflict".into(), @@ -250,6 +252,33 @@ fn edit_conflict_content(initial: String) -> Result> { } } +fn run_editor_command(editor: &OsStr, path: &Path) -> Result { + let command = editor.to_string_lossy(); + if command.trim().is_empty() { + return Err(crate::errors::Error::Parse( + "task body conflict requires VISUAL or EDITOR to resolve".into(), + )); + } + + #[cfg(windows)] + { + Ok(Command::new("cmd") + .arg("/C") + .arg(format!("{command} \"{}\"", path.display())) + .status()?) + } + + #[cfg(not(windows))] + { + Ok(Command::new("sh") + .arg("-c") + .arg(format!("{command} \"$1\"")) + .arg("tsk-editor") + .arg(path) + .status()?) + } +} + fn conflict_temp_path() -> Result { let mut path = std::env::temp_dir(); let nanos = std::time::SystemTime::now() diff --git a/tests/multi_user.rs b/tests/multi_user.rs index 3b67e3d..3670b4b 100644 --- a/tests/multi_user.rs +++ b/tests/multi_user.rs @@ -1201,7 +1201,7 @@ fn body_conflict_on_pull_opens_editor_and_commits_result() { let editor = editor_dir.path().join("resolve-conflict"); std::fs::write( &editor, - "#!/bin/sh\nprintf 'resolved title\\n\\nresolved body\\n' > \"$1\"\n", + "#!/bin/sh\nfor arg do path=$arg; done\nprintf 'resolved title\\n\\nresolved body\\n' > \"$path\"\n", ) .unwrap(); let mut perms = std::fs::metadata(&editor).unwrap().permissions(); @@ -1210,8 +1210,8 @@ fn body_conflict_on_pull_opens_editor_and_commits_result() { let mut cmd = Command::new(tsk_bin()); cmd.current_dir(&bob) - .env("EDITOR", &editor) - .env("VISUAL", &editor) + .env("EDITOR", "false") + .env("VISUAL", format!("{} --wait", editor.display())) .arg("git-pull"); let (code, stdout, stderr) = run(&mut cmd); assert_eq!( -- knotmirror 0.0.1