bridge_pull.go

  1package commands
  2
  3import (
  4	"context"
  5	"fmt"
  6	"os"
  7	"sync"
  8	"time"
  9
 10	"github.com/spf13/cobra"
 11
 12	"github.com/MichaelMure/git-bug/bridge"
 13	"github.com/MichaelMure/git-bug/bridge/core"
 14	"github.com/MichaelMure/git-bug/cache"
 15	"github.com/MichaelMure/git-bug/util/interrupt"
 16)
 17
 18var (
 19	importSince int64
 20	noResume    bool
 21)
 22
 23func runBridgePull(cmd *cobra.Command, args []string) error {
 24	if noResume && importSince != 0 {
 25		return fmt.Errorf("only one of --no-resume and --since flags should be used")
 26	}
 27
 28	backend, err := cache.NewRepoCache(repo)
 29	if err != nil {
 30		return err
 31	}
 32	defer backend.Close()
 33	interrupt.RegisterCleaner(backend.Close)
 34
 35	var b *core.Bridge
 36
 37	if len(args) == 0 {
 38		b, err = bridge.DefaultBridge(backend)
 39	} else {
 40		b, err = bridge.LoadBridge(backend, args[0])
 41	}
 42
 43	if err != nil {
 44		return err
 45	}
 46
 47	parentCtx := context.Background()
 48	ctx, cancel := context.WithCancel(parentCtx)
 49	defer cancel()
 50
 51	// buffered channel to avoid send block at the end
 52	done := make(chan struct{}, 1)
 53
 54	var mu sync.Mutex
 55	interruptCount := 0
 56	interrupt.RegisterCleaner(func() error {
 57		mu.Lock()
 58		if interruptCount > 0 {
 59			fmt.Println("Received another interrupt before graceful stop, terminating...")
 60			os.Exit(0)
 61		}
 62
 63		interruptCount++
 64		mu.Unlock()
 65
 66		fmt.Println("Received interrupt signal, stopping the import...\n(Hit ctrl-c again to kill the process.)")
 67
 68		// send signal to stop the importer
 69		cancel()
 70
 71		// block until importer gracefully shutdown
 72		<-done
 73		return nil
 74	})
 75
 76	var events <-chan core.ImportResult
 77	if noResume {
 78		events, err = b.ImportAll(ctx)
 79	} else {
 80		var since time.Time
 81		if importSince != 0 {
 82			since = time.Unix(importSince, 0)
 83		}
 84
 85		events, err = b.ImportAllSince(ctx, since)
 86		if err != nil {
 87			return err
 88		}
 89	}
 90
 91	importedIssues := 0
 92	importedIdentities := 0
 93	for result := range events {
 94		if result.Event != core.ImportEventNothing {
 95			fmt.Println(result.String())
 96		}
 97
 98		switch result.Event {
 99		case core.ImportEventBug:
100			importedIssues++
101		case core.ImportEventIdentity:
102			importedIdentities++
103		}
104	}
105
106	fmt.Printf("imported %d issues and %d identities with %s bridge\n", importedIssues, importedIdentities, b.Name)
107
108	// send done signal
109	close(done)
110
111	return err
112}
113
114var bridgePullCmd = &cobra.Command{
115	Use:     "pull [<name>]",
116	Short:   "Pull updates.",
117	PreRunE: loadRepo,
118	RunE:    runBridgePull,
119	Args:    cobra.MaximumNArgs(1),
120}
121
122func init() {
123	bridgeCmd.AddCommand(bridgePullCmd)
124	bridgePullCmd.Flags().BoolVarP(&noResume, "no-resume", "n", false, "force importing all bugs")
125	bridgePullCmd.Flags().Int64VarP(&importSince, "since", "s", 0, "import only bugs updated after the given date (must be a unix timestamp)")
126}