Skip to content

Commit 371c8fd

Browse files
chore(cts): clone CTS only shallowly (gfx-rs#7800)
1 parent 70368fe commit 371c8fd

1 file changed

Lines changed: 120 additions & 5 deletions

File tree

xtask/src/cts.rs

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,19 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
5353
if skip_checkout {
5454
bail!("Skipping CTS checkout doesn't make sense when CTS is not present");
5555
}
56-
log::info!("Cloning CTS");
57-
shell
56+
let mut cmd = shell
5857
.cmd("git")
5958
.args(["clone", CTS_GIT_URL, CTS_CHECKOUT_PATH])
60-
.quiet()
61-
.run()
62-
.context("Failed to clone CTS")?;
59+
.quiet();
60+
61+
if git_version_at_least(&shell, [2, 49, 0])? {
62+
log::info!("Cloning CTS shallowly with revision {cts_revision}");
63+
cmd = cmd.args(["--depth=1", "--revision", &cts_revision])
64+
} else {
65+
log::info!("Cloning full checkout of CTS with revision {cts_revision}");
66+
}
67+
68+
cmd.run().context("Failed to clone CTS")?;
6369

6470
shell.change_dir(CTS_CHECKOUT_PATH);
6571
} else if !skip_checkout {
@@ -120,3 +126,112 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
120126

121127
Ok(())
122128
}
129+
130+
fn git_version_at_least(shell: &Shell, version: GitVersion) -> anyhow::Result<bool> {
131+
let output = shell
132+
.cmd("git")
133+
.args(["--version"])
134+
.output()
135+
.context("Failed to invoke `git --version`")?;
136+
137+
let Some(code) = output.status.code() else {
138+
anyhow::bail!("`git --version` failed to return an exit code; interrupt via signal, maybe?")
139+
};
140+
141+
anyhow::ensure!(code == 0, "`git --version` returned a nonzero exit code");
142+
143+
let fmt_err_msg = "`git --version` did not have the expected structure";
144+
145+
let stdout = String::from_utf8(output.stdout).expect(fmt_err_msg);
146+
147+
let parsed = parse_git_version_output(&stdout).expect(fmt_err_msg);
148+
149+
Ok(parsed <= version)
150+
}
151+
152+
pub type GitVersion = [u8; 3];
153+
154+
fn parse_git_version_output(output: &str) -> anyhow::Result<GitVersion> {
155+
const PREFIX: &str = "git version ";
156+
157+
let raw_version = output
158+
.strip_prefix(PREFIX)
159+
.with_context(|| format!("missing `{PREFIX}` prefix"))?;
160+
161+
let raw_version = raw_version.trim_end(); // There should always be a newline at the end, but
162+
// we don't care if it's missing.
163+
164+
let parsed = GitVersion::try_from(
165+
raw_version
166+
.splitn(3, '.')
167+
.enumerate()
168+
.map(|(idx, s)| {
169+
s.parse().with_context(|| {
170+
format!("failed to parse version number {idx} ({s:?}) as `u8`")
171+
})
172+
})
173+
.collect::<Result<Vec<_>, _>>()?,
174+
)
175+
.map_err(|vec| anyhow::Error::msg(format!("less than 3 version numbers found: {vec:?}")))?;
176+
177+
log::debug!("detected Git version {raw_version}");
178+
179+
Ok(parsed)
180+
}
181+
182+
#[test]
183+
fn test_git_version_parsing() {
184+
macro_rules! test_ok {
185+
($input:expr, $expected:expr) => {
186+
assert_eq!(parse_git_version_output($input).unwrap(), $expected);
187+
};
188+
}
189+
test_ok!("git version 2.3.0", [2, 3, 0]);
190+
test_ok!("git version 0.255.0", [0, 255, 0]);
191+
test_ok!("git version 4.5.6", [4, 5, 6]);
192+
193+
macro_rules! test_err {
194+
($input:expr, $msg:expr) => {
195+
assert_eq!(
196+
parse_git_version_output($input).unwrap_err().to_string(),
197+
$msg
198+
)
199+
};
200+
}
201+
test_err!("2.3.0", "missing `git version ` prefix");
202+
test_err!("", "missing `git version ` prefix");
203+
204+
test_err!(
205+
"git version 1.2",
206+
"less than 3 version numbers found: [1, 2]"
207+
);
208+
209+
test_err!(
210+
"git version 9001",
211+
"failed to parse version number 0 (\"9001\") as `u8`"
212+
);
213+
test_err!(
214+
"git version ",
215+
"failed to parse version number 0 (\"\") as `u8`"
216+
);
217+
test_err!(
218+
"git version asdf",
219+
"failed to parse version number 0 (\"asdf\") as `u8`"
220+
);
221+
test_err!(
222+
"git version 23.beta",
223+
"failed to parse version number 1 (\"beta\") as `u8`"
224+
);
225+
test_err!(
226+
"git version 1.2.wat",
227+
"failed to parse version number 2 (\"wat\") as `u8`"
228+
);
229+
test_err!(
230+
"git version 1.2.3.",
231+
"failed to parse version number 2 (\"3.\") as `u8`"
232+
);
233+
test_err!(
234+
"git version 1.2.3.4",
235+
"failed to parse version number 2 (\"3.4\") as `u8`"
236+
);
237+
}

0 commit comments

Comments
 (0)