chore(cts): clone CTS only shallowly (#7800)

This commit is contained in:
Erich Gubler 2025-06-17 02:39:35 +09:00 committed by GitHub
parent 70368feeb0
commit 371c8fd1db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -53,13 +53,19 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
if skip_checkout {
bail!("Skipping CTS checkout doesn't make sense when CTS is not present");
}
log::info!("Cloning CTS");
shell
let mut cmd = shell
.cmd("git")
.args(["clone", CTS_GIT_URL, CTS_CHECKOUT_PATH])
.quiet()
.run()
.context("Failed to clone CTS")?;
.quiet();
if git_version_at_least(&shell, [2, 49, 0])? {
log::info!("Cloning CTS shallowly with revision {cts_revision}");
cmd = cmd.args(["--depth=1", "--revision", &cts_revision])
} else {
log::info!("Cloning full checkout of CTS with revision {cts_revision}");
}
cmd.run().context("Failed to clone CTS")?;
shell.change_dir(CTS_CHECKOUT_PATH);
} else if !skip_checkout {
@ -120,3 +126,112 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
Ok(())
}
fn git_version_at_least(shell: &Shell, version: GitVersion) -> anyhow::Result<bool> {
let output = shell
.cmd("git")
.args(["--version"])
.output()
.context("Failed to invoke `git --version`")?;
let Some(code) = output.status.code() else {
anyhow::bail!("`git --version` failed to return an exit code; interrupt via signal, maybe?")
};
anyhow::ensure!(code == 0, "`git --version` returned a nonzero exit code");
let fmt_err_msg = "`git --version` did not have the expected structure";
let stdout = String::from_utf8(output.stdout).expect(fmt_err_msg);
let parsed = parse_git_version_output(&stdout).expect(fmt_err_msg);
Ok(parsed <= version)
}
pub type GitVersion = [u8; 3];
fn parse_git_version_output(output: &str) -> anyhow::Result<GitVersion> {
const PREFIX: &str = "git version ";
let raw_version = output
.strip_prefix(PREFIX)
.with_context(|| format!("missing `{PREFIX}` prefix"))?;
let raw_version = raw_version.trim_end(); // There should always be a newline at the end, but
// we don't care if it's missing.
let parsed = GitVersion::try_from(
raw_version
.splitn(3, '.')
.enumerate()
.map(|(idx, s)| {
s.parse().with_context(|| {
format!("failed to parse version number {idx} ({s:?}) as `u8`")
})
})
.collect::<Result<Vec<_>, _>>()?,
)
.map_err(|vec| anyhow::Error::msg(format!("less than 3 version numbers found: {vec:?}")))?;
log::debug!("detected Git version {raw_version}");
Ok(parsed)
}
#[test]
fn test_git_version_parsing() {
macro_rules! test_ok {
($input:expr, $expected:expr) => {
assert_eq!(parse_git_version_output($input).unwrap(), $expected);
};
}
test_ok!("git version 2.3.0", [2, 3, 0]);
test_ok!("git version 0.255.0", [0, 255, 0]);
test_ok!("git version 4.5.6", [4, 5, 6]);
macro_rules! test_err {
($input:expr, $msg:expr) => {
assert_eq!(
parse_git_version_output($input).unwrap_err().to_string(),
$msg
)
};
}
test_err!("2.3.0", "missing `git version ` prefix");
test_err!("", "missing `git version ` prefix");
test_err!(
"git version 1.2",
"less than 3 version numbers found: [1, 2]"
);
test_err!(
"git version 9001",
"failed to parse version number 0 (\"9001\") as `u8`"
);
test_err!(
"git version ",
"failed to parse version number 0 (\"\") as `u8`"
);
test_err!(
"git version asdf",
"failed to parse version number 0 (\"asdf\") as `u8`"
);
test_err!(
"git version 23.beta",
"failed to parse version number 1 (\"beta\") as `u8`"
);
test_err!(
"git version 1.2.wat",
"failed to parse version number 2 (\"wat\") as `u8`"
);
test_err!(
"git version 1.2.3.",
"failed to parse version number 2 (\"3.\") as `u8`"
);
test_err!(
"git version 1.2.3.4",
"failed to parse version number 2 (\"3.4\") as `u8`"
);
}