From 11817b601b3d46ba60640565e232f54283edd8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AD=E5=BC=80=E7=AE=B1?= Date: Mon, 16 May 2022 21:57:02 +0800 Subject: [PATCH] Add support to sync fork branch with upstream repo (#2337) Fixes: #2335 --- github/github-accessors.go | 32 +++++++++++++++++++++++ github/github-accessors_test.go | 40 ++++++++++++++++++++++++++++ github/repos_merging.go | 34 ++++++++++++++++++++++++ github/repos_merging_test.go | 46 +++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/github/github-accessors.go b/github/github-accessors.go index 873b9753e7..f482d36bad 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -13910,6 +13910,38 @@ func (r *RenameOrgResponse) GetURL() string { return *r.URL } +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamRequest) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetBaseBranch returns the BaseBranch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetBaseBranch() string { + if r == nil || r.BaseBranch == nil { + return "" + } + return *r.BaseBranch +} + +// GetMergeType returns the MergeType field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMergeType() string { + if r == nil || r.MergeType == nil { + return "" + } + return *r.MergeType +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + // GetFrom returns the From field if it's non-nil, zero value otherwise. func (r *RepoName) GetFrom() string { if r == nil || r.From == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 71fd7323c7..2643c23fa7 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -16194,6 +16194,46 @@ func TestRenameOrgResponse_GetURL(tt *testing.T) { r.GetURL() } +func TestRepoMergeUpstreamRequest_GetBranch(tt *testing.T) { + var zeroValue string + r := &RepoMergeUpstreamRequest{Branch: &zeroValue} + r.GetBranch() + r = &RepoMergeUpstreamRequest{} + r.GetBranch() + r = nil + r.GetBranch() +} + +func TestRepoMergeUpstreamResult_GetBaseBranch(tt *testing.T) { + var zeroValue string + r := &RepoMergeUpstreamResult{BaseBranch: &zeroValue} + r.GetBaseBranch() + r = &RepoMergeUpstreamResult{} + r.GetBaseBranch() + r = nil + r.GetBaseBranch() +} + +func TestRepoMergeUpstreamResult_GetMergeType(tt *testing.T) { + var zeroValue string + r := &RepoMergeUpstreamResult{MergeType: &zeroValue} + r.GetMergeType() + r = &RepoMergeUpstreamResult{} + r.GetMergeType() + r = nil + r.GetMergeType() +} + +func TestRepoMergeUpstreamResult_GetMessage(tt *testing.T) { + var zeroValue string + r := &RepoMergeUpstreamResult{Message: &zeroValue} + r.GetMessage() + r = &RepoMergeUpstreamResult{} + r.GetMessage() + r = nil + r.GetMessage() +} + func TestRepoName_GetFrom(tt *testing.T) { var zeroValue string r := &RepoName{From: &zeroValue} diff --git a/github/repos_merging.go b/github/repos_merging.go index 7edda3efff..a8d860742c 100644 --- a/github/repos_merging.go +++ b/github/repos_merging.go @@ -18,6 +18,20 @@ type RepositoryMergeRequest struct { CommitMessage *string `json:"commit_message,omitempty"` } +// RepoMergeUpstreamRequest represents a request to sync a branch of +// a forked repository to keep it up-to-date with the upstream repository. +type RepoMergeUpstreamRequest struct { + Branch *string `json:"branch,omitempty"` +} + +// RepoMergeUpstreamResult represents the result of syncing a branch of +// a forked repository with the upstream repository. +type RepoMergeUpstreamResult struct { + Message *string `json:"message,omitempty"` + MergeType *string `json:"merge_type,omitempty"` + BaseBranch *string `json:"base_branch,omitempty"` +} + // Merge a branch in the specified repository. // // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#merge-a-branch @@ -36,3 +50,23 @@ func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, req return commit, resp, nil } + +// MergeUpstream syncs a branch of a forked repository to keep it up-to-date +// with the upstream repository. +// +// GitHub API docs: https://docs.github.com/en/rest/reference/branches#sync-a-fork-branch-with-the-upstream-repository +func (s *RepositoriesService) MergeUpstream(ctx context.Context, owner, repo string, request *RepoMergeUpstreamRequest) (*RepoMergeUpstreamResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merge-upstream", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + result := new(RepoMergeUpstreamResult) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/github/repos_merging_test.go b/github/repos_merging_test.go index 052631000a..0275915b9b 100644 --- a/github/repos_merging_test.go +++ b/github/repos_merging_test.go @@ -80,3 +80,49 @@ func TestRepositoryMergeRequest_Marshal(t *testing.T) { testJSONMarshal(t, u, want) } + +func TestRepositoriesService_MergeUpstream(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + input := &RepoMergeUpstreamRequest{ + Branch: String("b"), + } + + mux.HandleFunc("/repos/o/r/merge-upstream", func(w http.ResponseWriter, r *http.Request) { + v := new(RepoMergeUpstreamRequest) + json.NewDecoder(r.Body).Decode(v) + + testMethod(t, r, "POST") + if !cmp.Equal(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{"merge_type":"m"}`) + }) + + ctx := context.Background() + result, _, err := client.Repositories.MergeUpstream(ctx, "o", "r", input) + if err != nil { + t.Errorf("Repositories.MergeUpstream returned error: %v", err) + } + + want := &RepoMergeUpstreamResult{MergeType: String("m")} + if !cmp.Equal(result, want) { + t.Errorf("Repositories.MergeUpstream returned %+v, want %+v", result, want) + } + + const methodName = "MergeUpstream" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Repositories.MergeUpstream(ctx, "\n", "\n", input) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Repositories.MergeUpstream(ctx, "o", "r", input) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +}