Browse Source

Improve configuration merge

世界 1 year ago
parent
commit
36b0f2e91a
3 changed files with 16 additions and 18 deletions
  1. 9 4
      cmd/sing-box/cmd_run.go
  2. 1 2
      experimental/libbox/config.go
  3. 6 12
      option/config.go

+ 9 - 4
cmd/sing-box/cmd_run.go

@@ -17,6 +17,7 @@ import (
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing-box/option"
 	E "github.com/sagernet/sing/common/exceptions"
+	"github.com/sagernet/sing/common/json"
 	"github.com/sagernet/sing/common/json/badjson"
 
 	"github.com/spf13/cobra"
@@ -56,8 +57,7 @@ func readConfigAt(path string) (*OptionsEntry, error) {
 	if err != nil {
 		return nil, E.Cause(err, "read config at ", path)
 	}
-	var options option.Options
-	err = options.UnmarshalJSON(configContent)
+	options, err := json.UnmarshalExtended[option.Options](configContent)
 	if err != nil {
 		return nil, E.Cause(err, "decode config at ", path)
 	}
@@ -107,13 +107,18 @@ func readConfigAndMerge() (option.Options, error) {
 	if len(optionsList) == 1 {
 		return optionsList[0].options, nil
 	}
-	var mergedOptions option.Options
+	var mergedMessage json.RawMessage
 	for _, options := range optionsList {
-		mergedOptions, err = badjson.Merge(options.options, mergedOptions)
+		mergedMessage, err = badjson.MergeJSON(options.options.RawMessage, mergedMessage)
 		if err != nil {
 			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
 }
 

+ 1 - 2
experimental/libbox/config.go

@@ -20,8 +20,7 @@ import (
 )
 
 func parseConfig(configContent string) (option.Options, error) {
-	var options option.Options
-	err := options.UnmarshalJSON([]byte(configContent))
+	options, err := json.UnmarshalExtended[option.Options]([]byte(configContent))
 	if err != nil {
 		return option.Options{}, E.Cause(err, "decode config")
 	}

+ 6 - 12
option/config.go

@@ -2,13 +2,12 @@ package option
 
 import (
 	"bytes"
-	"strings"
 
-	E "github.com/sagernet/sing/common/exceptions"
 	"github.com/sagernet/sing/common/json"
 )
 
 type _Options struct {
+	RawMessage   json.RawMessage      `json:"-"`
 	Schema       string               `json:"$schema,omitempty"`
 	Log          *LogOptions          `json:"log,omitempty"`
 	DNS          *DNSOptions          `json:"dns,omitempty"`
@@ -22,19 +21,14 @@ type _Options struct {
 type Options _Options
 
 func (o *Options) UnmarshalJSON(content []byte) error {
-	decoder := json.NewDecoder(json.NewCommentFilter(bytes.NewReader(content)))
+	decoder := json.NewDecoder(bytes.NewReader(content))
 	decoder.DisallowUnknownFields()
 	err := decoder.Decode((*_Options)(o))
-	if err == nil {
-		return nil
+	if err != nil {
+		return err
 	}
-	if syntaxError, isSyntaxError := err.(*json.SyntaxError); isSyntaxError {
-		prefix := string(content[:syntaxError.Offset])
-		row := strings.Count(prefix, "\n") + 1
-		column := len(prefix) - strings.LastIndex(prefix, "\n") - 1
-		return E.Extend(syntaxError, "row ", row, ", column ", column)
-	}
-	return err
+	o.RawMessage = content
+	return nil
 }
 
 type LogOptions struct {