mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 17:47:03 +00:00
- storage: rename DataStore to Store - file: rename types to appease linter
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package filestore
|
||||
package file
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -15,10 +15,10 @@ import (
|
||||
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||
)
|
||||
|
||||
// FileMessage implements Message and contains a little bit of data about a
|
||||
// Message implements Message and contains a little bit of data about a
|
||||
// particular email message, and methods to retrieve the rest of it from disk.
|
||||
type FileMessage struct {
|
||||
mailbox *FileMailbox
|
||||
type Message struct {
|
||||
mailbox *Mailbox
|
||||
// Stored in GOB
|
||||
Fid string
|
||||
Fdate time.Time
|
||||
@@ -34,7 +34,7 @@ type FileMessage struct {
|
||||
|
||||
// NewMessage creates a new FileMessage object and sets the Date and Id fields.
|
||||
// It will also delete messages over messageCap if configured.
|
||||
func (mb *FileMailbox) NewMessage() (datastore.Message, error) {
|
||||
func (mb *Mailbox) NewMessage() (storage.Message, error) {
|
||||
// Load index
|
||||
if !mb.indexLoaded {
|
||||
if err := mb.readIndex(); err != nil {
|
||||
@@ -54,50 +54,50 @@ func (mb *FileMailbox) NewMessage() (datastore.Message, error) {
|
||||
|
||||
date := time.Now()
|
||||
id := generateID(date)
|
||||
return &FileMessage{mailbox: mb, Fid: id, Fdate: date, writable: true}, nil
|
||||
return &Message{mailbox: mb, Fid: id, Fdate: date, writable: true}, nil
|
||||
}
|
||||
|
||||
// ID gets the ID of the Message
|
||||
func (m *FileMessage) ID() string {
|
||||
func (m *Message) ID() string {
|
||||
return m.Fid
|
||||
}
|
||||
|
||||
// Date returns the date/time this Message was received by Inbucket
|
||||
func (m *FileMessage) Date() time.Time {
|
||||
func (m *Message) Date() time.Time {
|
||||
return m.Fdate
|
||||
}
|
||||
|
||||
// From returns the value of the Message From header
|
||||
func (m *FileMessage) From() string {
|
||||
func (m *Message) From() string {
|
||||
return m.Ffrom
|
||||
}
|
||||
|
||||
// To returns the value of the Message To header
|
||||
func (m *FileMessage) To() []string {
|
||||
func (m *Message) To() []string {
|
||||
return m.Fto
|
||||
}
|
||||
|
||||
// Subject returns the value of the Message Subject header
|
||||
func (m *FileMessage) Subject() string {
|
||||
func (m *Message) Subject() string {
|
||||
return m.Fsubject
|
||||
}
|
||||
|
||||
// String returns a string in the form: "Subject()" from From()
|
||||
func (m *FileMessage) String() string {
|
||||
func (m *Message) String() string {
|
||||
return fmt.Sprintf("\"%v\" from %v", m.Fsubject, m.Ffrom)
|
||||
}
|
||||
|
||||
// Size returns the size of the Message on disk in bytes
|
||||
func (m *FileMessage) Size() int64 {
|
||||
func (m *Message) Size() int64 {
|
||||
return m.Fsize
|
||||
}
|
||||
|
||||
func (m *FileMessage) rawPath() string {
|
||||
func (m *Message) rawPath() string {
|
||||
return filepath.Join(m.mailbox.path, m.Fid+".raw")
|
||||
}
|
||||
|
||||
// ReadHeader opens the .raw portion of a Message and returns a standard Go mail.Message object
|
||||
func (m *FileMessage) ReadHeader() (msg *mail.Message, err error) {
|
||||
func (m *Message) ReadHeader() (msg *mail.Message, err error) {
|
||||
file, err := os.Open(m.rawPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -113,7 +113,7 @@ func (m *FileMessage) ReadHeader() (msg *mail.Message, err error) {
|
||||
}
|
||||
|
||||
// ReadBody opens the .raw portion of a Message and returns a MIMEBody object
|
||||
func (m *FileMessage) ReadBody() (body *enmime.Envelope, err error) {
|
||||
func (m *Message) ReadBody() (body *enmime.Envelope, err error) {
|
||||
file, err := os.Open(m.rawPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,7 +133,7 @@ func (m *FileMessage) ReadBody() (body *enmime.Envelope, err error) {
|
||||
}
|
||||
|
||||
// RawReader opens the .raw portion of a Message as an io.ReadCloser
|
||||
func (m *FileMessage) RawReader() (reader io.ReadCloser, err error) {
|
||||
func (m *Message) RawReader() (reader io.ReadCloser, err error) {
|
||||
file, err := os.Open(m.rawPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -142,7 +142,7 @@ func (m *FileMessage) RawReader() (reader io.ReadCloser, err error) {
|
||||
}
|
||||
|
||||
// ReadRaw opens the .raw portion of a Message and returns it as a string
|
||||
func (m *FileMessage) ReadRaw() (raw *string, err error) {
|
||||
func (m *Message) ReadRaw() (raw *string, err error) {
|
||||
reader, err := m.RawReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -163,10 +163,10 @@ func (m *FileMessage) ReadRaw() (raw *string, err error) {
|
||||
|
||||
// Append data to a newly opened Message, this will fail on a pre-existing Message and
|
||||
// after Close() is called.
|
||||
func (m *FileMessage) Append(data []byte) error {
|
||||
func (m *Message) Append(data []byte) error {
|
||||
// Prevent Appending to a pre-existing Message
|
||||
if !m.writable {
|
||||
return datastore.ErrNotWritable
|
||||
return storage.ErrNotWritable
|
||||
}
|
||||
// Open file for writing if we haven't yet
|
||||
if m.writer == nil {
|
||||
@@ -190,7 +190,7 @@ func (m *FileMessage) Append(data []byte) error {
|
||||
|
||||
// Close this Message for writing - no more data may be Appended. Close() will also
|
||||
// trigger the creation of the .gob file.
|
||||
func (m *FileMessage) Close() error {
|
||||
func (m *Message) Close() error {
|
||||
// nil out the writer fields so they can't be used
|
||||
writer := m.writer
|
||||
writerFile := m.writerFile
|
||||
@@ -245,7 +245,7 @@ func (m *FileMessage) Close() error {
|
||||
|
||||
// Delete this Message from disk by removing it from the index and deleting the
|
||||
// raw files.
|
||||
func (m *FileMessage) Delete() error {
|
||||
func (m *Message) Delete() error {
|
||||
messages := m.mailbox.messages
|
||||
for i, mm := range messages {
|
||||
if m == mm {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package filestore
|
||||
package file
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -48,17 +48,17 @@ func countGenerator(c chan int) {
|
||||
}
|
||||
}
|
||||
|
||||
// FileDataStore implements DataStore aand is the root of the mail storage
|
||||
// Store implements DataStore aand is the root of the mail storage
|
||||
// hiearchy. It provides access to Mailbox objects
|
||||
type FileDataStore struct {
|
||||
hashLock datastore.HashLock
|
||||
type Store struct {
|
||||
hashLock storage.HashLock
|
||||
path string
|
||||
mailPath string
|
||||
messageCap int
|
||||
}
|
||||
|
||||
// NewFileDataStore creates a new DataStore object using the specified path
|
||||
func NewFileDataStore(cfg config.DataStoreConfig) datastore.DataStore {
|
||||
// New creates a new DataStore object using the specified path
|
||||
func New(cfg config.DataStoreConfig) storage.Store {
|
||||
path := cfg.Path
|
||||
if path == "" {
|
||||
log.Errorf("No value configured for datastore path")
|
||||
@@ -71,19 +71,19 @@ func NewFileDataStore(cfg config.DataStoreConfig) datastore.DataStore {
|
||||
log.Errorf("Error creating dir %q: %v", mailPath, err)
|
||||
}
|
||||
}
|
||||
return &FileDataStore{path: path, mailPath: mailPath, messageCap: cfg.MailboxMsgCap}
|
||||
return &Store{path: path, mailPath: mailPath, messageCap: cfg.MailboxMsgCap}
|
||||
}
|
||||
|
||||
// DefaultFileDataStore creates a new DataStore object. It uses the inbucket.Config object to
|
||||
// DefaultStore creates a new DataStore object. It uses the inbucket.Config object to
|
||||
// construct it's path.
|
||||
func DefaultFileDataStore() datastore.DataStore {
|
||||
func DefaultStore() storage.Store {
|
||||
cfg := config.GetDataStoreConfig()
|
||||
return NewFileDataStore(cfg)
|
||||
return New(cfg)
|
||||
}
|
||||
|
||||
// MailboxFor retrieves the Mailbox object for a specified email address, if the mailbox
|
||||
// does not exist, it will attempt to create it.
|
||||
func (ds *FileDataStore) MailboxFor(emailAddress string) (datastore.Mailbox, error) {
|
||||
func (ds *Store) MailboxFor(emailAddress string) (storage.Mailbox, error) {
|
||||
name, err := stringutil.ParseMailboxName(emailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -94,13 +94,13 @@ func (ds *FileDataStore) MailboxFor(emailAddress string) (datastore.Mailbox, err
|
||||
path := filepath.Join(ds.mailPath, s1, s2, dir)
|
||||
indexPath := filepath.Join(path, indexFileName)
|
||||
|
||||
return &FileMailbox{store: ds, name: name, dirName: dir, path: path,
|
||||
return &Mailbox{store: ds, name: name, dirName: dir, path: path,
|
||||
indexPath: indexPath}, nil
|
||||
}
|
||||
|
||||
// AllMailboxes returns a slice with all Mailboxes
|
||||
func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
||||
mailboxes := make([]datastore.Mailbox, 0, 100)
|
||||
func (ds *Store) AllMailboxes() ([]storage.Mailbox, error) {
|
||||
mailboxes := make([]storage.Mailbox, 0, 100)
|
||||
infos1, err := ioutil.ReadDir(ds.mailPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -127,7 +127,7 @@ func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
||||
mbdir := inf3.Name()
|
||||
mbpath := filepath.Join(ds.mailPath, l1, l2, mbdir)
|
||||
idx := filepath.Join(mbpath, indexFileName)
|
||||
mb := &FileMailbox{store: ds, dirName: mbdir, path: mbpath,
|
||||
mb := &Mailbox{store: ds, dirName: mbdir, path: mbpath,
|
||||
indexPath: idx}
|
||||
mailboxes = append(mailboxes, mb)
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
||||
}
|
||||
|
||||
// LockFor returns the RWMutex for this mailbox, or an error.
|
||||
func (ds *FileDataStore) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
||||
func (ds *Store) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
||||
name, err := stringutil.ParseMailboxName(emailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -150,38 +150,38 @@ func (ds *FileDataStore) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
||||
return ds.hashLock.Get(hash), nil
|
||||
}
|
||||
|
||||
// FileMailbox implements Mailbox, manages the mail for a specific user and
|
||||
// Mailbox implements Mailbox, manages the mail for a specific user and
|
||||
// correlates to a particular directory on disk.
|
||||
type FileMailbox struct {
|
||||
store *FileDataStore
|
||||
type Mailbox struct {
|
||||
store *Store
|
||||
name string
|
||||
dirName string
|
||||
path string
|
||||
indexLoaded bool
|
||||
indexPath string
|
||||
messages []*FileMessage
|
||||
messages []*Message
|
||||
}
|
||||
|
||||
// Name of the mailbox
|
||||
func (mb *FileMailbox) Name() string {
|
||||
func (mb *Mailbox) Name() string {
|
||||
return mb.name
|
||||
}
|
||||
|
||||
// String renders the name and directory path of the mailbox
|
||||
func (mb *FileMailbox) String() string {
|
||||
func (mb *Mailbox) String() string {
|
||||
return mb.name + "[" + mb.dirName + "]"
|
||||
}
|
||||
|
||||
// GetMessages scans the mailbox directory for .gob files and decodes them into
|
||||
// a slice of Message objects.
|
||||
func (mb *FileMailbox) GetMessages() ([]datastore.Message, error) {
|
||||
func (mb *Mailbox) GetMessages() ([]storage.Message, error) {
|
||||
if !mb.indexLoaded {
|
||||
if err := mb.readIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
messages := make([]datastore.Message, len(mb.messages))
|
||||
messages := make([]storage.Message, len(mb.messages))
|
||||
for i, m := range mb.messages {
|
||||
messages[i] = m
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func (mb *FileMailbox) GetMessages() ([]datastore.Message, error) {
|
||||
}
|
||||
|
||||
// GetMessage decodes a single message by Id and returns a Message object
|
||||
func (mb *FileMailbox) GetMessage(id string) (datastore.Message, error) {
|
||||
func (mb *Mailbox) GetMessage(id string) (storage.Message, error) {
|
||||
if !mb.indexLoaded {
|
||||
if err := mb.readIndex(); err != nil {
|
||||
return nil, err
|
||||
@@ -206,17 +206,17 @@ func (mb *FileMailbox) GetMessage(id string) (datastore.Message, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return nil, datastore.ErrNotExist
|
||||
return nil, storage.ErrNotExist
|
||||
}
|
||||
|
||||
// Purge deletes all messages in this mailbox
|
||||
func (mb *FileMailbox) Purge() error {
|
||||
func (mb *Mailbox) Purge() error {
|
||||
mb.messages = mb.messages[:0]
|
||||
return mb.writeIndex()
|
||||
}
|
||||
|
||||
// readIndex loads the mailbox index data from disk
|
||||
func (mb *FileMailbox) readIndex() error {
|
||||
func (mb *Mailbox) readIndex() error {
|
||||
// Clear message slice, open index
|
||||
mb.messages = mb.messages[:0]
|
||||
// Lock for reading
|
||||
@@ -242,7 +242,7 @@ func (mb *FileMailbox) readIndex() error {
|
||||
// Decode gob data
|
||||
dec := gob.NewDecoder(bufio.NewReader(file))
|
||||
for {
|
||||
msg := new(FileMessage)
|
||||
msg := new(Message)
|
||||
if err = dec.Decode(msg); err != nil {
|
||||
if err == io.EOF {
|
||||
// It's OK to get an EOF here
|
||||
@@ -259,7 +259,7 @@ func (mb *FileMailbox) readIndex() error {
|
||||
}
|
||||
|
||||
// writeIndex overwrites the index on disk with the current mailbox data
|
||||
func (mb *FileMailbox) writeIndex() error {
|
||||
func (mb *Mailbox) writeIndex() error {
|
||||
// Lock for writing
|
||||
indexMx.Lock()
|
||||
defer indexMx.Unlock()
|
||||
@@ -301,7 +301,7 @@ func (mb *FileMailbox) writeIndex() error {
|
||||
}
|
||||
|
||||
// createDir checks for the presence of the path for this mailbox, creates it if needed
|
||||
func (mb *FileMailbox) createDir() error {
|
||||
func (mb *Mailbox) createDir() error {
|
||||
dirMx.Lock()
|
||||
defer dirMx.Unlock()
|
||||
if _, err := os.Stat(mb.path); err != nil {
|
||||
@@ -314,7 +314,7 @@ func (mb *FileMailbox) createDir() error {
|
||||
}
|
||||
|
||||
// removeDir removes the mailbox, plus empty higher level directories
|
||||
func (mb *FileMailbox) removeDir() error {
|
||||
func (mb *Mailbox) removeDir() error {
|
||||
dirMx.Lock()
|
||||
defer dirMx.Unlock()
|
||||
// remove mailbox dir, including index file
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package filestore
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -359,7 +359,7 @@ func TestFSMissing(t *testing.T) {
|
||||
// Delete a message file without removing it from index
|
||||
msg, err := mb.GetMessage(sentIds[1])
|
||||
assert.Nil(t, err)
|
||||
fmsg := msg.(*FileMessage)
|
||||
fmsg := msg.(*Message)
|
||||
_ = os.Remove(fmsg.rawPath())
|
||||
msg, err = mb.GetMessage(sentIds[1])
|
||||
assert.Nil(t, err)
|
||||
@@ -508,7 +508,7 @@ func TestGetLatestMessage(t *testing.T) {
|
||||
}
|
||||
|
||||
// setupDataStore creates a new FileDataStore in a temporary directory
|
||||
func setupDataStore(cfg config.DataStoreConfig) (*FileDataStore, *bytes.Buffer) {
|
||||
func setupDataStore(cfg config.DataStoreConfig) (*Store, *bytes.Buffer) {
|
||||
path, err := ioutil.TempDir("", "inbucket")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -519,12 +519,12 @@ func setupDataStore(cfg config.DataStoreConfig) (*FileDataStore, *bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
|
||||
cfg.Path = path
|
||||
return NewFileDataStore(cfg).(*FileDataStore), buf
|
||||
return New(cfg).(*Store), buf
|
||||
}
|
||||
|
||||
// deliverMessage creates and delivers a message to the specific mailbox, returning
|
||||
// the size of the generated message.
|
||||
func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
||||
func deliverMessage(ds *Store, mbName string, subject string,
|
||||
date time.Time) (id string, size int64) {
|
||||
// Build fake SMTP message for delivery
|
||||
testMsg := make([]byte, 0, 300)
|
||||
@@ -544,7 +544,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmsg := msg.(*FileMessage)
|
||||
fmsg := msg.(*Message)
|
||||
fmsg.Fdate = date
|
||||
fmsg.Fid = id
|
||||
if err = msg.Append(testMsg); err != nil {
|
||||
@@ -557,7 +557,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
||||
return id, int64(len(testMsg))
|
||||
}
|
||||
|
||||
func teardownDataStore(ds *FileDataStore) {
|
||||
func teardownDataStore(ds *Store) {
|
||||
if err := os.RemoveAll(ds.path); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package datastore
|
||||
package storage
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package datastore_test
|
||||
package storage_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestHashLock(t *testing.T) {
|
||||
hl := &datastore.HashLock{}
|
||||
hl := &storage.HashLock{}
|
||||
|
||||
// Invalid hashes
|
||||
testCases := []struct {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package datastore
|
||||
package storage
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
@@ -47,14 +47,14 @@ func init() {
|
||||
type RetentionScanner struct {
|
||||
globalShutdown chan bool // Closes when Inbucket needs to shut down
|
||||
retentionShutdown chan bool // Closed after the scanner has shut down
|
||||
ds DataStore
|
||||
ds Store
|
||||
retentionPeriod time.Duration
|
||||
retentionSleep time.Duration
|
||||
}
|
||||
|
||||
// NewRetentionScanner launches a go-routine that scans for expired
|
||||
// messages, following the configured interval
|
||||
func NewRetentionScanner(ds DataStore, shutdownChannel chan bool) *RetentionScanner {
|
||||
func NewRetentionScanner(ds Store, shutdownChannel chan bool) *RetentionScanner {
|
||||
cfg := config.GetDataStoreConfig()
|
||||
rs := &RetentionScanner{
|
||||
globalShutdown: shutdownChannel,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package datastore
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Package datastore contains implementation independent datastore logic
|
||||
package datastore
|
||||
// Package storage contains implementation independent datastore logic
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -19,8 +19,8 @@ var (
|
||||
ErrNotWritable = errors.New("Message not writable")
|
||||
)
|
||||
|
||||
// DataStore is an interface to get Mailboxes stored in Inbucket
|
||||
type DataStore interface {
|
||||
// Store is an interface to get Mailboxes stored in Inbucket
|
||||
type Store interface {
|
||||
MailboxFor(emailAddress string) (Mailbox, error)
|
||||
AllMailboxes() ([]Mailbox, error)
|
||||
// LockFor is a temporary hack to fix #77 until Datastore revamp
|
||||
@@ -1,4 +1,4 @@
|
||||
package datastore
|
||||
package storage
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
Reference in New Issue
Block a user