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)) } }
func hash(x string) string { return helpers.SHA1([]byte(x)) }