Skip to content

Commit 7c75b50

Browse files
author
cshinaver
committed
(#1088) post-rewrite hook does not track intermediate commits from a rebase
1 parent 7520d22 commit 7c75b50

File tree

3 files changed

+92
-34
lines changed

3 files changed

+92
-34
lines changed

Diff for: git-branchless-lib/src/core/rewrite/rewrite_hooks.rs

+2-30
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
use std::collections::{HashMap, HashSet};
44

55
use std::fmt::Write;
6-
use std::fs::{self, File};
7-
use std::io::{self, stdin, BufRead, BufReader, Read, Write as WriteIo};
6+
use std::fs::File;
7+
use std::io::{stdin, BufRead, BufReader, Read, Write as WriteIo};
88
use std::path::{Path, PathBuf};
9-
use std::str::FromStr;
109
use std::time::SystemTime;
1110

1211
use console::style;
@@ -44,20 +43,6 @@ pub fn get_deferred_commits_path(repo: &Repo) -> PathBuf {
4443
repo.get_rebase_state_dir_path().join("deferred-commits")
4544
}
4645

47-
fn read_deferred_commits(repo: &Repo) -> eyre::Result<Vec<NonZeroOid>> {
48-
let deferred_commits_path = get_deferred_commits_path(repo);
49-
let contents = match fs::read_to_string(&deferred_commits_path) {
50-
Ok(contents) => contents,
51-
Err(err) if err.kind() == io::ErrorKind::NotFound => Default::default(),
52-
Err(err) => {
53-
return Err(err)
54-
.with_context(|| format!("Reading deferred commits at {deferred_commits_path:?}"))
55-
}
56-
};
57-
let commit_oids = contents.lines().map(NonZeroOid::from_str).try_collect()?;
58-
Ok(commit_oids)
59-
}
60-
6146
#[instrument(skip(stream))]
6247
fn read_rewritten_list_entries(
6348
stream: &mut impl Read,
@@ -148,19 +133,6 @@ pub fn hook_post_rewrite(
148133
let event_log_db = EventLogDb::new(&conn)?;
149134
let event_tx_id = event_log_db.make_transaction_id(now, "hook-post-rewrite")?;
150135

151-
{
152-
let deferred_commit_oids = read_deferred_commits(&repo)?;
153-
let commit_events = deferred_commit_oids
154-
.into_iter()
155-
.map(|commit_oid| Event::CommitEvent {
156-
timestamp,
157-
event_tx_id,
158-
commit_oid,
159-
})
160-
.collect_vec();
161-
event_log_db.add_events(commit_events)?;
162-
}
163-
164136
let (rewritten_oids, rewrite_events) = {
165137
let rewritten_oids = read_rewritten_list_entries(&mut stdin().lock())?;
166138
let events = rewritten_oids

Diff for: git-branchless-lib/src/testing.rs

+36-4
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,15 @@ then you can only run tests in the main `git-branchless` and \
498498
/// used to set the commit timestamp, which is factored into the commit
499499
/// hash. The filename is always appended to the message prefix.
500500
#[instrument]
501-
pub fn commit_file_with_contents_and_message(
501+
pub fn commit_file_with_contents_and_message_and_file_name(
502502
&self,
503503
name: &str,
504504
time: isize,
505505
contents: &str,
506506
message_prefix: &str,
507+
file_name: &str,
507508
) -> eyre::Result<NonZeroOid> {
508-
let message = format!("{message_prefix} {name}.txt");
509+
let message = format!("{message_prefix} {file_name}");
509510
self.write_file_txt(name, contents)?;
510511
self.run(&["add", "."])?;
511512
self.run_with_options(
@@ -524,6 +525,26 @@ then you can only run tests in the main `git-branchless` and \
524525
Ok(oid)
525526
}
526527

528+
/// Commit a file with given contents and message. The `time` argument is
529+
/// used to set the commit timestamp, which is factored into the commit
530+
/// hash. The filename is always appended to the message prefix.
531+
#[instrument]
532+
pub fn commit_file_with_contents_and_message(
533+
&self,
534+
name: &str,
535+
time: isize,
536+
contents: &str,
537+
message_prefix: &str,
538+
) -> eyre::Result<NonZeroOid> {
539+
self.commit_file_with_contents_and_message_and_file_name(
540+
name,
541+
time,
542+
contents,
543+
message_prefix,
544+
format!("{name}.txt").as_str(),
545+
)
546+
}
547+
527548
/// Commit a file with given contents and a default message. The `time`
528549
/// argument is used to set the commit timestamp, which is factored into the
529550
/// commit hash.
@@ -872,6 +893,18 @@ pub mod pty {
872893
branchless_subcommand: &str,
873894
args: &[&str],
874895
inputs: &[PtyAction],
896+
) -> eyre::Result<ExitStatus> {
897+
// add "branchless" to subcommand list
898+
run_in_pty_with_command(git, &["branchless", branchless_subcommand], args, inputs)
899+
}
900+
901+
/// Run the provided script in the context of a virtual terminal.
902+
#[track_caller]
903+
pub fn run_in_pty_with_command(
904+
git: &Git,
905+
command: &[&str],
906+
args: &[&str],
907+
inputs: &[PtyAction],
875908
) -> eyre::Result<ExitStatus> {
876909
// Use the native pty implementation for the system
877910
let pty_system = native_pty_system();
@@ -891,8 +924,7 @@ pub mod pty {
891924
cmd.env(k, v);
892925
}
893926
cmd.env("TERM", "xterm");
894-
cmd.arg("branchless");
895-
cmd.arg(branchless_subcommand);
927+
cmd.args(command);
896928
cmd.args(args);
897929
cmd.cwd(&git.repo_path);
898930

Diff for: git-branchless/tests/test_hooks.rs

+54
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ use lib::core::eventlog::{Event, EventLogDb, EventReplayer};
55
use lib::core::formatting::Glyphs;
66
use lib::git::GitVersion;
77
use lib::testing::make_git;
8+
use lib::testing::pty::{run_in_pty_with_command, PtyAction};
89
use lib::util::get_sh;
910
use std::process::Command;
1011

12+
const CARRIAGE_RETURN: &str = "\r";
13+
1114
#[test]
1215
fn test_abandoned_commit_message() -> eyre::Result<()> {
1316
let git = make_git()?;
@@ -385,3 +388,54 @@ fn test_git_am_recorded() -> eyre::Result<()> {
385388

386389
Ok(())
387390
}
391+
392+
#[cfg(unix)]
393+
#[test]
394+
fn test_git_rebase_multiple_fixup_does_not_strand_commits() -> eyre::Result<()> {
395+
let git = make_git()?;
396+
git.init_repo()?;
397+
398+
git.detach_head()?;
399+
git.commit_file_with_contents_and_message_and_file_name(
400+
"test1",
401+
1,
402+
"bleh",
403+
"create",
404+
"test1.txt",
405+
)?;
406+
git.commit_file_with_contents_and_message_and_file_name(
407+
"test2",
408+
2,
409+
"bleh",
410+
"fixup! create",
411+
"test1.txt",
412+
)?;
413+
git.commit_file_with_contents_and_message_and_file_name(
414+
"test3",
415+
3,
416+
"bleh",
417+
"fixup! create",
418+
"test1.txt",
419+
)?;
420+
421+
run_in_pty_with_command(
422+
&git,
423+
&["rebase"],
424+
&["-i", "--autosquash", "master"],
425+
&[
426+
PtyAction::WaitUntilContains(" "),
427+
PtyAction::Write(CARRIAGE_RETURN),
428+
],
429+
)?;
430+
431+
{
432+
let stdout = git.smartlog()?;
433+
insta::assert_snapshot!(stdout, @r###"
434+
O f777ecc (master) create initial.txt
435+
|
436+
@ 916a41f create test1.txt
437+
"###);
438+
}
439+
440+
Ok(())
441+
}

0 commit comments

Comments
 (0)