1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

storage: finish renaming storage packages for #79 #69

- storage: rename DataStore to Store
- file: rename types to appease linter
This commit is contained in:
James Hillyerd
2018-03-10 13:34:35 -08:00
parent 98d8288244
commit a58dfc5e4f
21 changed files with 135 additions and 135 deletions

View File

@@ -116,7 +116,7 @@ func main() {
msgHub := msghub.New(rootCtx, config.GetWebConfig().MonitorHistory) msgHub := msghub.New(rootCtx, config.GetWebConfig().MonitorHistory)
// Grab our datastore // Grab our datastore
ds := filestore.DefaultFileDataStore() ds := file.DefaultStore()
// Start HTTP server // Start HTTP server
web.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub) web.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub)

View File

@@ -65,7 +65,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
msg, err := mb.GetMessage(id) msg, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -150,7 +150,7 @@ func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *web.Context)
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -184,7 +184,7 @@ func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *web.Context)
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }

View File

@@ -31,7 +31,7 @@ const (
func TestRestMailboxList(t *testing.T) { func TestRestMailboxList(t *testing.T) {
// Setup // Setup
ds := &datastore.MockDataStore{} ds := &storage.MockDataStore{}
logbuf := setupWebServer(ds) logbuf := setupWebServer(ds)
// Test invalid mailbox name // Test invalid mailbox name
@@ -45,9 +45,9 @@ func TestRestMailboxList(t *testing.T) {
} }
// Test empty mailbox // Test empty mailbox
emptybox := &datastore.MockMailbox{} emptybox := &storage.MockMailbox{}
ds.On("MailboxFor", "empty").Return(emptybox, nil) ds.On("MailboxFor", "empty").Return(emptybox, nil)
emptybox.On("GetMessages").Return([]datastore.Message{}, nil) emptybox.On("GetMessages").Return([]storage.Message{}, nil)
w, err = testRestGet(baseURL + "/mailbox/empty") w, err = testRestGet(baseURL + "/mailbox/empty")
expectCode = 200 expectCode = 200
@@ -59,7 +59,7 @@ func TestRestMailboxList(t *testing.T) {
} }
// Test MailboxFor error // Test MailboxFor error
ds.On("MailboxFor", "error").Return(&datastore.MockMailbox{}, fmt.Errorf("Internal error")) ds.On("MailboxFor", "error").Return(&storage.MockMailbox{}, fmt.Errorf("Internal error"))
w, err = testRestGet(baseURL + "/mailbox/error") w, err = testRestGet(baseURL + "/mailbox/error")
expectCode = 500 expectCode = 500
if err != nil { if err != nil {
@@ -77,9 +77,9 @@ func TestRestMailboxList(t *testing.T) {
} }
// Test MailboxFor error // Test MailboxFor error
error2box := &datastore.MockMailbox{} error2box := &storage.MockMailbox{}
ds.On("MailboxFor", "error2").Return(error2box, nil) ds.On("MailboxFor", "error2").Return(error2box, nil)
error2box.On("GetMessages").Return([]datastore.Message{}, fmt.Errorf("Internal error 2")) error2box.On("GetMessages").Return([]storage.Message{}, fmt.Errorf("Internal error 2"))
w, err = testRestGet(baseURL + "/mailbox/error2") w, err = testRestGet(baseURL + "/mailbox/error2")
expectCode = 500 expectCode = 500
@@ -107,11 +107,11 @@ func TestRestMailboxList(t *testing.T) {
Subject: "subject 2", Subject: "subject 2",
Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)), Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)),
} }
goodbox := &datastore.MockMailbox{} goodbox := &storage.MockMailbox{}
ds.On("MailboxFor", "good").Return(goodbox, nil) ds.On("MailboxFor", "good").Return(goodbox, nil)
msg1 := data1.MockMessage() msg1 := data1.MockMessage()
msg2 := data2.MockMessage() msg2 := data2.MockMessage()
goodbox.On("GetMessages").Return([]datastore.Message{msg1, msg2}, nil) goodbox.On("GetMessages").Return([]storage.Message{msg1, msg2}, nil)
// Check return code // Check return code
w, err = testRestGet(baseURL + "/mailbox/good") w, err = testRestGet(baseURL + "/mailbox/good")
@@ -155,7 +155,7 @@ func TestRestMailboxList(t *testing.T) {
func TestRestMessage(t *testing.T) { func TestRestMessage(t *testing.T) {
// Setup // Setup
ds := &datastore.MockDataStore{} ds := &storage.MockDataStore{}
logbuf := setupWebServer(ds) logbuf := setupWebServer(ds)
// Test invalid mailbox name // Test invalid mailbox name
@@ -169,9 +169,9 @@ func TestRestMessage(t *testing.T) {
} }
// Test requesting a message that does not exist // Test requesting a message that does not exist
emptybox := &datastore.MockMailbox{} emptybox := &storage.MockMailbox{}
ds.On("MailboxFor", "empty").Return(emptybox, nil) ds.On("MailboxFor", "empty").Return(emptybox, nil)
emptybox.On("GetMessage", "0001").Return(&datastore.MockMessage{}, datastore.ErrNotExist) emptybox.On("GetMessage", "0001").Return(&storage.MockMessage{}, storage.ErrNotExist)
w, err = testRestGet(baseURL + "/mailbox/empty/0001") w, err = testRestGet(baseURL + "/mailbox/empty/0001")
expectCode = 404 expectCode = 404
@@ -183,7 +183,7 @@ func TestRestMessage(t *testing.T) {
} }
// Test MailboxFor error // Test MailboxFor error
ds.On("MailboxFor", "error").Return(&datastore.MockMailbox{}, fmt.Errorf("Internal error")) ds.On("MailboxFor", "error").Return(&storage.MockMailbox{}, fmt.Errorf("Internal error"))
w, err = testRestGet(baseURL + "/mailbox/error/0001") w, err = testRestGet(baseURL + "/mailbox/error/0001")
expectCode = 500 expectCode = 500
if err != nil { if err != nil {
@@ -201,9 +201,9 @@ func TestRestMessage(t *testing.T) {
} }
// Test GetMessage error // Test GetMessage error
error2box := &datastore.MockMailbox{} error2box := &storage.MockMailbox{}
ds.On("MailboxFor", "error2").Return(error2box, nil) ds.On("MailboxFor", "error2").Return(error2box, nil)
error2box.On("GetMessage", "0001").Return(&datastore.MockMessage{}, fmt.Errorf("Internal error 2")) error2box.On("GetMessage", "0001").Return(&storage.MockMessage{}, fmt.Errorf("Internal error 2"))
w, err = testRestGet(baseURL + "/mailbox/error2/0001") w, err = testRestGet(baseURL + "/mailbox/error2/0001")
expectCode = 500 expectCode = 500
@@ -228,7 +228,7 @@ func TestRestMessage(t *testing.T) {
Text: "This is some text", Text: "This is some text",
HTML: "This is some HTML", HTML: "This is some HTML",
} }
goodbox := &datastore.MockMailbox{} goodbox := &storage.MockMailbox{}
ds.On("MailboxFor", "good").Return(goodbox, nil) ds.On("MailboxFor", "good").Return(goodbox, nil)
msg1 := data1.MockMessage() msg1 := data1.MockMessage()
goodbox.On("GetMessage", "0001").Return(msg1, nil) goodbox.On("GetMessage", "0001").Return(msg1, nil)

View File

@@ -25,8 +25,8 @@ type InputMessageData struct {
HTML, Text string HTML, Text string
} }
func (d *InputMessageData) MockMessage() *datastore.MockMessage { func (d *InputMessageData) MockMessage() *storage.MockMessage {
msg := &datastore.MockMessage{} msg := &storage.MockMessage{}
msg.On("ID").Return(d.ID) msg.On("ID").Return(d.ID)
msg.On("From").Return(d.From) msg.On("From").Return(d.From)
msg.On("To").Return(d.To) msg.On("To").Return(d.To)
@@ -188,7 +188,7 @@ func testRestGet(url string) (*httptest.ResponseRecorder, error) {
return w, nil return w, nil
} }
func setupWebServer(ds datastore.DataStore) *bytes.Buffer { func setupWebServer(ds storage.Store) *bytes.Buffer {
// Capture log output // Capture log output
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
log.SetOutput(buf) log.SetOutput(buf)

View File

@@ -65,8 +65,8 @@ type Session struct {
state State // Current session state state State // Current session state
reader *bufio.Reader // Buffered reader for our net conn reader *bufio.Reader // Buffered reader for our net conn
user string // Mailbox name user string // Mailbox name
mailbox datastore.Mailbox // Mailbox instance mailbox storage.Mailbox // Mailbox instance
messages []datastore.Message // Slice of messages in mailbox messages []storage.Message // Slice of messages in mailbox
retain []bool // Messages to retain upon UPDATE (true=retain) retain []bool // Messages to retain upon UPDATE (true=retain)
msgCount int // Number of undeleted messages msgCount int // Number of undeleted messages
} }
@@ -432,7 +432,7 @@ func (ses *Session) transactionHandler(cmd string, args []string) {
} }
// Send the contents of the message to the client // Send the contents of the message to the client
func (ses *Session) sendMessage(msg datastore.Message) { func (ses *Session) sendMessage(msg storage.Message) {
reader, err := msg.RawReader() reader, err := msg.RawReader()
if err != nil { if err != nil {
ses.logError("Failed to read message for RETR command") ses.logError("Failed to read message for RETR command")
@@ -465,7 +465,7 @@ func (ses *Session) sendMessage(msg datastore.Message) {
} }
// Send the headers plus the top N lines to the client // Send the headers plus the top N lines to the client
func (ses *Session) sendMessageTop(msg datastore.Message, lineCount int) { func (ses *Session) sendMessageTop(msg storage.Message, lineCount int) {
reader, err := msg.RawReader() reader, err := msg.RawReader()
if err != nil { if err != nil {
ses.logError("Failed to read message for RETR command") ses.logError("Failed to read message for RETR command")

View File

@@ -17,14 +17,14 @@ type Server struct {
host string host string
domain string domain string
maxIdleSeconds int maxIdleSeconds int
dataStore datastore.DataStore dataStore storage.Store
listener net.Listener listener net.Listener
globalShutdown chan bool globalShutdown chan bool
waitgroup *sync.WaitGroup waitgroup *sync.WaitGroup
} }
// New creates a new Server struct // New creates a new Server struct
func New(cfg config.POP3Config, shutdownChan chan bool, ds datastore.DataStore) *Server { func New(cfg config.POP3Config, shutdownChan chan bool, ds storage.Store) *Server {
return &Server{ return &Server{
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port), host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
domain: cfg.Domain, domain: cfg.Domain,

View File

@@ -73,7 +73,7 @@ var commands = map[string]bool{
// recipientDetails for message delivery // recipientDetails for message delivery
type recipientDetails struct { type recipientDetails struct {
address, localPart, domainPart string address, localPart, domainPart string
mailbox datastore.Mailbox mailbox storage.Mailbox
} }
// Session holds the state of an SMTP session // Session holds the state of an SMTP session

View File

@@ -26,7 +26,7 @@ type scriptStep struct {
// Test commands in GREET state // Test commands in GREET state
func TestGreetState(t *testing.T) { func TestGreetState(t *testing.T) {
// Setup mock objects // Setup mock objects
mds := &datastore.MockDataStore{} mds := &storage.MockDataStore{}
server, logbuf, teardown := setupSMTPServer(mds) server, logbuf, teardown := setupSMTPServer(mds)
defer teardown() defer teardown()
@@ -83,7 +83,7 @@ func TestGreetState(t *testing.T) {
// Test commands in READY state // Test commands in READY state
func TestReadyState(t *testing.T) { func TestReadyState(t *testing.T) {
// Setup mock objects // Setup mock objects
mds := &datastore.MockDataStore{} mds := &storage.MockDataStore{}
server, logbuf, teardown := setupSMTPServer(mds) server, logbuf, teardown := setupSMTPServer(mds)
defer teardown() defer teardown()
@@ -144,9 +144,9 @@ func TestReadyState(t *testing.T) {
// Test commands in MAIL state // Test commands in MAIL state
func TestMailState(t *testing.T) { func TestMailState(t *testing.T) {
// Setup mock objects // Setup mock objects
mds := &datastore.MockDataStore{} mds := &storage.MockDataStore{}
mb1 := &datastore.MockMailbox{} mb1 := &storage.MockMailbox{}
msg1 := &datastore.MockMessage{} msg1 := &storage.MockMessage{}
mds.On("MailboxFor", "u1").Return(mb1, nil) mds.On("MailboxFor", "u1").Return(mb1, nil)
mb1.On("NewMessage").Return(msg1, nil) mb1.On("NewMessage").Return(msg1, nil)
mb1.On("Name").Return("u1") mb1.On("Name").Return("u1")
@@ -259,9 +259,9 @@ func TestMailState(t *testing.T) {
// Test commands in DATA state // Test commands in DATA state
func TestDataState(t *testing.T) { func TestDataState(t *testing.T) {
// Setup mock objects // Setup mock objects
mds := &datastore.MockDataStore{} mds := &storage.MockDataStore{}
mb1 := &datastore.MockMailbox{} mb1 := &storage.MockMailbox{}
msg1 := &datastore.MockMessage{} msg1 := &storage.MockMessage{}
mds.On("MailboxFor", "u1").Return(mb1, nil) mds.On("MailboxFor", "u1").Return(mb1, nil)
mb1.On("NewMessage").Return(msg1, nil) mb1.On("NewMessage").Return(msg1, nil)
mb1.On("Name").Return("u1") mb1.On("Name").Return("u1")
@@ -367,7 +367,7 @@ func (m *mockConn) SetDeadline(t time.Time) error { return nil }
func (m *mockConn) SetReadDeadline(t time.Time) error { return nil } func (m *mockConn) SetReadDeadline(t time.Time) error { return nil }
func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil } func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
func setupSMTPServer(ds datastore.DataStore) (s *Server, buf *bytes.Buffer, teardown func()) { func setupSMTPServer(ds storage.Store) (s *Server, buf *bytes.Buffer, teardown func()) {
// Test Server Config // Test Server Config
cfg := config.SMTPConfig{ cfg := config.SMTPConfig{
IP4address: net.IPv4(127, 0, 0, 1), IP4address: net.IPv4(127, 0, 0, 1),

View File

@@ -48,10 +48,10 @@ type Server struct {
storeMessages bool storeMessages bool
// Dependencies // Dependencies
dataStore datastore.DataStore // Mailbox/message store dataStore storage.Store // Mailbox/message store
globalShutdown chan bool // Shuts down Inbucket globalShutdown chan bool // Shuts down Inbucket
msgHub *msghub.Hub // Pub/sub for message info msgHub *msghub.Hub // Pub/sub for message info
retentionScanner *datastore.RetentionScanner // Deletes expired messages retentionScanner *storage.RetentionScanner // Deletes expired messages
// State // State
listener net.Listener // Incoming network connections listener net.Listener // Incoming network connections
@@ -83,7 +83,7 @@ var (
func NewServer( func NewServer(
cfg config.SMTPConfig, cfg config.SMTPConfig,
globalShutdown chan bool, globalShutdown chan bool,
ds datastore.DataStore, ds storage.Store,
msgHub *msghub.Hub) *Server { msgHub *msghub.Hub) *Server {
return &Server{ return &Server{
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port), host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
@@ -96,7 +96,7 @@ func NewServer(
globalShutdown: globalShutdown, globalShutdown: globalShutdown,
dataStore: ds, dataStore: ds,
msgHub: msgHub, msgHub: msgHub,
retentionScanner: datastore.NewRetentionScanner(ds, globalShutdown), retentionScanner: storage.NewRetentionScanner(ds, globalShutdown),
waitgroup: new(sync.WaitGroup), waitgroup: new(sync.WaitGroup),
} }
} }

View File

@@ -15,7 +15,7 @@ import (
type Context struct { type Context struct {
Vars map[string]string Vars map[string]string
Session *sessions.Session Session *sessions.Session
DataStore datastore.DataStore DataStore storage.Store
MsgHub *msghub.Hub MsgHub *msghub.Hub
WebConfig config.WebConfig WebConfig config.WebConfig
IsJSON bool IsJSON bool

View File

@@ -23,7 +23,7 @@ type Handler func(http.ResponseWriter, *http.Request, *Context) error
var ( var (
// DataStore is where all the mailboxes and messages live // DataStore is where all the mailboxes and messages live
DataStore datastore.DataStore DataStore storage.Store
// msgHub holds a reference to the message pub/sub system // msgHub holds a reference to the message pub/sub system
msgHub *msghub.Hub msgHub *msghub.Hub
@@ -51,7 +51,7 @@ func init() {
func Initialize( func Initialize(
cfg config.WebConfig, cfg config.WebConfig,
shutdownChan chan bool, shutdownChan chan bool,
ds datastore.DataStore, ds storage.Store,
mh *msghub.Hub) { mh *msghub.Hub) {
webConfig = cfg webConfig = cfg

View File

@@ -1,4 +1,4 @@
package filestore package file
import ( import (
"bufio" "bufio"
@@ -15,10 +15,10 @@ import (
"github.com/jhillyerd/inbucket/pkg/storage" "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. // particular email message, and methods to retrieve the rest of it from disk.
type FileMessage struct { type Message struct {
mailbox *FileMailbox mailbox *Mailbox
// Stored in GOB // Stored in GOB
Fid string Fid string
Fdate time.Time Fdate time.Time
@@ -34,7 +34,7 @@ type FileMessage struct {
// NewMessage creates a new FileMessage object and sets the Date and Id fields. // NewMessage creates a new FileMessage object and sets the Date and Id fields.
// It will also delete messages over messageCap if configured. // 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 // Load index
if !mb.indexLoaded { if !mb.indexLoaded {
if err := mb.readIndex(); err != nil { if err := mb.readIndex(); err != nil {
@@ -54,50 +54,50 @@ func (mb *FileMailbox) NewMessage() (datastore.Message, error) {
date := time.Now() date := time.Now()
id := generateID(date) 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 // ID gets the ID of the Message
func (m *FileMessage) ID() string { func (m *Message) ID() string {
return m.Fid return m.Fid
} }
// Date returns the date/time this Message was received by Inbucket // 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 return m.Fdate
} }
// From returns the value of the Message From header // From returns the value of the Message From header
func (m *FileMessage) From() string { func (m *Message) From() string {
return m.Ffrom return m.Ffrom
} }
// To returns the value of the Message To header // To returns the value of the Message To header
func (m *FileMessage) To() []string { func (m *Message) To() []string {
return m.Fto return m.Fto
} }
// Subject returns the value of the Message Subject header // Subject returns the value of the Message Subject header
func (m *FileMessage) Subject() string { func (m *Message) Subject() string {
return m.Fsubject return m.Fsubject
} }
// String returns a string in the form: "Subject()" from From() // 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) return fmt.Sprintf("\"%v\" from %v", m.Fsubject, m.Ffrom)
} }
// Size returns the size of the Message on disk in bytes // Size returns the size of the Message on disk in bytes
func (m *FileMessage) Size() int64 { func (m *Message) Size() int64 {
return m.Fsize return m.Fsize
} }
func (m *FileMessage) rawPath() string { func (m *Message) rawPath() string {
return filepath.Join(m.mailbox.path, m.Fid+".raw") 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 // 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()) file, err := os.Open(m.rawPath())
if err != nil { if err != nil {
return nil, err 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 // 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()) file, err := os.Open(m.rawPath())
if err != nil { if err != nil {
return nil, err 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 // 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()) file, err := os.Open(m.rawPath())
if err != nil { if err != nil {
return nil, err 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 // 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() reader, err := m.RawReader()
if err != nil { if err != nil {
return nil, err 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 // Append data to a newly opened Message, this will fail on a pre-existing Message and
// after Close() is called. // 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 // Prevent Appending to a pre-existing Message
if !m.writable { if !m.writable {
return datastore.ErrNotWritable return storage.ErrNotWritable
} }
// Open file for writing if we haven't yet // Open file for writing if we haven't yet
if m.writer == nil { 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 // Close this Message for writing - no more data may be Appended. Close() will also
// trigger the creation of the .gob file. // 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 // nil out the writer fields so they can't be used
writer := m.writer writer := m.writer
writerFile := m.writerFile 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 // Delete this Message from disk by removing it from the index and deleting the
// raw files. // raw files.
func (m *FileMessage) Delete() error { func (m *Message) Delete() error {
messages := m.mailbox.messages messages := m.mailbox.messages
for i, mm := range messages { for i, mm := range messages {
if m == mm { if m == mm {

View File

@@ -1,4 +1,4 @@
package filestore package file
import ( import (
"bufio" "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 // hiearchy. It provides access to Mailbox objects
type FileDataStore struct { type Store struct {
hashLock datastore.HashLock hashLock storage.HashLock
path string path string
mailPath string mailPath string
messageCap int messageCap int
} }
// NewFileDataStore creates a new DataStore object using the specified path // New creates a new DataStore object using the specified path
func NewFileDataStore(cfg config.DataStoreConfig) datastore.DataStore { func New(cfg config.DataStoreConfig) storage.Store {
path := cfg.Path path := cfg.Path
if path == "" { if path == "" {
log.Errorf("No value configured for datastore 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) 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. // construct it's path.
func DefaultFileDataStore() datastore.DataStore { func DefaultStore() storage.Store {
cfg := config.GetDataStoreConfig() cfg := config.GetDataStoreConfig()
return NewFileDataStore(cfg) return New(cfg)
} }
// MailboxFor retrieves the Mailbox object for a specified email address, if the mailbox // MailboxFor retrieves the Mailbox object for a specified email address, if the mailbox
// does not exist, it will attempt to create it. // 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) name, err := stringutil.ParseMailboxName(emailAddress)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -94,13 +94,13 @@ func (ds *FileDataStore) MailboxFor(emailAddress string) (datastore.Mailbox, err
path := filepath.Join(ds.mailPath, s1, s2, dir) path := filepath.Join(ds.mailPath, s1, s2, dir)
indexPath := filepath.Join(path, indexFileName) 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 indexPath: indexPath}, nil
} }
// AllMailboxes returns a slice with all Mailboxes // AllMailboxes returns a slice with all Mailboxes
func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) { func (ds *Store) AllMailboxes() ([]storage.Mailbox, error) {
mailboxes := make([]datastore.Mailbox, 0, 100) mailboxes := make([]storage.Mailbox, 0, 100)
infos1, err := ioutil.ReadDir(ds.mailPath) infos1, err := ioutil.ReadDir(ds.mailPath)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -127,7 +127,7 @@ func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
mbdir := inf3.Name() mbdir := inf3.Name()
mbpath := filepath.Join(ds.mailPath, l1, l2, mbdir) mbpath := filepath.Join(ds.mailPath, l1, l2, mbdir)
idx := filepath.Join(mbpath, indexFileName) idx := filepath.Join(mbpath, indexFileName)
mb := &FileMailbox{store: ds, dirName: mbdir, path: mbpath, mb := &Mailbox{store: ds, dirName: mbdir, path: mbpath,
indexPath: idx} indexPath: idx}
mailboxes = append(mailboxes, mb) 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. // 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) name, err := stringutil.ParseMailboxName(emailAddress)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -150,38 +150,38 @@ func (ds *FileDataStore) LockFor(emailAddress string) (*sync.RWMutex, error) {
return ds.hashLock.Get(hash), nil 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. // correlates to a particular directory on disk.
type FileMailbox struct { type Mailbox struct {
store *FileDataStore store *Store
name string name string
dirName string dirName string
path string path string
indexLoaded bool indexLoaded bool
indexPath string indexPath string
messages []*FileMessage messages []*Message
} }
// Name of the mailbox // Name of the mailbox
func (mb *FileMailbox) Name() string { func (mb *Mailbox) Name() string {
return mb.name return mb.name
} }
// String renders the name and directory path of the mailbox // 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 + "]" return mb.name + "[" + mb.dirName + "]"
} }
// GetMessages scans the mailbox directory for .gob files and decodes them into // GetMessages scans the mailbox directory for .gob files and decodes them into
// a slice of Message objects. // a slice of Message objects.
func (mb *FileMailbox) GetMessages() ([]datastore.Message, error) { func (mb *Mailbox) GetMessages() ([]storage.Message, error) {
if !mb.indexLoaded { if !mb.indexLoaded {
if err := mb.readIndex(); err != nil { if err := mb.readIndex(); err != nil {
return nil, err return nil, err
} }
} }
messages := make([]datastore.Message, len(mb.messages)) messages := make([]storage.Message, len(mb.messages))
for i, m := range mb.messages { for i, m := range mb.messages {
messages[i] = m 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 // 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 !mb.indexLoaded {
if err := mb.readIndex(); err != nil { if err := mb.readIndex(); err != nil {
return nil, err 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 // Purge deletes all messages in this mailbox
func (mb *FileMailbox) Purge() error { func (mb *Mailbox) Purge() error {
mb.messages = mb.messages[:0] mb.messages = mb.messages[:0]
return mb.writeIndex() return mb.writeIndex()
} }
// readIndex loads the mailbox index data from disk // readIndex loads the mailbox index data from disk
func (mb *FileMailbox) readIndex() error { func (mb *Mailbox) readIndex() error {
// Clear message slice, open index // Clear message slice, open index
mb.messages = mb.messages[:0] mb.messages = mb.messages[:0]
// Lock for reading // Lock for reading
@@ -242,7 +242,7 @@ func (mb *FileMailbox) readIndex() error {
// Decode gob data // Decode gob data
dec := gob.NewDecoder(bufio.NewReader(file)) dec := gob.NewDecoder(bufio.NewReader(file))
for { for {
msg := new(FileMessage) msg := new(Message)
if err = dec.Decode(msg); err != nil { if err = dec.Decode(msg); err != nil {
if err == io.EOF { if err == io.EOF {
// It's OK to get an EOF here // 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 // writeIndex overwrites the index on disk with the current mailbox data
func (mb *FileMailbox) writeIndex() error { func (mb *Mailbox) writeIndex() error {
// Lock for writing // Lock for writing
indexMx.Lock() indexMx.Lock()
defer indexMx.Unlock() 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 // 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() dirMx.Lock()
defer dirMx.Unlock() defer dirMx.Unlock()
if _, err := os.Stat(mb.path); err != nil { 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 // removeDir removes the mailbox, plus empty higher level directories
func (mb *FileMailbox) removeDir() error { func (mb *Mailbox) removeDir() error {
dirMx.Lock() dirMx.Lock()
defer dirMx.Unlock() defer dirMx.Unlock()
// remove mailbox dir, including index file // remove mailbox dir, including index file

View File

@@ -1,4 +1,4 @@
package filestore package file
import ( import (
"bytes" "bytes"
@@ -359,7 +359,7 @@ func TestFSMissing(t *testing.T) {
// Delete a message file without removing it from index // Delete a message file without removing it from index
msg, err := mb.GetMessage(sentIds[1]) msg, err := mb.GetMessage(sentIds[1])
assert.Nil(t, err) assert.Nil(t, err)
fmsg := msg.(*FileMessage) fmsg := msg.(*Message)
_ = os.Remove(fmsg.rawPath()) _ = os.Remove(fmsg.rawPath())
msg, err = mb.GetMessage(sentIds[1]) msg, err = mb.GetMessage(sentIds[1])
assert.Nil(t, err) assert.Nil(t, err)
@@ -508,7 +508,7 @@ func TestGetLatestMessage(t *testing.T) {
} }
// setupDataStore creates a new FileDataStore in a temporary directory // 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") path, err := ioutil.TempDir("", "inbucket")
if err != nil { if err != nil {
panic(err) panic(err)
@@ -519,12 +519,12 @@ func setupDataStore(cfg config.DataStoreConfig) (*FileDataStore, *bytes.Buffer)
log.SetOutput(buf) log.SetOutput(buf)
cfg.Path = path cfg.Path = path
return NewFileDataStore(cfg).(*FileDataStore), buf return New(cfg).(*Store), buf
} }
// deliverMessage creates and delivers a message to the specific mailbox, returning // deliverMessage creates and delivers a message to the specific mailbox, returning
// the size of the generated message. // 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) { date time.Time) (id string, size int64) {
// Build fake SMTP message for delivery // Build fake SMTP message for delivery
testMsg := make([]byte, 0, 300) testMsg := make([]byte, 0, 300)
@@ -544,7 +544,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmsg := msg.(*FileMessage) fmsg := msg.(*Message)
fmsg.Fdate = date fmsg.Fdate = date
fmsg.Fid = id fmsg.Fid = id
if err = msg.Append(testMsg); err != nil { if err = msg.Append(testMsg); err != nil {
@@ -557,7 +557,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
return id, int64(len(testMsg)) return id, int64(len(testMsg))
} }
func teardownDataStore(ds *FileDataStore) { func teardownDataStore(ds *Store) {
if err := os.RemoveAll(ds.path); err != nil { if err := os.RemoveAll(ds.path); err != nil {
panic(err) panic(err)
} }

View File

@@ -1,4 +1,4 @@
package datastore package storage
import ( import (
"strconv" "strconv"

View File

@@ -1,4 +1,4 @@
package datastore_test package storage_test
import ( import (
"testing" "testing"
@@ -7,7 +7,7 @@ import (
) )
func TestHashLock(t *testing.T) { func TestHashLock(t *testing.T) {
hl := &datastore.HashLock{} hl := &storage.HashLock{}
// Invalid hashes // Invalid hashes
testCases := []struct { testCases := []struct {

View File

@@ -1,4 +1,4 @@
package datastore package storage
import ( import (
"container/list" "container/list"
@@ -47,14 +47,14 @@ func init() {
type RetentionScanner struct { type RetentionScanner struct {
globalShutdown chan bool // Closes when Inbucket needs to shut down globalShutdown chan bool // Closes when Inbucket needs to shut down
retentionShutdown chan bool // Closed after the scanner has shut down retentionShutdown chan bool // Closed after the scanner has shut down
ds DataStore ds Store
retentionPeriod time.Duration retentionPeriod time.Duration
retentionSleep time.Duration retentionSleep time.Duration
} }
// NewRetentionScanner launches a go-routine that scans for expired // NewRetentionScanner launches a go-routine that scans for expired
// messages, following the configured interval // messages, following the configured interval
func NewRetentionScanner(ds DataStore, shutdownChannel chan bool) *RetentionScanner { func NewRetentionScanner(ds Store, shutdownChannel chan bool) *RetentionScanner {
cfg := config.GetDataStoreConfig() cfg := config.GetDataStoreConfig()
rs := &RetentionScanner{ rs := &RetentionScanner{
globalShutdown: shutdownChannel, globalShutdown: shutdownChannel,

View File

@@ -1,4 +1,4 @@
package datastore package storage
import ( import (
"fmt" "fmt"

View File

@@ -1,5 +1,5 @@
// Package datastore contains implementation independent datastore logic // Package storage contains implementation independent datastore logic
package datastore package storage
import ( import (
"errors" "errors"
@@ -19,8 +19,8 @@ var (
ErrNotWritable = errors.New("Message not writable") ErrNotWritable = errors.New("Message not writable")
) )
// DataStore is an interface to get Mailboxes stored in Inbucket // Store is an interface to get Mailboxes stored in Inbucket
type DataStore interface { type Store interface {
MailboxFor(emailAddress string) (Mailbox, error) MailboxFor(emailAddress string) (Mailbox, error)
AllMailboxes() ([]Mailbox, error) AllMailboxes() ([]Mailbox, error)
// LockFor is a temporary hack to fix #77 until Datastore revamp // LockFor is a temporary hack to fix #77 until Datastore revamp

View File

@@ -1,4 +1,4 @@
package datastore package storage
import ( import (
"io" "io"

View File

@@ -105,7 +105,7 @@ func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *web.Context) (er
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
msg, err := mb.GetMessage(id) msg, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -154,7 +154,7 @@ func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *web.Context) (er
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -191,7 +191,7 @@ func MailboxSource(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -237,7 +237,7 @@ func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *web.Co
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }
@@ -290,7 +290,7 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *web.Contex
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err) return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
} }
message, err := mb.GetMessage(id) message, err := mb.GetMessage(id)
if err == datastore.ErrNotExist { if err == storage.ErrNotExist {
http.NotFound(w, req) http.NotFound(w, req)
return nil return nil
} }