From 2b0f02ae030066482480b7dbbe38d6f7d58ac898 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 31 Dec 2017 16:50:53 -0800 Subject: [PATCH] Move maildir related functionality to own package. --- cmd/mailhash/mailhash.go | 30 ++++++------- maildir.go | 80 ----------------------------------- maildir_test.go | 91 ---------------------------------------- 3 files changed, 16 insertions(+), 185 deletions(-) delete mode 100644 maildir.go delete mode 100644 maildir_test.go diff --git a/cmd/mailhash/mailhash.go b/cmd/mailhash/mailhash.go index 1800791..143429b 100644 --- a/cmd/mailhash/mailhash.go +++ b/cmd/mailhash/mailhash.go @@ -7,17 +7,19 @@ import ( "os" "path/filepath" "strings" + "xinu.tv/email" + "xinu.tv/email/maildir" "github.com/golang/glog" ) var ( - dryrun = flag.Bool("dryrun", true, "don't actually rename files, just log actions.") - saveFile = flag.String("save", "", "filename to store unread status.") - loadFile = flag.String("load", "", "filename to load unread status.") - maildir = flag.String("maildir", "", "Maildir root") - skipFiles = flag.String("skip", "maildirfolder,log,msgid.cache,razor-agent.log", + dryrun = flag.Bool("dryrun", true, "don't actually rename files, just log actions.") + saveFile = flag.String("save", "", "filename to store unread status.") + loadFile = flag.String("load", "", "filename to load unread status.") + maildirPath = flag.String("maildir", "", "Maildir root") + skipFiles = flag.String("skip", "maildirfolder,log,msgid.cache,razor-agent.log", "comma separated files to skip") ) @@ -62,7 +64,7 @@ func (m *Messages) hashMail(path string, info os.FileInfo, err error) error { glog.Infof("%q", err.Error()) return nil } - md := email.NewInfo(path) + md := maildir.NewInfo(path) m.Statuses = append(m.Statuses, Status{ Path: path, Hash: h, @@ -82,8 +84,8 @@ func (m *Messages) LoadStatus(statusFile string) error { return dec.Decode(&m.Statuses) } -func (m *Messages) SaveStatus(maildir, statusFile string) error { - if err := filepath.Walk(maildir, m.hashMail); err != nil { +func (m *Messages) SaveStatus(maildirPath, statusFile string) error { + if err := filepath.Walk(maildirPath, m.hashMail); err != nil { return err } @@ -110,13 +112,13 @@ func (m *Messages) SaveStatus(maildir, statusFile string) error { return nil } -func (m Messages) Reconcile(maildir string) error { +func (m Messages) Reconcile(maildirPath string) error { hashMap := make(map[string]*Status, len(m.Statuses)) for i, msg := range m.Statuses { hashMap[msg.Hash] = &m.Statuses[i] } - return filepath.Walk(maildir, func(path string, info os.FileInfo, err error) error { + return filepath.Walk(maildirPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -144,7 +146,7 @@ func (m Messages) Reconcile(maildir string) error { return nil } - md := email.NewInfo(path) + md := maildir.NewInfo(path) s, ok := hashMap[chksum] if !ok { return nil @@ -192,7 +194,7 @@ func main() { Skip: skip, } - if *maildir == "" { + if *maildirPath == "" { fmt.Println("Must specify Maildir with -maildir") os.Exit(1) } @@ -203,7 +205,7 @@ func main() { } if *saveFile != "" { - if err := m.SaveStatus(*maildir, *saveFile); err != nil { + if err := m.SaveStatus(*maildirPath, *saveFile); err != nil { glog.Fatal(err) } m.PrintStats() @@ -214,7 +216,7 @@ func main() { glog.Fatal(err) } m.PrintStats() - if err := m.Reconcile(*maildir); err != nil { + if err := m.Reconcile(*maildirPath); err != nil { glog.Fatal(err) } } diff --git a/maildir.go b/maildir.go deleted file mode 100644 index 0ea3010..0000000 --- a/maildir.go +++ /dev/null @@ -1,80 +0,0 @@ -// Package email helps manage emails stored in Maildir format. A good -// write-up on the format is available at http://cr.yp.to/proto/maildir.html -package email - -import ( - "bytes" - "fmt" - "strings" -) - -// Info represents the info bits encoded as the suffix of a Maildir file. info -// starting with "2,": Each character after the comma is an independent flag. -// Flag "P" (passed): the user has resent/forwarded/bounced this message to someone else. -// Flag "R" (replied): the user has replied to this message. -// Flag "S" (seen): the user has viewed this message, though perhaps he didn't read all the way through it. -// Flag "T" (trashed): the user has moved this message to the trash; the trash will be emptied by a later user action. -// Flag "D" (draft): the user considers this message a draft; toggled at user discretion. -// Flag "F" (flagged): user-defined flag; toggled at user discretion. -// New flags may be defined later. Flags must be stored in ASCII order: e.g., "2,FRS". -type Info struct { - Base string // The portion of the filename before the ':'. - Passed bool - Replied bool - Seen bool - Trashed bool - Draft bool - Flagged bool -} - -// NewInfo returns an Info containing the version 2 Maildir flags parsed from -// fn's suffix. -func NewInfo(fn string) (info Info) { - info.Base = fn - i := strings.LastIndex(fn, ":") - if i != -1 { - info.Base = fn[:i] - infoStr := fn[i:] - i = strings.Index(infoStr, ",") - if i == -1 { - return - } - - flags := infoStr[i:] - info.Passed = strings.Contains(flags, "P") - info.Replied = strings.Contains(flags, "R") - info.Seen = strings.Contains(flags, "S") - info.Trashed = strings.Contains(flags, "T") - info.Draft = strings.Contains(flags, "D") - info.Flagged = strings.Contains(flags, "F") - } - return -} - -func (i Info) String() string { - if i.Passed || i.Replied || i.Seen || i.Trashed || i.Draft || i.Flagged { - b := new(bytes.Buffer) - fmt.Fprintf(b, "%s:2,", i.Base) - if i.Passed { - fmt.Fprint(b, "P") - } - if i.Replied { - fmt.Fprint(b, "R") - } - if i.Seen { - fmt.Fprint(b, "S") - } - if i.Trashed { - fmt.Fprint(b, "T") - } - if i.Draft { - fmt.Fprint(b, "D") - } - if i.Flagged { - fmt.Fprint(b, "F") - } - return b.String() - } - - return i.Base -} diff --git a/maildir_test.go b/maildir_test.go deleted file mode 100644 index 27beee3..0000000 --- a/maildir_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package email - -import ( - "reflect" - "testing" -) - -func TestInfo(t *testing.T) { - datum := []struct { - input string - want Info - clean string // Expected result from .String(), empty defaults to input. - }{ - { - input: "mail:2,PRSTDF", - want: Info{ - Base: "mail", - Passed: true, - Replied: true, - Seen: true, - Trashed: true, - Draft: true, - Flagged: true, - }, - }, - { - input: "mail:2,PRTDF", - want: Info{ - Base: "mail", - Passed: true, - Replied: true, - Seen: false, - Trashed: true, - Draft: true, - Flagged: true, - }, - }, - { - input: "mail:2,PRSTD", - want: Info{ - Base: "mail", - Passed: true, - Replied: true, - Seen: true, - Trashed: true, - Draft: true, - Flagged: false, - }, - }, - { - input: "mail:2,RSTDF", - want: Info{ - Base: "mail", - Passed: false, - Replied: true, - Seen: true, - Trashed: true, - Draft: true, - Flagged: true, - }, - }, - { - input: "mail", - want: Info{ - Base: "mail", - }, - }, - { - input: "mail:2,", - want: Info{ - Base: "mail", - }, - clean: "mail", - }, - } - - for i, d := range datum { - got := NewInfo(d.input) - if !reflect.DeepEqual(d.want, got) { - t.Errorf("%d. Got %#v want %#v", i, got, d.want) - } - - expected := d.input - if d.clean != "" { - expected = d.clean - } - if gotStr := got.String(); gotStr != expected { - t.Errorf("%d. Got %q want %q", i, gotStr, expected) - } - } -}