1package commands
 2
 3import (
 4	"context"
 5	"os"
 6	"sync"
 7	"time"
 8
 9	"github.com/spf13/cobra"
10
11	"github.com/MichaelMure/git-bug/bridge"
12	"github.com/MichaelMure/git-bug/bridge/core"
13	"github.com/MichaelMure/git-bug/util/interrupt"
14)
15
16func newBridgePushCommand() *cobra.Command {
17	env := newEnv()
18
19	cmd := &cobra.Command{
20		Use:     "push [NAME]",
21		Short:   "Push updates.",
22		PreRunE: loadBackendEnsureUser(env),
23		RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
24			return runBridgePush(env, args)
25		}),
26		Args:              cobra.MaximumNArgs(1),
27		ValidArgsFunction: completeBridge(env),
28	}
29
30	return cmd
31}
32
33func runBridgePush(env *Env, args []string) error {
34	var b *core.Bridge
35	var err error
36
37	if len(args) == 0 {
38		b, err = bridge.DefaultBridge(env.backend)
39	} else {
40		b, err = bridge.LoadBridge(env.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	done := make(chan struct{}, 1)
52
53	var mu sync.Mutex
54	interruptCount := 0
55	interrupt.RegisterCleaner(func() error {
56		mu.Lock()
57		if interruptCount > 0 {
58			env.err.Println("Received another interrupt before graceful stop, terminating...")
59			os.Exit(0)
60		}
61
62		interruptCount++
63		mu.Unlock()
64
65		env.err.Println("Received interrupt signal, stopping the import...\n(Hit ctrl-c again to kill the process.)")
66
67		// send signal to stop the importer
68		cancel()
69
70		// block until importer gracefully shutdown
71		<-done
72		return nil
73	})
74
75	events, err := b.ExportAll(ctx, time.Time{})
76	if err != nil {
77		return err
78	}
79
80	exportedIssues := 0
81	for result := range events {
82		if result.Event != core.ExportEventNothing {
83			env.out.Println(result.String())
84		}
85
86		switch result.Event {
87		case core.ExportEventBug:
88			exportedIssues++
89		}
90	}
91
92	env.out.Printf("exported %d issues with %s bridge\n", exportedIssues, b.Name)
93
94	// send done signal
95	close(done)
96	return nil
97}