on master help sign in
Fix transaction composition order in History::changes_since (#4981)
bcdb475Michael Davis
helix-core/src/history.rs+1−1
@@ -131,7 +131,7 @@ impl History {
131 .map(|&n| self.revisions[n].inversion.clone());
131 .map(|&n| self.revisions[n].inversion.clone());
132 let down_txns = down.iter().map(|&n| self.revisions[n].transaction.clone());
132 let down_txns = down.iter().map(|&n| self.revisions[n].transaction.clone());
133
133
134− up_txns.chain(down_txns).reduce(|acc, tx| tx.compose(acc))
134+ down_txns.chain(up_txns).reduce(|acc, tx| tx.compose(acc))
135 }
135 }
136
136
137 /// Undo the last edit.
137 /// Undo the last edit.
helix-term/tests/test/splits.rs+25
@@ -161,5 +161,30 @@ async fn test_changes_in_splits_apply_to_all_views() -> anyhow::Result<()> {
161 ))
161 ))
162 .await?;
162 .await?;
163
163
164+ // See <https://github.com/helix-editor/helix/issues/4957>.
165+ // This sequence undoes part of the history and then adds new changes, creating a
166+ // new branch in the history tree. `View::sync_changes` applies transactions down
167+ // and up to the lowest common ancestor in the path between old and new revision
168+ // numbers. If we apply these up/down transactions in the wrong order, this case
169+ // panics.
170+ // The key sequence:
171+ // * 3[<space> Create three empty lines so we are at the end of the document.
172+ // * <C-w>v<C-s> Create a split and save that point at the end of the document
173+ // in the jumplist.
174+ // * <C-w>w Switch back to the first window.
175+ // * uu Undo twice (not three times which would bring us back to the
176+ // root of the tree).
177+ // * 3[<space> Create three empty lines. Now the end of the document is past
178+ // where it was on step 1.
179+ // * <C-w>q Close window 1, focusing window 2 and causing a sync. This step
180+ // panics if we don't apply in the right order.
181+ // * %d Clean up the buffer.
182+ test((
183+ "#[|]#",
184+ "3[<space><C-w>v<C-s><C-w>wuu3[<space><C-w>q%d",
185+ "#[|]#",
186+ ))
187+ .await?;
188+
164 Ok(())
189 Ok(())
165}
190}