Skip to content

Commit 9db5ee6

Browse files
committed
sync: redownload messages that disappear from the maildir
If we detect a message that exists in notmuch, exists on the server, but is not in the maildir, treat it a little like a "new" message and redownload it from the server.
1 parent edb6205 commit 9db5ee6

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/local.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,8 @@ impl Local {
305305
}
306306
Ok(())
307307
}
308+
309+
pub fn email_exists_on_disk(&self, email: &Email) -> bool {
310+
email.path.exists()
311+
}
308312
}

src/sync.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -281,22 +281,40 @@ pub fn sync(
281281
})
282282
.unwrap_or_else(|| full_sync(&mut remote))?;
283283

284+
// Get ids for any emails we think are in the maildir but are not
285+
let missing_ids: HashSet<jmap::Id> = local_emails
286+
.values()
287+
.filter(|e| !local.email_exists_on_disk(e))
288+
.map(|e| e.id.clone())
289+
.collect();
290+
284291
// Retrieve the updated `Email` objects from the server.
285292
stdout.set_color(&info_color_spec).context(LogSnafu {})?;
286293
write!(stdout, "Retrieving metadata...").context(LogSnafu {})?;
287294
stdout.reset().context(LogSnafu {})?;
288-
writeln!(stdout, " ({} possibly changed)", updated_ids.len()).context(LogSnafu {})?;
295+
write!(stdout, " ({} possibly changed)", updated_ids.len()).context(LogSnafu {})?;
296+
if !missing_ids.is_empty() {
297+
write!(stdout, " ({} lost)", missing_ids.len()).context(LogSnafu {})?
298+
}
299+
writeln!(stdout, "").context(LogSnafu {})?;
289300
stdout.flush().context(LogSnafu {})?;
290301

291302
let remote_emails = remote
292-
.get_emails(updated_ids.iter(), &mailboxes, &config.tags)
303+
.get_emails(
304+
[updated_ids, missing_ids.clone()].iter().flatten(),
305+
&mailboxes,
306+
&config.tags,
307+
)
293308
.context(GetRemoteEmailsSnafu {})?;
294309

295310
// Before merging, download the new files into the cache.
296311
let mut new_emails: HashMap<jmap::Id, NewEmail> = remote_emails
297312
.values()
298313
.filter(|remote_email| match local_emails.get(&remote_email.id) {
299-
Some(local_email) => local_email.blob_id != remote_email.blob_id,
314+
Some(local_email) => {
315+
local_email.blob_id != remote_email.blob_id
316+
|| !local.email_exists_on_disk(local_email)
317+
}
300318
None => true,
301319
})
302320
.map(|remote_email| {
@@ -313,7 +331,10 @@ pub fn sync(
313331

314332
let new_emails_missing_from_cache: Vec<&NewEmail> = new_emails
315333
.values()
316-
.filter(|x| !x.cache_path.exists() && !local_emails.contains_key(&x.remote_email.id))
334+
.filter(|x| match local_emails.get(&x.remote_email.id) {
335+
Some(le) => !local.email_exists_on_disk(le),
336+
None => !x.cache_path.exists(),
337+
})
317338
.collect();
318339

319340
if !new_emails_missing_from_cache.is_empty() {
@@ -442,8 +463,10 @@ pub fn sync(
442463
.add_new_email(&new_email)
443464
.context(AddLocalEmailSnafu {})?;
444465
if let Some(e) = local_emails.get(&new_email.remote_email.id) {
445-
// Move the old message to the destroyed emails set.
446-
destroyed_local_emails.push(e);
466+
// It already existed; delete old versions, but not ones we're reloading
467+
if !missing_ids.contains(&e.id) {
468+
destroyed_local_emails.push(e);
469+
}
447470
}
448471
Ok((local_email.id.clone(), local_email))
449472
})

0 commit comments

Comments
 (0)