From 5ca6022d007bc83daba1e7297480d37f56554455 Mon Sep 17 00:00:00 2001 From: Moritz Poldrack Date: Fri, 29 Jul 2022 22:31:54 +0200 Subject: [PATCH] lint: ensure errors are at least logged (errcheck) Signed-off-by: Moritz Poldrack Acked-by: Robin Jarry --- aerc.go | 15 ++++++-- commands/account/export-mbox.go | 5 ++- commands/msg/forward.go | 14 +++++-- commands/msg/invite.go | 11 +++++- commands/msg/pipe.go | 13 +++++-- commands/msg/recall.go | 5 ++- commands/msg/reply.go | 11 +++++- completer/completer.go | 2 +- config/config.go | 5 ++- lib/calendar/calendar.go | 5 ++- lib/crypto/gpg/gpgbin/encrypt.go | 9 +++-- lib/crypto/gpg/gpgbin/gpgbin.go | 12 +++++- lib/crypto/gpg/gpgbin/keys.go | 5 ++- lib/crypto/gpg/gpgbin/sign.go | 9 +++-- lib/crypto/gpg/gpgbin/verify.go | 13 +++++-- lib/crypto/gpg/reader.go | 8 ++-- lib/crypto/gpg/writer.go | 19 +++++++--- lib/crypto/pgp/pgp.go | 7 +++- lib/msgstore.go | 4 +- lib/socket.go | 47 +++++++++++++++++------- lib/threadbuilder.go | 2 +- logging/logger.go | 8 ++-- logging/panic-logger.go | 2 +- widgets/account-wizard.go | 13 ++++--- widgets/compose.go | 63 +++++++++++++++++++++++++------- widgets/dirtree.go | 11 +++++- widgets/msglist.go | 6 ++- widgets/msgviewer.go | 40 ++++++++++++++++---- widgets/terminal.go | 15 ++++++-- worker/imap/open.go | 2 +- worker/mbox/models.go | 5 ++- worker/notmuch/lib/database.go | 16 ++++++-- worker/types/thread.go | 2 +- 33 files changed, 301 insertions(+), 103 deletions(-) diff --git a/aerc.go b/aerc.go index cd8c4da..9ce704b 100644 --- a/aerc.go +++ b/aerc.go @@ -164,7 +164,10 @@ func main() { deferLoop := make(chan struct{}) c := crypto.New(conf.General.PgpProvider) - c.Init() + err = c.Init() + if err != nil { + logging.Warnf("failed to initialise crypto interface: %v", err) + } defer c.Close() aerc = widgets.NewAerc(conf, c, func(cmd []string) error { @@ -205,7 +208,10 @@ func main() { err := lib.ConnectAndExec(arg) if err != nil { fmt.Fprintf(os.Stderr, "Failed to communicate to aerc: %v\n", err) - aerc.CloseBackends() + err = aerc.CloseBackends() + if err != nil { + logging.Warnf("failed to close backends: %v", err) + } return } } @@ -223,5 +229,8 @@ func main() { time.Sleep(16 * time.Millisecond) } } - aerc.CloseBackends() + err = aerc.CloseBackends() + if err != nil { + logging.Warnf("failed to close backends: %v", err) + } } diff --git a/commands/account/export-mbox.go b/commands/account/export-mbox.go index 3e86fc1..b68e1cc 100644 --- a/commands/account/export-mbox.go +++ b/commands/account/export-mbox.go @@ -96,7 +96,10 @@ func (ExportMbox) Execute(aerc *widgets.Aerc, args []string) error { done <- false case *types.FullMessage: mu.Lock() - mboxer.Write(file, msg.Content.Reader, "", t) + err := mboxer.Write(file, msg.Content.Reader, "", t) + if err != nil { + logging.Warnf("failed to write mbox: %v", err) + } for i, uid := range uids { if uid == msg.Content.Uid { uids = append(uids[:i], uids[i+1:]...) diff --git a/commands/msg/forward.go b/commands/msg/forward.go index cd62417..ddc2791 100644 --- a/commands/msg/forward.go +++ b/commands/msg/forward.go @@ -133,14 +133,20 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error { store.FetchFull([]uint32{msg.Uid}, func(fm *types.FullMessage) { tmpFile, err := os.Create(tmpFileName) if err != nil { - println(err) - // TODO: Do something with the error - addTab() + logging.Warnf("failed to create temporary attachment: %v", err) + _, err = addTab() + if err != nil { + logging.Warnf("failed to add tab: %v", err) + } return } defer tmpFile.Close() - io.Copy(tmpFile, fm.Content.Reader) + _, err = io.Copy(tmpFile, fm.Content.Reader) + if err != nil { + logging.Warnf("failed to write to tmpfile: %w", err) + return + } composer, err := addTab() if err != nil { return diff --git a/commands/msg/invite.go b/commands/msg/invite.go index 936cea7..4e8d01d 100644 --- a/commands/msg/invite.go +++ b/commands/msg/invite.go @@ -8,6 +8,7 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/calendar" "git.sr.ht/~rjarry/aerc/lib/format" + "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" "github.com/emersion/go-message/mail" @@ -153,7 +154,10 @@ func (invite) Execute(aerc *widgets.Aerc, args []string) error { } composer.SetContents(cr.PlainText) - composer.AppendPart(cr.MimeType, cr.Params, cr.CalendarText) + err = composer.AppendPart(cr.MimeType, cr.Params, cr.CalendarText) + if err != nil { + return fmt.Errorf("failed to write invitation: %w", err) + } composer.FocusTerminal() tab := aerc.NewTab(composer, subject) @@ -180,7 +184,10 @@ func (invite) Execute(aerc *widgets.Aerc, args []string) error { aerc.PushError(err.Error()) return } else { - addTab(cr) + err := addTab(cr) + if err != nil { + logging.Warnf("failed to add tab: %v", err) + } } }) return nil diff --git a/commands/msg/pipe.go b/commands/msg/pipe.go index 176d1f0..7a2489a 100644 --- a/commands/msg/pipe.go +++ b/commands/msg/pipe.go @@ -96,7 +96,10 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error { defer logging.PanicHandler() defer pipe.Close() - io.Copy(pipe, reader) + _, err := io.Copy(pipe, reader) + if err != nil { + logging.Errorf("failed to send data to pipe: %w", err) + } }() err = ecmd.Run() if err != nil { @@ -224,10 +227,14 @@ func newMessagesReader(messages []*types.FullMessage, useMbox bool) io.Reader { go func() { defer pw.Close() for _, msg := range messages { + var err error if useMbox { - mboxer.Write(pw, msg.Content.Reader, "", time.Now()) + err = mboxer.Write(pw, msg.Content.Reader, "", time.Now()) } else { - io.Copy(pw, msg.Content.Reader) + _, err = io.Copy(pw, msg.Content.Reader) + } + if err != nil { + logging.Warnf("failed to write data: %v", err) } } }() diff --git a/commands/msg/recall.go b/commands/msg/recall.go index f0bafc7..8434b8d 100644 --- a/commands/msg/recall.go +++ b/commands/msg/recall.go @@ -182,7 +182,10 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error { composer.SetEncrypt(md.IsEncrypted) } if md.IsSigned { - composer.SetSign(md.IsSigned) + err = composer.SetSign(md.IsSigned) + if err != nil { + logging.Warnf("failed to set signed state: %v", err) + } } } addTab() diff --git a/commands/msg/reply.go b/commands/msg/reply.go index dd5aa19..8365172 100644 --- a/commands/msg/reply.go +++ b/commands/msg/reply.go @@ -12,6 +12,7 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/format" + "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" "github.com/emersion/go-message/mail" @@ -224,9 +225,15 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error { store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) { buf := new(bytes.Buffer) - buf.ReadFrom(reader) + _, err := buf.ReadFrom(reader) + if err != nil { + logging.Warnf("failed to fetch bodypart: %v", err) + } original.Text = buf.String() - addTab() + err = addTab() + if err != nil { + logging.Warnf("failed to add tab: %v", err) + } }) return nil } else { diff --git a/completer/completer.go b/completer/completer.go index 83a9c12..4a65ca7 100644 --- a/completer/completer.go +++ b/completer/completer.go @@ -95,7 +95,7 @@ func (c *Completer) completeAddress(s string) ([]string, string, error) { // programs will do to signal no matches. We don't want to spam the user with // spurious error messages, so we'll ignore any errors that arise at this // point. - defer cmd.Wait() + defer cmd.Wait() //nolint:errcheck // see above completions, err := readCompletions(stdout) if err != nil { diff --git a/config/config.go b/config/config.go index 249fa27..e87dccf 100644 --- a/config/config.go +++ b/config/config.go @@ -1042,7 +1042,10 @@ func (config AercConfig) mergeContextualUi(baseUi UIConfig, continue } - mergo.Merge(&baseUi, contextualUi.UiConfig, mergo.WithOverride) + err := mergo.Merge(&baseUi, contextualUi.UiConfig, mergo.WithOverride) + if err != nil { + logging.Warnf("merge ui failed: %v", err) + } if contextualUi.UiConfig.StyleSetName != "" { baseUi.style = contextualUi.UiConfig.style } diff --git a/lib/calendar/calendar.go b/lib/calendar/calendar.go index ebe1b77..c15e035 100644 --- a/lib/calendar/calendar.go +++ b/lib/calendar/calendar.go @@ -119,7 +119,10 @@ type calendar struct { func parse(reader io.Reader) (*calendar, error) { // fix capitalized mailto for parsing of ics file var sb strings.Builder - io.Copy(&sb, reader) + _, err := io.Copy(&sb, reader) + if err != nil { + return nil, fmt.Errorf("failed to copy calendar data: %w", err) + } re := regexp.MustCompile("MAILTO:(.+@)") str := re.ReplaceAllString(sb.String(), "mailto:${1}") diff --git a/lib/crypto/gpg/gpgbin/encrypt.go b/lib/crypto/gpg/gpgbin/encrypt.go index 31245a7..9ca4526 100644 --- a/lib/crypto/gpg/gpgbin/encrypt.go +++ b/lib/crypto/gpg/gpgbin/encrypt.go @@ -25,15 +25,18 @@ func Encrypt(r io.Reader, to []string, from string) ([]byte, error) { args = append(args, "--encrypt", "-") g := newGpg(r, args) - g.cmd.Run() + err := g.cmd.Run() + if err != nil { + return nil, fmt.Errorf("gpg: failed to run encryption: %w", err) + } outRdr := bytes.NewReader(g.stdout.Bytes()) var md models.MessageDetails - err := parse(outRdr, &md) + err = parse(outRdr, &md) if err != nil { return nil, fmt.Errorf("gpg: failure to encrypt: %v. check public key(s)", err) } var buf bytes.Buffer - io.Copy(&buf, md.Body) + _, _ = io.Copy(&buf, md.Body) return buf.Bytes(), nil } diff --git a/lib/crypto/gpg/gpgbin/gpgbin.go b/lib/crypto/gpg/gpgbin/gpgbin.go index 2eb83dc..1e8c7dc 100644 --- a/lib/crypto/gpg/gpgbin/gpgbin.go +++ b/lib/crypto/gpg/gpgbin/gpgbin.go @@ -63,7 +63,11 @@ func getIdentity(key uint64) string { var outbuf strings.Builder cmd.Stdout = &outbuf - cmd.Run() + err := cmd.Run() + if err != nil { + logging.Errorf("gpg: failed to get identity: %v", err) + return "" + } out := strings.Split(outbuf.String(), "\n") for _, line := range out { if strings.HasPrefix(line, "uid") { @@ -85,7 +89,11 @@ func getKeyId(s string, private bool) string { var outbuf strings.Builder cmd.Stdout = &outbuf - cmd.Run() + err := cmd.Run() + if err != nil { + logging.Errorf("gpg: failed to get key ID: %v", err) + return "" + } out := strings.Split(outbuf.String(), "\n") for _, line := range out { if strings.HasPrefix(line, "fpr") { diff --git a/lib/crypto/gpg/gpgbin/keys.go b/lib/crypto/gpg/gpgbin/keys.go index bef90cf..ca166e9 100644 --- a/lib/crypto/gpg/gpgbin/keys.go +++ b/lib/crypto/gpg/gpgbin/keys.go @@ -36,7 +36,10 @@ func ExportPublicKey(k string) (io.Reader, error) { var stderr strings.Builder cmd.Stdout = &outbuf cmd.Stderr = &stderr - cmd.Run() + err := cmd.Run() + if err != nil { + return nil, fmt.Errorf("gpg: export failed: %w", err) + } if strings.Contains(stderr.String(), "gpg") { return nil, fmt.Errorf("gpg: error exporting key") } diff --git a/lib/crypto/gpg/gpgbin/sign.go b/lib/crypto/gpg/gpgbin/sign.go index 31fd2b5..caf31d1 100644 --- a/lib/crypto/gpg/gpgbin/sign.go +++ b/lib/crypto/gpg/gpgbin/sign.go @@ -17,15 +17,18 @@ func Sign(r io.Reader, from string) ([]byte, string, error) { } g := newGpg(r, args) - g.cmd.Run() + err := g.cmd.Run() + if err != nil { + return nil, "", fmt.Errorf("failed to run signing: %w", err) + } outRdr := bytes.NewReader(g.stdout.Bytes()) var md models.MessageDetails - err := parse(outRdr, &md) + err = parse(outRdr, &md) if err != nil { return nil, "", fmt.Errorf("failed to parse messagedetails: %v", err) } var buf bytes.Buffer - io.Copy(&buf, md.Body) + _, _ = io.Copy(&buf, md.Body) return buf.Bytes(), md.Micalg, nil } diff --git a/lib/crypto/gpg/gpgbin/verify.go b/lib/crypto/gpg/gpgbin/verify.go index be9f26f..e593084 100644 --- a/lib/crypto/gpg/gpgbin/verify.go +++ b/lib/crypto/gpg/gpgbin/verify.go @@ -2,6 +2,7 @@ package gpgbin import ( "bytes" + "fmt" "io" "io/ioutil" "os" @@ -19,7 +20,7 @@ func Verify(m io.Reader, s io.Reader) (*models.MessageDetails, error) { if err != nil { return nil, err } - io.Copy(sig, s) + _, _ = io.Copy(sig, s) sig.Close() defer os.Remove(sig.Name()) args = append(args, sig.Name(), "-") @@ -29,11 +30,17 @@ func Verify(m io.Reader, s io.Reader) (*models.MessageDetails, error) { return nil, err } g := newGpg(bytes.NewReader(orig), args) - g.cmd.Run() + err = g.cmd.Run() + if err != nil { + return nil, fmt.Errorf("gpg: failed to run verification: %w", err) + } out := bytes.NewReader(g.stdout.Bytes()) md := new(models.MessageDetails) - parse(out, md) + err = parse(out, md) + if err != nil { + return nil, fmt.Errorf("gpg: failed to parse result: %w", err) + } md.Body = bytes.NewReader(orig) diff --git a/lib/crypto/gpg/reader.go b/lib/crypto/gpg/reader.go index bf977ed..40da82f 100644 --- a/lib/crypto/gpg/reader.go +++ b/lib/crypto/gpg/reader.go @@ -38,7 +38,7 @@ func NewReader(h textproto.Header, body io.Reader) (*Reader, error) { } var headerBuf bytes.Buffer - textproto.WriteHeader(&headerBuf, h) + _ = textproto.WriteHeader(&headerBuf, h) return &Reader{ Header: h, @@ -123,7 +123,7 @@ func newEncryptedReader(h textproto.Header, mr *textproto.MultipartReader) (*Rea } var headerBuf bytes.Buffer - textproto.WriteHeader(&headerBuf, cleartextHeader) + _ = textproto.WriteHeader(&headerBuf, cleartextHeader) md.Body = io.MultiReader(&headerBuf, cleartext) return &Reader{ @@ -139,11 +139,11 @@ func newSignedReader(h textproto.Header, mr *textproto.MultipartReader, micalg s return nil, fmt.Errorf("gpgmail: failed to read signed part in multipart/signed message: %v", err) } var headerBuf bytes.Buffer - textproto.WriteHeader(&headerBuf, p.Header) + _ = textproto.WriteHeader(&headerBuf, p.Header) var msg bytes.Buffer headerRdr := bytes.NewReader(headerBuf.Bytes()) fullMsg := io.MultiReader(headerRdr, p) - io.Copy(&msg, fullMsg) + _, _ = io.Copy(&msg, fullMsg) sig, err := mr.NextPart() if err != nil { diff --git a/lib/crypto/gpg/writer.go b/lib/crypto/gpg/writer.go index 96d083e..0648ec2 100644 --- a/lib/crypto/gpg/writer.go +++ b/lib/crypto/gpg/writer.go @@ -30,7 +30,10 @@ func (es *EncrypterSigner) Close() (err error) { if err != nil { return err } - es.encryptedWriter.Write(enc) + _, err = es.encryptedWriter.Write(enc) + if err != nil { + return fmt.Errorf("gpg: failed to write encrypted writer: %w", err) + } return nil } @@ -65,8 +68,8 @@ func (s *Signer) Close() (err error) { } boundary := s.mw.Boundary() fmt.Fprintf(s.w, "--%s\r\n", boundary) - s.w.Write(s.signedMsg.Bytes()) - s.w.Write([]byte("\r\n")) + _, _ = s.w.Write(s.signedMsg.Bytes()) + _, _ = s.w.Write([]byte("\r\n")) var signedHeader textproto.Header signedHeader.Set("Content-Type", "application/pgp-signature; name=\"signature.asc\"") @@ -100,7 +103,10 @@ func Encrypt(w io.Writer, h textproto.Header, rcpts []string, from string) (io.W mw := textproto.NewMultipartWriter(w) if forceBoundary != "" { - mw.SetBoundary(forceBoundary) + err := mw.SetBoundary(forceBoundary) + if err != nil { + return nil, fmt.Errorf("gpg: failed to set boundary: %w", err) + } } params := map[string]string{ @@ -154,7 +160,10 @@ func Sign(w io.Writer, h textproto.Header, from string) (io.WriteCloser, error) mw := textproto.NewMultipartWriter(w) if forceBoundary != "" { - mw.SetBoundary(forceBoundary) + err := mw.SetBoundary(forceBoundary) + if err != nil { + return nil, fmt.Errorf("gpg: failed to set boundary: %w", err) + } } var msg bytes.Buffer diff --git a/lib/crypto/pgp/pgp.go b/lib/crypto/pgp/pgp.go index c305f06..579395f 100644 --- a/lib/crypto/pgp/pgp.go +++ b/lib/crypto/pgp/pgp.go @@ -31,7 +31,10 @@ var ( func (m *Mail) Init() error { logging.Infof("Initializing PGP keyring") - os.MkdirAll(path.Join(xdg.DataHome(), "aerc"), 0o700) + err := os.MkdirAll(path.Join(xdg.DataHome(), "aerc"), 0o700) + if err != nil { + return fmt.Errorf("failed to create data directory: %v", err) + } lockpath := path.Join(xdg.DataHome(), "aerc", "keyring.lock") lockfile, err := os.OpenFile(lockpath, os.O_CREATE|os.O_EXCL, 0o600) @@ -294,7 +297,7 @@ func (m *Mail) ExportKey(k string) (io.Reader, error) { if err != nil { return nil, fmt.Errorf("pgp: error exporting key: %v", err) } - w.Write(pks.Bytes()) + _, err = w.Write(pks.Bytes()) if err != nil { return nil, fmt.Errorf("pgp: error exporting key: %v", err) } diff --git a/lib/msgstore.go b/lib/msgstore.go index ec15d42..fd67c79 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -225,7 +225,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { newMap := make(map[uint32]*models.MessageInfo) for i := len(msg.Threads) - 1; i >= 0; i-- { - msg.Threads[i].Walk(func(t *types.Thread, level int, currentErr error) error { + _ = msg.Threads[i].Walk(func(t *types.Thread, level int, currentErr error) error { uid := t.Uid uids = append([]uint32{uid}, uids...) if msg, ok := store.Messages[uid]; ok { @@ -316,7 +316,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { store.results = newResults for _, thread := range store.Threads() { - thread.Walk(func(t *types.Thread, _ int, _ error) error { + _ = thread.Walk(func(t *types.Thread, _ int, _ error) error { if _, deleted := toDelete[t.Uid]; deleted { t.Deleted = true } diff --git a/lib/socket.go b/lib/socket.go index fa36172..c83cc8a 100644 --- a/lib/socket.go +++ b/lib/socket.go @@ -64,40 +64,56 @@ func (as *AercServer) handleClient(conn net.Conn) { clientId := atomic.AddInt64(&lastId, 1) logging.Debugf("unix:%d accepted connection", clientId) scanner := bufio.NewScanner(conn) - conn.SetDeadline(time.Now().Add(1 * time.Minute)) + err := conn.SetDeadline(time.Now().Add(1 * time.Minute)) + if err != nil { + logging.Errorf("failed to set deadline: %v", err) + } for scanner.Scan() { - conn.SetDeadline(time.Now().Add(1 * time.Minute)) + err = conn.SetDeadline(time.Now().Add(1 * time.Minute)) + if err != nil { + logging.Errorf("failed to update deadline: %v", err) + } msg := scanner.Text() logging.Debugf("unix:%d got message %s", clientId, msg) if !strings.ContainsRune(msg, ':') { - conn.Write([]byte("error: invalid command\n")) + _, innererr := conn.Write([]byte("error: invalid command\n")) + if innererr != nil { + logging.Errorf("failed to write error message: %v", innererr) + } continue } prefix := msg[:strings.IndexRune(msg, ':')] + var err error switch prefix { case "mailto": mailto, err := url.Parse(msg) if err != nil { - conn.Write([]byte(fmt.Sprintf("error: %v\n", err))) + _, innererr := conn.Write([]byte(fmt.Sprintf("error: %v\n", err))) + if innererr != nil { + logging.Errorf("failed to write error message: %v", innererr) + } break } if as.OnMailto != nil { err = as.OnMailto(mailto) - } - if err != nil { - conn.Write([]byte(fmt.Sprintf("result: %v\n", err))) - } else { - conn.Write([]byte("result: success\n")) + if err != nil { + logging.Errorf("mailto failed: %v", err) + } } case "mbox": - var err error if as.OnMbox != nil { err = as.OnMbox(msg) } + } + if err != nil { + _, err = conn.Write([]byte(fmt.Sprintf("result: %v\n", err))) if err != nil { - conn.Write([]byte(fmt.Sprintf("result: %v\n", err))) - } else { - conn.Write([]byte("result: success\n")) + logging.Errorf("failed to send error: %v") + } + } else { + _, err = conn.Write([]byte("result: success\n")) + if err != nil { + logging.Errorf("failed to send successmessage: %v") } } } @@ -110,7 +126,10 @@ func ConnectAndExec(msg string) error { if err != nil { return err } - conn.Write([]byte(msg + "\n")) + _, err = conn.Write([]byte(msg + "\n")) + if err != nil { + return fmt.Errorf("failed to send message: %w", err) + } scanner := bufio.NewScanner(conn) if !scanner.Scan() { return errors.New("No response from server") diff --git a/lib/threadbuilder.go b/lib/threadbuilder.go index ce56afe..6cd98e8 100644 --- a/lib/threadbuilder.go +++ b/lib/threadbuilder.go @@ -155,7 +155,7 @@ func (builder *ThreadBuilder) sortThreads(threads []*types.Thread, orderedUids [ func (builder *ThreadBuilder) RebuildUids(threads []*types.Thread) { uids := make([]uint32, 0, len(threads)) for i := len(threads) - 1; i >= 0; i-- { - threads[i].Walk(func(t *types.Thread, level int, currentErr error) error { + _ = threads[i].Walk(func(t *types.Thread, level int, currentErr error) error { uids = append(uids, t.Uid) return nil }) diff --git a/logging/logger.go b/logging/logger.go index 0ecc35c..cf7192e 100644 --- a/logging/logger.go +++ b/logging/logger.go @@ -36,7 +36,7 @@ func Debugf(message string, args ...interface{}) { if len(args) > 0 { message = fmt.Sprintf(message, args...) } - dbg.Output(2, message) + dbg.Output(2, message) //nolint:errcheck // we can't do anything with what we log } func Infof(message string, args ...interface{}) { @@ -46,7 +46,7 @@ func Infof(message string, args ...interface{}) { if len(args) > 0 { message = fmt.Sprintf(message, args...) } - info.Output(2, message) + info.Output(2, message) //nolint:errcheck // we can't do anything with what we log } func Warnf(message string, args ...interface{}) { @@ -56,7 +56,7 @@ func Warnf(message string, args ...interface{}) { if len(args) > 0 { message = fmt.Sprintf(message, args...) } - warn.Output(2, message) + warn.Output(2, message) //nolint:errcheck // we can't do anything with what we log } func Errorf(message string, args ...interface{}) { @@ -66,5 +66,5 @@ func Errorf(message string, args ...interface{}) { if len(args) > 0 { message = fmt.Sprintf(message, args...) } - err.Output(2, message) + err.Output(2, message) //nolint:errcheck // we can't do anything with what we log } diff --git a/logging/panic-logger.go b/logging/panic-logger.go index b80e6cf..9f57f65 100644 --- a/logging/panic-logger.go +++ b/logging/panic-logger.go @@ -42,7 +42,7 @@ func PanicHandler() { fmt.Fprintln(panicLog, strings.Repeat("#", 80)) fmt.Fprintf(outputs, "%s\n", panicMessage) fmt.Fprintf(panicLog, "Error: %v\n\n", r) - panicLog.Write(debug.Stack()) + panicLog.Write(debug.Stack()) //nolint:errcheck // we are already in a panic, so not much we can do here fmt.Fprintf(os.Stderr, "\nThis error was also written to: %s\n", filename) panic(r) } diff --git a/widgets/account-wizard.go b/widgets/account-wizard.go index 9ddecfb..5ed39d5 100644 --- a/widgets/account-wizard.go +++ b/widgets/account-wizard.go @@ -493,16 +493,17 @@ func (wizard *AccountWizard) finish(tutorial bool) { return } sec, _ = file.NewSection(wizard.accountName.String()) - sec.NewKey("source", wizard.imapUrl.String()) - sec.NewKey("outgoing", wizard.smtpUrl.String()) - sec.NewKey("default", "INBOX") + // these can't really fail + sec.NewKey("source", wizard.imapUrl.String()) //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty + sec.NewKey("outgoing", wizard.smtpUrl.String()) //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty + sec.NewKey("default", "INBOX") //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty if wizard.smtpMode == SMTP_STARTTLS { - sec.NewKey("smtp-starttls", "yes") + sec.NewKey("smtp-starttls", "yes") //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty } - sec.NewKey("from", fmt.Sprintf("%s <%s>", + sec.NewKey("from", fmt.Sprintf("%s <%s>", //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty wizard.fullName.String(), wizard.email.String())) if wizard.copySent { - sec.NewKey("copy-to", "Sent") + sec.NewKey("copy-to", "Sent") //nolint:errcheck // can't fail. option shadowing is not enabled and the key is not empty } if !wizard.temporary { diff --git a/widgets/compose.go b/widgets/compose.go index 5e8a808..b2a5e05 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -119,11 +119,15 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig, c.AddSignature() c.updateGrid() - c.updateCrypto() + err = c.updateCrypto() + if err != nil { + logging.Warnf("failed to update crypto: %v", err) + } c.ShowTerminal() if c.acctConfig.PgpAutoSign { - c.SetSign(true) + err = c.SetSign(true) + logging.Warnf("failed to enable message signing: %v", err) } if c.acctConfig.PgpOpportunisticEncrypt { c.SetEncrypt(true) @@ -196,7 +200,10 @@ func (c *Composer) SetAttachKey(attach bool) error { } } if found { - c.DeleteAttachment(name) + err := c.DeleteAttachment(name) + if err != nil { + return fmt.Errorf("failed to delete attachment '%s: %v", name, err) + } } else { attach = !attach } @@ -264,7 +271,10 @@ func (c *Composer) Sign() bool { func (c *Composer) SetEncrypt(encrypt bool) *Composer { if !encrypt { c.encrypt = encrypt - c.updateCrypto() + err := c.updateCrypto() + if err != nil { + logging.Warnf("failed to update crypto: %v", err) + } return c } // Check on any attempt to encrypt, and any lost focus of "to", "cc", or @@ -337,17 +347,38 @@ func (c *Composer) updateCrypto() error { // Note: this does not reload the editor. You must call this before the first // Draw() call. func (c *Composer) SetContents(reader io.Reader) *Composer { - c.email.Seek(0, io.SeekStart) - io.Copy(c.email, reader) - c.email.Sync() - c.email.Seek(0, io.SeekStart) + _, err := c.email.Seek(0, io.SeekStart) + if err != nil { + logging.Warnf("failed to seek beginning of mail: %v", err) + } + _, err = io.Copy(c.email, reader) + if err != nil { + logging.Warnf("failed to copy mail: %v", err) + } + err = c.email.Sync() + if err != nil { + logging.Warnf("failed to sync mail: %v", err) + } + _, err = c.email.Seek(0, io.SeekStart) + if err != nil { + logging.Warnf("failed to seek beginning of mail after sync: %v", err) + } return c } func (c *Composer) AppendContents(reader io.Reader) { - c.email.Seek(0, io.SeekEnd) - io.Copy(c.email, reader) - c.email.Sync() + _, err := c.email.Seek(0, io.SeekEnd) + if err != nil { + logging.Warnf("failed to seek beginning of mail: %v", err) + } + _, err = io.Copy(c.email, reader) + if err != nil { + logging.Warnf("failed to copy mail: %v", err) + } + err = c.email.Sync() + if err != nil { + logging.Warnf("failed to sync mail: %v", err) + } } func (c *Composer) AppendPart(mimetype string, params map[string]string, body io.Reader) error { @@ -648,7 +679,10 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error { if err != nil { return err } - io.Copy(writer, &buf) + _, err = io.Copy(writer, &buf) + if err != nil { + return fmt.Errorf("failed to write message: %w", err) + } return nil } else { @@ -1242,6 +1276,9 @@ func (c *Composer) checkEncryptionKeys(_ string) bool { // If callbacks were registered, encrypt will be set when user removes // recipients with missing keys c.encrypt = true - c.updateCrypto() + err = c.updateCrypto() + if err != nil { + logging.Warnf("failed update crypto: %v", err) + } return true } diff --git a/widgets/dirtree.go b/widgets/dirtree.go index 7b10f02..9486852 100644 --- a/widgets/dirtree.go +++ b/widgets/dirtree.go @@ -8,6 +8,7 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib/ui" + "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/worker/types" "github.com/gdamore/tcell/v2" ) @@ -363,10 +364,13 @@ func (dt *DirectoryTree) buildTree() { dt.list = make([]*types.Thread, 0) for _, node := range threads { - node.Walk(func(t *types.Thread, lvl int, err error) error { + err := node.Walk(func(t *types.Thread, lvl int, err error) error { dt.list = append(dt.list, t) return nil }) + if err != nil { + logging.Warnf("failed to walk tree: %v", err) + } } } @@ -420,12 +424,15 @@ func isVisible(node *types.Thread) bool { } func getAnyUid(node *types.Thread) (uid uint32) { - node.Walk(func(t *types.Thread, l int, err error) error { + err := node.Walk(func(t *types.Thread, l int, err error) error { if t.FirstChild == nil { uid = t.Uid } return nil }) + if err != nil { + logging.Warnf("failed to get uid: %v", err) + } return } diff --git a/widgets/msglist.go b/widgets/msglist.go index 1ddf46d..96b91cf 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -13,6 +13,7 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/lib/ui" + "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" ) @@ -93,7 +94,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) { for i := len(threads) - 1; i >= 0; i-- { var lastSubject string - threads[i].Walk(func(t *types.Thread, _ int, currentErr error) error { + err := threads[i].Walk(func(t *types.Thread, _ int, currentErr error) error { if currentErr != nil { return currentErr } @@ -132,6 +133,9 @@ func (ml *MessageList) Draw(ctx *ui.Context) { row++ return nil }) + if err != nil { + logging.Warnf("failed to walk threads: %v", err) + } if row >= ctx.Height() { break } diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index be578b9..115eb3f 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -645,7 +645,10 @@ func (pv *PartViewer) attemptCopy() { pv.copySourceToSinkStripAnsi() } else { // if it's binary we have to rely on the filter to be sane - io.Copy(pv.sink, pv.source) + _, err := io.Copy(pv.sink, pv.source) + if err != nil { + logging.Warnf("failed to copy: %w", err) + } } pv.sink.Close() }() @@ -667,14 +670,23 @@ func (pv *PartViewer) writeMailHeaders() { } field := fmt.Sprintf( "%s: %s\n", fields.Key(), value) - pv.pagerin.Write([]byte(field)) + _, err = pv.pagerin.Write([]byte(field)) + if err != nil { + logging.Errorf("failed to write to stdin of pager: %v", err) + } } // virtual header if len(info.Labels) != 0 { labels := fmtHeader(info, "Labels", "") - pv.pagerin.Write([]byte(fmt.Sprintf("Labels: %s\n", labels))) + _, err := pv.pagerin.Write([]byte(fmt.Sprintf("Labels: %s\n", labels))) + if err != nil { + logging.Errorf("failed to write to stdin of pager: %v", err) + } + } + _, err := pv.pagerin.Write([]byte{'\n'}) + if err != nil { + logging.Errorf("failed to write to stdin of pager: %v", err) } - pv.pagerin.Write([]byte{'\n'}) } } @@ -689,7 +701,10 @@ func (pv *PartViewer) hyperlinks(r io.Reader) (reader io.Reader) { func (pv *PartViewer) copyFilterOutToPager() { stdout, _ := pv.filter.StdoutPipe() stderr, _ := pv.filter.StderrPipe() - pv.filter.Start() + err := pv.filter.Start() + if err != nil { + logging.Warnf("failed to start filter: %v", err) + } ch := make(chan interface{}) go func() { defer logging.PanicHandler() @@ -718,7 +733,10 @@ func (pv *PartViewer) copyFilterOutToPager() { <-ch <-ch - pv.filter.Wait() + err := pv.filter.Wait() + if err != nil { + logging.Warnf("failed to wait for the filter process: %v", err) + } pv.pagerin.Close() }() } @@ -732,7 +750,10 @@ func (pv *PartViewer) copySourceToSinkStripAnsi() { for scanner.Scan() { text := scanner.Text() text = ansi.ReplaceAllString(text, "") - io.WriteString(pv.sink, text+"\n") + _, err := io.WriteString(pv.sink, text+"\n") + if err != nil { + logging.Warnf("failed write ", err) + } } if err := scanner.Err(); err != nil { fmt.Fprintf(os.Stderr, "failed to read line: %v\n", err) @@ -819,7 +840,10 @@ func (pv *PartViewer) Draw(ctx *ui.Context) { func (pv *PartViewer) Cleanup() { if pv.pager != nil && pv.pager.Process != nil { - pv.pager.Process.Kill() + err := pv.pager.Process.Kill() + if err != nil { + logging.Warnf("failed to kill pager process: %v", err) + } pv.pager = nil } } diff --git a/widgets/terminal.go b/widgets/terminal.go index 962b02e..293481d 100644 --- a/widgets/terminal.go +++ b/widgets/terminal.go @@ -190,8 +190,14 @@ func (term *Terminal) Close(err error) { term.pty = nil } if term.cmd != nil && term.cmd.Process != nil { - term.cmd.Process.Kill() - term.cmd.Wait() + err := term.cmd.Process.Kill() + if err != nil { + logging.Warnf("failed to kill process: %v", err) + } + err = term.cmd.Wait() + if err != nil { + logging.Warnf("failed for wait for process to terminate: %v", err) + } term.cmd = nil } if !term.closed && term.OnClose != nil { @@ -277,7 +283,10 @@ func (term *Terminal) Draw(ctx *ui.Context) { if ctx.Width() != cols || ctx.Height() != rows { term.writeMutex.Lock() - pty.Setsize(term.pty, &winsize) + err := pty.Setsize(term.pty, &winsize) + if err != nil { + logging.Warnf("failed to set terminal size: %v", err) + } term.vterm.SetSize(ctx.Height(), ctx.Width()) term.writeMutex.Unlock() rect := vterm.NewRect(0, ctx.Width(), 0, ctx.Height()) diff --git a/worker/imap/open.go b/worker/imap/open.go index 15cfa31..c734ba8 100644 --- a/worker/imap/open.go +++ b/worker/imap/open.go @@ -130,7 +130,7 @@ func (imapw *IMAPWorker) handleDirectoryThreaded( // Only initialize if we are not filtering var uids []uint32 for i := len(aercThreads) - 1; i >= 0; i-- { - aercThreads[i].Walk(func(t *types.Thread, level int, currentErr error) error { + aercThreads[i].Walk(func(t *types.Thread, level int, currentErr error) error { //nolint:errcheck // error indicates skipped threads uids = append(uids, t.Uid) return nil }) diff --git a/worker/mbox/models.go b/worker/mbox/models.go index f97530e..d98b14f 100644 --- a/worker/mbox/models.go +++ b/worker/mbox/models.go @@ -87,7 +87,10 @@ func (md *mailboxContainer) Copy(dest, src string, uids []uint32) error { if err != nil { return fmt.Errorf("could not get flags for message with uid %d", uidSrc) } - destmbox.Append(r, flags) + err = destmbox.Append(r, flags) + if err != nil { + return fmt.Errorf("could not append data to mbox: %v", err) + } } } md.mailboxes[dest] = destmbox diff --git a/worker/notmuch/lib/database.go b/worker/notmuch/lib/database.go index ac1a28e..780e7ab 100644 --- a/worker/notmuch/lib/database.go +++ b/worker/notmuch/lib/database.go @@ -234,7 +234,11 @@ func (db *DB) msgModify(key string, } defer msg.Close() - cb(msg) + err = cb(msg) + if err != nil { + logging.Warnf("callback failed: %v", err) + } + err = msg.TagsToMaildirFlags() if err != nil { logging.Errorf("could not sync maildir flags: %v", err) @@ -248,10 +252,16 @@ func (db *DB) MsgModifyTags(key string, add, remove []string) error { err := db.msgModify(key, func(msg *notmuch.Message) error { ierr := msg.Atomic(func(msg *notmuch.Message) { for _, t := range add { - msg.AddTag(t) + err := msg.AddTag(t) + if err != nil { + logging.Warnf("failed to add tag: %v", err) + } } for _, t := range remove { - msg.RemoveTag(t) + err := msg.RemoveTag(t) + if err != nil { + logging.Warnf("failed to add tag: %v", err) + } } }) return ierr diff --git a/worker/types/thread.go b/worker/types/thread.go index 705b3e4..d37d206 100644 --- a/worker/types/thread.go +++ b/worker/types/thread.go @@ -101,7 +101,7 @@ func getMaxUID(thread *Thread) uint32 { // TODO: should we make this part of the Thread type to avoid recomputation? var Uid uint32 - thread.Walk(func(t *Thread, _ int, currentErr error) error { + _ = thread.Walk(func(t *Thread, _ int, currentErr error) error { if t.Uid > Uid { Uid = t.Uid }