Skip to content

Commit bd4aa43

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 bd4aa43

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
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: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,22 +281,29 @@ 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.values().filter(|e| !local.email_exists_on_disk(e)).map(|e| e.id.clone()).collect();
286+
284287
// Retrieve the updated `Email` objects from the server.
285288
stdout.set_color(&info_color_spec).context(LogSnafu {})?;
286289
write!(stdout, "Retrieving metadata...").context(LogSnafu {})?;
287290
stdout.reset().context(LogSnafu {})?;
288-
writeln!(stdout, " ({} possibly changed)", updated_ids.len()).context(LogSnafu {})?;
291+
write!(stdout, " ({} possibly changed)", updated_ids.len()).context(LogSnafu {})?;
292+
if !missing_ids.is_empty() {
293+
write!(stdout, " ({} lost)", missing_ids.len()).context(LogSnafu {})?
294+
}
295+
writeln!(stdout, "").context(LogSnafu {})?;
289296
stdout.flush().context(LogSnafu {})?;
290297

291298
let remote_emails = remote
292-
.get_emails(updated_ids.iter(), &mailboxes, &config.tags)
299+
.get_emails([updated_ids, missing_ids.clone()].iter().flatten(), &mailboxes, &config.tags)
293300
.context(GetRemoteEmailsSnafu {})?;
294301

295302
// Before merging, download the new files into the cache.
296303
let mut new_emails: HashMap<jmap::Id, NewEmail> = remote_emails
297304
.values()
298305
.filter(|remote_email| match local_emails.get(&remote_email.id) {
299-
Some(local_email) => local_email.blob_id != remote_email.blob_id,
306+
Some(local_email) => local_email.blob_id != remote_email.blob_id || !local.email_exists_on_disk(local_email),
300307
None => true,
301308
})
302309
.map(|remote_email| {
@@ -310,10 +317,13 @@ pub fn sync(
310317
)
311318
})
312319
.collect();
313-
320+
314321
let new_emails_missing_from_cache: Vec<&NewEmail> = new_emails
315322
.values()
316-
.filter(|x| !x.cache_path.exists() && !local_emails.contains_key(&x.remote_email.id))
323+
.filter(|x| match local_emails.get(&x.remote_email.id) {
324+
Some(le) => !local.email_exists_on_disk(le),
325+
None => !x.cache_path.exists(),
326+
})
317327
.collect();
318328

319329
if !new_emails_missing_from_cache.is_empty() {
@@ -442,8 +452,10 @@ pub fn sync(
442452
.add_new_email(&new_email)
443453
.context(AddLocalEmailSnafu {})?;
444454
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);
455+
// It already existed; delete old versions, but not ones we're reloading
456+
if !missing_ids.contains(&e.id) {
457+
destroyed_local_emails.push(e);
458+
}
447459
}
448460
Ok((local_email.id.clone(), local_email))
449461
})

0 commit comments

Comments
 (0)