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

     1  package fitapp
     2  
     3  import (
     4  	"fmt"
     5  	bugs "github.com/grantbow/fit/issues"
     6  	"io/ioutil"
     7  	"os"
     8  	"regexp"
     9  	"sort"
    10  )
    11  
    12  //var dops = bugs.Directory(os.PathSeparator)
    13  //var sops = string(os.PathSeparator)
    14  
    15  // issueNamer takes a bug and an int index then outputs a string.
    16  func issueNamer(b bugs.Issue, idx int) string {
    17  	id := b.Identifier()
    18  	//fmt.Printf("debug b.Dir %v id %v\n", b.Dir, id)
    19  	if id != "" {
    20  		return fmt.Sprintf("Issue %s", id)
    21  	}
    22  	return fmt.Sprintf("Issue %d", idx+1)
    23  }
    24  
    25  // listTags takes an array of os.FileInfo directories and prints bugs.
    26  func listTags(files []os.FileInfo, args argumentList, config bugs.Config) {
    27  	b := bugs.Issue{}
    28  	for idx := range files {
    29  		b.LoadIssue(bugs.Directory(bugs.FitDirer(config)+dops+bugs.Directory(files[idx].Name())), config)
    30  
    31  		for _, tag := range args {
    32  			if b.HasTag(bugs.TagBoolTrue(tag)) {
    33  				fmt.Printf("%s: %s\n", issueNamer(b, idx), b.Title("tags"))
    34  			}
    35  		}
    36  	}
    37  }
    38  
    39  // List is a subcommand to print lists and individual issues.
    40  func List(args argumentList, config bugs.Config, topRecurse bool) {
    41  	fitdir := bugs.FitDirer(config)
    42  	issues := readIssues(string(fitdir))
    43  	sort.Sort(byDir(issues))
    44  
    45  	var wantTags bool = false
    46  	if args.HasArgument("--tags") || args.HasArgument("-t") {
    47  		wantTags = true
    48  	}
    49  	var matchRegex bool = false
    50  	if args.HasArgument("--match") || args.HasArgument("-m") {
    51  		matchRegex = true
    52  	}
    53  	var wantRecursive bool = false
    54  	if args.HasArgument("--recursive") || args.HasArgument("-r") {
    55  		wantRecursive = true
    56  	}
    57  
    58  	//fmt.Printf("debug topRecurse %v wantRecursive %v config.MultipleDirs %v \n", topRecurse, wantRecursive, config.MultipleDirs == true)
    59  	if topRecurse == true && (wantRecursive == true || config.MultipleDirs == true) {
    60  		// print warning if below the .git directory
    61  		//fmt.Printf("debug config.FitDir %v len %v config.ScmDir %v len %v\n",
    62  		//	config.FitDir, len(config.FitDir),
    63  		//	config.ScmDir, len(config.ScmDir))
    64  		if config.ScmType == "git" &&
    65  			len(config.ScmDir) != len(config.FitDir)+5 {
    66  			fmt.Printf("\n===== WARNING, path from .git to %s: %s\n", config.FitDirName, config.FitDir[len(config.ScmDir)-5:])
    67  		} else if config.ScmType == "hg" &&
    68  			len(config.ScmDir) != len(config.FitDir)+4 {
    69  			fmt.Printf("\n===== WARNING, path from .hg to %s: %s\n", config.FitDirName, config.FitDir[len(config.ScmDir)-4:])
    70  		}
    71  	}
    72  
    73  	fmt.Printf("\n===== list %s\n", config.FitDir+sops+config.FitDirName)
    74  	if matchRegex && (len(args) > 1) {
    75  		for i, length := 0, len(args); i < length; i += 1 {
    76  			// TODO for _, tag := range args { // idx not needed
    77  			if args[i] == "--match" || args[i] == "-m" ||
    78  				args[i] == "--tags" || args[i] == "-t" ||
    79  				args[i] == "--recursive" || args[i] == "-r" {
    80  				continue
    81  			}
    82  			fmt.Printf("===== matching (?i)%s\n", args[i])
    83  			for idx, issue := range issues {
    84  				if issue.IsDir() != true {
    85  					continue
    86  				}
    87  				re, err := regexp.Compile("(?i)" + args[i])
    88  				if err == nil {
    89  					s := re.Find([]byte(issue.Name()))
    90  					if s != nil {
    91  						printIssueByDir(idx, issue, fitdir, config, wantTags)
    92  					} // else { continue }
    93  				} // else { continue }
    94  			}
    95  		}
    96  	} else if len(args) == 0 || (wantTags && len(args) == 1) || // --regex alone makes no sense
    97  		(wantRecursive && len(args) == 1) ||
    98  		(wantTags && wantRecursive && len(args) == 2) ||
    99  		config.MultipleDirs == true {
   100  		// No parameters, print a list of all bugs
   101  		//os.Stdout = stdout
   102  		foundsome := 0
   103  		for idx, issue := range issues {
   104  			if issue.IsDir() != true {
   105  				continue
   106  			}
   107  			printIssueByDir(idx, issue, fitdir, config, wantTags)
   108  			foundsome += 1
   109  		}
   110  		if foundsome == 0 {
   111  			fmt.Printf("   << found no issues >>\n")
   112  		}
   113  		if topRecurse == true && (wantRecursive || config.MultipleDirs == true) {
   114  			fi, _ := os.Stat(config.FitDir)
   115  			//if fierr != nil {
   116  			//	panic(fierr)
   117  			//}
   118  			checkDirTreeDown(args, config, fi, false)
   119  		}
   120  		return
   121  	} else {
   122  		// Get a list of tags, so that when we encounter
   123  		// an error we can check if it's because the user
   124  		// provided a tagname instead of a IssueID. If they
   125  		// did, then list bugs matching that tag instead
   126  		// of full descriptions
   127  		//tags := getAllTags(config) // defined in Tag.go
   128  		tags := uniqueTagList(config)
   129  		// There were parameters, so show the full description of each
   130  		// of those issues
   131  		for i, length := 0, len(args); i < length; i += 1 {
   132  			// TODO for _, tag := range args { // idx not needed
   133  			if args[i] == "--match" || args[i] == "-m" ||
   134  				args[i] == "--tags" || args[i] == "-t" ||
   135  				args[i] == "--recursive" || args[i] == "-r" {
   136  				continue
   137  			}
   138  			b, err := bugs.LoadIssueByHeuristic(args[i], config)
   139  			if err != nil {
   140  				for _, tagname := range tags {
   141  					if tagname == args[i] && matchRegex == false {
   142  						listTags(issues, args, config)
   143  						return
   144  					}
   145  				}
   146  				fmt.Printf("%s\n", err.Error())
   147  				continue
   148  			}
   149  
   150  			// err == nil so issue loaded
   151  			b.ViewIssue()
   152  			if i < length-1 {
   153  				fmt.Printf("\n--\n\n")
   154  			}
   155  		}
   156  	}
   157  	//fmt.Printf("\n")
   158  
   159  	//if wantRecursive && topRecurse == true {
   160  	// the first readdir is special so as to not find the same/regular fit dir
   161  	//	fi, _ := os.Stat(config.FitDir)
   162  	//if fierr != nil {
   163  	//	panic(fierr)
   164  	//}
   165  	//	checkDirTreeDown(args, config, fi, false)
   166  	//fileinfos, _ := ioutil.ReadDir(config.FitDir) // IssueRootDir
   167  	//for _, node := range fileinfos {
   168  	//	// search for a non-"issues" dir containing an "issues" subdir
   169  	//	if node.Name() != "issues" &&
   170  	//		node.IsDir() == true {
   171  	//		os.Chdir(node.Name())
   172  	//		checkDirTreeDown(args, config, node, true)
   173  	//		os.Chdir(wd) // go back
   174  	//	}
   175  	//}
   176  	//}
   177  }
   178  
   179  func checkDirTreeDown(args argumentList, config bugs.Config, node os.FileInfo, allowHits bool) {
   180  	// check pwd
   181  	topwd, _ := os.Getwd()
   182  	//fmt.Printf("/////  debug checkDirTreeDown fit dir %s\n", topwd)
   183  	if dirinfo, err := os.Stat(topwd + sops + config.FitDir); err == nil && dirinfo.IsDir() && allowHits {
   184  		//fmt.Printf("\n/////  topwd FitDir %s\n", topwd+sops+config.FitDir)
   185  		newConfig := config
   186  		newConfig.FitDir = string(topwd) // IssueRootDir
   187  		List(args, newConfig, false)     // process
   188  	}
   189  
   190  	// recursively check subdirs
   191  	fileinfos, _ := ioutil.ReadDir(topwd)
   192  	//fmt.Printf("/////  debug checkDirTreeDown subdir %s\n", topwd) // +sops+node.Name())
   193  	for _, nodee := range fileinfos {
   194  		if nodee.Name() != config.FitDir &&
   195  			nodee.IsDir() == true {
   196  			wd, _ := os.Getwd() // save for go back
   197  			// candidate
   198  			os.Chdir(nodee.Name())                      // go down
   199  			checkDirTreeDown(args, config, nodee, true) // calls itself
   200  			os.Chdir(wd)                                // go back
   201  		}
   202  	}
   203  }
   204  
   205  func printIssueByDir(idx int, issue os.FileInfo, fitdir bugs.Directory, config bugs.Config, wantTags bool) {
   206  	// TODO: same next eight lines func (idx, issue)
   207  	var dir bugs.Directory = fitdir + dops + bugs.Directory(issue.Name())
   208  	b := bugs.Issue{Dir: dir, DescriptionFileName: config.DescriptionFileName} // usually Description
   209  	name := issueNamer(b, idx)                                                 // Issue idx: b.Title
   210  	if wantTags == false {
   211  		fmt.Printf("%s: %s\n", name, b.Title(""))
   212  	} else {
   213  		fmt.Printf("%s: %s\n", name, b.Title("tags"))
   214  	}
   215  }