Skip to content

Commit e8acf6f

Browse files
authored
Merge pull request #681 from pkgw/partial-reruns
src/engines: incorporate remaining data into digest when closing input files
2 parents 9a817d6 + de81af5 commit e8acf6f

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/engines/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,12 +469,20 @@ impl<'a> ExecutionState<'a> {
469469
let p: *const InputHandle = &*self.input_handles[i];
470470

471471
if p == handle {
472-
let ih = self.input_handles.swap_remove(i);
472+
let mut ih = self.input_handles.swap_remove(i);
473+
let mut rv = false;
474+
475+
if let Err(e) = ih.scan_remainder() {
476+
tt_warning!(self.status, "error closing out input {}", ih.name().to_string_lossy(); e);
477+
rv = true;
478+
}
479+
473480
let (name, digest_opt) = ih.into_name_digest();
474481
self.events.input_closed(name, digest_opt);
475-
return false;
482+
return rv;
476483
}
477484
}
485+
478486
// TODO: Handle the error better. This indicates a bug in the engine.
479487
tt_error!(
480488
self.status,

src/io/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,37 @@ impl InputHandle {
141141
self.inner
142142
}
143143

144+
/// Read any remaining data in the file and incorporate them into the
145+
/// digest. This helps the rerun detection logic work correctly in
146+
/// the somewhat-unusual case that a file is read then written, but
147+
/// only part of the file is read, not the entire thing. This seems
148+
/// to happen with biblatex XML state files.
149+
pub fn scan_remainder(&mut self) -> Result<()> {
150+
const BUFSIZE: usize = 1024;
151+
let mut buf: [u8; BUFSIZE] = [0; BUFSIZE];
152+
153+
loop {
154+
let n = match self.inner.read(&mut buf[..]) {
155+
Ok(n) => n,
156+
157+
// There are times when the engine tries to open and read
158+
// directories. When closing out such a handle, we'll get this
159+
// error, but we should ignore it.
160+
Err(ref ioe) if ioe.raw_os_error() == Some(libc::EISDIR) => return Ok(()),
161+
162+
Err(e) => return Err(e.into()),
163+
};
164+
165+
if n == 0 {
166+
break;
167+
}
168+
169+
self.digest.update(&buf[..n]);
170+
}
171+
172+
Ok(())
173+
}
174+
144175
/// Consumes the object and returns the SHA256 sum of the content that was
145176
/// read. No digest is returned if there was ever a seek on the input
146177
/// stream, since in that case the results will not be reliable. We also

0 commit comments

Comments
 (0)