github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/utils/argsutils.go (about)

     1  package utils
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    10  )
    11  
    12  // Removes the provided flag and value from the command arguments
    13  func RemoveFlagFromCommand(args *[]string, flagIndex, flagValueIndex int) {
    14  	argsCopy := *args
    15  	// Remove flag from Command if required.
    16  	if flagIndex != -1 {
    17  		argsCopy = append(argsCopy[:flagIndex], argsCopy[flagValueIndex+1:]...)
    18  	}
    19  	*args = argsCopy
    20  }
    21  
    22  // Find value of required CLI flag in Command.
    23  // If flag does not exist, the returned index is -1 and nil is returned as the error.
    24  // Return values:
    25  // err - error if flag exists but failed to extract its value.
    26  // flagIndex - index of flagName in Command.
    27  // flagValueIndex - index in Command in which the value of the flag exists.
    28  // flagValue - value of flagName.
    29  func FindFlag(flagName string, args []string) (flagIndex, flagValueIndex int, flagValue string, err error) {
    30  	flagIndex = -1
    31  	flagValueIndex = -1
    32  	for index, arg := range args {
    33  		// Check current argument.
    34  		if !strings.HasPrefix(arg, flagName) {
    35  			continue
    36  		}
    37  
    38  		// Get flag value.
    39  		flagValue, flagValueIndex, err = getFlagValueAndValueIndex(flagName, args, index)
    40  		if err != nil {
    41  			return
    42  		}
    43  
    44  		// If was not the correct flag, continue looking.
    45  		if flagValueIndex == -1 {
    46  			continue
    47  		}
    48  
    49  		// Return value.
    50  		flagIndex = index
    51  		return
    52  	}
    53  
    54  	// Flag not found.
    55  	return
    56  }
    57  
    58  // Boolean flag can be provided in one of the following forms:
    59  // 1. --flag=value, where value can be true/false
    60  // 2. --flag, here the value is true
    61  // Return values:
    62  // flagIndex - index of flagName in args.
    63  // flagValue - value of flagName.
    64  // err - error if flag exists, but we failed to extract its value.
    65  // If flag does not exist flagIndex = -1 with false value and nil error.
    66  func FindBooleanFlag(flagName string, args []string) (flagIndex int, flagValue bool, err error) {
    67  	var arg string
    68  	for flagIndex, arg = range args {
    69  		if strings.HasPrefix(arg, flagName) {
    70  			value := strings.TrimPrefix(arg, flagName)
    71  			if len(value) == 0 {
    72  				flagValue = true
    73  			} else if strings.HasPrefix(value, "=") {
    74  				flagValue, err = strconv.ParseBool(value[1:])
    75  			} else {
    76  				continue
    77  			}
    78  			return
    79  		}
    80  	}
    81  	return -1, false, nil
    82  }
    83  
    84  // Get the provided flag's value, and the index of the value.
    85  // Value-index can either be same as flag's index, or the next one.
    86  // Return error if flag is found, but couldn't extract value.
    87  // If the provided index doesn't contain the searched flag, return flagIndex = -1.
    88  func getFlagValueAndValueIndex(flagName string, args []string, flagIndex int) (flagValue string, flagValueIndex int, err error) {
    89  	indexValue := args[flagIndex]
    90  
    91  	// Check if flag is in form '--key=value'
    92  	indexValue = strings.TrimPrefix(indexValue, flagName)
    93  	if strings.HasPrefix(indexValue, "=") {
    94  		if len(indexValue) > 1 {
    95  			return indexValue[1:], flagIndex, nil
    96  		}
    97  		return "", -1, errorutils.CheckError(errors.New(fmt.Sprintf("Flag %s is provided with empty value.", flagName)))
    98  	}
    99  
   100  	// Check if it is a different flag with same prefix, e.g --server-id-another
   101  	if len(indexValue) > 0 {
   102  		return "", -1, nil
   103  	}
   104  
   105  	// If reached here, expect the flag value in next argument.
   106  	if len(args) < flagIndex+2 {
   107  		// Flag value does not exist.
   108  		return "", -1, errorutils.CheckError(errors.New(fmt.Sprintf("Failed extracting value of provided flag: %s.", flagName)))
   109  	}
   110  
   111  	nextIndexValue := args[flagIndex+1]
   112  	// Don't allow next value to be a flag.
   113  	if strings.HasPrefix(nextIndexValue, "-") {
   114  		// Flag value does not exist.
   115  		return "", -1, errorutils.CheckError(errors.New(fmt.Sprintf("Failed extracting value of provided flag: %s.", flagName)))
   116  	}
   117  
   118  	return nextIndexValue, flagIndex + 1, nil
   119  }
   120  
   121  // Find the first match of any of the provided flags in args.
   122  // Return same values as FindFlag.
   123  func FindFlagFirstMatch(flags, args []string) (flagIndex, flagValueIndex int, flagValue string, err error) {
   124  	// Look for provided flags.
   125  	for _, flag := range flags {
   126  		flagIndex, flagValueIndex, flagValue, err = FindFlag(flag, args)
   127  		if err != nil {
   128  			return
   129  		}
   130  		if flagIndex != -1 {
   131  			// Found value for flag.
   132  			return
   133  		}
   134  	}
   135  	return
   136  }
   137  
   138  func ExtractBuildDetailsFromArgs(args []string) (cleanArgs []string, buildConfig *BuildConfiguration, err error) {
   139  	var flagIndex, valueIndex int
   140  	buildConfig = &BuildConfiguration{}
   141  	cleanArgs = append([]string(nil), args...)
   142  
   143  	// Extract build-info information from the args.
   144  	flagIndex, valueIndex, buildConfig.BuildName, err = FindFlag("--build-name", cleanArgs)
   145  	if err != nil {
   146  		return
   147  	}
   148  	RemoveFlagFromCommand(&cleanArgs, flagIndex, valueIndex)
   149  
   150  	flagIndex, valueIndex, buildConfig.BuildNumber, err = FindFlag("--build-number", cleanArgs)
   151  	if err != nil {
   152  		return
   153  	}
   154  	RemoveFlagFromCommand(&cleanArgs, flagIndex, valueIndex)
   155  
   156  	// Retrieve build name and build number from env if both missing
   157  	buildConfig.BuildName, buildConfig.BuildNumber = GetBuildNameAndNumber(buildConfig.BuildName, buildConfig.BuildNumber)
   158  	flagIndex, valueIndex, buildConfig.Module, err = FindFlag("--module", cleanArgs)
   159  	if err != nil {
   160  		return
   161  	}
   162  	RemoveFlagFromCommand(&cleanArgs, flagIndex, valueIndex)
   163  	err = ValidateBuildAndModuleParams(buildConfig)
   164  	return
   165  }
   166  
   167  func ExtractInsecureTlsFromArgs(args []string) (cleanArgs []string, insecureTls bool, err error) {
   168  	cleanArgs = append([]string(nil), args...)
   169  
   170  	flagIndex, insecureTls, err := FindBooleanFlag("--insecure-tls", args)
   171  	if err != nil {
   172  		return
   173  	}
   174  	RemoveFlagFromCommand(&cleanArgs, flagIndex, flagIndex)
   175  	return
   176  }