Example #1
0
func (a BugApplication) List(args []string) {
	issues, _ := ioutil.ReadDir(string(bugs.GetRootDir()) + "/issues")

	// No parameters, print a list of all bugs
	if len(args) == 0 {
		for idx, issue := range issues {
			var dir bugs.Directory = bugs.Directory(issue.Name())
			fmt.Printf("Issue %d: %s\n", idx+1, dir.ToTitle())
		}
		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.GetRootDir() + "/issues/" + bugs.Directory(issues[idx-1].Name())))
			b.ViewBug()
			if i < length-1 {
				fmt.Printf("\n--\n\n")
			}
		}
	}
	fmt.Printf("\n")
}
Example #2
0
func (a BugApplication) Edit(args []string) {
	issues, _ := ioutil.ReadDir(string(bugs.GetRootDir()) + "/issues")

	// 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.GetRootDir()) + "/issues/" + 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")
	}
}
Example #3
0
func (a BugApplication) Roadmap() {
	issues, _ := ioutil.ReadDir(string(bugs.GetRootDir()) + "/issues")
	var bgs [](bugs.Bug)
	for idx, _ := range issues {
		b := bugs.Bug{}
		b.LoadBug(bugs.Directory(bugs.GetRootDir() + "/issues/" + bugs.Directory(issues[idx].Name())))
		bgs = append(bgs, b)
	}
	sort.Sort(BugListByMilestone(bgs))

	fmt.Printf("# Roadmap for %s\n", bugs.GetRootDir().GetShortName().ToTitle())
	milestone := ""
	for i := len(bgs) - 1; i >= 0; i -= 1 {
		b := bgs[i]
		newMilestone := b.Milestone()
		if milestone != newMilestone {
			if newMilestone == "" {
				fmt.Printf("\n## No milestone set:\n")
			} else {
				fmt.Printf("\n## %s:\n", newMilestone)
			}
		}
		fmt.Printf("- %s\n", b.Title)
		milestone = newMilestone

	}
}
Example #4
0
func (s SettingsHandler) Get(r *http.Request, p map[string]interface{}) (string, error) {
	settings := struct {
		Title     string
		Directory string
	}{bugs.GetRootDir().GetShortName().ToTitle(), string(bugs.GetRootDir())}
	retVal, _ := json.Marshal(settings)
	return string(retVal), nil
}
Example #5
0
func (a BugApplication) Roadmap(args ArgumentList) {
	bgs := bugs.GetAllBugs()
	sort.Sort(BugListByMilestone(bgs))

	fmt.Printf("# Roadmap for %s\n", bugs.GetRootDir().GetShortName().ToTitle())
	milestone := ""
	for i := len(bgs) - 1; i >= 0; i -= 1 {
		b := bgs[i]
		newMilestone := b.Milestone()
		if milestone != newMilestone {
			if newMilestone == "" {
				fmt.Printf("\n## No milestone set:\n")
			} else {
				fmt.Printf("\n## %s:\n", newMilestone)
			}
		}
		if args.HasArgument("--simple") == false {
			fmt.Printf("- %s\n", b.Title("status priority"))
		} else {
			fmt.Printf("- %s\n", b.Title(""))
		}
		milestone = newMilestone

	}
}
Example #6
0
func (m BugPageHandler) Get(r *http.Request, extras map[string]interface{}) (string, error) {
	if r.URL.Path == "/issues" || r.URL.Path == "/issues/" {
		return getBugList()
	}
	bugDir := string(bugs.GetRootDir()) + r.URL.Path
	b := bugs.Bug{}
	b.LoadBug(bugs.Directory(bugDir))

	switch r.URL.Query().Get("format") {
	case "json":
		bJSON, _ := json.Marshal(b)
		return string(bJSON), nil
	default:
		page := BugRenderer{Bug: b}
		page.RootElement = "RBugPage"
		page.Title = b.Title("")
		page.JSFiles = []string{
			// Bootstrap JS
			//"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js",
			// React JS
			"https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js",
			"https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js",
			"/js/BugPage.js",
		}
		page.CSSFiles = []string{
			"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css",
			"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"}
		return HTMLPageRenderer.Render(page), nil
	}

}
Example #7
0
func (a BugApplication) Purge() {
	cmd := exec.Command("git", "clean", "-fd", string(bugs.GetRootDir())+"/issues")

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()

	if err != nil {
		log.Fatal(err)
	}
}
Example #8
0
func getBugList() (string, error) {
	issues, _ := ioutil.ReadDir(string(bugs.GetRootDir()) + "/issues")

	var issuesSlice []string

	for _, issue := range issues {
		issuesSlice = append(issuesSlice, issue.Name())
	}

	retVal, _ := json.Marshal(issuesSlice)
	return string(retVal), nil
}
Example #9
0
func main() {
	app := BugApplication{}
	if bugs.GetRootDir() == "" {
		fmt.Printf("Could not find issues directory.\n")
		fmt.Printf("Make sure either the PMIT environment variable is set, or a parent directory of your working directory has an issues folder.\n")
		fmt.Printf("Aborting.\n")
		os.Exit(2)
	}
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "add", "new", "create":
			app.Create(os.Args[2:])
		case "view", "list":
			app.List(os.Args[2:])
		case "priority":
			app.Priority(os.Args[2:])
		case "status":
			app.Status(os.Args[2:])
		case "milestone":
			app.Milestone(os.Args[2:])
		case "tag":
			app.Tag(os.Args[2:])
		case "mv", "rename", "retitle", "relabel":
			app.Relabel(os.Args[2:])
		case "purge":
			app.Purge()
		case "rm", "close":
			app.Close(os.Args[2:])
		case "edit":
			app.Edit(os.Args[2:])
		case "--version", "version":
			app.Version()
		case "env":
			app.Env()
		case "dir", "pwd":
			app.Pwd()
		case "commit":
			app.Commit()
		case "roadmap":
			app.Roadmap(os.Args[2:])
		case "help":
			fallthrough
		default:
			app.Help(os.Args[1:]...)
		}
	} else {
		app.Help()
	}
}
Example #10
0
func (a BugApplication) Close(args []string) {
	issues, _ := ioutil.ReadDir(string(bugs.GetRootDir()) + "/issues")

	// 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.GetRootDir() + "/issues/" + bugs.Directory(issues[idx-1].Name())
			fmt.Printf("Removing %s\n", dir)
			os.RemoveAll(string(dir))
		}
	}
}
Example #11
0
func Roadmap(args ArgumentList) {
	var bgs []bugs.Bug

	if args.HasArgument("--filter") {
		tags := strings.Split(args.GetArgument("--filter", ""), ",")
		fmt.Printf("%s", tags)
		bgs = bugs.FindBugsByTag(tags)
	} else {
		bgs = bugs.GetAllBugs()
	}
	sort.Sort(BugListByMilestone(bgs))

	fmt.Printf("# Roadmap for %s\n", bugs.GetRootDir().GetShortName().ToTitle())
	milestone := ""
	for i := len(bgs) - 1; i >= 0; i -= 1 {
		b := bgs[i]
		newMilestone := b.Milestone()
		if milestone != newMilestone {
			if newMilestone == "" {
				fmt.Printf("\n## No milestone set:\n")
			} else {
				fmt.Printf("\n## %s:\n", newMilestone)
			}
		}
		if args.HasArgument("--simple") {
			fmt.Printf("- %s\n", b.Title(""))
		} else {
			options := ""
			if !args.HasArgument("--no-status") {
				options += "status"
			}
			if !args.HasArgument("--no-priority") {
				options += " priority"
			}
			if !args.HasArgument("--no-identifier") {
				options += " identifier"
			}

			if args.HasArgument("--tags") {
				options += "tags"
			}
			fmt.Printf("- %s\n", b.Title(options))
		}
		milestone = newMilestone

	}
}
Example #12
0
func (a BugApplication) Relabel(Args []string) {
	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.GetRootDir() + "/issues/" + 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")
	}
}
Example #13
0
func listTags(files []os.FileInfo, args []string) {
	hasTag := func(tags []string, tag string) bool {
		for _, candidate := range tags {
			if candidate == tag {
				return true
			}
		}
		return false
	}
	b := bugs.Bug{}
	for idx, _ := range files {
		b.LoadBug(bugs.Directory(bugs.GetRootDir() + "/issues/" + bugs.Directory(files[idx].Name())))

		tags := b.StringTags()
		for _, tag := range args {
			if hasTag(tags, tag) {
				fmt.Printf("Issue %d: %s (%s)\n", idx+1, b.Title, strings.Join(tags, ", "))
			}
		}
	}
}
Example #14
0
func (a BugApplication) Pwd() {
	fmt.Printf("%s", bugs.GetRootDir()+"/issues")
}
Example #15
0
func (a BugApplication) Env() {
	fmt.Printf("Settings used by this command:\n")
	fmt.Printf("\nIssues directory:\t%s/issues/", bugs.GetRootDir())
	fmt.Printf("\nEditor:\t%s", getEditor())
	fmt.Printf("\n")
}
Example #16
0
// 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")
		}
	}
}
Example #17
0
File: main.go Project: Komosa/bug
func main() {
	if bugs.GetRootDir() == "" {
		fmt.Printf("Could not find issues directory.\n")
		fmt.Printf("Make sure either the PMIT environment variable is set, or a parent directory of your working directory has an issues folder.\n")
		fmt.Println("(If you just started new repo, you probably want to create directory named `issues`).")
		fmt.Printf("Aborting.\n")
		os.Exit(2)
	}

	// Create a pipe for a pager to use
	r, w, err := os.Pipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	// Capture STDOUT for the Pager
	stdout := os.Stdout

	// Don't capture the output on MacOS, because for some reason
	// it doesn't work and results in nothing getting printed
	if runtime.GOOS != "darwin" {
		os.Stdout = w
	}

	// Invoke less -RF attached to the pipe
	// we created
	cmd := exec.Command("less", "-RF")
	cmd.Stdin = r
	cmd.Stdout = stdout
	cmd.Stderr = os.Stderr
	// Make sure the pipe is closed after we
	// finish, then restore STDOUT
	defer func() {
		w.Close()
		if err := cmd.Run(); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		os.Stdout = stdout
	}()

	if len(os.Args) > 1 {
		if len(os.Args) >= 3 && os.Args[2] == "--help" {
			os.Args[1], os.Args[2] = "help", os.Args[1]
		}
		switch os.Args[1] {
		case "add", "new", "create":
			os.Stdout = stdout
			bugapp.Create(os.Args[2:])
		case "view", "list":
			// bug list with no parameters shouldn't autopage,
			// bug list with bugs to view should. So the original
			// stdout is passed as a parameter.
			bugapp.List(os.Args[2:], stdout)
		case "priority":
			bugapp.Priority(os.Args[2:])
		case "status":
			bugapp.Status(os.Args[2:])
		case "milestone":
			bugapp.Milestone(os.Args[2:])
		case "id", "identifier":
			bugapp.Identifier(os.Args[2:])
		case "tag":
			bugapp.Tag(os.Args[2:])
		case "mv", "rename", "retitle", "relabel":
			bugapp.Relabel(os.Args[2:])
		case "purge":
			// This shouldn't autopage
			os.Stdout = stdout
			bugapp.Purge()
		case "rm", "close":
			bugapp.Close(os.Args[2:])
		case "edit":
			// Edit needs the original Stdout since it
			// invokes an editor
			os.Stdout = stdout
			bugapp.Edit(os.Args[2:])
		case "--version", "version":
			bugapp.Version()
		case "env":
			bugapp.Env()
		case "dir", "pwd":
			bugapp.Pwd()
		case "commit":
			bugapp.Commit(os.Args[2:])
		case "roadmap":
			bugapp.Roadmap(os.Args[2:])
		case "help":
			fallthrough
		default:
			bugapp.Help(os.Args[1:]...)
		}
	} else {
		bugapp.Help()
	}
}