Class: Imap::Backup::Serializer

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/imap/backup/serializer.rb,
lib/imap/backup/serializer/appender.rb,
lib/imap/backup/serializer/directory.rb,
lib/imap/backup/serializer/folder_maker.rb,
lib/imap/backup/serializer/integrity_checker.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



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

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



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

def folder
  @folder
end

#pathString (readonly)

Returns an account’s backup path.

Returns:

  • (String)

    an account’s backup path



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

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



171
172
173
174
175
176
# File 'lib/imap/backup/serializer.rb', line 171

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



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/imap/backup/serializer.rb', line 140

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



115
116
117
# File 'lib/imap/backup/serializer.rb', line 115

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

#deletevoid

This method returns an undefined value.

Deletes the serialized data



121
122
123
124
125
# File 'lib/imap/backup/serializer.rb', line 121

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)


194
195
196
197
198
199
200
201
202
203
# File 'lib/imap/backup/serializer.rb', line 194

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



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/imap/backup/serializer.rb', line 209

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)



229
230
231
# File 'lib/imap/backup/serializer.rb', line 229

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



160
161
162
163
164
# File 'lib/imap/backup/serializer.rb', line 160

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:



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

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

#messagesArray<Hash>

Returns:

  • (Array<Hash>)


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

def messages
  validate!
  imap.messages
end

#reloadvoid

This method returns an undefined value.

Forces a reload of the serialized files



240
241
242
243
# File 'lib/imap/backup/serializer.rb', line 240

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



234
235
236
# File 'lib/imap/backup/serializer.rb', line 234

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

#transaction(&block) ⇒ void

This method returns an undefined value.

Calls the supplied block. 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



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

def transaction(&block)
  block.call
end

#uid_validityInteger

Returns the UID validity for the folder.

Returns:

  • (Integer)

    the UID validity for the folder



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

def uid_validity
  validate!
  imap.uid_validity
end

#uidsArray<Integer>

Returns The uids of all messages.

Returns:

  • (Array<Integer>)

    The uids of all messages



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

def uids
  validate!
  imap.uids
end

#update(uid, flags: nil) ⇒ void

This method returns an undefined value.

Updates a messages flags

Parameters:

  • uid (Integer)

    the message’s UID

  • flags (Array<Symbol>) (defaults to: nil)

    the flags to set on the message



182
183
184
185
186
187
188
# File 'lib/imap/backup/serializer.rb', line 182

def update(uid, flags: nil)
  message = imap.get(uid)
  return if !message

  message.flags = flags if flags
  imap.save
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



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

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



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

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
  Logger.logger.info("Metadata file '#{imap.pathname}' is invalid") if !imap_valid
  Logger.logger.info("Mailbox '#{mbox.pathname}' is invalid") if !mbox_valid

  delete

  false
end