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}