github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/config/diff.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package config 5 6 import ( 7 "fmt" 8 "reflect" 9 10 "github.com/masterhung0112/hk_server/v5/model" 11 ) 12 13 type ConfigDiffs []ConfigDiff 14 15 type ConfigDiff struct { 16 Path string `json:"path"` 17 BaseVal interface{} `json:"base_val"` 18 ActualVal interface{} `json:"actual_val"` 19 } 20 21 func diff(base, actual reflect.Value, label string) ([]ConfigDiff, error) { 22 var diffs []ConfigDiff 23 24 if base.IsZero() && actual.IsZero() { 25 return diffs, nil 26 } 27 28 if base.IsZero() || actual.IsZero() { 29 return append(diffs, ConfigDiff{ 30 Path: label, 31 BaseVal: base.Interface(), 32 ActualVal: actual.Interface(), 33 }), nil 34 } 35 36 baseType := base.Type() 37 actualType := actual.Type() 38 39 if baseType.Kind() == reflect.Ptr { 40 base = reflect.Indirect(base) 41 actual = reflect.Indirect(actual) 42 baseType = base.Type() 43 actualType = actual.Type() 44 } 45 46 if baseType != actualType { 47 return nil, fmt.Errorf("not same type %s %s", baseType, actualType) 48 } 49 50 switch baseType.Kind() { 51 case reflect.Struct: 52 if base.NumField() != actual.NumField() { 53 return nil, fmt.Errorf("not same number of fields in struct") 54 } 55 for i := 0; i < base.NumField(); i++ { 56 fieldLabel := baseType.Field(i).Name 57 if label != "" { 58 fieldLabel = label + "." + fieldLabel 59 } 60 d, err := diff(base.Field(i), actual.Field(i), fieldLabel) 61 if err != nil { 62 return nil, err 63 } 64 diffs = append(diffs, d...) 65 } 66 default: 67 if !reflect.DeepEqual(base.Interface(), actual.Interface()) { 68 diffs = append(diffs, ConfigDiff{ 69 Path: label, 70 BaseVal: base.Interface(), 71 ActualVal: actual.Interface(), 72 }) 73 } 74 } 75 76 return diffs, nil 77 } 78 79 func Diff(base, actual *model.Config) (ConfigDiffs, error) { 80 if base == nil || actual == nil { 81 return nil, fmt.Errorf("input configs should not be nil") 82 } 83 baseVal := reflect.Indirect(reflect.ValueOf(base)) 84 actualVal := reflect.Indirect(reflect.ValueOf(actual)) 85 return diff(baseVal, actualVal, "") 86 } 87 88 func (cd ConfigDiffs) String() string { 89 return fmt.Sprintf("%+v", []ConfigDiff(cd)) 90 }