func (a BugApplication) Edit(args ArgumentList) { issues, _ := ioutil.ReadDir(string(bugs.GetIssuesDir())) // No parameters, print a list of all bugs if len(args) == 1 { idx, err := strconv.Atoi(args[0]) if idx > len(issues) || idx < 1 { fmt.Printf("Invalid issue number %d\n", idx) return } dir := bugs.Directory(bugs.GetIssuesDir()) + bugs.Directory(issues[idx-1].Name()) cmd := exec.Command(getEditor(), string(dir)+"/Description") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { log.Fatal(err) } } else { fmt.Printf("Usage: %s edit issuenum\n", os.Args[0]) fmt.Printf("\nNo issue number specified\n") } }
func List(args ArgumentList, stdout *os.File) { issues, _ := ioutil.ReadDir(string(bugs.GetIssuesDir())) var wantTags bool = false if args.HasArgument("--tags") { wantTags = true } // No parameters, print a list of all bugs if len(args) == 0 || (wantTags && len(args) == 1) { //os.Stdout = stdout for idx, issue := range issues { if issue.IsDir() != true { continue } var dir bugs.Directory = bugs.GetIssuesDir() + bugs.Directory(issue.Name()) b := bugs.Bug{dir} name := getBugName(b, idx) if wantTags == false { fmt.Printf("%s: %s\n", name, b.Title("")) } else { fmt.Printf("%s: %s\n", name, b.Title("tags")) } } return } // getAllTags() is defined in Tag.go // Get a list of tags, so that when we encounter // an error we can check if it's because the user // provided a tagname instead of a BugID. If they // did, then list bugs matching that tag instead // of full descriptions tags := getAllTags() // There were parameters, so show the full description of each // of those issues for i, length := 0, len(args); i < length; i += 1 { b, err := bugs.LoadBugByHeuristic(args[i]) if err != nil { for _, tagname := range tags { if tagname == args[i] { listTags(issues, args) return } } fmt.Printf("%s\n", err.Error()) continue } b.ViewBug() if i < length-1 { fmt.Printf("\n--\n\n") } } fmt.Printf("\n") }
func (a BugApplication) List(args ArgumentList) { issues, _ := ioutil.ReadDir(string(bugs.GetIssuesDir())) var wantTags bool = false if args.HasArgument("--tags") { wantTags = true } // No parameters, print a list of all bugs if len(args) == 0 || (wantTags && len(args) == 1) { for idx, issue := range issues { if issue.IsDir() != true { continue } var dir bugs.Directory = bugs.GetIssuesDir() + bugs.Directory(issue.Name()) b := bugs.Bug{dir} if wantTags == false { fmt.Printf("Issue %d: %s\n", idx+1, b.Title("")) } else { fmt.Printf("Issue %d: %s\n", idx+1, b.Title("tags")) } } return } // There were parameters, so show the full description of each // of those issues b := bugs.Bug{} for i, length := 0, len(args); i < length; i += 1 { idx, err := strconv.Atoi(args[i]) if err != nil { listTags(issues, args) return } if idx > len(issues) || idx < 1 { fmt.Printf("Invalid issue number %d\n", idx) continue } if err == nil { b.LoadBug(bugs.Directory(bugs.GetIssuesDir() + bugs.Directory(issues[idx-1].Name()))) b.ViewBug() if i < length-1 { fmt.Printf("\n--\n\n") } } } fmt.Printf("\n") }
func beImport() { wd, err := os.Getwd() if dir := walkAndSearch(wd, []string{".be"}); err != nil || dir == nil { fmt.Fprintf(os.Stderr, "Could not find any Bugs Everywhere repository relative to current path.\n") os.Exit(3) } else { files, err := dir.Readdir(-1) sort.Sort(fileSorter(files)) if err != nil { fmt.Fprintf(os.Stderr, "Error importing BE database: %s\n", err.Error()) os.Exit(4) } issuesDir := bugs.GetIssuesDir() lastIdentifier := "" nextIdentifier := "" for idx, file := range files { if file.IsDir() { if idx < len(files)-1 { nextIdentifier = files[idx+1].Name() } name := shortestPrefix(file.Name(), nextIdentifier, lastIdentifier, 3) beImportBugs(name, string(issuesDir), dir.Name(), file.Name()) lastIdentifier = file.Name() } } } }
func listTags(files []os.FileInfo, args ArgumentList) { b := bugs.Bug{} for idx, _ := range files { b.LoadBug(bugs.Directory(bugs.GetIssuesDir() + bugs.Directory(files[idx].Name()))) for _, tag := range args { if b.HasTag(bugs.Tag(tag)) { fmt.Printf("%s: %s\n", getBugName(b, idx), b.Title("tags")) } } } }
// This will try and commit the $(bug pwd) directory // transparently. It does the following steps: // // 1. "git stash create" // 2. "git reset --mixed" (unstage the user's currently staged files) // 3. "git add $(bug pwd)" // 4. "git commit" // 5a. "git reset --hard" (if there was any stash created, // this is necessary for 5b to work.) // 5b. "git stash apply --index" the stash from step 1 func (a BugApplication) Commit() { scm, _, err := scm.DetectSCM() if err != nil { fmt.Printf("Error: %s\n", err.Error()) return } err = scm.Commit(bugs.GetIssuesDir(), "Added or removed issues with the tool \"bug\"") if err != nil { fmt.Printf("Could not commit: %s\n", err.Error()) return } }
func (a BugApplication) Purge() { scm, _, err := scm.DetectSCM() if err != nil { fmt.Printf("Error: %s\n", err.Error()) return } err = scm.Purge(bugs.GetIssuesDir()) if err != nil { fmt.Printf("Error: %s\n", err.Error()) return } }
func (a BugApplication) Env() { scm, scmdir, scmerr := scm.DetectSCM() fmt.Printf("Settings used by this command:\n") fmt.Printf("\nEditor: %s", getEditor()) fmt.Printf("\nIssues directory: %s", bugs.GetIssuesDir()) if scmerr == nil { fmt.Printf("\n\nSCM Type:\t%s", scm.GetSCMType()) fmt.Printf("\n%s directory:\t%s", scm.GetSCMType(), scmdir) } else { fmt.Printf("\n\nSCM Type: None (purge and commit commands unavailable)") } fmt.Printf("\n") }
func (a BugApplication) Close(args ArgumentList) { issues, _ := ioutil.ReadDir(string(bugs.GetIssuesDir())) // No parameters, print a list of all bugs if len(args) == 0 { fmt.Printf("Usage: %s close IssueNumber\n\nMust provide an IssueNumber to close as parameter\n", os.Args[0]) return } // There were parameters, so show the full description of each // of those issues for i := 0; i < len(args); i += 1 { idx, err := strconv.Atoi(args[i]) if idx > len(issues) || idx < 1 { fmt.Printf("Invalid issue number %d\n", idx) continue } if err == nil { dir := bugs.GetIssuesDir() + bugs.Directory(issues[idx-1].Name()) fmt.Printf("Removing %s\n", dir) os.RemoveAll(string(dir)) } } }
func (a BugApplication) Create(Args ArgumentList) { if len(Args) < 1 || (len(Args) < 2 && Args[0] == "-n") { fmt.Printf("Usage: %s create [-n] Bug Description\n", os.Args[0]) fmt.Printf("\nNo Bug Description provided.\n") return } var noDesc bool = false if Args.HasArgument("-n") { noDesc = true Args = Args[1:] } var bug bugs.Bug bug = bugs.Bug{ Dir: bugs.GetIssuesDir() + bugs.TitleToDir(strings.Join(Args, " ")), } dir, _ := bug.GetDirectory() fmt.Printf("Created issue: %s\n", bug.Title("")) var mode os.FileMode mode = 0775 os.Mkdir(string(dir), mode) if noDesc { txt := []byte("") ioutil.WriteFile(string(dir)+"/Description", txt, 0644) } else { cmd := exec.Command(getEditor(), string(dir)+"/Description") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { log.Fatal(err) } } }
func (a BugApplication) Relabel(Args ArgumentList) { if len(Args) < 2 { fmt.Printf("Usage: %s relabel issuenum New Title\n", os.Args[0]) return } b, err := bugs.LoadBugByStringIndex(Args[0]) if err != nil { fmt.Printf("Could not load bug: %s\n", err.Error()) return } currentDir, _ := b.GetDirectory() newDir := bugs.GetIssuesDir() + bugs.TitleToDir(strings.Join(Args[1:], " ")) fmt.Printf("Moving %s to %s\n", currentDir, newDir) err = os.Rename(string(currentDir), string(newDir)) if err != nil { fmt.Printf("Error moving directory\n") } }
func Create(Args ArgumentList) { if len(Args) < 1 || (len(Args) < 2 && Args[0] == "-n") { fmt.Fprintf(os.Stderr, "Usage: %s create [-n] Bug Description\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\nNo Bug Description provided.\n") return } var noDesc bool = false if Args.HasArgument("-n") { noDesc = true Args = Args[1:] } Args, argVals := Args.GetAndRemoveArguments([]string{"--tag", "--status", "--priority", "--milestone", "--identifier"}) tag := argVals[0] status := argVals[1] priority := argVals[2] milestone := argVals[3] identifier := argVals[4] if Args.HasArgument("--generate-id") { for i, token := range Args { if token == "--generate-id" { if i+1 < len(Args) { Args = append(Args[:i], Args[i+1:]...) break } else { Args = Args[:i] break } } } identifier = generateID(strings.Join(Args, " ")) } var bug bugs.Bug bug = bugs.Bug{ Dir: bugs.GetIssuesDir() + bugs.TitleToDir(strings.Join(Args, " ")), } dir := bug.GetDirectory() var mode os.FileMode mode = 0775 os.Mkdir(string(dir), mode) if noDesc { txt := []byte("") ioutil.WriteFile(string(dir)+"/Description", txt, 0644) } else { cmd := exec.Command(getEditor(), string(dir)+"/Description") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { log.Fatal(err) } } if tag != "" { bug.TagBug(bugs.Tag(tag)) } if status != "" { bug.SetStatus(status) } if priority != "" { bug.SetPriority(priority) } if milestone != "" { bug.SetMilestone(milestone) } if identifier != "" { bug.SetIdentifier(identifier) } fmt.Printf("Created issue: %s\n", bug.Title("")) }
// This will try and commit the $(bug pwd) directory // transparently. It does the following steps: // // 1. "git stash create" // 2. "git reset --mixed" (unstage the user's currently staged files) // 3. "git add $(bug pwd)" // 4. "git commit" // 5a. "git reset --hard" (if there was any stash created, // this is necessary for 5b to work.) // 5b. "git stash apply --index" the stash from step 1 func (a BugApplication) Commit() { type FileStatus struct { IndexStatus string WorkingDirStatus string Filename string } statusOutput := func(dir bugs.Directory) []FileStatus { cmd := exec.Command("git", "status", "--porcelain", "-z", string(dir)) output, err := cmd.Output() if err != nil { fmt.Printf("Could not check git status") return nil } fileStatusLines := strings.Split(string(output), "\000") var files []FileStatus for _, line := range fileStatusLines { if len(line) == 0 { continue } files = append(files, FileStatus{ IndexStatus: line[0:1], WorkingDirStatus: line[1:2], Filename: line[2:], }) } return files } // Before doing anything, check git status to see if // the index is in a state that's going to cause an // error sOutput := statusOutput(bugs.GetIssuesDir()) for _, file := range sOutput { if file.IndexStatus == "D" { fmt.Printf("You have manually staged changes in your issue directory which will conflict with %s commit.\n", os.Args[0]) return } } sOutput = statusOutput(bugs.GetRootDir()) for _, file := range sOutput { if file.IndexStatus == "A" { fmt.Printf("You have a new file staged in your git index, which will cause conflicts with %s commit. Please either commit your changes or unstage %s.\n", os.Args[0], file.Filename) return } } cmd := exec.Command("git", "stash", "create") output, err := cmd.Output() if err != nil { fmt.Printf("Could not execute git stash create") return } var stashHash string = strings.Trim(string(output), "\n") // Unstage everything, if there was anything stashed, so that // we don't commit things that the user has staged that aren't // issues if stashHash != "" { cmd = exec.Command("git", "reset", "--mixed") err = cmd.Run() if err != nil { } } // Commit the issues directory // git add $(bug pwd) // git commit -m "Added new issues" -q cmd = exec.Command("git", "add", "-A", string(bugs.GetRootDir())+"/issues") err = cmd.Run() if err != nil { fmt.Printf("Could not add to index?\n") } cmd = exec.Command("git", "commit", "-m", "Added or removes issues with the tool \"bug\"", "-q") err = cmd.Run() if err != nil { // If nothing was added commit will have an error, // but we don't care it just means there's nothing // to commit. fmt.Printf("No new issues commited\n") } // There were changes that had been stashed, so we need // to restore them with git stash apply.. first, we // need to do a "git reset --hard" so that the dirty working // tree doesn't cause an error. This isn't as scary as it // sounds, since immediately after git reset --hard we apply // a stash which has the exact same changes that we just threw // away. if stashHash != "" { cmd = exec.Command("git", "reset", "--hard") err = cmd.Run() if err != nil { fmt.Printf("Error resetting the git working tree\n") fmt.Printf("The stash which should have your changes is: %s\n", stashHash) } cmd = exec.Command("git", "stash", "apply", "--index", stashHash) err = cmd.Run() if err != nil { fmt.Printf("Error restoring the git working tree") fmt.Printf("The stash which should have your changes is: %s\n", stashHash) // If nothing was stashed, it's not the end of the world. //fmt.Printf("Could not pop from stash\n") } } }
func Pwd() { fmt.Printf("%s", bugs.GetIssuesDir()) }
func (a BugApplication) Pwd() { fmt.Printf("%s", bugs.GetIssuesDir()) }