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  }