Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [1.24.x, 1.25.x]
go-version: [1.26.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
Expand Down
5 changes: 0 additions & 5 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ linters:
- unconvert
- unparam
settings:
govet:
disable:
# printf: non-constant format string in call to fmt.Errorf (govet)
# showing up since golangci-lint version 1.60.1
- printf
nakedret:
max-func-lines: 0 # Disallow any unnamed return statement
exclusions:
Expand Down
5 changes: 2 additions & 3 deletions data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
)

Expand Down Expand Up @@ -48,7 +47,7 @@ type sourceData struct {
}

func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewReader(s.data)), nil
return io.NopCloser(bytes.NewReader(s.data)), nil
}

// sourceReadCloser represents an input stream with Close method.
Expand All @@ -69,7 +68,7 @@ func parseDataSource(source interface{}) (dataSource, error) {
case io.ReadCloser:
return &sourceReadCloser{s}, nil
case io.Reader:
return &sourceReadCloser{ioutil.NopCloser(s)}, nil
return &sourceReadCloser{io.NopCloser(s)}, nil
default:
return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
}
Expand Down
3 changes: 1 addition & 2 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"sync"
Expand Down Expand Up @@ -532,7 +531,7 @@ func (f *File) SaveToIndent(filename, indent string) error {
return err
}

return ioutil.WriteFile(filename, buf.Bytes(), 0666)
return os.WriteFile(filename, buf.Bytes(), 0666)
}

// SaveTo writes content to file system.
Expand Down
6 changes: 3 additions & 3 deletions file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package ini

import (
"bytes"
"io/ioutil"
"os"
"runtime"
"sort"
"testing"
Expand Down Expand Up @@ -421,10 +421,10 @@ func TestFile_WriteTo(t *testing.T) {

golden := "testdata/TestFile_WriteTo.golden"
if *update {
require.NoError(t, ioutil.WriteFile(golden, buf.Bytes(), 0644))
require.NoError(t, os.WriteFile(golden, buf.Bytes(), 0644))
}

expected, err := ioutil.ReadFile(golden)
expected, err := os.ReadFile(golden)
require.NoError(t, err)
assert.Equal(t, string(expected), buf.String())
})
Expand Down
4 changes: 2 additions & 2 deletions ini_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package ini
import (
"bytes"
"flag"
"io/ioutil"
"io"
"path/filepath"
"runtime"
"testing"
Expand Down Expand Up @@ -58,7 +58,7 @@ func TestLoad(t *testing.T) {
"testdata/minimal.ini",
[]byte("NAME = ini\nIMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s"),
bytes.NewReader([]byte(`VERSION = v1`)),
ioutil.NopCloser(bytes.NewReader([]byte("[author]\nNAME = Unknwon"))),
io.NopCloser(bytes.NewReader([]byte("[author]\nNAME = Unknwon"))),
)
require.NoError(t, err)
require.NotNil(t, f)
Expand Down
2 changes: 1 addition & 1 deletion key.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (k *Key) transformValue(val string) string {
}

// Substitute by new value and take off leading '%(' and trailing ')s'.
val = strings.ReplaceAll(val, vr, nk.value)
val = strings.ReplaceAll(val, vr, nk.String())
}
return val
}
Expand Down
19 changes: 19 additions & 0 deletions key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ func TestKey_Helpers(t *testing.T) {
}
return in
}
t.Cleanup(func() { f.ValueMapper = nil })
assert.Equal(t, "github.com/go-ini/ini", sec.Key("IMPORT_PATH").String())
})
})
Expand Down Expand Up @@ -635,4 +636,22 @@ bar = %(missing)s

assert.Equal(t, "%(missing)s", f.Section("foo").Key("bar").String())
})

t.Run("ValueMapper applies to substituted reference value", func(t *testing.T) {
f, err := Load([]byte(`
ACCOUNT_ID = ${LFSD_R2_ACCOUNT_ID}
ENDPOINT = https://%(ACCOUNT_ID)s.r2.cloudflarestorage.com
`))
require.NoError(t, err)
require.NotNil(t, f)

f.ValueMapper = func(in string) string {
if in == "${LFSD_R2_ACCOUNT_ID}" {
return "abc123"
}
return in
}

assert.Equal(t, "https://abc123.r2.cloudflarestorage.com", f.Section("").Key("ENDPOINT").String())
})
}
38 changes: 19 additions & 19 deletions struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func wrapStrictError(err error, isStrict bool) error {
// because we want to use default value that is already assigned to struct.
func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
vt := t
isPtr := t.Kind() == reflect.Ptr
isPtr := t.Kind() == reflect.Pointer
if isPtr {
vt = t.Elem()
}
Expand Down Expand Up @@ -278,7 +278,7 @@ func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bo
// mapToField maps the given value to the matching field of the given section.
// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
if val.Kind() == reflect.Ptr {
if val.Kind() == reflect.Pointer {
val = val.Elem()
}
typ := val.Type()
Expand All @@ -299,8 +299,8 @@ func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int,
}

isStruct := tpField.Type.Kind() == reflect.Struct
isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
isStructPtr := tpField.Type.Kind() == reflect.Pointer && tpField.Type.Elem().Kind() == reflect.Struct
isAnonymousPtr := tpField.Type.Kind() == reflect.Pointer && tpField.Anonymous
if isAnonymousPtr {
field.Set(reflect.New(tpField.Type.Elem()))
}
Expand Down Expand Up @@ -381,7 +381,7 @@ func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (
func (s *Section) mapTo(v interface{}, isStrict bool) error {
typ := reflect.TypeOf(v)
val := reflect.ValueOf(v)
if typ.Kind() == reflect.Ptr {
if typ.Kind() == reflect.Pointer {
typ = typ.Elem()
val = val.Elem()
} else {
Expand Down Expand Up @@ -500,13 +500,13 @@ func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, all
case reflect.String:
buf.WriteString(slice.Index(i).String())
case reflect.Int, reflect.Int64:
buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
fmt.Fprint(&buf, slice.Index(i).Int())
case reflect.Uint, reflect.Uint64:
buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
fmt.Fprint(&buf, slice.Index(i).Uint())
case reflect.Float64:
buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
fmt.Fprint(&buf, slice.Index(i).Float())
case reflect.Bool:
buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
fmt.Fprint(&buf, slice.Index(i).Bool())
case reflectTime:
buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
default:
Expand Down Expand Up @@ -535,7 +535,7 @@ func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
case reflect.Slice:
return reflectSliceWithProperType(key, field, delim, allowShadow)
case reflect.Ptr:
case reflect.Pointer:
if !field.IsNil() {
return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
}
Expand All @@ -559,7 +559,7 @@ func isEmptyValue(v reflect.Value) bool {
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
case reflect.Interface, reflect.Pointer:
return v.IsNil()
case reflectTime:
t, ok := v.Interface().(time.Time)
Expand All @@ -574,7 +574,7 @@ type StructReflector interface {
}

func (s *Section) reflectFrom(val reflect.Value) error {
if val.Kind() == reflect.Ptr {
if val.Kind() == reflect.Pointer {
val = val.Elem()
}
typ := val.Type()
Expand Down Expand Up @@ -606,14 +606,14 @@ func (s *Section) reflectFrom(val reflect.Value) error {
continue
}

if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Pointer || tpField.Type.Kind() == reflect.Struct) {
if err := s.reflectFrom(field); err != nil {
return fmt.Errorf("reflect from field %q: %v", fieldName, err)
}
continue
}

if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
if (tpField.Type.Kind() == reflect.Pointer && tpField.Type.Elem().Kind() == reflect.Struct) ||
(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
// Note: The only error here is section doesn't exist.
sec, err := s.f.GetSection(fieldName)
Expand Down Expand Up @@ -641,7 +641,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
sliceOf := field.Type().Elem().Kind()

for i := 0; i < field.Len(); i++ {
if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
if sliceOf != reflect.Struct && sliceOf != reflect.Pointer {
return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
}

Expand Down Expand Up @@ -688,11 +688,11 @@ func (s *Section) ReflectFrom(v interface{}) error {
val := reflect.ValueOf(v)

if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Pointer) {
// Clear sections to make sure none exists before adding the new ones
s.f.DeleteSection(s.name)

if typ.Kind() == reflect.Ptr {
if typ.Kind() == reflect.Pointer {
sec, err := s.f.NewSection(s.name)
if err != nil {
return err
Expand All @@ -702,7 +702,7 @@ func (s *Section) ReflectFrom(v interface{}) error {

slice := val.Slice(0, val.Len())
sliceOf := val.Type().Elem().Kind()
if sliceOf != reflect.Ptr {
if sliceOf != reflect.Pointer {
return fmt.Errorf("not a slice of pointers")
}

Expand All @@ -721,7 +721,7 @@ func (s *Section) ReflectFrom(v interface{}) error {
return nil
}

if typ.Kind() == reflect.Ptr {
if typ.Kind() == reflect.Pointer {
val = val.Elem()
} else {
return errors.New("not a pointer to a struct")
Expand Down