Commit e56e8ca1bb
Verified · cmc
Layout: unified · split
cmd/gitbay/local.go +34 −6
| @@ -471,12 +471,21 @@ func cmdMRApplySuggestion(args []string) int { | |||
| 471 | fmt.Fprintln(os.Stderr, "gitbay:", err) | 471 | fmt.Fprintln(os.Stderr, "gitbay:", err) |
| 472 | return protocol.ExitFailure | 472 | return protocol.ExitFailure |
| 473 | } | 473 | } |
| 474 | if args, err = withRepo(t, args); err != nil { | 474 | asJSON := false |
| 475 | var rest []string | ||
| 476 | for _, a := range args { | ||
| 477 | if a == "--json" { | ||
| 478 | asJSON = true | ||
| 479 | continue | ||
| 480 | } | ||
| 481 | rest = append(rest, a) | ||
| 482 | } | ||
| 483 | if args, err = withRepo(t, rest); err != nil { | ||
| 475 | fmt.Fprintln(os.Stderr, "gitbay:", err) | 484 | fmt.Fprintln(os.Stderr, "gitbay:", err) |
| 476 | return protocol.ExitUsage | 485 | return protocol.ExitUsage |
| 477 | } | 486 | } |
| 478 | if len(args) != 3 { | 487 | if len(args) != 3 { |
| 479 | fmt.Fprintln(os.Stderr, "usage: gitbay mr apply-suggestion [<owner/name>] <n> <thread-id>") | 488 | fmt.Fprintln(os.Stderr, "usage: gitbay mr apply-suggestion [<owner/name>] <n> <thread-id> [--json]") |
| 480 | return protocol.ExitUsage | 489 | return protocol.ExitUsage |
| 481 | } | 490 | } |
| 482 | repo, n, thread := args[0], args[1], args[2] | 491 | repo, n, thread := args[0], args[1], args[2] |
| @@ -516,7 +525,11 @@ func cmdMRApplySuggestion(args []string) int { | |||
| 516 | fmt.Fprintf(os.Stderr, "gitbay: thread %s carries no suggestion\n", thread) | 525 | fmt.Fprintf(os.Stderr, "gitbay: thread %s carries no suggestion\n", thread) |
| 517 | return protocol.ExitUsage | 526 | return protocol.ExitUsage |
| 518 | case s.Apply != "local": | 527 | case s.Apply != "local": |
| 519 | return runSSH(t, []string{"mr", "apply-suggestion", repo, n, thread}, strings.NewReader("")) | 528 | argv := []string{"mr", "apply-suggestion", repo, n, thread} |
| 529 | if asJSON { | ||
| 530 | argv = append(argv, "--json") | ||
| 531 | } | ||
| 532 | return runSSH(t, argv, strings.NewReader("")) | ||
| 520 | case s.Outdated: | 533 | case s.Outdated: |
| 521 | fmt.Fprintf(os.Stderr, "gitbay: suggestion in thread %s is outdated: %s\n", thread, s.Reason) | 534 | fmt.Fprintf(os.Stderr, "gitbay: suggestion in thread %s is outdated: %s\n", thread, s.Reason) |
| 522 | return protocol.ExitUsage | 535 | return protocol.ExitUsage |
| @@ -611,10 +624,25 @@ func cmdMRApplySuggestion(args []string) int { | |||
| 611 | if code := runGitLocal("push", "--quiet", url, sha+":refs/heads/"+branch); code != 0 { | 624 | if code := runGitLocal("push", "--quiet", url, sha+":refs/heads/"+branch); code != 0 { |
| 612 | return code | 625 | return code |
| 613 | } | 626 | } |
| 614 | if _, code := captureSSH(t, []string{"mr", "resolve", repo, n, thread}); code != 0 { | 627 | // The commit has landed, so a thread that cannot be resolved (the |
| 615 | return code | 628 | // server's resolve rule is narrower than who can push) is a warning, |
| 629 | // not a failure; captureSSH has already printed the server's reason. | ||
| 630 | _, code = captureSSH(t, []string{"mr", "resolve", repo, n, thread}) | ||
| 631 | resolved := code == 0 | ||
| 632 | if asJSON { | ||
| 633 | out, _ := json.Marshal(protocol.Envelope{ProtocolVersion: protocol.Version, Data: map[string]any{ | ||
| 634 | "thread": tn, "sha": sha, "source": mr.Data.Source, "branch": branch, "resolved": resolved}}) | ||
| 635 | fmt.Println(string(out)) | ||
| 636 | } else { | ||
| 637 | fmt.Printf("applied thread %s to %s at %.10s", thread, mr.Data.Source, sha) | ||
| 638 | if resolved { | ||
| 639 | fmt.Print("; thread resolved") | ||
| 640 | } | ||
| 641 | fmt.Println() | ||
| 642 | } | ||
| 643 | if !resolved { | ||
| 644 | fmt.Fprintf(os.Stderr, "gitbay: warning: thread %s is still open\n", thread) | ||
| 616 | } | 645 | } |
| 617 | fmt.Printf("applied thread %s to %s at %.10s; thread resolved\n", thread, mr.Data.Source, sha) | ||
| 618 | return 0 | 646 | return 0 |
| 619 | } | 647 | } |
| 620 | 648 | ||
e2e/suggestion_test.go +18 −2
| @@ -112,10 +112,13 @@ func TestSuggestionAppliedByServer(t *testing.T) { | |||
| 112 | t.Fatalf("reader applied a suggestion: exit %d %s", code, errOut) | 112 | t.Fatalf("reader applied a suggestion: exit %d %s", code, errOut) |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | out, errOut, code := c.run(t, dir, "", "mr", "apply-suggestion", "1", thread) | 115 | out, errOut, code := c.run(t, dir, "", "mr", "apply-suggestion", "1", thread, "--json") |
| 116 | if code != 0 { | 116 | if code != 0 { |
| 117 | t.Fatalf("apply-suggestion: exit %d\n%s\n%s", code, out, errOut) | 117 | t.Fatalf("apply-suggestion: exit %d\n%s\n%s", code, out, errOut) |
| 118 | } | 118 | } |
| 119 | if !strings.Contains(out, `"resolved":true`) { | ||
| 120 | t.Errorf("apply-suggestion --json = %s", out) | ||
| 121 | } | ||
| 119 | mustGit(t, dir, env, "fetch", "-q", "origin", "feat") | 122 | mustGit(t, dir, env, "fetch", "-q", "origin", "feat") |
| 120 | if got := mustGit(t, dir, env, "show", "FETCH_HEAD:lib.txt"); got != "one\nTWO\nTWO AND A HALF\nthree\n" { | 123 | if got := mustGit(t, dir, env, "show", "FETCH_HEAD:lib.txt"); got != "one\nTWO\nTWO AND A HALF\nthree\n" { |
| 121 | t.Fatalf("lib.txt = %q", got) | 124 | t.Fatalf("lib.txt = %q", got) |
| @@ -174,11 +177,24 @@ func TestSuggestionAppliedLocallyWhenSigned(t *testing.T) { | |||
| 174 | t.Fatalf("server-side apply on a require-signed repository: exit %d %s", code, errOut) | 177 | t.Fatalf("server-side apply on a require-signed repository: exit %d %s", code, errOut) |
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | out, errOut, code := c.run(t, dir, "", "mr", "apply-suggestion", "1", thread) | 180 | out, errOut, code := c.run(t, dir, "", "mr", "apply-suggestion", "1", thread, "--json") |
| 178 | if code != 0 { | 181 | if code != 0 { |
| 179 | t.Fatalf("local apply-suggestion: exit %d\n%s\n%s", code, out, errOut) | 182 | t.Fatalf("local apply-suggestion: exit %d\n%s\n%s", code, out, errOut) |
| 180 | } | 183 | } |
| 184 | var res struct { | ||
| 185 | Data struct { | ||
| 186 | SHA string `json:"sha"` | ||
| 187 | Branch string `json:"branch"` | ||
| 188 | Resolved bool `json:"resolved"` | ||
| 189 | } `json:"data"` | ||
| 190 | } | ||
| 191 | if err := json.Unmarshal([]byte(out), &res); err != nil || res.Data.Branch != "feat" || !res.Data.Resolved { | ||
| 192 | t.Fatalf("local apply-suggestion --json = %s (%v)", out, err) | ||
| 193 | } | ||
| 181 | mustGit(t, dir, env, "fetch", "-q", "origin", "feat") | 194 | mustGit(t, dir, env, "fetch", "-q", "origin", "feat") |
| 195 | if tip := strings.TrimSpace(mustGit(t, dir, env, "rev-parse", "FETCH_HEAD")); tip != res.Data.SHA { | ||
| 196 | t.Errorf("reported sha %s, branch at %s", res.Data.SHA, tip) | ||
| 197 | } | ||
| 182 | if got := mustGit(t, dir, env, "show", "FETCH_HEAD:lib.txt"); got != "one\nTWO\nTWO AND A HALF\nthree\n" { | 198 | if got := mustGit(t, dir, env, "show", "FETCH_HEAD:lib.txt"); got != "one\nTWO\nTWO AND A HALF\nthree\n" { |
| 183 | t.Fatalf("lib.txt = %q", got) | 199 | t.Fatalf("lib.txt = %q", got) |
| 184 | } | 200 | } |