mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
Improve configuration merge
This commit is contained in:
parent
fe053e26b5
commit
36b0f2e91a
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/json"
|
||||||
"github.com/sagernet/sing/common/json/badjson"
|
"github.com/sagernet/sing/common/json/badjson"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -56,8 +57,7 @@ func readConfigAt(path string) (*OptionsEntry, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "read config at ", path)
|
return nil, E.Cause(err, "read config at ", path)
|
||||||
}
|
}
|
||||||
var options option.Options
|
options, err := json.UnmarshalExtended[option.Options](configContent)
|
||||||
err = options.UnmarshalJSON(configContent)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "decode config at ", path)
|
return nil, E.Cause(err, "decode config at ", path)
|
||||||
}
|
}
|
||||||
|
@ -107,13 +107,18 @@ func readConfigAndMerge() (option.Options, error) {
|
||||||
if len(optionsList) == 1 {
|
if len(optionsList) == 1 {
|
||||||
return optionsList[0].options, nil
|
return optionsList[0].options, nil
|
||||||
}
|
}
|
||||||
var mergedOptions option.Options
|
var mergedMessage json.RawMessage
|
||||||
for _, options := range optionsList {
|
for _, options := range optionsList {
|
||||||
mergedOptions, err = badjson.Merge(options.options, mergedOptions)
|
mergedMessage, err = badjson.MergeJSON(options.options.RawMessage, mergedMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return option.Options{}, E.Cause(err, "merge config at ", options.path)
|
return option.Options{}, E.Cause(err, "merge config at ", options.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var mergedOptions option.Options
|
||||||
|
err = mergedOptions.UnmarshalJSON(mergedMessage)
|
||||||
|
if err != nil {
|
||||||
|
return option.Options{}, E.Cause(err, "unmarshal merged config")
|
||||||
|
}
|
||||||
return mergedOptions, nil
|
return mergedOptions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseConfig(configContent string) (option.Options, error) {
|
func parseConfig(configContent string) (option.Options, error) {
|
||||||
var options option.Options
|
options, err := json.UnmarshalExtended[option.Options]([]byte(configContent))
|
||||||
err := options.UnmarshalJSON([]byte(configContent))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return option.Options{}, E.Cause(err, "decode config")
|
return option.Options{}, E.Cause(err, "decode config")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,12 @@ package option
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"strings"
|
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
"github.com/sagernet/sing/common/json"
|
"github.com/sagernet/sing/common/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _Options struct {
|
type _Options struct {
|
||||||
|
RawMessage json.RawMessage `json:"-"`
|
||||||
Schema string `json:"$schema,omitempty"`
|
Schema string `json:"$schema,omitempty"`
|
||||||
Log *LogOptions `json:"log,omitempty"`
|
Log *LogOptions `json:"log,omitempty"`
|
||||||
DNS *DNSOptions `json:"dns,omitempty"`
|
DNS *DNSOptions `json:"dns,omitempty"`
|
||||||
|
@ -22,19 +21,14 @@ type _Options struct {
|
||||||
type Options _Options
|
type Options _Options
|
||||||
|
|
||||||
func (o *Options) UnmarshalJSON(content []byte) error {
|
func (o *Options) UnmarshalJSON(content []byte) error {
|
||||||
decoder := json.NewDecoder(json.NewCommentFilter(bytes.NewReader(content)))
|
decoder := json.NewDecoder(bytes.NewReader(content))
|
||||||
decoder.DisallowUnknownFields()
|
decoder.DisallowUnknownFields()
|
||||||
err := decoder.Decode((*_Options)(o))
|
err := decoder.Decode((*_Options)(o))
|
||||||
if err == nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
if syntaxError, isSyntaxError := err.(*json.SyntaxError); isSyntaxError {
|
o.RawMessage = content
|
||||||
prefix := string(content[:syntaxError.Offset])
|
return nil
|
||||||
row := strings.Count(prefix, "\n") + 1
|
|
||||||
column := len(prefix) - strings.LastIndex(prefix, "\n") - 1
|
|
||||||
return E.Extend(syntaxError, "row ", row, ", column ", column)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogOptions struct {
|
type LogOptions struct {
|
||||||
|
|
Loading…
Reference in a new issue