Skip to content

Commit 1454659

Browse files
committed
patch: merge dotnet configs recursively
1 parent 331da4f commit 1454659

File tree

2 files changed

+77
-45
lines changed

2 files changed

+77
-45
lines changed

dotnet/config.go

+69-43
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package dotnet
22

3-
import (
4-
"encoding/json"
5-
"fmt"
6-
)
3+
import "reflect"
74

85
type GcConfig struct {
96
Enable *bool `codec:"enable"`
@@ -34,25 +31,55 @@ type ThreadingConfig struct {
3431

3532
type ConfigFile struct {
3633
RuntimeOptions struct {
34+
Tfm string `json:"tfm,omitempty"`
35+
Framework struct {
36+
Name string `json:"name,omitempty"`
37+
Version string `json:"version,omitempty"`
38+
} `json:"framework"`
3739
ConfigProperties struct {
38-
Enable *bool `json:"System.GC.Server,omitempty"`
39-
Concurrent *bool `json:"System.GC.Concurrent,omitempty"`
40-
HeapCount *uint16 `json:"System.GC.HeapCount,omitempty"`
41-
HeapHardLimit *uint64 `json:"System.GC.HeapHardLimit,omitempty,"`
42-
HeapHardLimitPercent *uint8 `json:"System.GC.HeapHardLimitPercent,omitempty"`
43-
NoAffinity *bool `json:"System.GC.NoAffinitize,omitempty"`
44-
HeapAffinityMask *uint16 `json:"System.GC.HeapAffinitizeMask,omitempty"`
45-
HeapAffinityRanges *string `json:"System.GC.HeapAffinitizeRanges,omitempty"`
46-
CpuGroup *bool `json:"System.GC.CpuGroup,omitempty"`
47-
HighMemPercent *uint8 `json:"System.GC.HighMemPercent,omitempty"`
48-
RetainVM *bool `json:"System.GC.RetainVM,omitempty"`
49-
InvariantCulture *bool `json:"System.Globalization.InvariantCulture,omitempty"`
50-
UseNls *bool `json:"System.Globalization.UseNls,omitempty"`
51-
PredefinedCulturesOnly *bool `json:"System.Globalization.PredefinedCulturesOnly,omitempty"`
52-
ThreadPoolMinThreads *uint32 `json:"System.Threading.ThreadPool.MinThreads,omitempty"`
53-
ThreadPoolMaxThreads *uint32 `json:"System.Threading.ThreadPool.MaxThreads,omitempty"`
54-
UseWindowsThreadPool *bool `json:"System.Threading.ThreadPool.UseWindowsThreadPool,omitempty"`
55-
AutoReleasePoolSupport *bool `json:"System.Threading.Thread.EnableAutoreleasePool,omitempty"`
40+
Enable *bool `json:"System.GC.Server,omitempty"`
41+
Concurrent *bool `json:"System.GC.Concurrent,omitempty"`
42+
LatencyMode *int `json:"System.GC.LatencyMode,omitempty"`
43+
ForceCompact *bool `json:"System.GC.ForceCompact,omitempty"`
44+
TrimCommit *bool `json:"System.GC.TrimCommit,omitempty"`
45+
CompactOnBackgroundThread *bool `json:"System.GC.CompactOnBackgroundThread,omitempty"`
46+
RegionSize *int64 `json:"System.GC.RegionSize,omitempty"`
47+
AllowVeryLargeObjects *bool `json:"System.GC.AllowVeryLargeObjects,omitempty"`
48+
ServerHeapAffinitizeMask *uint64 `json:"System.GC.ServerHeapAffinitizeMask,omitempty"`
49+
HeapCount *uint16 `json:"System.GC.HeapCount,omitempty"`
50+
HeapHardLimit *uint64 `json:"System.GC.HeapHardLimit,omitempty,"`
51+
HeapHardLimitPercent *uint8 `json:"System.GC.HeapHardLimitPercent,omitempty"`
52+
NoAffinity *bool `json:"System.GC.NoAffinitize,omitempty"`
53+
HeapAffinityMask *uint16 `json:"System.GC.HeapAffinitizeMask,omitempty"`
54+
HeapAffinityRanges *string `json:"System.GC.HeapAffinitizeRanges,omitempty"`
55+
CpuGroup *bool `json:"System.GC.CpuGroup,omitempty"`
56+
HighMemPercent *uint8 `json:"System.GC.HighMemPercent,omitempty"`
57+
RetainVM *bool `json:"System.GC.RetainVM,omitempty"`
58+
InvariantCulture *bool `json:"System.Globalization.InvariantCulture,omitempty"`
59+
UseNls *bool `json:"System.Globalization.UseNls,omitempty"`
60+
PreferSystemLibraries *bool `json:"System.Globalization.PreferSystemLibraries,omitempty"`
61+
GlobalizationInvariant *bool `json:"System.Globalization.Invariant,omitempty"`
62+
PredefinedCulturesOnly *bool `json:"System.Globalization.PredefinedCulturesOnly,omitempty"`
63+
ThreadPoolMinThreads *uint32 `json:"System.Threading.ThreadPool.MinThreads,omitempty"`
64+
ThreadPoolMaxThreads *uint32 `json:"System.Threading.ThreadPool.MaxThreads,omitempty"`
65+
ThreadPoolMinIOCompletionThreads *int `json:"System.Threading.ThreadPool.MinIOCompletionThreads,omitempty"`
66+
ThreadPoolMaxIOCompletionThreads *int `json:"System.Threading.ThreadPool.MaxIOCompletionThreads,omitempty"`
67+
ThreadPoolUnfairSemaphoreSpinLimit *int `json:"System.Threading.ThreadPool.UnfairSemaphoreSpinLimit,omitempty"`
68+
ThreadUseAllCpuGroups *bool `json:"System.Threading.UseAllCpuGroups,omitempty"`
69+
UseWindowsThreadPool *bool `json:"System.Threading.ThreadPool.UseWindowsThreadPool,omitempty"`
70+
AutoReleasePoolSupport *bool `json:"System.Threading.Thread.EnableAutoreleasePool,omitempty"`
71+
StartupHook *string `json:"System.StartupHook,omitempty"`
72+
UseReadyToRun *bool `json:"System.Runtime.UseReadyToRun,omitempty"`
73+
UseTieredCompilation *bool `json:"System.Runtime.TieredCompilation,omitempty"`
74+
TieredCompilationQuickJit *bool `json:"System.Runtime.TieredCompilation.QuickJit,omitempty"`
75+
TieredCompilationQuickJitForLoops *bool `json:"System.Runtime.TieredCompilation.QuickJitForLoops,omitempty"`
76+
DisableJitOptimizations *bool `json:"System.Runtime.DisableJitOptimizations,omitempty"`
77+
EnableDiagnostics *bool `json:"System.Runtime.EnableDiagnostics,omitempty"`
78+
MaxStackSize *int64 `json:"System.Runtime.MaxStackSize,omitempty"`
79+
DefaultTimeZone *string `json:"System.Runtime.DefaultTimeZone,omitempty"`
80+
AssemblyLoadNoOptimizations *bool `json:"System.Runtime.Loader.AssemblyLoadNoOptimizations,omitempty"`
81+
EnableAssemblyLoadContextRedirection *bool `json:"System.Runtime.Loader.EnableAssemblyLoadContextRedirection,omitempty"`
82+
MetaDataUpdaterSupport *bool `json:"System.Reflection.Metadata.MetadataUpdater.IsSupported,omitempty"`
5683
} `json:"configProperties"`
5784
} `json:"runtimeOptions"`
5885
}
@@ -95,30 +122,29 @@ func addThreadingConfig(hcl *ThreadingConfig, conf *ConfigFile) {
95122
conf.RuntimeOptions.ConfigProperties.AutoReleasePoolSupport = hcl.AutoReleasePoolSupport
96123
}
97124

98-
func mergeDotnetConfigs(fileConf []byte, parsedConf []byte) ([]byte, error) {
99-
var conf1, conf2 map[string]any
100-
if err := json.Unmarshal(fileConf, &conf1); err != nil {
101-
return nil, fmt.Errorf("failed to unmarshal task config: %v", err)
102-
}
103-
if err := json.Unmarshal(parsedConf, &conf2); err != nil {
104-
return nil, fmt.Errorf("failed to unmarshal parsed config: %v", err)
105-
}
125+
func MergeConfigs(dest, src any) error {
126+
destVal := reflect.ValueOf(dest).Elem()
127+
srcVal := reflect.ValueOf(src).Elem()
128+
129+
var mergeRecursive func(dest, src reflect.Value) error
130+
mergeRecursive = func(dest, src reflect.Value) error {
131+
for i := 0; i < src.NumField(); i++ {
132+
srcField := src.Field(i)
133+
destField := dest.Field(i)
106134

107-
for _, confName := range [2]string{"runtimeOptions", "configProperties"} {
108-
if parsedConfRunOpts, ok := conf2[confName].(map[string]any); ok {
109-
if fileConfRunOpts, ok := conf1[confName].(map[string]any); ok {
110-
for key, val := range parsedConfRunOpts {
111-
if _, ok := fileConfRunOpts[key]; !ok {
112-
fileConfRunOpts[key] = val
113-
}
135+
switch srcField.Kind() {
136+
case reflect.Struct:
137+
if err := mergeRecursive(destField, srcField); err != nil {
138+
return err
139+
}
140+
default:
141+
if !srcField.IsZero() && destField.CanSet() {
142+
destField.Set(srcField)
114143
}
115-
conf2[confName] = fileConfRunOpts
116144
}
117145
}
146+
return nil
118147
}
119-
marshal, err := json.Marshal(conf2)
120-
if err != nil {
121-
return nil, err
122-
}
123-
return marshal, nil
148+
149+
return mergeRecursive(destVal, srcVal)
124150
}

dotnet/driver.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,19 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
499499
addGlobalizationConfig(taskConfig.Globalization, fileConfig)
500500
addThreadingConfig(taskConfig.Threading, fileConfig)
501501

502-
data, _ := json.Marshal(fileConfig)
503502
dotnetConfigPath := path.Join(cfg.TaskDir().LocalDir, fmt.Sprintf("%s.runtimeconfig.json", taskConfig.AppName))
504503

505504
if content, err := os.ReadFile(dotnetConfigPath); !os.IsNotExist(err) {
506-
data, _ = mergeDotnetConfigs(data, content)
505+
var parsedConfig = new(ConfigFile)
506+
if err := json.Unmarshal(content, parsedConfig); err != nil {
507+
return nil, nil, fmt.Errorf("failed to parse dotnet config file: %v", err)
508+
}
509+
if err := MergeConfigs(fileConfig, parsedConfig); err != nil {
510+
return nil, nil, fmt.Errorf("failed to merge dotnet config file: %v", err)
511+
}
507512
}
508513

514+
data, _ := json.Marshal(fileConfig)
509515
fo, err := os.Create(dotnetConfigPath)
510516
if err != nil {
511517
return nil, nil, fmt.Errorf("failed to create %s.runtimeconfig.json: %v", taskConfig.AppName, err)

0 commit comments

Comments
 (0)