modernize go code

This commit is contained in:
Mechiel Lukkien
2025-09-30 17:04:53 +02:00
parent a9e15afd22
commit 48d910beed
20 changed files with 50 additions and 74 deletions
+4
View File
@@ -94,6 +94,10 @@ govendor:
go mod vendor
./genlicenses.sh
modernize:
# skip slicescontains because it rewrites to unintuitive slices.ContainsFunc
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -category=-slicescontains -fix -test ./...
test-integration:
-docker compose -f docker-compose-integration.yml kill
-docker compose -f docker-compose-integration.yml down
+11 -33
View File
@@ -323,15 +323,11 @@ func DKIMAdd(ctx context.Context, domain, selector dns.Domain, algorithm, hash s
// All good, time to update the config.
nd := d
nd.DKIM.Selectors = map[string]config.Selector{}
for name, osel := range d.DKIM.Selectors {
nd.DKIM.Selectors[name] = osel
}
maps.Copy(nd.DKIM.Selectors, d.DKIM.Selectors)
nd.DKIM.Selectors[selector.Name()] = nsel
nc := c
nc.Domains = map[string]config.Domain{}
for name, dom := range c.Domains {
nc.Domains[name] = dom
}
maps.Copy(nc.Domains, c.Domains)
nc.Domains[domain.Name()] = nd
if err := mox.WriteDynamicLocked(ctx, log, nc); err != nil {
@@ -384,9 +380,7 @@ func DKIMRemove(ctx context.Context, domain, selector dns.Domain) (rerr error) {
nd.DKIM = config.DKIM{Selectors: nsels, Sign: nsign}
nc := c
nc.Domains = map[string]config.Domain{}
for name, dom := range c.Domains {
nc.Domains[name] = dom
}
maps.Copy(nc.Domains, c.Domains)
nc.Domains[domain.Name()] = nd
if err := mox.WriteDynamicLocked(ctx, log, nc); err != nil {
@@ -431,9 +425,7 @@ func DomainAdd(ctx context.Context, disabled bool, domain dns.Domain, accountNam
// leave no trace.
nc := c
nc.Domains = map[string]config.Domain{}
for name, d := range c.Domains {
nc.Domains[name] = d
}
maps.Copy(nc.Domains, c.Domains)
// Only enable mta-sts for domain if there is a listener with mta-sts.
var withMTASTS bool
@@ -467,9 +459,7 @@ func DomainAdd(ctx context.Context, disabled bool, domain dns.Domain, accountNam
} else if accountName != mox.Conf.Static.Postmaster.Account {
nacc := nc.Accounts[accountName]
nd := map[string]config.Destination{}
for k, v := range nacc.Destinations {
nd[k] = v
}
maps.Copy(nd, nacc.Destinations)
pmaddr := smtp.NewAddress("postmaster", domain)
nd[pmaddr.String()] = config.Destination{}
nacc.Destinations = nd
@@ -598,9 +588,7 @@ func DomainSave(ctx context.Context, domainName string, xmodify func(config *con
// Compose new config without modifying existing data structures. If we fail, we
// leave no trace.
nc.Domains = map[string]config.Domain{}
for name, d := range mox.Conf.Dynamic.Domains {
nc.Domains[name] = d
}
maps.Copy(nc.Domains, mox.Conf.Dynamic.Domains)
nc.Domains[domainName] = dom
if err := mox.WriteDynamicLocked(ctx, log, nc); err != nil {
@@ -679,9 +667,7 @@ func AccountAdd(ctx context.Context, account, address string) (rerr error) {
// leave no trace.
nc := c
nc.Accounts = map[string]config.Account{}
for name, a := range c.Accounts {
nc.Accounts[name] = a
}
maps.Copy(nc.Accounts, c.Accounts)
nc.Accounts[account] = MakeAccountConfig(addr)
if err := mox.WriteDynamicLocked(ctx, log, nc); err != nil {
@@ -848,13 +834,9 @@ func AddressAdd(ctx context.Context, address, account string) (rerr error) {
// leave no trace.
nc := c
nc.Accounts = map[string]config.Account{}
for name, a := range c.Accounts {
nc.Accounts[name] = a
}
maps.Copy(nc.Accounts, c.Accounts)
nd := map[string]config.Destination{}
for name, d := range a.Destinations {
nd[name] = d
}
maps.Copy(nd, a.Destinations)
nd[destAddr] = config.Destination{}
a.Destinations = nd
nc.Accounts[account] = a
@@ -1023,9 +1005,7 @@ func AddressRemove(ctx context.Context, address string) (rerr error) {
nc := mox.Conf.Dynamic
nc.Accounts = map[string]config.Account{}
for name, a := range mox.Conf.Dynamic.Accounts {
nc.Accounts[name] = a
}
maps.Copy(nc.Accounts, mox.Conf.Dynamic.Accounts)
nc.Accounts[ad.Account] = na
nc.Domains = domains
@@ -1145,9 +1125,7 @@ func AccountSave(ctx context.Context, account string, xmodify func(acc *config.A
// leave no trace.
nc := c
nc.Accounts = map[string]config.Account{}
for name, a := range c.Accounts {
nc.Accounts[name] = a
}
maps.Copy(nc.Accounts, c.Accounts)
nc.Accounts[account] = acc
if err := mox.WriteDynamicLocked(ctx, log, nc); err != nil {
+1
View File
@@ -316,6 +316,7 @@ done
- Gather feedback on recent changes.
- Check if dependencies need updates.
- Run "make modernize".
- Update to latest publicsuffix/ list.
- Check code if there are deprecated features that can be removed.
- Generate apidiff and check if breaking changes can be prevented. Update moxtools.
+2 -2
View File
@@ -816,8 +816,8 @@ func portServes(name string, l config.Listener) map[int]*serve {
}
// Thunderbird requests an autodiscovery URL at the email address domain name, so
// autoconfig prefix is optional.
if strings.HasPrefix(dom.ASCII, "autoconfig.") {
dom.ASCII = strings.TrimPrefix(dom.ASCII, "autoconfig.")
if after, ok := strings.CutPrefix(dom.ASCII, "autoconfig."); ok {
dom.ASCII = after
dom.Unicode = strings.TrimPrefix(dom.Unicode, "autoconfig.")
}
// Autodiscovery uses a SRV record. It shouldn't point to a CNAME. So we directly
+3 -3
View File
@@ -475,7 +475,7 @@ func HandleForward(h *config.WebForward, w http.ResponseWriter, r *http.Request,
upgrade := r.Header.Get("Upgrade")
if upgrade != "" && !(r.ProtoMajor == 1 && r.ProtoMinor == 0) {
// Websockets have case-insensitive string "websocket".
for _, s := range strings.Split(upgrade, ",") {
for s := range strings.SplitSeq(upgrade, ",") {
if strings.EqualFold(textproto.TrimString(s), "websocket") {
forwardWebsocket(h, w, r, path)
return true
@@ -549,7 +549,7 @@ func forwardWebsocket(h *config.WebForward, w http.ResponseWriter, r *http.Reque
// ../rfc/6455:1153
var connectionUpgrade bool
for _, s := range strings.Split(r.Header.Get("Connection"), ",") {
for s := range strings.SplitSeq(r.Header.Get("Connection"), ",") {
if strings.EqualFold(textproto.TrimString(s), "upgrade") {
connectionUpgrade = true
break
@@ -854,7 +854,7 @@ func removeHopByHopHeaders(h http.Header) {
// RFC 7230, section 6.1: Remove headers listed in the "Connection" header.
// ../rfc/7230:2817
for _, f := range h["Connection"] {
for _, sf := range strings.Split(f, ",") {
for sf := range strings.SplitSeq(f, ",") {
if sf = textproto.TrimString(sf); sf != "" {
h.Del(sf)
}
+2 -3
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"maps"
"net"
"net/http"
"net/http/httptest"
@@ -243,9 +244,7 @@ func TestWebsocket(t *testing.T) {
clone := func(m map[string]string) map[string]string {
r := map[string]string{}
for k, v := range m {
r[k] = v
}
maps.Copy(r, m)
return r
}
+1 -1
View File
@@ -20,7 +20,7 @@ func FuzzParser(f *testing.F) {
if err != nil {
f.Fatalf("reading seed: %v", err)
}
for _, s := range strings.Split(string(buf), "\n") {
for s := range strings.SplitSeq(string(buf), "\n") {
f.Add(s + "\r\n")
}
f.Add("1:3")
+1 -1
View File
@@ -1048,7 +1048,7 @@ func bodyFldLang(p *message.Part) token {
return nilt
}
var l listspace
for _, s := range strings.Split(*p.ContentLanguage, ",") {
for s := range strings.SplitSeq(*p.ContentLanguage, ",") {
s = strings.TrimSpace(s)
if s == "" {
return string0(*p.ContentLanguage)
+1 -1
View File
@@ -462,7 +462,7 @@ func testSearch(t *testing.T, uidonly bool) {
// esearchall makes an UntaggedEsearch response with All set, for comparisons.
func esearchall0(ss string) imapclient.NumSet {
seqset := imapclient.NumSet{}
for _, rs := range strings.Split(ss, ",") {
for rs := range strings.SplitSeq(ss, ",") {
t := strings.Split(rs, ":")
if len(t) > 2 {
panic("bad seqset")
+4 -4
View File
@@ -417,7 +417,7 @@ func usage(l []cmd, unlisted bool) {
if c.unlisted && !unlisted {
continue
}
for _, line := range strings.Split(c.params, "\n") {
for line := range strings.SplitSeq(c.params, "\n") {
x := append([]string{"mox"}, c.words...)
if line != "" {
x = append(x, line)
@@ -2008,7 +2008,7 @@ exchanged during connection set up.
tlsConfig.RootCAs = pool
}
if tlsCiphersuites != "" {
for _, s := range strings.Split(tlsCiphersuites, ",") {
for s := range strings.SplitSeq(tlsCiphersuites, ",") {
s = strings.TrimSpace(s)
c, ok := ciphersuites[s]
if !ok {
@@ -2021,7 +2021,7 @@ exchanged during connection set up.
}
}
if tlsCurves != "" {
for _, s := range strings.Split(tlsCurves, ",") {
for s := range strings.SplitSeq(tlsCurves, ",") {
s = strings.TrimSpace(s)
if c, ok := curves[s]; !ok {
log.Fatalf("unknown ecc key exchange algorithm %q", s)
@@ -2128,7 +2128,7 @@ connection.
allowedUsages := []adns.TLSAUsage{}
if usages != "" {
for _, s := range strings.Split(usages, ",") {
for s := range strings.SplitSeq(usages, ",") {
var usage adns.TLSAUsage
switch strings.ToLower(s) {
case "pkix-ta", strconv.Itoa(int(adns.TLSAUsagePKIXTA)):
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// new message.
func NeedsQuotedPrintable(text string) bool {
// ../rfc/2045:1025
for _, line := range strings.Split(text, "\r\n") {
for line := range strings.SplitSeq(text, "\r\n") {
// 78 should be fine too, qp itself has a requirement of 76 bytes on a line, but
// using qp for anything longer than 76 is safer.
if len(line) > 76 || strings.Contains(line, "\r") || strings.Contains(line, "\n") {
+2 -3
View File
@@ -17,6 +17,7 @@ import (
"fmt"
"io"
"log/slog"
"maps"
"net"
"net/http"
"net/url"
@@ -130,9 +131,7 @@ func (c *Config) LogLevelRemove(log mlog.Log, pkg string) {
// must be called with log lock held.
func (c *Config) copyLogLevels() map[string]slog.Level {
m := map[string]slog.Level{}
for pkg, level := range c.Log {
m[pkg] = level
}
maps.Copy(m, c.Log)
return m
}
+2 -2
View File
@@ -37,7 +37,7 @@ func RestorePassedFiles() {
// 0,1,2 are stdin,stdout,stderr, 3 is the first passed fd (first listeners, then files).
var o uintptr = 3
for _, addr := range strings.Split(s, ",") {
for addr := range strings.SplitSeq(s, ",") {
passedListeners[addr] = os.NewFile(o, addr)
o++
}
@@ -46,7 +46,7 @@ func RestorePassedFiles() {
if files == "" {
return
}
for _, path := range strings.Split(files, ",") {
for path := range strings.SplitSeq(files, ",") {
passedFiles[path] = append(passedFiles[path], os.NewFile(o, path))
o++
}
+4 -4
View File
@@ -94,7 +94,7 @@ func ctlcmdQueueHoldrulesRemove(ctl *ctl, id int64) {
// filtering the messages the operation applies to.
func flagFilterSort(fs *flag.FlagSet, f *queue.Filter, s *queue.Sort) {
fs.Func("ids", "comma-separated list of message IDs", func(v string) error {
for _, s := range strings.Split(v, ",") {
for s := range strings.SplitSeq(v, ",") {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
@@ -144,7 +144,7 @@ func flagFilterSort(fs *flag.FlagSet, f *queue.Filter, s *queue.Sort) {
// flagRetiredFilterSort has filters for retired messages.
func flagRetiredFilterSort(fs *flag.FlagSet, f *queue.RetiredFilter, s *queue.RetiredSort) {
fs.Func("ids", "comma-separated list of retired message IDs", func(v string) error {
for _, s := range strings.Split(v, ",") {
for s := range strings.SplitSeq(v, ",") {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
@@ -608,7 +608,7 @@ func ctlcmdQueueRetiredPrint(ctl *ctl, id string) {
// filtering the webhooks the operation applies to.
func flagHookFilterSort(fs *flag.FlagSet, f *queue.HookFilter, s *queue.HookSort) {
fs.Func("ids", "comma-separated list of webhook IDs", func(v string) error {
for _, s := range strings.Split(v, ",") {
for s := range strings.SplitSeq(v, ",") {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
@@ -650,7 +650,7 @@ func flagHookFilterSort(fs *flag.FlagSet, f *queue.HookFilter, s *queue.HookSort
// for filtering the webhooks the operation applies to.
func flagHookRetiredFilterSort(fs *flag.FlagSet, f *queue.HookRetiredFilter, s *queue.HookRetiredSort) {
fs.Func("ids", "comma-separated list of retired webhook IDs", func(v string) error {
for _, s := range strings.Split(v, ",") {
for s := range strings.SplitSeq(v, ",") {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
+4 -4
View File
@@ -216,9 +216,9 @@ func cmdUpdatesServe(c *cmd) {
if fromVersion != nil {
nextchange:
for i, c := range cl.Changes {
for _, line := range strings.Split(strings.Split(c.Text, "\n\n")[0], "\n") {
if strings.HasPrefix(line, "version:") {
v, err := updates.ParseVersion(strings.TrimSpace(strings.TrimPrefix(line, "version:")))
for line := range strings.SplitSeq(strings.Split(c.Text, "\n\n")[0], "\n") {
if after, ok := strings.CutPrefix(line, "version:"); ok {
v, err := updates.ParseVersion(strings.TrimSpace(after))
if err == nil && !v.After(*fromVersion) {
cl.Changes = cl.Changes[:i]
break nextchange
@@ -232,7 +232,7 @@ func cmdUpdatesServe(c *cmd) {
accept := r.Header.Get("Accept")
var html bool
accept:
for _, ac := range strings.Split(accept, ",") {
for ac := range strings.SplitSeq(accept, ",") {
var ok bool
for i, kv := range strings.Split(strings.TrimSpace(ac), ";") {
if i == 0 {
+2 -3
View File
@@ -13,6 +13,7 @@ import (
"fmt"
"io"
"log/slog"
"maps"
"net/http"
"net/url"
"os"
@@ -509,9 +510,7 @@ func (Account) DestinationSave(ctx context.Context, destName string, oldDest, ne
// Make copy of reference values.
nd := map[string]config.Destination{}
for dn, d := range conf.Destinations {
nd[dn] = d
}
maps.Copy(nd, conf.Destinations)
nd[destName] = newDest
conf.Destinations = nd
})
+1 -1
View File
@@ -1892,7 +1892,7 @@ func dnsblsStatus(ctx context.Context, log mlog.Log, resolver dns.Resolver) (res
func (Admin) MonitorDNSBLsSave(ctx context.Context, text string) {
var zones []dns.Domain
publicZones := mox.Conf.Static.Listeners["public"].SMTP.DNSBLZones
for _, line := range strings.Split(text, "\n") {
for line := range strings.SplitSeq(text, "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
+1 -1
View File
@@ -1241,7 +1241,7 @@ func (s server) MessageGet(ctx context.Context, req webapi.MessageGetRequest) (r
var refs []string
for _, s := range h.Values("References") {
s = strings.ReplaceAll(s, "\t", " ")
for _, w := range strings.Split(s, " ") {
for w := range strings.SplitSeq(s, " ") {
if w != "" {
refs = append(refs, w)
}
+2 -6
View File
@@ -1998,9 +1998,7 @@ func (Webmail) RulesetAdd(ctx context.Context, rcptTo string, ruleset config.Rul
}
nd := map[string]config.Destination{}
for addr, d := range acc.Destinations {
nd[addr] = d
}
maps.Copy(nd, acc.Destinations)
dest.Rulesets = append(slices.Clone(dest.Rulesets), ruleset)
nd[rcptTo] = dest
acc.Destinations = nd
@@ -2018,9 +2016,7 @@ func (Webmail) RulesetRemove(ctx context.Context, rcptTo string, ruleset config.
}
nd := map[string]config.Destination{}
for addr, d := range acc.Destinations {
nd[addr] = d
}
maps.Copy(nd, acc.Destinations)
var l []config.Ruleset
skipped := 0
for _, rs := range dest.Rulesets {
+1 -1
View File
@@ -29,7 +29,7 @@ func Export(log mlog.Log, accName string, w http.ResponseWriter, r *http.Request
messageIDstr := r.FormValue("messageids")
var messageIDs []int64
if messageIDstr != "" {
for _, s := range strings.Split(messageIDstr, ",") {
for s := range strings.SplitSeq(messageIDstr, ",") {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
http.Error(w, fmt.Sprintf("400 - bad request - bad message id %q: %v", s, err), http.StatusBadRequest)