Improve how attachments are saved to the db and disk.

This mostly aims to make the Geary.Attachment and ImapDB.Attachment
objects usable more generally for managing attachments, allowing
these to be instantiated once, persisted, and then reused, rather than
going through a number of representations (GMime, SQlite, Geary) and
having to be saved and re-loaded.

* src/engine/api/geary-attachment.vala (Attachment): Remove id property
  and allow both file and filesize properties to be set after instances
  are constructed. Update call sites.

* src/engine/api/geary-email.vala (Email): Remove get_attachment_by_id
  since it unused.

* src/engine/imap-db/imap-db-attachment.vala (Attachment): Chase
  Geary.Attachment API changes, move object-specific persistence code
  into methods on the actual object class itself and modernise a
  bit. Rename static methods to be a bit more terse. Update call sites
  and add unit tests.

* src/engine/imap-db/imap-db-folder.vala (Folder): Rather than saving
  attachments to the db then reloading them to add them to their email
  objects, just instantiate Attachment instances once, save and then add
  them.

* src/engine/imap-db/imap-db-gc.vala (GC): Replace custom SQL with
  existing accessor for listing attachments.

* src/engine/util/util-stream.vala (MimeOutputStream): New adaptor class
  for GMime streams to GIO output streams.
This commit is contained in:
Michael James Gratton 2018-05-05 12:18:22 +10:00
parent 15d8789685
commit 037af00740
12 changed files with 619 additions and 354 deletions

View file

@ -10,7 +10,6 @@ extern const string _SOURCE_ROOT_DIR;
class Geary.AttachmentTest : TestCase {
private const string ATTACHMENT_ID = "test-id";
private const string CONTENT_TYPE = "image/png";
private const string CONTENT_ID = "test-content-id";
private const string CONTENT_DESC = "Mea navis volitans anguillis plena est";
@ -21,19 +20,19 @@ class Geary.AttachmentTest : TestCase {
private Mime.ContentDisposition? content_disposition;
private File? file;
private class TestAttachment : Attachment {
// A test article
internal TestAttachment(string id,
Mime.ContentType content_type,
internal TestAttachment(Mime.ContentType content_type,
string? content_id,
string? content_description,
Mime.ContentDisposition content_disposition,
string? content_filename,
File file,
int64 filesize) {
base(id, content_type, content_id, content_description,
content_disposition, content_filename, file, filesize);
GLib.File file) {
base(content_type, content_id, content_description,
content_disposition, content_filename);
set_file_info(file, 742);
}
}
@ -76,14 +75,12 @@ class Geary.AttachmentTest : TestCase {
public void get_safe_file_name_with_content_name() throws Error {
const string TEST_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -97,14 +94,12 @@ class Geary.AttachmentTest : TestCase {
const string TEST_FILENAME = "test-filename.jpg";
const string RESULT_FILENAME = "test-filename.jpg.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -118,14 +113,12 @@ class Geary.AttachmentTest : TestCase {
const string TEST_FILENAME = "test-filename";
const string RESULT_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -138,14 +131,12 @@ class Geary.AttachmentTest : TestCase {
public void get_safe_file_name_with_no_content_name() throws Error {
const string RESULT_FILENAME = CONTENT_ID + ".png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
null,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -156,16 +147,14 @@ class Geary.AttachmentTest : TestCase {
}
public void get_safe_file_name_with_no_content_name_or_id() throws Error {
const string RESULT_FILENAME = ATTACHMENT_ID + ".png";
const string RESULT_FILENAME = "attachment.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
null,
CONTENT_DESC,
content_disposition,
null,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -179,14 +168,12 @@ class Geary.AttachmentTest : TestCase {
const string ALT_TEXT = "some text";
const string RESULT_FILENAME = "some text.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.content_type,
null,
CONTENT_DESC,
content_disposition,
null,
this.file,
742
this.file
);
test.get_safe_file_name.begin(ALT_TEXT, (obj, ret) => {
@ -199,14 +186,12 @@ class Geary.AttachmentTest : TestCase {
public void get_safe_file_name_with_default_content_type() throws Error {
const string TEST_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -221,14 +206,12 @@ class Geary.AttachmentTest : TestCase {
const string TEST_FILENAME = "test-filename.jpg";
const string RESULT_FILENAME = "test-filename.jpg.png";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file,
742
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
@ -242,14 +225,12 @@ class Geary.AttachmentTest : TestCase {
throws Error {
const string TEST_FILENAME = "test-filename.unlikely";
Attachment test = new TestAttachment(
ATTACHMENT_ID,
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
File.new_for_path(TEST_FILENAME),
742
File.new_for_path(TEST_FILENAME)
);
test.get_safe_file_name.begin(null, (obj, ret) => {