Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 37 additions & 14 deletions cmd/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"os"
"path/filepath"
"sync"
"sync/atomic"
"time"

"github.com/fatih/color"
Expand Down Expand Up @@ -35,33 +37,54 @@ var pushCmd = &cobra.Command{
if err != nil {
return err
}
pushed := 0

// Serial filter pass — cheap disk reads, avoids concurrent isModified races.
var jobs []*issue.Issue
for _, iss := range issues {
if iss.Number == 0 {
if err := pushOne(root, iss); err != nil {
return err
}
pushed++
jobs = append(jobs, iss)
continue
}
mod, err := isModified(root, iss)
if err != nil {
return err
}
if mod {
jobs = append(jobs, iss)
}
}

if len(jobs) == 0 {
_, err := color.New(color.FgHiBlack).Println("Nothing to push.")
return err
}

const concurrency = 10
sem := make(chan struct{}, concurrency)
var wg sync.WaitGroup
errCh := make(chan error, len(jobs))
var pushed atomic.Int32

for _, iss := range jobs {
wg.Add(1)
sem <- struct{}{}
go func(iss *issue.Issue) {
defer wg.Done()
defer func() { <-sem }()
if err := pushOne(root, iss); err != nil {
return err
errCh <- err
return
}
pushed++
}
pushed.Add(1)
}(iss)
}
if pushed == 0 {
if _, err := color.New(color.FgHiBlack).Println("Nothing to push."); err != nil {
return err
}
} else {
fmt.Printf("%s %d issue(s)\n", color.GreenString("Pushed"), pushed)
wg.Wait()
close(errCh)
if err := <-errCh; err != nil {
return err
}

fmt.Printf("%s %d issue(s)\n", color.GreenString("Pushed"), pushed.Load())
return nil
},
}
Expand Down
38 changes: 29 additions & 9 deletions cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,43 @@ var syncCmd = &cobra.Command{
return err
}

// Step 1: push any new T-numbered issues
// Step 1: push any new T-numbered issues in parallel
local, err := loadAllLocal(root)
if err != nil {
return err
}
newCount := 0

var newIssues []*issue.Issue
for _, iss := range local {
if iss.Number == 0 {
fmt.Printf("Pushing new issue: %s\n", color.CyanString(iss.Title))
if err := pushOne(root, iss); err != nil {
return err
}
newCount++
newIssues = append(newIssues, iss)
}
}
if newCount > 0 {
fmt.Printf("%s %d new issue(s)\n\n", color.GreenString("Pushed"), newCount)

if len(newIssues) > 0 {
const concurrency = 10
sem := make(chan struct{}, concurrency)
var wg sync.WaitGroup
errCh := make(chan error, len(newIssues))

for _, iss := range newIssues {
wg.Add(1)
sem <- struct{}{}
go func(iss *issue.Issue) {
defer wg.Done()
defer func() { <-sem }()
fmt.Printf("Pushing new issue: %s\n", color.CyanString(iss.Title))
if err := pushOne(root, iss); err != nil {
errCh <- err
}
}(iss)
}
wg.Wait()
close(errCh)
if err := <-errCh; err != nil {
return err
}
fmt.Printf("%s %d new issue(s)\n\n", color.GreenString("Pushed"), len(newIssues))
}

// Reload — T-issues now have real numbers
Expand Down