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 }