github.com/grantbow/fit@v0.7.1-0.20220916164603-1f7c88ac81e6/fitapp/utils.go (about)

     1  package fitapp
     2  
     3  import (
     4  	_ "flag" // used in commented code
     5  	"fmt"
     6  	bugs "github.com/grantbow/fit/issues"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  var dops = bugs.Directory(os.PathSeparator)
    15  var sops = string(os.PathSeparator)
    16  
    17  type argumentList []string
    18  
    19  // HasArgument checks pkg global argumentList for an argument parameter. Returns true or false.
    20  func (args argumentList) HasArgument(arg string) bool {
    21  	for _, argCandidate := range args {
    22  		if arg == argCandidate {
    23  			return true
    24  		}
    25  	}
    26  	return false
    27  }
    28  
    29  // GetArgument gets an argument from the pkg global argumentList. Returns a string.
    30  func (args argumentList) GetArgument(argname, defaultVal string) string {
    31  	for idx, argCandidate := range args {
    32  		if argname == argCandidate {
    33  			// If it's the last argument, then return string
    34  			// "true" because we can't return idx+1, but it
    35  			// shouldn't be the default value when the argument
    36  			// isn't provided either..
    37  			if idx >= len(args)-1 {
    38  				return "true"
    39  			}
    40  			return args[idx+1]
    41  		}
    42  	}
    43  	return defaultVal
    44  }
    45  
    46  // GetAndRemoveArguments returns an argumentList and corresponding values as an argumentList and a slice of strings.
    47  func (args argumentList) GetAndRemoveArguments(argnames []string) (argumentList, []string) {
    48  	var nextArgumentType int = -1
    49  	matches := make([]string, len(argnames))
    50  	var retArgs []string
    51  	for idx, argCandidate := range args {
    52  		// The last token was in argnames, so this one
    53  		// is the value. Set it in matches and reset
    54  		// nextArgumentType and continue to the next
    55  		// possible token
    56  		if nextArgumentType != -1 {
    57  			matches[nextArgumentType] = argCandidate
    58  			nextArgumentType = -1
    59  			continue
    60  		}
    61  
    62  		// Check if this is a argname we're looking for
    63  		for argidx, argname := range argnames {
    64  			if argname == argCandidate {
    65  				if idx >= len(args)-1 {
    66  					matches[argidx] = "true"
    67  				}
    68  				nextArgumentType = argidx
    69  				break
    70  			}
    71  		}
    72  
    73  		// It wasn't an argname, so add it to the return
    74  		if nextArgumentType == -1 {
    75  			retArgs = append(retArgs, argCandidate)
    76  		}
    77  	}
    78  	return retArgs, matches
    79  }
    80  
    81  // check will panic with an error
    82  func check(e error) {
    83  	if e != nil {
    84  		//	fmt.Fprintf(os.Stderr, "err: %s", err.Error())
    85  		//	return NoConfigError
    86  		panic(e)
    87  	}
    88  }
    89  
    90  // captureOutput accepts a function for testing and returns stdout string and stderr string.
    91  func captureOutput(f func(), t *testing.T) (string, string) {
    92  	// Capture STDOUT with a pipe
    93  	stdout := os.Stdout
    94  	stderr := os.Stderr
    95  	so, op, _ := os.Pipe() //outpipe
    96  	oe, ep, _ := os.Pipe() //errpipe
    97  	defer func(stdout, stderr *os.File) {
    98  		os.Stdout = stdout
    99  		os.Stderr = stderr
   100  	}(stdout, stderr)
   101  
   102  	os.Stdout = op
   103  	os.Stderr = ep
   104  
   105  	f()
   106  
   107  	os.Stdout = stdout
   108  	os.Stderr = stderr
   109  
   110  	op.Close()
   111  	ep.Close()
   112  
   113  	errOutput, err := ioutil.ReadAll(oe)
   114  	if err != nil {
   115  		t.Error("Could not get output from stderr")
   116  	}
   117  	stdOutput, err := ioutil.ReadAll(so)
   118  	if err != nil {
   119  		t.Error("Could not get output from stdout")
   120  	}
   121  	return string(stdOutput), string(errOutput)
   122  }
   123  
   124  // fieldHandler is used for Priority, Milestone and Status, not Identifier
   125  func fieldHandler(command string, args argumentList,
   126  	setCallback func(bugs.Issue, string, bugs.Config) error, retrieveCallback func(bugs.Issue) string, config bugs.Config) {
   127  	if len(args) < 1 {
   128  		fmt.Printf("Usage: %s %s IssueID [set %s]\n", os.Args[0], command, command)
   129  		return
   130  	}
   131  
   132  	b, err := bugs.LoadIssueByHeuristic(args[0], config)
   133  	if err != nil {
   134  		fmt.Printf("Invalid IssueID: %s\n", err.Error())
   135  		return
   136  	}
   137  	if len(args) > 1 {
   138  		newValue := strings.Join(args[1:], " ")
   139  		err := setCallback(*b, newValue, config)
   140  		if err != nil {
   141  			fmt.Printf("Error setting %s: %s", command, err.Error())
   142  		}
   143  	} else {
   144  		val := retrieveCallback(*b)
   145  		if val == "" {
   146  			fmt.Printf("%s not defined\n", command)
   147  		} else {
   148  			fmt.Printf("%s\n", val)
   149  		}
   150  	}
   151  }
   152  
   153  // dirDump accepts a string directory and returns a string.
   154  func dirDump(dir string) string {
   155  	a := []string{}
   156  	err := filepath.Walk(dir,
   157  		func(path string, info os.FileInfo, err error) error {
   158  			if err != nil {
   159  				return err
   160  			}
   161  			a = append(a, fmt.Sprintf("%v", path))
   162  			return nil
   163  		})
   164  	if err != nil {
   165  		fmt.Printf("dirDump error %s", err.Error())
   166  	}
   167  	//for _, file := range files {
   168  	//	a = append(a, fmt.Sprintf("%v", file))
   169  	//}
   170  	return strings.Join(a, ",\n")
   171  }
   172  
   173  // dirDumpFI accepts an array of os.FileInfo and returns a string
   174  func dirDumpFI(files []os.FileInfo) string {
   175  	a := []string{}
   176  	for _, file := range files {
   177  		a = append(a, fmt.Sprintf("%v", file))
   178  	}
   179  	return strings.Join(a, ",\n")
   180  }
   181  
   182  // SkipRootCheck is a helper function to avoid unnecessary filesystem checking.
   183  func SkipRootCheck(args *[]string) bool {
   184  	ret := false
   185  	switch len(*args) {
   186  	case 0, 1:
   187  		ret = true
   188  	case 2:
   189  		if (*args)[1] == "help" ||
   190  			(*args)[1] == "--help" ||
   191  			(*args)[1] == "-h" ||
   192  			(*args)[1] == "status" ||
   193  			(*args)[1] == "version" ||
   194  			(*args)[1] == "about" ||
   195  			(*args)[1] == "--version" ||
   196  			(*args)[1] == "-v" ||
   197  			(*args)[1] == "environment" ||
   198  			(*args)[1] == "config" ||
   199  			(*args)[1] == "settings" ||
   200  			(*args)[1] == "env" {
   201  			ret = true
   202  		}
   203  	case 3:
   204  		if (*args)[2] == "--help" ||
   205  			(*args)[1] == "help" {
   206  			ret = true
   207  		}
   208  	}
   209  	return ret
   210  }
   211  
   212  // also in issues/utils.go
   213  func removeFi(slice []os.FileInfo, i int) []os.FileInfo {
   214  	//flag.Parse()
   215  	//Debug("debug len " + string(len(slice)) + " i " + string(i) + " slice[0].Name() " + string(slice[0].Name()) + "\n")
   216  	//fmt.Printf("%+v\n", flag.Args()) // didn't seem to help, needs more work to make it active
   217  	//
   218  	//fmt.Printf("debug ok 01 \n")
   219  	//fmt.Printf("debug len " + string(len(slice)) + " i " + string(i) + " slice[0].Name() " + string(slice[0].Name()) + "\n")
   220  	//fmt.Printf("debug removeFi args len " + string(len(slice)) + " i " + string(i) + "\n")
   221  	if (len(slice) == 1) && (i == 0) {
   222  		return []os.FileInfo{}
   223  	} else if i < len(slice)-2 {
   224  		copy(slice[i:], slice[i+1:])
   225  	}
   226  	return slice[:len(slice)-1]
   227  }
   228  
   229  // also in issues/utils.go
   230  func readIssues(dirname string) []os.FileInfo {
   231  	//var issueList []os.FileInfo
   232  	fis, _ := ioutil.ReadDir(string(dirname))
   233  	issueList := fis
   234  	for idx, fi := range issueList {
   235  		//Debug("debug fi " + string(fi.Name()) + "idx " + string(idx) + "\n")
   236  		//fmt.Printf("debug readIssues loop fi " + string(fi.Name()) + "idx " + string(idx) + "\n")
   237  		if fi.IsDir() != true {
   238  			//fmt.Printf("debug before removeFi name " + fi.Name() + " idx " + string(idx) + "\n")
   239  			issueList = removeFi(issueList, idx)
   240  		}
   241  	}
   242  	return issueList
   243  }
   244  
   245  //byDir allows sort.Sort(byDir(issues))
   246  // type and three functions are needed - also see Issue.go for type byIssue
   247  // rather than a custom Len function for os.FileInfo, Len is calculated in Less
   248  type byDir []os.FileInfo
   249  
   250  func (t byDir) Len() int {
   251  	return len(t)
   252  }
   253  func (t byDir) Swap(i, j int) {
   254  	t[i], t[j] = t[j], t[i]
   255  }
   256  func (t byDir) Less(i, j int) bool {
   257  	return (t[i]).ModTime().Unix() < (t[j]).ModTime().Unix()
   258  }