예제 #1
0
파일: main.go 프로젝트: afcuttin/todos
func work(root string, files []string) {

	//Load configuration
	global := OpenConfiguration(HOME_DIRECTORY_CONFIG)
	defer global.File.Close()
	local := OpenConfiguration(root)
	defer local.File.Close()

	if global.Config.GithubToken == "" {

		fmt.Println("[Todos] Missing Github token. Set it in ~/.todos/conf.json")

	} else if local.Config.Owner == "" || local.Config.Repo == "" {

		fmt.Println("[Todos] You need to setup the repo running 'todos setup'")

	} else {

		o := &oauth.Transport{
			Token: &oauth.Token{AccessToken: global.Config.GithubToken},
		}

		owner := local.Config.Owner
		repo := local.Config.Repo

		fmt.Printf("[Todos] Scanning changed files on %s/%s\n", owner, repo)

		client := github.NewClient(o.Client())

		existingRegex, err := regexp.Compile(ISSUE_URL_REGEX)
		logOnError(err)
		todoRegex, err := regexp.Compile(TODO_REGEX)
		logOnError(err)

		cacheFile := LoadIssueCache(root)
		cacheChanges := false

		//Leave first two lines blank so it displays as the commit description
		closedIssues := []string{"", ""}

		for _, file := range files {

			// In the cache files are saved as a relative path to the project root
			relativeFilePath := pathDifference(root, file)

			fileIssuesCache := cacheFile.GetIssuesInFile(relativeFilePath)
			fileIssuesCacheCopy := fileIssuesCache

			removed := 0

			fmt.Println("[Todos] Checking file:", relativeFilePath)

			lines, err := ReadFileLines(file)
			logOnError(err)

			changes := false

			cb := make(chan Issue)
			issuesCount := 0

			for i, line := range lines {

				ex := existingRegex.FindString(line)
				todo := todoRegex.FindString(line)

				if ex != "" {

					for i, is := range fileIssuesCache {

						if is != nil && is.Hash == helpers.SHA1([]byte(ex)) {

							cacheChanges = true
							fileIssuesCacheCopy = fileIssuesCacheCopy.remove(i)
							removed++
						}
					}

				} else if todo != "" {

					issuesCount++
					go func(line int, cb chan Issue) {

						branch, _ := GitBranch()

						filename := path.Base(file)

						body := fmt.Sprintf(ISSUE_BODY, filename, fmt.Sprintf(GITHUB_FILE_URL, owner, repo, branch, relativeFilePath))
						issue, _, err := client.Issues.Create(owner, repo, &github.IssueRequest{Title: &todo, Body: &body})
						logOnError(err)

						if issue != nil {
							cb <- Issue{IssueURL: *issue.HTMLURL, IssueNumber: *issue.Number, Line: line, File: relativeFilePath}
						}
					}(i, cb)
				}
			}
		loop:
			for issuesCount > 0 {

				select {
				case issue := <-cb:

					ref := fmt.Sprintf("[Issue: %s]", issue.IssueURL)
					lines[issue.Line] = fmt.Sprintf("%s %s", lines[issue.Line], ref)
					fmt.Printf("[Todos] Created issue #%d\n", issue.IssueNumber)
					changes = true
					issuesCount--

					issue.Hash = helpers.SHA1([]byte(ref))
					cacheFile.Issues = append(cacheFile.Issues, &issue)
					cacheChanges = true

				case <-timeout(3 * time.Second):
					break loop
				}
			}

			closeCount := 0
			closeCb := make(chan Issue)
			for _, is := range fileIssuesCacheCopy {

				if is != nil {

					closeCount++
					go func(i Issue) {

						var closed string = "closed"
						_, _, err := client.Issues.Edit(owner, repo, is.IssueNumber, &github.IssueRequest{State: &closed})
						logOnError(err)
						closeCb <- i
					}(*is)
				}
			}

		loops:
			for closeCount > 0 {
				select {
				case is := <-closeCb:
					closeCount--
					issueClosing := fmt.Sprintf("[Todos] Closed issue #%d", is.IssueNumber)
					fmt.Println(issueClosing)
					closedIssues = append(closedIssues, issueClosing)
					cacheFile.RemoveIssue(is)
					cacheChanges = true

				case <-timeout(3 * time.Second):
					break loops
				}
			}

			if changes {
				logOnError(WriteFileLines(file, lines, false))
				GitAdd(file)
			} else {
				fmt.Println("[Todos] No new todos found")
			}
		}

		if cacheChanges {
			logOnError(cacheFile.WriteIssueCache())
			GitAdd(IssueCacheFilePath(root))
		}
		if len(closedIssues) <= 2 {

			closedIssues = []string{}
		}

		logOnError(WriteFileLines(path.Join(root, TODOS_DIRECTORY, CLOSED_ISSUES_FILENAME), closedIssues, false))
	}
}
예제 #2
0
func hash(x string) string {

	return helpers.SHA1([]byte(x))
}