Commit

Checkout tries a failed fetch twice more, after 2 s and 5 s

A fetch from a pull request's fork failed with 'transfer closed with 152 bytes remaining to read', and the check failed with it; the next run's fetch was fine. actions/checkout retries the same way.

syntaqxcommitted Parent9436c01Browse files
1 file+18−20/1 viewed
+18−2
4444 matches!(process::run(command, Duration::from_secs(600), &mut self.log, &mut commands), Ok(Ended::Exited(0)))
4545 }
4646
47+ /// A fetch, tried again after a short wait when it fails: a transfer
48+ /// cut short on the way ("transfer closed with N bytes remaining") is
49+ /// over by the next try. Three tries in all, as actions/checkout does.
50+ fn fetch_retrying(&mut self, dir: &Path, args: &[&str], auth: Option<&str>) -> bool {
51+ for (attempt, wait) in [0u64, 2, 5].into_iter().enumerate() {
52+ if attempt > 0 {
53+ self.log.line(&format!("The fetch failed; trying again in {wait} s ({} of 3).", attempt + 1));
54+ std::thread::sleep(Duration::from_secs(wait));
55+ }
56+ if self.git(dir, args, auth) {
57+ return true;
58+ }
59+ }
60+ false
61+ }
62+
4763 /// `actions/checkout`, against g1t.
4864 fn checkout(&mut self, with: &BTreeMap<String, String>) -> (bool, BTreeMap<String, String>) {
4965 let checkout = self.spec["checkout"].clone();
93109 }
94110 args.push("origin");
95111 args.push(&fetch);
96− if !self.git(&path, &args, auth.as_deref()) {
112+ if !self.fetch_retrying(&path, &args, auth.as_deref()) {
97113 self.log.line(&format!("##[error]Could not fetch {fetch} from {repository}."));
98114 return (false, BTreeMap::new());
99115 }
100116 let target = sha.clone().unwrap_or_else(|| "FETCH_HEAD".into());
101117 // The commit may be further back than a shallow fetch reaches.
102118 let present = Command::new("git").current_dir(&path).args(["cat-file", "-e", &format!("{target}^{{commit}}")]).status().is_ok_and(|s| s.success());
103− if !present && !self.git(&path, &["fetch", "--no-tags", "--quiet", "origin"], auth.as_deref()) {
119+ if !present && !self.fetch_retrying(&path, &["fetch", "--no-tags", "--quiet", "origin"], auth.as_deref()) {
104120 return (false, BTreeMap::new());
105121 }
106122 let checked_out = match &branch {