mirror of
https://gitea.com/gitea/tea.git
synced 2024-09-22 04:36:00 -04:00
355fd7aa53
improved logging try to use local branch before creating pulls/<PR> useful for checking out your own PRs reorder imports refactor pulls checkout isolated "gitea API to local git cfg" aspect work around go-git limitation As we cant manage multiple remote URLs properly, we just set the correct URL protocol ahead of time. This logic won't apply for already existing HTTPS remotes, these should be deleted before using `tea pr checkout`. use SSH if user has key in gitea Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Norwin Roosen <git@nroo.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/192 Reviewed-by: 6543 <6543@noreply.gitea.io> Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-Authored-By: Norwin <noerw@noreply.gitea.io> Co-Committed-By: Norwin <noerw@noreply.gitea.io>
116 lines
3.3 KiB
Go
116 lines
3.3 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package pulls
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"code.gitea.io/tea/cmd/flags"
|
|
"code.gitea.io/tea/modules/config"
|
|
local_git "code.gitea.io/tea/modules/git"
|
|
"code.gitea.io/tea/modules/utils"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
// CmdPullsCheckout is a command to locally checkout the given PR
|
|
var CmdPullsCheckout = cli.Command{
|
|
Name: "checkout",
|
|
Usage: "Locally check out the given PR",
|
|
Description: `Locally check out the given PR`,
|
|
Action: runPullsCheckout,
|
|
ArgsUsage: "<pull index>",
|
|
Flags: flags.AllDefaultFlags,
|
|
}
|
|
|
|
func runPullsCheckout(ctx *cli.Context) error {
|
|
login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue)
|
|
if ctx.Args().Len() != 1 {
|
|
log.Fatal("Must specify a PR index")
|
|
}
|
|
idx, err := utils.ArgToIndex(ctx.Args().First())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
localRepo, err := local_git.RepoForWorkdir()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
localBranchName, remoteBranchName, newRemoteName, remoteURL, err :=
|
|
gitConfigForPR(localRepo, login, owner, repo, idx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// verify related remote is in local repo, otherwise add it
|
|
localRemote, err := localRepo.GetOrCreateRemote(remoteURL, newRemoteName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
localRemoteName := localRemote.Config().Name
|
|
|
|
// get auth & fetch remote
|
|
fmt.Printf("Fetching PR %v (head %s:%s) from remote '%s'\n",
|
|
idx, remoteURL, remoteBranchName, localRemoteName)
|
|
url, err := local_git.ParseURL(remoteURL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
auth, err := local_git.GetAuthForURL(url, login.User, login.SSHKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = localRemote.Fetch(&git.FetchOptions{Auth: auth})
|
|
if err == git.NoErrAlreadyUpToDate {
|
|
fmt.Println(err)
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
// checkout local branch
|
|
fmt.Printf("Creating branch '%s'\n", localBranchName)
|
|
err = localRepo.TeaCreateBranch(localBranchName, remoteBranchName, localRemoteName)
|
|
if err == git.ErrBranchExists {
|
|
fmt.Println("There may be changes since you last checked out, run `git pull` to get them.")
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
return localRepo.TeaCheckout(localBranchName)
|
|
}
|
|
|
|
func gitConfigForPR(repo *local_git.TeaRepo, login *config.Login, owner, repoName string, idx int64) (localBranch, remoteBranch, remoteName, remoteURL string, err error) {
|
|
// fetch PR source-repo & -branch from gitea
|
|
pr, _, err := login.Client().GetPullRequest(owner, repoName, idx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// test if we can pull via SSH, and configure git remote accordingly
|
|
remoteURL = pr.Head.Repository.CloneURL
|
|
keys, _, err := login.Client().ListMyPublicKeys(gitea.ListPublicKeysOptions{})
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(keys) != 0 {
|
|
remoteURL = pr.Head.Repository.SSHURL
|
|
}
|
|
|
|
// try to find a matching existing branch, otherwise return branch in pulls/ namespace
|
|
localBranch = fmt.Sprintf("pulls/%v-%v", idx, pr.Head.Ref)
|
|
if b, _ := repo.TeaFindBranchBySha(pr.Head.Sha, remoteURL); b != nil {
|
|
localBranch = b.Name
|
|
}
|
|
|
|
remoteBranch = pr.Head.Ref
|
|
remoteName = fmt.Sprintf("pulls/%v", pr.Head.Repository.Owner.UserName)
|
|
return
|
|
}
|