From 02bb3aecf37203886251233b843c70ddee628df6 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Mon, 12 Jun 2023 13:31:44 -0700 Subject: [PATCH] tree: don't read file contents on contents/executable "conflict" If one side changes the contents and one side changes the executable bit, we get a non-trivial conflict in the `TreeValue`s, but once we've split them up into `FileId`s and bools, we can trivially resolve them separately, without having to read file contents. --- lib/src/tree.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/src/tree.rs b/lib/src/tree.rs index 5de239178..0329fd4ee 100644 --- a/lib/src/tree.rs +++ b/lib/src/tree.rs @@ -680,11 +680,19 @@ fn try_resolve_file_conflict( } let executable = if let Some(executable) = trivial_merge(&executable_removes, &executable_adds) { - executable + *executable } else { // We're unable to determine whether the result should be executable return Ok(None); }; + if let Some(resolved_file_id) = trivial_merge(&removed_file_ids, &added_file_ids) { + // Don't bother reading the file contents if the conflict can be trivially + // resolved. + return Ok(Some(TreeValue::File { + id: resolved_file_id.clone(), + executable, + })); + } let mut removed_contents = vec![]; let mut added_contents = vec![]; for file_id in removed_file_ids { @@ -716,10 +724,7 @@ fn try_resolve_file_conflict( match merge_result { MergeResult::Resolved(merged_content) => { let id = store.write_file(filename, &mut merged_content.as_slice())?; - Ok(Some(TreeValue::File { - id, - executable: *executable, - })) + Ok(Some(TreeValue::File { id, executable })) } MergeResult::Conflict(_) => Ok(None), }