github.com/grantbow/fit@v0.7.1-0.20220916164603-1f7c88ac81e6/cmd/fit/main.go (about) 1 // bug manages plain text issue files. 2 package main 3 4 import ( 5 "fmt" 6 fitapp "github.com/grantbow/fit/fitapp" 7 issues "github.com/grantbow/fit/issues" 8 scm "github.com/grantbow/fit/scm" 9 "os" 10 "strings" 11 ) 12 13 func main() { 14 15 config := issues.Config{} 16 config.ProgramVersion = fitapp.ProgramVersion() 17 config.DescriptionFileName = "Description" 18 config.FitDirName = "fit" 19 rootPresent := false 20 skip := fitapp.SkipRootCheck(&os.Args) // too few args or help or env 21 // see fitapp/utils.go 22 23 // detect scm first to determine backup location for .fit.yml 24 scmoptions := make(map[string]bool) 25 handler, detectedDir, ErrH := scm.DetectSCM(scmoptions, config) 26 //a, b, c := scm.DetectSCM(scmoptions, config) 27 //fmt.Printf("%+v %+v %+v\n", a, b, c) 28 if ErrH != nil { 29 fmt.Printf("Warn: no .git or .hg directory. Use \"{git|hg} init\".\n") 30 //fmt.Printf("Warn: %s\n", ErrH) // No SCM found 31 //a, b := handler.SCMIssuesUpdaters() 32 //fmt.Printf("%+v %+v\n", a, b) 33 if handler != nil { 34 if _, ErrU := handler.SCMIssuesUpdaters(config); ErrU != nil { 35 if _, ErrCa := handler.SCMIssuesCacher(config); ErrCa != nil { 36 fmt.Printf("Warn: %s\n", ErrCa) 37 } else { 38 fmt.Printf("Warn: %s\n", ErrU) 39 } 40 } 41 } 42 } else { 43 config.ScmDir = string(detectedDir) 44 config.ScmType = handler.SCMTyper() 45 } 46 47 if rd := issues.RootDirer(&config); rd != "" { 48 // issues/Directory.go func RootDirer sets config.FitDir runs os.Chdir() 49 rootPresent = true 50 config.FitYmlDir = config.FitDir // default 51 fitYmlFileName := ".fit.yml" 52 bugYmlFileName := ".bug.yml" 53 if ErrC := issues.ConfigRead(fitYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 54 // tried to read FitDir fit config, must try both fit and bug 55 config.FitYmlDir = config.FitDir 56 config.FitYml = config.FitYmlDir + string(os.PathSeparator) + fitYmlFileName 57 //var sops = string(os.PathSeparator) not yet available 58 //var dops = Directory(os.PathSeparator) 59 } else if ErrC := issues.ConfigRead(bugYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 60 // tried to read FitDir bug config, must try both fit and bug 61 config.FitYmlDir = config.FitDir 62 config.FitYml = config.FitDir + string(os.PathSeparator) + bugYmlFileName 63 } else if config.ScmType == "git" { 64 // TODO: collapse else if ...git... && else if ...hg... with .git(4 char len, stl ScmTypeLen) and .hg(3 char len) 65 s := len(config.ScmDir) 66 //fmt.Printf("debug s01 %v\n scmdir %v\n dir %v\n", s, config.ScmDir, string(config.ScmDir[:s-4])+fitYmlFileName) 67 if ErrC := issues.ConfigRead(string(config.ScmDir[:s-4])+fitYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 68 // tried to read .git fit config 69 config.FitYmlDir = string(config.ScmDir[:s-5]) 70 config.FitYml = string(config.ScmDir[:s-4]) + fitYmlFileName 71 //fmt.Printf("debug 02\n %v\n", config.FitYml) 72 } else if ErrC := issues.ConfigRead(string(config.ScmDir[:s-4])+bugYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 73 // tried to read .git bug config 74 config.FitYmlDir = string(config.ScmDir[:s-5]) 75 config.FitYml = string(config.ScmDir[:s-4]) + bugYmlFileName 76 } 77 } else if config.ScmType == "hg" { 78 // try to read .hg fit config 79 s := len(config.ScmDir) 80 //fmt.Printf("debug s03 %v\n scmdir %v\n dir %v\n", s, config.ScmDir, string(config.ScmDir[:s-3])+fitYmlFileName) 81 if ErrC := issues.ConfigRead(string(config.ScmDir[:s-3])+fitYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 82 // tried to read .hg fit config 83 config.FitYmlDir = string(config.ScmDir[:s-4]) 84 config.FitYml = string(config.ScmDir[:s-3]) + fitYmlFileName 85 //fmt.Printf("debug 04\n %v\n", config.FitYml) 86 } else if ErrC := issues.ConfigRead(string(config.ScmDir[:s-3])+bugYmlFileName, &config, fitapp.ProgramVersion()); ErrC == nil { 87 // tried to read .hg fit config 88 config.FitYmlDir = string(config.ScmDir[:s-4]) 89 config.FitYml = string(config.ScmDir[:s-3]) + bugYmlFileName 90 //fmt.Printf("debug 04\n %v\n", config.FitYml) 91 } 92 } 93 //} else { // no 94 } 95 96 if !rootPresent { 97 if skip { 98 fmt.Printf("Warn: no `" + config.FitDirName + "` directory\n") 99 } else { // !skip 100 //fitapp.PrintVersion() 101 fmt.Printf("bug manages plain text issues with git or hg.\n") 102 fmt.Printf("Error: Could not find `fit` or `issues` directory.\n") 103 fmt.Printf(" Check that the current or a parent directory has a fit directory\n") 104 fmt.Printf(" or set the FIT environment variable.\n") 105 //fmt.Printf("Each issues directory contains issues.\n") 106 //fmt.Printf("Each issue directory contains a text file named Description.\n") 107 fmt.Printf("Use \"bug help\" or \"bug help help\" for details.\n") 108 fmt.Printf("Aborting.\n") 109 os.Exit(2) 110 } 111 } 112 113 issues.FitDirer(config) // from issues/Directory.go, uses config.FitDir from issues/Bug.go 114 115 // flags package is nice but this seemed more direct at the time 116 // because of subcommands and 117 // arguments that can be space separated names 118 // glog requires the use of flag 119 osArgs := os.Args // TODO: use an env var and assign to osArgs to setup for testing 120 //fmt.Printf("A %s %#v\n", "osArgs: ", osArgs) 121 if len(osArgs) <= 1 { 122 if rootPresent { 123 fitapp.List([]string{}, config, true) 124 } else { 125 fmt.Printf("Usage: " + os.Args[0] + " <command> [options]\n") 126 fmt.Printf("\nUse \"bug help\" or \"bug help <command>\" for details.\n") 127 } 128 } else if len(osArgs) == 2 && 129 (osArgs[1] == "--help" || 130 osArgs[1] == "help" || 131 osArgs[1] == "-h") { 132 fitapp.Help("help") // just bug help 133 } else if len(osArgs) >= 3 && 134 (osArgs[2] == "--help" || 135 osArgs[2] == "help" || 136 osArgs[2] == "-h") { // 'bug cmd --help' just like 'bug help cmd' 137 //fmt.Printf("B %s %#v\n", "osArgs: ", osArgs) 138 fitapp.Help(osArgs[1]) 139 } else { 140 switch osArgs[1] { 141 // subcommands without osArgs first 142 case "notags", "notag": 143 fitapp.TagsNone(config) 144 case "idslist", "idsassigned", "ids", "identifiers": 145 fitapp.IdsAssigned(config) 146 case "noids", "noid", "noidentifiers", "noidentifier": 147 fitapp.IdsNone(config) 148 case "env", "environment", "config", "settings": 149 fitapp.Env(config) 150 case "pwd", "dir", "cwd": 151 fitapp.Pwd(config) 152 case "version", "about", "--version", "-v": 153 fitapp.PrintVersion() 154 case "purge": 155 fitapp.Purge(config) 156 case "twilio": 157 fitapp.Twilio(config) 158 case "staging", "staged", "cached", "cache", "index": 159 // TODO: scm/Staged.go 160 if b, err := handler.SCMIssuesUpdaters(config); err != nil { 161 fmt.Printf("Files in " + config.FitDirName + "/ need committing, see $ git status --porcelain -u -- :/" + config.FitDirName + "\nor if already in the index see $ git diff --name-status --cached HEAD -- :/" + config.FitDirName + "\n") 162 if _, ErrCach := handler.SCMIssuesCacher(config); ErrCach != nil { 163 for _, bline := range strings.Split(string(b), "\n") { 164 //if c, bline 165 //if bline in c { 166 //} else { 167 fmt.Printf("%v\n", string(bline)) 168 //} 169 } 170 } else { 171 fmt.Printf("%v\n", string(b)) 172 } 173 } else { 174 fmt.Printf("No files in " + config.FitDirName + "/ need committing, see $ git status --porcelain -u :/" + config.FitDirName + " \":top\"\n") 175 } 176 // subcommands that pass osArgs 177 case "tagslist", "taglist", "tagsassigned", "tags": 178 fitapp.TagsAssigned(osArgs[2:], config) 179 case "list", "view", "show", "display", "ls": 180 // bug list with no parameters shouldn't autopage, 181 // bug list with issues to view should. So the original 182 fitapp.List(osArgs[2:], config, true) 183 case "find": 184 fitapp.Find(osArgs[2:], config) 185 case "create", "add", "new": 186 //fmt.Printf("%s %#v\n", "osArgs: ", len(osArgs)) 187 fitapp.Create(osArgs[2:], config) 188 //fmt.Printf("%s %#v\n", "osArgs: ", len(osArgs)) 189 case "edit": 190 fitapp.Edit(osArgs[2:], config) 191 case "retitle", "mv", "rename", "relabel": 192 fitapp.Relabel(osArgs[2:], config) 193 case "close", "rm": 194 fitapp.Close(osArgs[2:], config) 195 case "tag": 196 fitapp.Tag(osArgs[2:], config) // boolean only 197 case "id", "identifier": 198 fitapp.Identifier(osArgs[2:], config) 199 case "status": 200 if len(osArgs) == 2 { 201 // overview like a git status 202 fitapp.Env(config) 203 } else { 204 // get or set the status of an issue 205 fitapp.Status(osArgs[2:], config) 206 } 207 case "priority": 208 fitapp.Priority(osArgs[2:], config) 209 case "milestone": 210 fitapp.Milestone(osArgs[2:], config) 211 case "import": 212 fitapp.Import(osArgs[2:], config) 213 case "commit", "save": 214 fitapp.Commit(osArgs[2:], config) 215 case "roadmap": 216 fitapp.Roadmap(osArgs[2:], config) 217 case "help", "--help", "-h": 218 //fmt.Printf("C %s %#v\n", "osArgs: ", osArgs) 219 fitapp.Help(osArgs[2]) 220 default: 221 //if 222 if len(osArgs) == 2 { 223 buglist, _ := issues.LoadIssueByHeuristic(osArgs[1], config) 224 //fmt.Printf("%+v\n", buglist) 225 if buglist != nil { // || ae, ok := bugerr.(issues.ErrNotFound); ! ok { // bug list when possible, not help 226 fitapp.List(osArgs[1:], config, true) 227 } else { 228 fitapp.Help(osArgs[1:]...) 229 } 230 } 231 } 232 } 233 }