aboutsummaryrefslogtreecommitdiffstats
path: root/commands/bridge/bridge_pull.go
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2022-09-10 11:09:19 +0200
committerMichael Muré <batolettre@gmail.com>2022-11-20 17:18:09 +0100
commitacc9a6f3a6df2961c3ae44352216d915cb9b5315 (patch)
treee159372673104ade1f15ddc1a84aa9da93e93552 /commands/bridge/bridge_pull.go
parenta3fa445a9c76631c4cd16f93e1c1c68a954adef7 (diff)
downloadgit-bug-acc9a6f3a6df2961c3ae44352216d915cb9b5315.tar.gz
commands: reorg into different packages
Diffstat (limited to 'commands/bridge/bridge_pull.go')
-rw-r--r--commands/bridge/bridge_pull.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/commands/bridge/bridge_pull.go b/commands/bridge/bridge_pull.go
new file mode 100644
index 00000000..d1fc279a
--- /dev/null
+++ b/commands/bridge/bridge_pull.go
@@ -0,0 +1,155 @@
+package bridgecmd
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/araddon/dateparse"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+
+ "github.com/MichaelMure/git-bug/bridge"
+ "github.com/MichaelMure/git-bug/bridge/core"
+ "github.com/MichaelMure/git-bug/commands/completion"
+ "github.com/MichaelMure/git-bug/commands/execenv"
+ "github.com/MichaelMure/git-bug/util/interrupt"
+)
+
+type bridgePullOptions struct {
+ importSince string
+ noResume bool
+}
+
+func newBridgePullCommand() *cobra.Command {
+ env := execenv.NewEnv()
+ options := bridgePullOptions{}
+
+ cmd := &cobra.Command{
+ Use: "pull [NAME]",
+ Short: "Pull updates from a remote bug tracker",
+ PreRunE: execenv.LoadBackend(env),
+ RunE: execenv.CloseBackend(env, func(cmd *cobra.Command, args []string) error {
+ return runBridgePull(env, options, args)
+ }),
+ Args: cobra.MaximumNArgs(1),
+ ValidArgsFunction: completion.Bridge(env),
+ }
+
+ flags := cmd.Flags()
+ flags.SortFlags = false
+
+ flags.BoolVarP(&options.noResume, "no-resume", "n", false, "force importing all bugs")
+ flags.StringVarP(&options.importSince, "since", "s", "", "import only bugs updated after the given date (ex: \"200h\" or \"june 2 2019\")")
+
+ return cmd
+}
+
+func runBridgePull(env *execenv.Env, opts bridgePullOptions, args []string) error {
+ if opts.noResume && opts.importSince != "" {
+ return fmt.Errorf("only one of --no-resume and --since flags should be used")
+ }
+
+ var b *core.Bridge
+ var err error
+
+ if len(args) == 0 {
+ b, err = bridge.DefaultBridge(env.Backend)
+ } else {
+ b, err = bridge.LoadBridge(env.Backend, args[0])
+ }
+
+ if err != nil {
+ return err
+ }
+
+ parentCtx := context.Background()
+ ctx, cancel := context.WithCancel(parentCtx)
+ defer cancel()
+
+ // buffered channel to avoid send block at the end
+ done := make(chan struct{}, 1)
+
+ var mu sync.Mutex
+ interruptCount := 0
+ interrupt.RegisterCleaner(func() error {
+ mu.Lock()
+ if interruptCount > 0 {
+ env.Err.Println("Received another interrupt before graceful stop, terminating...")
+ os.Exit(0)
+ }
+
+ interruptCount++
+ mu.Unlock()
+
+ env.Err.Println("Received interrupt signal, stopping the import...\n(Hit ctrl-c again to kill the process.)")
+
+ // send signal to stop the importer
+ cancel()
+
+ // block until importer gracefully shutdown
+ <-done
+ return nil
+ })
+
+ var events <-chan core.ImportResult
+ switch {
+ case opts.noResume:
+ events, err = b.ImportAllSince(ctx, time.Time{})
+ case opts.importSince != "":
+ since, err2 := parseSince(opts.importSince)
+ if err2 != nil {
+ return errors.Wrap(err2, "import time parsing")
+ }
+ events, err = b.ImportAllSince(ctx, since)
+ default:
+ events, err = b.ImportAll(ctx)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ importedIssues := 0
+ importedIdentities := 0
+ for result := range events {
+ switch result.Event {
+ case core.ImportEventNothing:
+ // filtered
+
+ case core.ImportEventBug:
+ importedIssues++
+ env.Out.Println(result.String())
+
+ case core.ImportEventIdentity:
+ importedIdentities++
+ env.Out.Println(result.String())
+
+ case core.ImportEventError:
+ if result.Err != context.Canceled {
+ env.Out.Println(result.String())
+ }
+
+ default:
+ env.Out.Println(result.String())
+ }
+ }
+
+ env.Out.Printf("imported %d issues and %d identities with %s bridge\n", importedIssues, importedIdentities, b.Name)
+
+ // send done signal
+ close(done)
+
+ return nil
+}
+
+func parseSince(since string) (time.Time, error) {
+ duration, err := time.ParseDuration(since)
+ if err == nil {
+ return time.Now().Add(-duration), nil
+ }
+
+ return dateparse.ParseLocal(since)
+}