aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Cox <me@jasoncarloscox.com>2024-02-22 20:25:16 -0500
committerRobin Jarry <robin@jarry.cc>2024-04-13 21:46:35 +0200
commit4a0bb5d1840f282989bb6b4e3ec16d3da4d5c7f7 (patch)
tree4440ae9566d38fb52ce0f12ac3fccbcf9bd10f32
parent8312b46f144cc1bcf5b6838854df2a9b167c1c3a (diff)
downloadaerc-4a0bb5d1840f282989bb6b4e3ec16d3da4d5c7f7.tar.gz
aerc-4a0bb5d1840f282989bb6b4e3ec16d3da4d5c7f7.zip
ipc: retry failed command directly, not over IPC
If IPC fails the first time we try it, we know that no other aerc instance is running. When we retry, run the command directly instead of going through the current instance's own IPC server. Signed-off-by: Jason Cox <me@jasoncarloscox.com> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--app/aerc.go33
-rw-r--r--app/app.go1
-rw-r--r--lib/ipc/handler.go6
-rw-r--r--lib/ipc/receive.go46
-rw-r--r--main.go20
5 files changed, 40 insertions, 66 deletions
diff --git a/app/aerc.go b/app/aerc.go
index 7418e979..667696f7 100644
--- a/app/aerc.go
+++ b/app/aerc.go
@@ -698,7 +698,31 @@ func (aerc *Aerc) RegisterChoices(choices []Choice) {
aerc.prompts.Push(p)
}
-func (aerc *Aerc) Mailto(addr *url.URL) error {
+func (aerc *Aerc) Command(args []string) error {
+ switch {
+ case len(args) == 0:
+ return nil // noop success, i.e. ping
+ case strings.HasPrefix(args[0], "mailto:"):
+ mailto, err := url.Parse(args[0])
+ if err != nil {
+ return err
+ }
+ return aerc.mailto(mailto)
+ case strings.HasPrefix(args[0], "mbox:"):
+ return aerc.mbox(args[0])
+ case strings.HasPrefix(args[0], ":"):
+ cmdline := args[0]
+ if len(args) > 1 {
+ cmdline = opt.QuoteArgs(args...).String()
+ }
+ defer ui.Invalidate()
+ return aerc.cmd(cmdline, nil, nil)
+ default:
+ return errors.New("command not understood")
+ }
+}
+
+func (aerc *Aerc) mailto(addr *url.URL) error {
var subject string
var body string
var acctName string
@@ -790,7 +814,7 @@ func (aerc *Aerc) Mailto(addr *url.URL) error {
return nil
}
-func (aerc *Aerc) Mbox(source string) error {
+func (aerc *Aerc) mbox(source string) error {
acctConf := config.AccountConfig{}
if selectedAcct := aerc.SelectedAccount(); selectedAcct != nil {
acctConf = *selectedAcct.acct
@@ -819,11 +843,6 @@ func (aerc *Aerc) Mbox(source string) error {
return nil
}
-func (aerc *Aerc) Command(cmd string) error {
- defer ui.Invalidate()
- return aerc.cmd(cmd, nil, nil)
-}
-
func (aerc *Aerc) CloseBackends() error {
var returnErr error
for _, acct := range aerc.accounts {
diff --git a/app/app.go b/app/app.go
index ca9c59bb..7e06ce3b 100644
--- a/app/app.go
+++ b/app/app.go
@@ -26,6 +26,7 @@ func Init(
func Drawable() ui.DrawableInteractive { return &aerc }
func IPCHandler() ipc.Handler { return &aerc }
+func Command(args []string) error { return aerc.Command(args) }
func HandleMessage(msg types.WorkerMessage) { aerc.HandleMessage(msg) }
func CloseBackends() error { return aerc.CloseBackends() }
diff --git a/lib/ipc/handler.go b/lib/ipc/handler.go
index 10f42753..9ed81be0 100644
--- a/lib/ipc/handler.go
+++ b/lib/ipc/handler.go
@@ -1,9 +1,5 @@
package ipc
-import "net/url"
-
type Handler interface {
- Mailto(addr *url.URL) error
- Mbox(source string) error
- Command(cmdline string) error
+ Command(args []string) error
}
diff --git a/lib/ipc/receive.go b/lib/ipc/receive.go
index 4f6258ad..ff837d0f 100644
--- a/lib/ipc/receive.go
+++ b/lib/ipc/receive.go
@@ -5,14 +5,10 @@ import (
"context"
"errors"
"net"
- "net/url"
"os"
- "strings"
"sync/atomic"
"time"
- "git.sr.ht/~rjarry/go-opt"
-
"git.sr.ht/~rjarry/aerc/config"
"git.sr.ht/~rjarry/aerc/lib/log"
"git.sr.ht/~rjarry/aerc/lib/xdg"
@@ -101,44 +97,12 @@ func (as *AercServer) Serve() {
}
func (as *AercServer) handleMessage(req *Request) *Response {
- if len(req.Arguments) == 0 {
- return &Response{} // send noop success message, i.e. ping
+ if config.General.DisableIPC {
+ return &Response{Error: "command rejected: IPC is disabled"}
}
- var err error
- switch {
- case strings.HasPrefix(req.Arguments[0], "mailto:"):
- mailto, err := url.Parse(req.Arguments[0])
- if err != nil {
- return &Response{Error: err.Error()}
- }
- err = as.handler.Mailto(mailto)
- if err != nil {
- return &Response{
- Error: err.Error(),
- }
- }
- case strings.HasPrefix(req.Arguments[0], "mbox:"):
- err = as.handler.Mbox(req.Arguments[0])
- if err != nil {
- return &Response{Error: err.Error()}
- }
- case strings.HasPrefix(req.Arguments[0], ":"):
- if config.General.DisableIPC {
- return &Response{
- Error: "command rejected: IPC is disabled",
- }
- }
- cmdline := req.Arguments[0]
- if len(req.Arguments) > 1 {
- cmdline = opt.QuoteArgs(req.Arguments...).String()
- }
- err = as.handler.Command(cmdline)
- if err != nil {
- return &Response{Error: err.Error()}
- }
-
- default:
- return &Response{Error: "command not understood"}
+ err := as.handler.Command(req.Arguments)
+ if err != nil {
+ return &Response{Error: err.Error()}
}
return &Response{}
}
diff --git a/main.go b/main.go
index f73ac1e9..cc65dc44 100644
--- a/main.go
+++ b/main.go
@@ -212,25 +212,19 @@ func main() {
// set the aerc version so that we can use it in the template funcs
templates.SetVersion(Version)
- enableIpc := func() {
+ endStartup := func() {
startupDone()
if len(opts.Command) == 0 {
return
}
- // retry execution
- response, err := ipc.ConnectAndExec(opts.Command)
- var errMsg string
+ // Retry execution. Since IPC has already failed, we know no
+ // other aerc instance is running; run the command directly.
+ err := app.Command(opts.Command)
if err != nil {
- errMsg = err.Error()
- } else {
- errMsg = response.Error
- }
-
- if errMsg != "" {
// no other aerc instance is running, so let
// this one stay running but show the error
- errMsg = fmt.Sprintf("Startup command (%s) failed: %s\n",
- strings.Join(opts.Command, " "), errMsg)
+ errMsg := fmt.Sprintf("Startup command (%s) failed: %s\n",
+ strings.Join(opts.Command, " "), err)
log.Errorf(errMsg)
app.PushError(errMsg)
}
@@ -265,7 +259,7 @@ loop:
// it will be ready. And in some cases, it may never be.
// At least, we can be confident that accepting IPC
// commands will not crash the whole process.
- once.Do(enableIpc)
+ once.Do(endStartup)
case callback := <-ui.Callbacks:
callback()
case <-ui.Redraw: