github.com/grantbow/fit@v0.7.1-0.20220916164603-1f7c88ac81e6/fitapp/be.go (about) 1 package fitapp 2 3 import ( 4 "encoding/json" 5 "fmt" 6 bugs "github.com/grantbow/fit/issues" 7 "io/ioutil" 8 "os" 9 "sort" 10 "strings" 11 ) 12 13 //var dops = bugs.Directory(os.PathSeparator) 14 //var sops = string(os.PathSeparator) 15 16 func beImportComments(b bugs.Issue, directory string, includeHeaders bool) string { 17 file := directory + sops + "body" 18 data, _ := ioutil.ReadFile(file) 19 if includeHeaders == false { 20 return string(data) 21 } 22 23 /* Be appears to store comment metadata in a JSON file named values 24 with the format: 25 { 26 "Author": "Dave MacFarlane <driusan@gmail.com>", 27 "Content-type": "text/plain", 28 "Date": "Tue, 12 Jan 2016 21:44:24 +0000" 29 } 30 */ 31 type BeValues struct { 32 Author string `json:"Author"` 33 ContentType string `json:"Content-type"` 34 Date string `json:"Date"` 35 } 36 file = directory + sops + "values" 37 jsonVal, _ := ioutil.ReadFile(file) 38 var beComment BeValues 39 json.Unmarshal([]byte(jsonVal), &beComment) 40 return "---------- Comment ---------\nFrom:" + beComment.Author + "\nDate:" + beComment.Date + "\n\n" + string(data) 41 } 42 43 func beImportIssue(identifier, issuesDir, fullbepath string, config bugs.Config) { 44 /* BE appears to store the top level data of a bug 45 in a json file with the format: 46 { 47 "creator": "Dave MacFarlane <driusan@gmail.com>", 48 "reporter": "Dave MacFarlane <driusan@gmail.com>", 49 "severity": "minor", 50 "status": "open", 51 "summary": "abc", 52 "time": "Tue, 12 Jan 2016 00:05:28 +0000" 53 } 54 55 and the Description of bugs entirely in comments. 56 All we really care about is the summary so that we 57 can get the directory name for the issues/ directory, 58 but the severity+status can also be used as a status 59 to ensure that we have at least 1 file to be tracked 60 by git. 61 */ 62 63 type BeValues struct { 64 Creator string `json:"creator"` 65 Reporter string `json:"reporter"` 66 Severity string `json:"severity"` 67 Status string `json:"status"` 68 Summary string `json:"summary"` 69 Time string `json:"time"` 70 } 71 file := fullbepath + sops + "values" 72 73 fmt.Printf("File: %s\n", file) 74 data, _ := ioutil.ReadFile(file) 75 var beIssue BeValues 76 err := json.Unmarshal([]byte(data), &beIssue) 77 if err != nil { 78 fmt.Printf("Error unmarshalling data: %s\n", err.Error()) 79 } 80 81 fmt.Printf("%s\n", beIssue) 82 83 bugdir := bugs.TitleToDir(beIssue.Summary) 84 85 b := bugs.Issue{Dir: bugs.Directory(issuesDir) + bugdir} 86 if dir := b.Direr(); dir != "" { 87 os.Mkdir(string(dir), 0755) 88 } 89 if beIssue.Status != "" && beIssue.Severity != "" { 90 b.SetStatus(beIssue.Status+":"+beIssue.Severity, config) 91 } 92 93 comments := fullbepath + sops + "comments" + sops 94 dir, err := os.Open(comments) 95 96 files, err := dir.Readdir(-1) 97 var DescriptionStr string 98 if len(files) > 0 && err == nil { 99 for _, file := range files { 100 if file.IsDir() { 101 DescriptionStr = DescriptionStr + "\n" + 102 beImportComments(b, comments+file.Name(), len(files) > 1) 103 } 104 } 105 } 106 b.SetDescription(DescriptionStr, config) 107 b.SetIdentifier(identifier, config) 108 } 109 func beImportIssues(prefix, issuesdir, bedir, dirname string, config bugs.Config) { 110 bugsdir := bedir + sops + dirname + sops + "bugs" 111 dir, err := os.Open(bugsdir) 112 if err != nil { 113 fmt.Fprintf(os.Stderr, "Could not open directory %s\n", bugsdir) 114 } 115 files, _ := dir.Readdir(-1) 116 117 lastIdentifier := "" 118 nextIdentifier := "" 119 sort.Sort(fileSorter(files)) 120 for idx, file := range files { 121 if file.IsDir() { 122 if idx < len(files)-1 { 123 nextIdentifier = files[idx+1].Name() 124 } 125 name := shortestPrefix(file.Name(), nextIdentifier, lastIdentifier, 3) 126 identifier := fmt.Sprintf("%s%s%s", prefix, sops, name) 127 beImportIssue(identifier, issuesdir, bugsdir+sops+file.Name(), config) 128 lastIdentifier = file.Name() 129 } 130 } 131 } 132 133 type fileSorter []os.FileInfo 134 135 func (a fileSorter) Len() int { 136 return len(a) 137 } 138 func (a fileSorter) Less(i, j int) bool { 139 return a[i].Name() < a[j].Name() 140 } 141 func (a fileSorter) Swap(i, j int) { 142 a[i], a[j] = a[j], a[i] 143 } 144 145 func beImport(config bugs.Config) { 146 wd, err := os.Getwd() 147 if dir := walkAndSearch(wd, []string{".be"}); err != nil || dir == nil { 148 fmt.Fprintf(os.Stderr, "Could not find any Bugs Everywhere repository relative to current path.\n") 149 os.Exit(3) 150 } else { 151 files, err := dir.Readdir(-1) 152 sort.Sort(fileSorter(files)) 153 if err != nil { 154 fmt.Fprintf(os.Stderr, "Error importing BE database: %s\n", err.Error()) 155 os.Exit(4) 156 } 157 158 issuesDir := bugs.FitDirer(config) 159 lastIdentifier := "" 160 nextIdentifier := "" 161 for idx, file := range files { 162 if file.IsDir() { 163 if idx < len(files)-1 { 164 nextIdentifier = files[idx+1].Name() 165 } 166 name := shortestPrefix(file.Name(), nextIdentifier, lastIdentifier, 3) 167 168 beImportIssues(name, string(issuesDir), dir.Name(), file.Name(), config) 169 lastIdentifier = file.Name() 170 } 171 } 172 } 173 } 174 175 func walkAndSearch(startpath string, dirnames []string) *os.File { 176 for _, dirname := range dirnames { 177 if dirinfo, err := os.Stat(startpath + sops + dirname); err == nil && dirinfo.IsDir() { 178 file, err := os.Open(startpath + sops + dirname) 179 if err != nil { 180 return nil 181 } 182 return file 183 } 184 } 185 186 pieces := strings.Split(startpath, sops) 187 188 for i := len(pieces); i > 0; i -= 1 { 189 dir := strings.Join(pieces[0:i], sops) 190 for _, dirname := range dirnames { 191 if dirinfo, err := os.Stat(dir + sops + dirname); err == nil && dirinfo.IsDir() { 192 file, err := os.Open(dir + sops + dirname) 193 if err != nil { 194 return nil 195 } 196 return file 197 } 198 } 199 } 200 return nil 201 } 202 203 func shortestPrefix(name, nextIdentifier, lastIdentifier string, min int) string { 204 for i := 0; i < len(name); i += 1 { 205 if i < min { 206 continue 207 } 208 if nextIdentifier != "" && len(nextIdentifier) <= i { 209 if name[0:i] == nextIdentifier[0:i] { 210 continue 211 } 212 } 213 214 if lastIdentifier != "" && len(lastIdentifier) <= i { 215 if name[0:i] == lastIdentifier[0:i] { 216 continue 217 } 218 } 219 return name[0:i] 220 } 221 return name 222 }