github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/util/ui/ui_for_push.go (about)

     1  package ui
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  
    10  	"code.cloudfoundry.org/cli/types"
    11  
    12  	"github.com/fatih/color"
    13  )
    14  
    15  var ErrValueMissmatch = errors.New("values provided were of different types")
    16  
    17  type Change struct {
    18  	Header       string
    19  	CurrentValue interface{}
    20  	NewValue     interface{}
    21  	HiddenValue  bool
    22  }
    23  
    24  // DisplayChangeForPush will display the header and old/new value with the
    25  // appropriately red/green minuses and pluses.
    26  func (ui *UI) DisplayChangeForPush(header string, stringTypePadding int, hiddenValue bool, originalValue interface{}, newValue interface{}) error {
    27  	ui.terminalLock.Lock()
    28  	defer ui.terminalLock.Unlock()
    29  
    30  	originalType := reflect.ValueOf(originalValue).Type()
    31  	newType := reflect.ValueOf(newValue).Type()
    32  	if originalType != newType {
    33  		return ErrValueMissmatch
    34  	}
    35  
    36  	offset := strings.Repeat(" ", stringTypePadding)
    37  
    38  	switch oVal := originalValue.(type) {
    39  	case int:
    40  		nVal := newValue.(int)
    41  		ui.displayDiffForInt(offset, header, oVal, nVal)
    42  	case types.NullInt:
    43  		nVal := newValue.(types.NullInt)
    44  		ui.displayDiffForNullInt(offset, header, oVal, nVal)
    45  	case uint64:
    46  		nVal := newValue.(uint64)
    47  		ui.displayDiffForUint64(offset, header, oVal, nVal)
    48  	case string:
    49  		nVal := newValue.(string)
    50  		ui.displayDiffForString(offset, header, hiddenValue, oVal, nVal)
    51  	case []string:
    52  		nVal := newValue.([]string)
    53  		if len(oVal) == 0 && len(nVal) == 0 {
    54  			return nil
    55  		}
    56  
    57  		ui.displayDiffForStrings(offset, header, oVal, nVal)
    58  	case map[string]string:
    59  		nVal := newValue.(map[string]string)
    60  		if len(oVal) == 0 && len(nVal) == 0 {
    61  			return nil
    62  		}
    63  
    64  		ui.displayDiffForMapStringString(offset, header, oVal, nVal)
    65  	default:
    66  		panic(fmt.Sprintf("diff display does not have case for '%s'", header))
    67  	}
    68  	return nil
    69  }
    70  
    71  // DisplayChangesForPush will display the set of changes via
    72  // DisplayChangeForPush in the order given.
    73  func (ui *UI) DisplayChangesForPush(changeSet []Change) error {
    74  	if len(changeSet) == 0 {
    75  		return nil
    76  	}
    77  
    78  	var columnWidth int
    79  	for _, change := range changeSet {
    80  		if width := wordSize(ui.TranslateText(change.Header)); width > columnWidth {
    81  			columnWidth = width
    82  		}
    83  	}
    84  
    85  	for _, change := range changeSet {
    86  		padding := columnWidth - wordSize(ui.TranslateText(change.Header)) + 3
    87  		err := ui.DisplayChangeForPush(change.Header, padding, change.HiddenValue, change.CurrentValue, change.NewValue)
    88  		if err != nil {
    89  			return err
    90  		}
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  func (ui UI) displayDiffForInt(offset string, header string, oldValue int, newValue int) {
    97  	if oldValue != newValue {
    98  		formattedOld := fmt.Sprintf("- %s%s%d", ui.TranslateText(header), offset, oldValue)
    99  		formattedNew := fmt.Sprintf("+ %s%s%d", ui.TranslateText(header), offset, newValue)
   100  
   101  		if oldValue != 0 {
   102  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   103  		}
   104  		fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   105  	} else {
   106  		fmt.Fprintf(ui.Out, "  %s%s%d\n", ui.TranslateText(header), offset, oldValue)
   107  	}
   108  }
   109  
   110  func (ui UI) displayDiffForMapStringString(offset string, header string, oldMap map[string]string, newMap map[string]string) {
   111  	var oldKeys []string
   112  	for key := range oldMap {
   113  		oldKeys = append(oldKeys, key)
   114  	}
   115  
   116  	var newKeys []string
   117  	for key := range newMap {
   118  		newKeys = append(newKeys, key)
   119  	}
   120  
   121  	sortedKeys := sortedUniqueArray(oldKeys, newKeys)
   122  
   123  	fmt.Fprintf(ui.Out, "  %s\n", ui.TranslateText(header))
   124  	for _, key := range sortedKeys {
   125  		newVal, ok := newMap[key]
   126  		if !ok {
   127  			formattedOld := fmt.Sprintf("-   %s", key)
   128  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   129  			continue
   130  		}
   131  		oldVal, ok := oldMap[key]
   132  		if !ok {
   133  			formattedNew := fmt.Sprintf("+   %s", key)
   134  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   135  			continue
   136  		}
   137  
   138  		if oldVal == newVal {
   139  			fmt.Fprintf(ui.Out, "    %s\n", key)
   140  		} else {
   141  			formattedOld := fmt.Sprintf("-   %s", key)
   142  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   143  			formattedNew := fmt.Sprintf("+   %s", key)
   144  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   145  		}
   146  	}
   147  }
   148  
   149  func (ui UI) displayDiffForNullInt(offset string, header string, oldValue types.NullInt, newValue types.NullInt) {
   150  	if oldValue != newValue {
   151  		formattedOld := fmt.Sprintf("- %s%s%d", ui.TranslateText(header), offset, oldValue.Value)
   152  		formattedNew := fmt.Sprintf("+ %s%s%d", ui.TranslateText(header), offset, newValue.Value)
   153  
   154  		if oldValue.IsSet {
   155  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   156  		}
   157  		fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   158  	} else {
   159  		fmt.Fprintf(ui.Out, "  %s%s%d\n", ui.TranslateText(header), offset, oldValue.Value)
   160  	}
   161  }
   162  
   163  func (ui UI) displayDiffForString(offset string, header string, hiddenValue bool, oVal string, nVal string) {
   164  	if oVal != nVal {
   165  		var formattedOld, formattedNew string
   166  		if hiddenValue {
   167  			formattedOld = fmt.Sprintf("- %s%s%s", ui.TranslateText(header), offset, RedactedValue)
   168  			formattedNew = fmt.Sprintf("+ %s%s%s", ui.TranslateText(header), offset, RedactedValue)
   169  		} else {
   170  			formattedOld = fmt.Sprintf("- %s%s%s", ui.TranslateText(header), offset, oVal)
   171  			formattedNew = fmt.Sprintf("+ %s%s%s", ui.TranslateText(header), offset, nVal)
   172  		}
   173  
   174  		if oVal != "" {
   175  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   176  		}
   177  		if nVal != "" {
   178  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   179  		}
   180  	} else {
   181  		if hiddenValue {
   182  			fmt.Fprintf(ui.Out, "  %s%s%s\n", ui.TranslateText(header), offset, RedactedValue)
   183  		} else {
   184  			fmt.Fprintf(ui.Out, "  %s%s%s\n", ui.TranslateText(header), offset, oVal)
   185  		}
   186  	}
   187  }
   188  
   189  func (ui UI) displayDiffForStrings(offset string, header string, oldList []string, newList []string) {
   190  	fmt.Fprintf(ui.Out, "  %s\n", ui.TranslateText(header))
   191  
   192  	fullList := sortedUniqueArray(oldList, newList)
   193  	for _, item := range fullList {
   194  		inOld := existsIn(item, oldList)
   195  		inNew := existsIn(item, newList)
   196  
   197  		switch {
   198  		case inOld && inNew:
   199  			fmt.Fprintf(ui.Out, "    %s\n", item)
   200  		case inOld:
   201  			formattedOld := fmt.Sprintf("-   %s", item)
   202  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   203  		default:
   204  			formattedNew := fmt.Sprintf("+   %s", item)
   205  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   206  		}
   207  	}
   208  }
   209  
   210  func (ui UI) displayDiffForUint64(offset string, header string, oldValue uint64, newValue uint64) {
   211  	if oldValue != newValue {
   212  		formattedOld := fmt.Sprintf("- %s%s%d", ui.TranslateText(header), offset, oldValue)
   213  		formattedNew := fmt.Sprintf("+ %s%s%d", ui.TranslateText(header), offset, newValue)
   214  
   215  		if oldValue != 0 {
   216  			fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed)))
   217  		}
   218  		fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen)))
   219  	} else {
   220  		fmt.Fprintf(ui.Out, "  %s%s%d\n", ui.TranslateText(header), offset, oldValue)
   221  	}
   222  }
   223  
   224  func existsIn(str string, ary []string) bool {
   225  	for _, val := range ary {
   226  		if val == str {
   227  			return true
   228  		}
   229  	}
   230  	return false
   231  }
   232  
   233  func sortedUniqueArray(ary1 []string, ary2 []string) []string {
   234  	uniq := append([]string{}, ary1...)
   235  
   236  	for _, str := range ary2 {
   237  		if !existsIn(str, uniq) {
   238  			uniq = append(uniq, str)
   239  		}
   240  	}
   241  
   242  	sort.Strings(uniq)
   243  	return uniq
   244  }