Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/git/git_rebase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,28 @@ pub enum RebaseOutcome {
/// initial rebase in `weave::run_rebase`).
pub fn continue_rebase(workdir: &Path) -> Result<RebaseOutcome> {
use std::process::Command;
let status = Command::new("git")
use std::time::Instant;

use crate::trace as loom_trace;

let start = Instant::now();
let output = Command::new("git")
.current_dir(workdir)
.args(["rebase", "--continue"])
.env("GIT_EDITOR", "true")
.status()?;
if status.success() {
.output()?;

let duration_ms = start.elapsed().as_millis();
let stderr = String::from_utf8_lossy(&output.stderr);
loom_trace::log_command(
"git",
"rebase --continue",
duration_ms,
output.status.success(),
&stderr,
);

if output.status.success() {
Ok(RebaseOutcome::Completed)
} else {
Ok(RebaseOutcome::Conflicted)
Expand Down Expand Up @@ -104,3 +120,7 @@ pub fn continue_rebase_or_abort(workdir: &Path) -> Result<()> {
}
}
}

#[cfg(test)]
#[path = "git_rebase_test.rs"]
mod tests;
34 changes: 34 additions & 0 deletions src/git/git_rebase_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::core::test_helpers::TestRepo;
use crate::core::weave;
use crate::trace;

/// Regression (#159): `continue_rebase` must capture git's output and route it
/// to the trace, instead of running with inherited stdio and leaking git's
/// "Successfully rebased" / "Updated refs" messages to the terminal. Before the
/// fix it logged nothing at all, so asserting the trace records the step proves
/// the output is now captured (you can only log stderr you captured).
#[test]
fn continue_rebase_captures_output_to_trace() {
let test_repo = TestRepo::new();
let c1 = test_repo.commit("first", "a.txt");
test_repo.commit("second", "b.txt");
let workdir = test_repo.workdir();

// Pause a rebase at the first commit so there is something to continue.
weave::start_edit_rebase(&test_repo.repo, &workdir, c1).unwrap();

// The trace logger is thread-local and cargo reuses threads across tests;
// clear any logger a prior test leaked so our init reliably takes effect.
let _ = trace::finalize();
let git_dir = test_repo.repo.path().to_path_buf();
trace::init(&git_dir, "git loom fold");
let outcome = super::continue_rebase(&workdir).unwrap();
let log_path = trace::finalize().expect("trace should have recorded an entry");

assert!(matches!(outcome, super::RebaseOutcome::Completed));
let content = std::fs::read_to_string(&log_path).unwrap();
assert!(
content.contains("[git] rebase --continue"),
"trace should record the continue step, got:\n{content}"
);
}
Loading