Add skip file support, and only log parse errors @ INFO level.
This commit is contained in:
parent
73f1751d5b
commit
9becd3e2e7
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"xinu.tv/email"
|
"xinu.tv/email"
|
||||||
|
|
||||||
@ -13,10 +14,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dryrun = flag.Bool("dryrun", true, "don't actually rename files, just log actions.")
|
dryrun = flag.Bool("dryrun", true, "don't actually rename files, just log actions.")
|
||||||
saveFile = flag.String("save", "", "filename to store unread status.")
|
saveFile = flag.String("save", "", "filename to store unread status.")
|
||||||
loadFile = flag.String("load", "", "filename to load unread status.")
|
loadFile = flag.String("load", "", "filename to load unread status.")
|
||||||
maildir = flag.String("maildir", "", "Maildir root")
|
maildir = flag.String("maildir", "", "Maildir root")
|
||||||
|
skipFiles = flag.String("skip", "maildirfolder,log,msgid.cache,razor-agent.log",
|
||||||
|
"comma separated files to skip")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
@ -25,7 +28,12 @@ type Status struct {
|
|||||||
Read bool `json:"read,omitempty"`
|
Read bool `json:"read,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Messages []Status
|
type Messages struct {
|
||||||
|
// Filenames to skip when hash mail.
|
||||||
|
Skip map[string]struct{}
|
||||||
|
// Read mail status.
|
||||||
|
Statuses []Status
|
||||||
|
}
|
||||||
|
|
||||||
var headers = []string{"to", "from", "cc", "date", "subject"}
|
var headers = []string{"to", "from", "cc", "date", "subject"}
|
||||||
|
|
||||||
@ -38,17 +46,19 @@ func (m *Messages) hashMail(path string, info os.FileInfo, err error) error {
|
|||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := os.Open(path)
|
r, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
h, err := email.Hash(r, headers)
|
h, err := email.Hash(r, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("%s %q", path, err.Error())
|
glog.Errorf("%s not an mail file", path)
|
||||||
|
glog.Info("%q", err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
md := email.NewInfo(path)
|
md := email.NewInfo(path)
|
||||||
*m = append(*m, Status{
|
m.Statuses = append(m.Statuses, Status{
|
||||||
Path: path,
|
Path: path,
|
||||||
Hash: fmt.Sprintf("%x", h.Sum(nil)),
|
Hash: fmt.Sprintf("%x", h.Sum(nil)),
|
||||||
Read: md.Seen,
|
Read: md.Seen,
|
||||||
@ -64,7 +74,7 @@ func (m *Messages) LoadStatus(statusFile string) error {
|
|||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
dec := json.NewDecoder(r)
|
dec := json.NewDecoder(r)
|
||||||
return dec.Decode(m)
|
return dec.Decode(&m.Statuses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messages) SaveStatus(maildir, statusFile string) error {
|
func (m *Messages) SaveStatus(maildir, statusFile string) error {
|
||||||
@ -96,9 +106,9 @@ func (m *Messages) SaveStatus(maildir, statusFile string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m Messages) Reconcile(maildir string) error {
|
func (m Messages) Reconcile(maildir string) error {
|
||||||
hashMap := make(map[string]*Status, len(m))
|
hashMap := make(map[string]*Status, len(m.Statuses))
|
||||||
for i, msg := range m {
|
for i, msg := range m.Statuses {
|
||||||
hashMap[msg.Hash] = &m[i]
|
hashMap[msg.Hash] = &m.Statuses[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Walk(maildir, func(path string, info os.FileInfo, err error) error {
|
return filepath.Walk(maildir, func(path string, info os.FileInfo, err error) error {
|
||||||
@ -110,6 +120,12 @@ func (m Messages) Reconcile(maildir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base := filepath.Base(path)
|
||||||
|
if _, ok := m.Skip[base]; ok {
|
||||||
|
glog.Infoln("Skipping", path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
r, err := os.Open(path)
|
r, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
@ -117,7 +133,8 @@ func (m Messages) Reconcile(maildir string) error {
|
|||||||
|
|
||||||
h, err := email.Hash(r, headers)
|
h, err := email.Hash(r, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("%s %q", path, err.Error())
|
glog.Errorf("%s not an mail file", path)
|
||||||
|
glog.Infof("%q", err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +160,7 @@ func (m Messages) Reconcile(maildir string) error {
|
|||||||
|
|
||||||
func (m Messages) PrintStats() {
|
func (m Messages) PrintStats() {
|
||||||
r, u, t := 0, 0, 0
|
r, u, t := 0, 0, 0
|
||||||
for _, msg := range m {
|
for _, msg := range m.Statuses {
|
||||||
t++
|
t++
|
||||||
if msg.Read {
|
if msg.Read {
|
||||||
r++
|
r++
|
||||||
@ -159,7 +176,16 @@ func (m Messages) PrintStats() {
|
|||||||
func main() {
|
func main() {
|
||||||
defer glog.Flush()
|
defer glog.Flush()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
m := Messages{}
|
skipStr := strings.Split(*skipFiles, ",")
|
||||||
|
skip := make(map[string]struct{}, len(skipStr))
|
||||||
|
for _, s := range skipStr {
|
||||||
|
skip[s] = struct{}{}
|
||||||
|
}
|
||||||
|
glog.Infoln("Skip files", skip)
|
||||||
|
|
||||||
|
m := Messages{
|
||||||
|
Skip: skip,
|
||||||
|
}
|
||||||
|
|
||||||
if *maildir == "" {
|
if *maildir == "" {
|
||||||
fmt.Println("Must specify Maildir with -maildir")
|
fmt.Println("Must specify Maildir with -maildir")
|
||||||
@ -184,6 +210,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
m.PrintStats()
|
m.PrintStats()
|
||||||
if err := m.Reconcile(*maildir); err != nil {
|
if err := m.Reconcile(*maildir); err != nil {
|
||||||
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user