add ./miri squash
This commit is contained in:
parent
2260f77e50
commit
e2d2c56b2e
3 changed files with 84 additions and 10 deletions
|
|
@ -19,12 +19,10 @@ When you get a review, please take care of the requested changes in new commits.
|
|||
existing commits. Generally avoid force-pushing. The only time you should force push is when there
|
||||
is a conflict with the master branch (in that case you should rebase across master, not merge), and
|
||||
all the way at the end of the review process when the reviewer tells you that the PR is done and you
|
||||
should squash the commits. For the latter case, use `git rebase --keep-base ...` to squash without
|
||||
changing the base commit your PR branches off of. Use your own judgment and the reviewer's guidance
|
||||
to decide whether the PR should be squashed into a single commit or multiple logically separate
|
||||
commits. (All this is to work around the fact that Github is quite bad at dealing with force pushes
|
||||
and does not support `git range-diff`. Maybe one day Github will be good at git and then life can
|
||||
become easier.)
|
||||
should squash the commits. If you are unsure how to use `git rebase` to squash commits, use `./miri
|
||||
squash` which automates the process but leaves little room for customization. (All this is to work
|
||||
around the fact that Github is quite bad at dealing with force pushes and does not support `git
|
||||
range-diff`. Maybe one day Github will be good at git and then life can become easier.)
|
||||
|
||||
Most PRs bounce back and forth between the reviewer and the author several times, so it is good to
|
||||
keep track of who is expected to take the next step. We are using the `S-waiting-for-review` and
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter, Write};
|
||||
use std::fmt::Write as _;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, BufRead, BufReader, BufWriter, Write as _};
|
||||
use std::ops::Not;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
|
@ -169,7 +170,8 @@ impl Command {
|
|||
| Command::Toolchain { .. }
|
||||
| Command::Bench { .. }
|
||||
| Command::RustcPull { .. }
|
||||
| Command::RustcPush { .. } => {}
|
||||
| Command::RustcPush { .. }
|
||||
| Command::Squash => {}
|
||||
}
|
||||
// Then run the actual command.
|
||||
match self {
|
||||
|
|
@ -188,6 +190,7 @@ impl Command {
|
|||
Command::Toolchain { flags } => Self::toolchain(flags),
|
||||
Command::RustcPull { commit } => Self::rustc_pull(commit.clone()),
|
||||
Command::RustcPush { github_user, branch } => Self::rustc_push(github_user, branch),
|
||||
Command::Squash => Self::squash(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -383,6 +386,72 @@ impl Command {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn squash() -> Result<()> {
|
||||
let sh = Shell::new()?;
|
||||
sh.change_dir(miri_dir()?);
|
||||
// Figure out base wrt latest upstream master.
|
||||
// (We can't trust any of the local ones, they can all be outdated.)
|
||||
let origin_master = {
|
||||
cmd!(sh, "git fetch https://github.com/rust-lang/miri/")
|
||||
.quiet()
|
||||
.ignore_stdout()
|
||||
.ignore_stderr()
|
||||
.run()?;
|
||||
cmd!(sh, "git rev-parse FETCH_HEAD").read()?
|
||||
};
|
||||
let base = cmd!(sh, "git merge-base HEAD {origin_master}").read()?;
|
||||
// Rebase onto that, setting ourselves as the sequence editor so that we can edit the sequence programmatically.
|
||||
// We want to forward the host stdin so apparently we cannot use `cmd!`.
|
||||
let mut cmd = process::Command::new("git");
|
||||
cmd.arg("rebase").arg(&base).arg("--interactive");
|
||||
cmd.env("GIT_SEQUENCE_EDITOR", env::current_exe()?);
|
||||
cmd.env("MIRI_SCRIPT_IS_GIT_SEQUENCE_EDITOR", "1");
|
||||
cmd.current_dir(sh.current_dir());
|
||||
let result = cmd.status()?;
|
||||
if !result.success() {
|
||||
bail!("`git rebase` failed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn squash_sequence_editor() -> Result<()> {
|
||||
let sequence_file = env::args().nth(1).expect("git should pass us a filename");
|
||||
if sequence_file == "fmt" {
|
||||
// This is probably us being called as a git hook as part of the rebase. Let's just
|
||||
// ignore this. Sadly `git rebase` does not have a flag to skip running hooks.
|
||||
return Ok(());
|
||||
}
|
||||
// Read the provided sequence and adjust it.
|
||||
let rebase_sequence = {
|
||||
let mut rebase_sequence = String::new();
|
||||
let file = fs::File::open(&sequence_file).with_context(|| {
|
||||
format!("failed to read rebase sequence from {sequence_file:?}")
|
||||
})?;
|
||||
let file = io::BufReader::new(file);
|
||||
for line in file.lines() {
|
||||
let line = line?;
|
||||
// The first line is left unchanged.
|
||||
if rebase_sequence.is_empty() {
|
||||
writeln!(rebase_sequence, "{line}").unwrap();
|
||||
continue;
|
||||
}
|
||||
// If this is a "pick" like, make it "squash".
|
||||
if let Some(rest) = line.strip_prefix("pick ") {
|
||||
writeln!(rebase_sequence, "squash {rest}").unwrap();
|
||||
continue;
|
||||
}
|
||||
// We've reached the end of the relevant part of the sequence, and we can stop.
|
||||
break;
|
||||
}
|
||||
rebase_sequence
|
||||
};
|
||||
// Write out the adjusted sequence.
|
||||
fs::write(&sequence_file, rebase_sequence).with_context(|| {
|
||||
format!("failed to write adjusted rebase sequence to {sequence_file:?}")
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bench(
|
||||
target: Option<String>,
|
||||
no_install: bool,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ pub enum Command {
|
|||
#[arg(default_value = "miri-sync")]
|
||||
branch: String,
|
||||
},
|
||||
/// Squash the commits of the current feature branch into one.
|
||||
Squash,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
|
|
@ -154,7 +156,7 @@ impl Command {
|
|||
flags.extend(remainder);
|
||||
Ok(())
|
||||
}
|
||||
Self::Bench { .. } | Self::RustcPull { .. } | Self::RustcPush { .. } =>
|
||||
Self::Bench { .. } | Self::RustcPull { .. } | Self::RustcPush { .. } | Self::Squash =>
|
||||
bail!("unexpected \"--\" found in arguments"),
|
||||
}
|
||||
}
|
||||
|
|
@ -170,6 +172,11 @@ pub struct Cli {
|
|||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// If we are invoked as the git sequence editor, jump to that logic.
|
||||
if !std::env::var_os("MIRI_SCRIPT_IS_GIT_SEQUENCE_EDITOR").unwrap_or_default().is_empty() {
|
||||
return Command::squash_sequence_editor();
|
||||
}
|
||||
|
||||
// Split the arguments into the part before the `--` and the part after.
|
||||
// The `--` itself ends up in the second part.
|
||||
let miri_args: Vec<_> = std::env::args().take_while(|x| *x != "--").collect();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue