Class: Imap::Backup::Serializer

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/imap/backup/serializer.rb,
lib/imap/backup/serializer/imap.rb,
lib/imap/backup/serializer/mbox.rb,
lib/imap/backup/serializer/message.rb,
lib/imap/backup/serializer/appender.rb,
lib/imap/backup/serializer/directory.rb,
lib/imap/backup/serializer/transaction.rb,
lib/imap/backup/serializer/folder_maker.rb,
lib/imap/backup/serializer/integrity_checker.rb,
lib/imap/backup/serializer/version2_migrator.rb,
lib/imap/backup/serializer/message_enumerator.rb,
lib/imap/backup/serializer/permission_checker.rb,
lib/imap/backup/serializer/unused_name_finder.rb,
lib/imap/backup/serializer/delayed_metadata_serializer.rb

Overview

Handles serialization for a folder

Defined Under Namespace

Classes: Appender, DelayedMetadataSerializer, Directory, FolderIntegrityError, FolderMaker, Imap, IntegrityChecker, Mbox, Message, MessageEnumerator, PermissionChecker, Transaction, UnusedNameFinder, Version2Migrator

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, folder) ⇒ Serializer

Returns a new instance of Serializer.

Parameters:

  • path (String)

    an account’s backup path

  • folder (String)

    a folder name



75
76
77
78
79
# File 'lib/imap/backup/serializer.rb', line 75

def initialize(path, folder)
  @path = path
  @folder = folder
  @validated = nil
end

Instance Attribute Details

#folderString (readonly)

Returns a folder name.

Returns:

  • (String)

    a folder name



69
70
71
# File 'lib/imap/backup/serializer.rb', line 69

def folder
  @folder
end

#pathString (readonly)

Returns an account’s backup path.

Returns:

  • (String)

    an account’s backup path



71
72
73
# File 'lib/imap/backup/serializer.rb', line 71

def path
  @path
end

Class Method Details

.folder_path_for(path:, folder:) ⇒ String

Returns the full path to a serialized folder (without file extensions).

Parameters:

  • path (String)

    an account’s backup path

  • folder (String)

    a folder name

Returns:

  • (String)

    the full path to a serialized folder (without file extensions)



23
24
25
26
# File 'lib/imap/backup/serializer.rb', line 23

def self.folder_path_for(path:, folder:)
  relative = File.join(path, folder)
  File.expand_path(relative)
end

Instance Method Details

#append(uid, message, flags) ⇒ void

This method returns an undefined value.

Appends a message to the serialized data

Parameters:

  • uid (Integer)

    the message’s UID

  • message (Integer)

    the message text

  • flags (Array[Symbol])

    the message’s flags



174
175
176
177
178
179
# File 'lib/imap/backup/serializer.rb', line 174

def append(uid, message, flags)
  validate!

  appender = Serializer::Appender.new(folder: sanitized, imap: imap, mbox: mbox)
  appender.append(uid: uid, message: message, flags: flags)
end

#apply_uid_validity(value) ⇒ String?

Sets the folder’s UID validity. If the existing value is nil, it sets the new value and ensures that both the metadata file and the mailbox are saved. If the supplied value is the same as the existing value, it does nothing. If the supplied valued is different to the existing value, it renames the existing folder to a new name, and creates a new folder with the supplied value.

Parameters:

  • value (Integer)

    The new UID validity value

Returns:

  • (String, nil)

    The name of the new folder



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/imap/backup/serializer.rb', line 143

def apply_uid_validity(value)
  validate!

  case
  when uid_validity.nil?
    internal_force_uid_validity(value)
    nil
  when uid_validity == value
    # NOOP
    nil
  else
    apply_new_uid_validity(value)
  end
end

#check_integrity!void

This method returns an undefined value.

Checks that the folder’s data is stored correctly



118
119
120
# File 'lib/imap/backup/serializer.rb', line 118

def check_integrity!
  IntegrityChecker.new(imap: imap, mbox: mbox).run
end

#deletevoid

This method returns an undefined value.

Deletes the serialized data



124
125
126
127
128
# File 'lib/imap/backup/serializer.rb', line 124

def delete
  imap.delete
  mbox.delete
  reload
end

#each_message(required_uids = nil, &block) ⇒ Enumerator, void

Enumerates over a series of messages. When called without a block, returns an Enumerator

Parameters:

  • required_uids (Array<Integer>) (defaults to: nil)

    the UIDs of the message to enumerate over

Returns:

  • (Enumerator, void)


185
186
187
188
189
190
191
192
193
194
# File 'lib/imap/backup/serializer.rb', line 185

def each_message(required_uids = nil, &block)
  return enum_for(:each_message, required_uids) if !block

  required_uids ||= uids

  validate!

  enumerator = Serializer::MessageEnumerator.new(imap: imap)
  enumerator.run(uids: required_uids, &block)
end

#filter(&block) ⇒ void

This method returns an undefined value.

Calls the supplied block on each message in the folder and discards those for which the block returns a false result

Parameters:

  • block (block)

    the block to call



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/imap/backup/serializer.rb', line 200

def filter(&block)
  temp_name = Serializer::UnusedNameFinder.new(serializer: self).run
  temp_folder_path = self.class.folder_path_for(path: path, folder: temp_name)
  new_mbox = Serializer::Mbox.new(temp_folder_path)
  new_imap = Serializer::Imap.new(temp_folder_path)
  new_imap.uid_validity = imap.uid_validity
  appender = Serializer::Appender.new(folder: temp_name, imap: new_imap, mbox: new_mbox)
  enumerator = Serializer::MessageEnumerator.new(imap: imap)
  enumerator.run(uids: uids) do |message|
    keep = block.call(message)
    appender.append(uid: message.uid, message: message.body, flags: message.flags) if keep
  end
  imap.delete
  new_imap.rename imap.folder_path
  mbox.delete
  new_mbox.rename mbox.folder_path
  reload
end

#folder_pathString

Returns the path to the serialized folder (without file extensions).

Returns:

  • (String)

    the path to the serialized folder (without file extensions)



220
221
222
# File 'lib/imap/backup/serializer.rb', line 220

def folder_path
  self.class.folder_path_for(path: path, folder: sanitized)
end

#force_uid_validity(value) ⇒ void

This method returns an undefined value.

Overwrites the UID validity of the folder and ensures that both the metadata file and the mailbox are saved.

Parameters:

  • value (Integer)

    the new UID validity



163
164
165
166
167
# File 'lib/imap/backup/serializer.rb', line 163

def force_uid_validity(value)
  validate!

  internal_force_uid_validity(value)
end

#get(uid) ⇒ Serializer::Message

Get message metadata

Parameters:

  • uid (Integer)

    a message UID

Returns:



36
37
38
39
# File 'lib/imap/backup/serializer.rb', line 36

def get(uid)
  validate!
  imap.get(uid)
end

#messagesArray<Hash>

Returns:

  • (Array<Hash>)


42
43
44
45
# File 'lib/imap/backup/serializer.rb', line 42

def messages
  validate!
  imap.messages
end

#reloadvoid

This method returns an undefined value.

Forces a reload of the serialized files



231
232
233
234
# File 'lib/imap/backup/serializer.rb', line 231

def reload
  @imap = nil
  @mbox = nil
end

#sanitizedString

Returns The folder’s name adapted for using as a file name.

Returns:

  • (String)

    The folder’s name adapted for using as a file name



225
226
227
# File 'lib/imap/backup/serializer.rb', line 225

def sanitized
  @sanitized ||= Naming.to_local_path(folder)
end

#transaction(&block) ⇒ void

This method returns an undefined value.

Calls the supplied block without implementing transactional behaviour. This method is present so that this class implements the same interface as DelayedMetadataSerializer

Parameters:

  • block (block)

    the block that is wrapped by the transaction



87
88
89
# File 'lib/imap/backup/serializer.rb', line 87

def transaction(&block)
  block.call
end

#uid_validityInteger

Returns the UID validity for the folder.

Returns:

  • (Integer)

    the UID validity for the folder



48
49
50
51
# File 'lib/imap/backup/serializer.rb', line 48

def uid_validity
  validate!
  imap.uid_validity
end

#uidsArray<Integer>

Returns The uids of all messages.

Returns:

  • (Array<Integer>)

    The uids of all messages



54
55
56
57
# File 'lib/imap/backup/serializer.rb', line 54

def uids
  validate!
  imap.uids
end

#update_uid(old, new) ⇒ void

This method returns an undefined value.

Update a message’s metadata, replacing its UID

Parameters:

  • old (Integer)

    the existing message UID

  • new (Integer)

    the new UID to apply to the message



63
64
65
66
# File 'lib/imap/backup/serializer.rb', line 63

def update_uid(old, new)
  validate!
  imap.update_uid(old, new)
end

#validate!Boolean

Checks that the metadata files are valid, migrates the metadata file from older versions, if necessary, or deletes any existing files if the pair are not valid.

Returns:

  • (Boolean)

    indicates whether there are existing, valid files



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/imap/backup/serializer.rb', line 95

def validate!
  return true if @validated

  optionally_migrate2to3

  imap_valid = imap.valid?
  mbox_valid = mbox.valid?
  if imap_valid && mbox_valid
    @validated = true
    return true
  end
  warn_imap = !imap_valid && imap.exist?
  Logger.logger.info("Metadata file '#{imap.pathname}' is invalid") if warn_imap
  warn_mbox = !mbox_valid && mbox.exist?
  Logger.logger.info("Mailbox '#{mbox.pathname}' is invalid") if warn_mbox

  delete

  false
end