Drop features to reduce friction on first use #395
|
@ -28,14 +28,7 @@ var LoginFlag = cli.StringFlag{
|
|||
var RepoFlag = cli.StringFlag{
|
||||
Name: "repo",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Override local repository path or gitea repository slug to interact with. Optional",
|
||||
}
|
||||
|
||||
// RemoteFlag provides flag to specify remote repository
|
||||
var RemoteFlag = cli.StringFlag{
|
||||
Name: "remote",
|
||||
Aliases: []string{"R"},
|
||||
Usage: "Discover Gitea login from remote. Optional",
|
||||
Usage: "Override remote repository to interact with. Optional. Format: `repo` or `owner/repo`",
|
||||
}
|
||||
|
||||
// OutputFlag provides flag to specify output type
|
||||
|
@ -82,7 +75,6 @@ var LoginOutputFlags = []cli.Flag{
|
|||
var LoginRepoFlags = []cli.Flag{
|
||||
&LoginFlag,
|
||||
&RepoFlag,
|
||||
&RemoteFlag,
|
||||
}
|
||||
|
||||
// AllDefaultFlags defines flags that should be available
|
||||
|
@ -91,7 +83,6 @@ var LoginRepoFlags = []cli.Flag{
|
|||
// https://github.com/urfave/cli/issues/585
|
||||
var AllDefaultFlags = append([]cli.Flag{
|
||||
&RepoFlag,
|
||||
&RemoteFlag,
|
||||
}, LoginOutputFlags...)
|
||||
|
||||
// IssuePRFlags defines flags that should be available on issue & pr listing flags.
|
||||
|
|
|
@ -49,11 +49,6 @@ var CmdLoginAdd = cli.Command{
|
|||
EnvVars: []string{"GITEA_SERVER_PASSWORD"},
|
||||
Usage: "Password for basic auth (will create token)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ssh-key",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Path to a SSH key to use, overrides auto-discovery",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Aliases: []string{"i"},
|
||||
|
@ -75,7 +70,6 @@ func runLoginAdd(ctx *cli.Context) error {
|
|||
ctx.String("token"),
|
||||
ctx.String("user"),
|
||||
ctx.String("password"),
|
||||
ctx.String("ssh-key"),
|
||||
ctx.String("url"),
|
||||
ctx.Bool("insecure"))
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ var CmdOrganizationDelete = cli.Command{
|
|||
Action: RunOrganizationDelete,
|
||||
Flags: []cli.Flag{
|
||||
&flags.LoginFlag,
|
||||
&flags.RemoteFlag,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -23,7 +24,11 @@ var CmdPullsCreate = cli.Command{
|
|||
Flags: append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "head",
|
||||
Usage: "Set head branch (default is current one)",
|
||||
Usage: "Set head branch (default is locally checked out branch)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "head-repo",
|
||||
Usage: "Set head repo (default is remote repo for local branch)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "base",
|
||||
|
@ -48,12 +53,16 @@ func runPullsCreate(cmd *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
headRepoSlug := ctx.String("head-repo") // may contain `owner` or `owner/repo`
|
||||
headOwner, _ := utils.GetOwnerAndRepo(headRepoSlug, headRepoSlug)
|
||||
|
||||
return task.CreatePull(
|
||||
ctx.Login,
|
||||
ctx.Owner,
|
||||
ctx.Repo,
|
||||
ctx.String("base"),
|
||||
ctx.String("head"),
|
||||
headOwner,
|
||||
opts,
|
||||
)
|
||||
}
|
||||
|
|
4
main.go
4
main.go
|
@ -69,8 +69,10 @@ func formatBuiltWith(Tags string) string {
|
|||
|
||||
var appDescription = `tea is a productivity helper for Gitea. It can be used to manage most entities on one
|
||||
or multiple Gitea instances and provides local helpers like 'tea pull checkout'.
|
||||
|
||||
tea makes use of context provided by the repository in $PWD if available, but is still
|
||||
usable independently of $PWD. Configuration is persisted in $XDG_CONFIG_HOME/tea.
|
||||
usable independently of $PWD. tea works best in a upstream/fork workflow, when the local
|
||||
main branch tracks the upstream repo. Configuration is persisted in $XDG_CONFIG_HOME/tea.
|
||||
`
|
||||
|
||||
var helpTemplate = bold(`
|
||||
|
|
|
@ -80,38 +80,22 @@ func InitCommand(ctx *cli.Context) *TeaContext {
|
|||
// these flags are used as overrides to the context detection via local git repo
|
||||
repoFlag := ctx.String("repo")
|
||||
loginFlag := ctx.String("login")
|
||||
remoteFlag := ctx.String("remote")
|
||||
|
||||
var (
|
||||
c TeaContext
|
||||
err error
|
||||
repoPath string // empty means PWD
|
||||
repoFlagPathExists bool
|
||||
c TeaContext
|
||||
err error
|
||||
)
|
||||
|
||||
// check if repoFlag can be interpreted as path to local repo.
|
||||
if len(repoFlag) != 0 {
|
||||
if repoFlagPathExists, err = utils.DirExists(repoFlag); err != nil {
|
||||
// try to read git repo & extract context, ignoring if PWD is not a repo
|
||||
if c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(""); err != nil {
|
||||
if err == errNotAGiteaRepo || err == gogit.ErrRepositoryNotExists {
|
||||
// we can deal with that, commands needing the optional values use ctx.Ensure()
|
||||
} else {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
if repoFlagPathExists {
|
||||
repoPath = repoFlag
|
||||
}
|
||||
}
|
||||
|
||||
if len(repoFlag) == 0 || repoFlagPathExists {
|
||||
// try to read git repo & extract context, ignoring if PWD is not a repo
|
||||
if c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(repoPath, remoteFlag); err != nil {
|
||||
if err == errNotAGiteaRepo || err == gogit.ErrRepositoryNotExists {
|
||||
// we can deal with that, commands needing the optional values use ctx.Ensure()
|
||||
} else {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(repoFlag) != 0 && !repoFlagPathExists {
|
||||
// if repoFlag is not a valid path, use it to override repoSlug
|
||||
if len(repoFlag) != 0 {
|
||||
c.RepoSlug = repoFlag
|
||||
}
|
||||
|
||||
|
@ -144,7 +128,7 @@ and then run your command again.`)
|
|||
}
|
||||
|
||||
// contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo
|
||||
func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) {
|
||||
func contextFromLocalRepo(repoPath string) (*git.TeaRepo, *config.Login, string, error) {
|
||||
repo, err := git.RepoFromPath(repoPath)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
|
@ -160,7 +144,8 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L
|
|||
}
|
||||
|
||||
// if only one remote exists
|
||||
if len(gitConfig.Remotes) >= 1 && len(remoteValue) == 0 {
|
||||
remoteValue := ""
|
||||
if len(gitConfig.Remotes) >= 1 {
|
||||
for remote := range gitConfig.Remotes {
|
||||
remoteValue = remote
|
||||
}
|
||||
|
|
|
@ -6,71 +6,20 @@ package git
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
git_transport "github.com/go-git/go-git/v5/plumbing/transport"
|
||||
gogit_http "github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
gogit_ssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type pwCallback = func(string) (string, error)
|
||||
|
||||
// GetAuthForURL returns the appropriate AuthMethod to be used in Push() / Pull()
|
||||
// operations depending on the protocol, and prompts the user for credentials if
|
||||
// necessary.
|
||||
func GetAuthForURL(remoteURL *url.URL, authToken, keyFile string, passwordCallback pwCallback) (git_transport.AuthMethod, error) {
|
||||
func GetAuthForURL(remoteURL *url.URL, authToken string) (git_transport.AuthMethod, error) {
|
||||
switch remoteURL.Scheme {
|
||||
case "http", "https":
|
||||
// gitea supports push/pull via app token as username.
|
||||
return &gogit_http.BasicAuth{Password: "", Username: authToken}, nil
|
||||
|
||||
case "ssh":
|
||||
// try to select right key via ssh-agent. if it fails, try to read a key manually
|
||||
user := remoteURL.User.Username()
|
||||
auth, err := gogit_ssh.DefaultAuthBuilder(user)
|
||||
if err != nil {
|
||||
signer, err2 := readSSHPrivKey(keyFile, passwordCallback)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
auth = &gogit_ssh.PublicKeys{User: user, Signer: signer}
|
||||
}
|
||||
return auth, nil
|
||||
}
|
||||
return nil, fmt.Errorf("don't know how to handle url scheme %v", remoteURL.Scheme)
|
||||
}
|
||||
|
||||
func readSSHPrivKey(keyFile string, passwordCallback pwCallback) (sig ssh.Signer, err error) {
|
||||
if keyFile != "" {
|
||||
keyFile, err = utils.AbsPathWithExpansion(keyFile)
|
||||
} else {
|
||||
keyFile, err = utils.AbsPathWithExpansion("~/.ssh/id_rsa")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sshKey, err := ioutil.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not read ssh key '%s'", keyFile)
|
||||
}
|
||||
sig, err = ssh.ParsePrivateKey(sshKey)
|
||||
if _, ok := err.(*ssh.PassphraseMissingError); ok && passwordCallback != nil {
|
||||
// allow for up to 3 password attempts
|
||||
for i := 0; i < 3; i++ {
|
||||
var pass string
|
||||
pass, err = passwordCallback(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig, err = ssh.ParsePrivateKeyWithPassphrase(sshKey, []byte(pass))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return sig, err
|
||||
}
|
||||
|
|
|
@ -58,12 +58,13 @@ func (r TeaRepo) TeaDeleteLocalBranch(branch *git_config.Branch) error {
|
|||
}
|
||||
|
||||
// TeaDeleteRemoteBranch removes the given branch on the given remote via git protocol
|
||||
func (r TeaRepo) TeaDeleteRemoteBranch(remoteName, remoteBranch string, auth git_transport.AuthMethod) error {
|
||||
func (r TeaRepo) TeaDeleteRemoteBranch(remoteName, remoteBranch, remoteURLOverride string, auth git_transport.AuthMethod) error {
|
||||
// delete remote branch via git protocol:
|
||||
// an empty source in the refspec means remote deletion to git 🙃
|
||||
refspec := fmt.Sprintf(":%s", git_plumbing.NewBranchReferenceName(remoteBranch))
|
||||
return r.Push(&git.PushOptions{
|
||||
RemoteName: remoteName,
|
||||
RemoteURL: remoteURLOverride,
|
||||
RefSpecs: []git_config.RefSpec{git_config.RefSpec(refspec)},
|
||||
Prune: true,
|
||||
Auth: auth,
|
||||
|
|
|
@ -53,3 +53,13 @@ func ParseURL(rawURL string) (u *url.URL, err error) {
|
|||
p := &URLParser{}
|
||||
return p.Parse(rawURL)
|
||||
}
|
||||
|
||||
// Takes the output of ParseURL and normalizes it to a gitea https url.
|
||||
func ToHttpsURL(u *url.URL, insecure bool) *url.URL {
|
||||
u.User = nil
|
||||
u.Scheme = "https"
|
||||
if insecure {
|
||||
u.Scheme = "http"
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
// CreateLogin create an login interactive
|
||||
func CreateLogin() error {
|
||||
var name, token, user, passwd, sshKey, giteaURL string
|
||||
var name, token, user, passwd, giteaURL string
|
||||
var insecure = false
|
||||
|
||||
promptI := &survey.Input{Message: "URL of Gitea instance: "}
|
||||
|
@ -64,28 +64,13 @@ func CreateLogin() error {
|
|||
}
|
||||
}
|
||||
|
||||
var optSettings bool
|
||||
promptYN = &survey.Confirm{
|
||||
Message: "Set Optional settings: ",
|
||||
Message: "Allow Insecure connections: ",
|
||||
Default: false,
|
||||
}
|
||||
if err = survey.AskOne(promptYN, &optSettings); err != nil {
|
||||
if err = survey.AskOne(promptYN, &insecure); err != nil {
|
||||
return err
|
||||
}
|
||||
if optSettings {
|
||||
promptI = &survey.Input{Message: "SSH Key Path (leave empty for auto-discovery):"}
|
||||
if err := survey.AskOne(promptI, &sshKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
promptYN = &survey.Confirm{
|
||||
Message: "Allow Insecure connections: ",
|
||||
Default: false,
|
||||
}
|
||||
if err = survey.AskOne(promptYN, &insecure); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return task.CreateLogin(name, token, user, passwd, sshKey, giteaURL, insecure)
|
||||
return task.CreateLogin(name, token, user, passwd, giteaURL, insecure)
|
||||
}
|
||||
|
|
|
@ -52,8 +52,6 @@ func CreatePull(login *config.Login, owner, repo string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
head = task.GetHeadSpec(headOwner, headBranch, owner)
|
||||
|
||||
opts := gitea.CreateIssueOption{Title: task.GetDefaultPRTitle(head)}
|
||||
if err = promptIssueProperties(login, owner, repo, &opts); err != nil {
|
||||
return err
|
||||
|
@ -65,5 +63,6 @@ func CreatePull(login *config.Login, owner, repo string) error {
|
|||
repo,
|
||||
base,
|
||||
head,
|
||||
headOwner,
|
||||
&opts)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// CreateLogin create a login to be stored in config
|
||||
func CreateLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool) error {
|
||||
func CreateLogin(name, token, user, passwd, giteaURL string, insecure bool) error {
|
||||
// checks ...
|
||||
// ... if we have a url
|
||||
if len(giteaURL) == 0 {
|
||||
|
@ -52,7 +52,6 @@ func CreateLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bo
|
|||
URL: serverURL.String(),
|
||||
Token: token,
|
||||
Insecure: insecure,
|
||||
SSHKey: sshKey,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
|
||||
|
@ -81,13 +80,6 @@ func CreateLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bo
|
|||
// so we just use the hostname
|
||||
login.SSHHost = serverURL.Hostname()
|
||||
|
||||
if len(sshKey) == 0 {
|
||||
login.SSHKey, err = findSSHKey(client)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: problem while finding a SSH key: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = config.AddLogin(&login); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
// 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 task
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// findSSHKey retrieves the ssh keys registered in gitea, and tries to find
|
||||
// a matching private key in ~/.ssh/. If no match is found, path is empty.
|
||||
func findSSHKey(client *gitea.Client) (string, error) {
|
||||
// get keys registered on gitea instance
|
||||
keys, _, err := client.ListMyPublicKeys(gitea.ListPublicKeysOptions{})
|
||||
if err != nil || len(keys) == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// enumerate ~/.ssh/*.pub files
|
||||
glob, err := utils.AbsPathWithExpansion("~/.ssh/*.pub")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
localPubkeyPaths, err := filepath.Glob(glob)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// parse each local key with present privkey & compare fingerprints to online keys
|
||||
for _, pubkeyPath := range localPubkeyPaths {
|
||||
var pubkeyFile []byte
|
||||
pubkeyFile, err = ioutil.ReadFile(pubkeyPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fields := strings.Split(string(pubkeyFile), " ")
|
||||
if len(fields) < 2 { // first word is key type, second word is key material
|
||||
continue
|
||||
}
|
||||
|
||||
var keymaterial []byte
|
||||
keymaterial, err = base64.StdEncoding.DecodeString(fields[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var pubkey ssh.PublicKey
|
||||
pubkey, err = ssh.ParsePublicKey(keymaterial)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
privkeyPath := strings.TrimSuffix(pubkeyPath, ".pub")
|
||||
var exists bool
|
||||
exists, err = utils.FileExist(privkeyPath)
|
||||
if err != nil || !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
// if pubkey fingerprints match, return path to corresponding privkey.
|
||||
fingerprint := ssh.FingerprintSHA256(pubkey)
|
||||
for _, key := range keys {
|
||||
if fingerprint == key.Fingerprint {
|
||||
return privkeyPath, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", err
|
||||
}
|
|
@ -90,11 +90,15 @@ func doPRFetch(
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, callback)
|
||||
url = local_git.ToHttpsURL(url, login.Insecure)
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fetchOpts := &git.FetchOptions{Auth: auth}
|
||||
fetchOpts := &git.FetchOptions{
|
||||
Auth: auth,
|
||||
RemoteURL: url.String(),
|
||||
}
|
||||
if isRemoteDeleted(pr) {
|
||||
// When the head branch is already deleted, pr.Head.Ref points to
|
||||
// `refs/pull/<idx>/head`, where the commits stay available.
|
||||
|
|
|
@ -101,11 +101,12 @@ call me again with the --ignore-sha flag`, remoteBranch)
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, callback)
|
||||
url = local_git.ToHttpsURL(url, login.Insecure)
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = r.TeaDeleteRemoteBranch(branch.Remote, remoteBranch, auth)
|
||||
err = r.TeaDeleteRemoteBranch(branch.Remote, remoteBranch, url.String(), auth)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// CreatePull creates a PR in the given repo and prints the result
|
||||
func CreatePull(login *config.Login, repoOwner, repoName, base, head string, opts *gitea.CreateIssueOption) error {
|
||||
func CreatePull(login *config.Login, repoOwner, repoName, base, head, headOwner string, opts *gitea.CreateIssueOption) error {
|
||||
// open local git repo
|
||||
localRepo, err := local_git.RepoForWorkdir()
|
||||
if err != nil {
|
||||
|
@ -31,13 +31,24 @@ func CreatePull(login *config.Login, repoOwner, repoName, base, head string, opt
|
|||
}
|
||||
}
|
||||
|
||||
// default is current one
|
||||
if len(head) == 0 {
|
||||
headOwner, headBranch, err := GetDefaultPRHead(localRepo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headBranch := head
|
||||
|
||||
// default is current branch & associated repo owner
|
||||
defaultHeadOwner, defaultHeadBranch, err := GetDefaultPRHead(localRepo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(headBranch) == 0 {
|
||||
headBranch = defaultHeadBranch
|
||||
}
|
||||
if len(headOwner) == 0 {
|
||||
headBranch = defaultHeadOwner
|
||||
}
|
||||
|
||||
// only override head if unspecified, or headOwner was set, for backwards
|
||||
// compatibility: still support `owner:branch` inputs for head var
|
||||
if len(head) == 0 || len(headOwner) != 0 {
|
||||
head = GetHeadSpec(headOwner, headBranch, repoOwner)
|
||||
}
|
||||
|
||||
|
|
9
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
|
@ -91,6 +91,8 @@ func (o *CloneOptions) Validate() error {
|
|||
type PullOptions struct {
|
||||
// Name of the remote to be pulled. If empty, uses the default.
|
||||
RemoteName string
|
||||
// RemoteURL overrides the remote repo address with a custom URL
|
||||
RemoteURL string
|
||||
// Remote branch to clone. If empty, uses HEAD.
|
||||
ReferenceName plumbing.ReferenceName
|
||||
// Fetch only ReferenceName if true.
|
||||
|
@ -147,7 +149,9 @@ const (
|
|||
type FetchOptions struct {
|
||||
// Name of the remote to fetch from. Defaults to origin.
|
||||
RemoteName string
|
||||
RefSpecs []config.RefSpec
|
||||
// RemoteURL overrides the remote repo address with a custom URL
|
||||
RemoteURL string
|
||||
RefSpecs []config.RefSpec
|
||||
// Depth limit fetching to the specified number of commits from the tip of
|
||||
// each remote branch history.
|
||||
Depth int
|
||||
|
@ -192,6 +196,8 @@ func (o *FetchOptions) Validate() error {
|
|||
type PushOptions struct {
|
||||
// RemoteName is the name of the remote to be pushed to.
|
||||
RemoteName string
|
||||
// RemoteURL overrides the remote repo address with a custom URL
|
||||
RemoteURL string
|
||||
// RefSpecs specify what destination ref to update with what source
|
||||
// object. A refspec with empty src can be used to delete a reference.
|
||||
RefSpecs []config.RefSpec
|
||||
|
@ -569,6 +575,7 @@ func (o *CreateTagOptions) loadConfigTagger(r *Repository) error {
|
|||
|
||||
// ListOptions describes how a remote list should be performed.
|
||||
type ListOptions struct {
|
||||
// TODO: add remote URL
|
||||
// Auth credentials, if required, to use with the remote repository.
|
||||
Auth transport.AuthMethod
|
||||
// InsecureSkipTLS skips ssl verify if protocal is https
|
||||
|
|
17
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
17
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/internal/url"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/cache"
|
||||
"github.com/go-git/go-git/v5/plumbing/format/packfile"
|
||||
|
@ -103,7 +104,11 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
|||
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
|
||||
}
|
||||
|
||||
s, err := newSendPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if o.RemoteURL == "" {
|
||||
o.RemoteURL = r.c.URLs[0]
|
||||
}
|
||||
|
||||
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -183,12 +188,12 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
|||
var hashesToPush []plumbing.Hash
|
||||
// Avoid the expensive revlist operation if we're only doing deletes.
|
||||
if !allDelete {
|
||||
if r.c.IsFirstURLLocal() {
|
||||
if url.IsLocalEndpoint(o.RemoteURL) {
|
||||
// If we're are pushing to a local repo, it might be much
|
||||
// faster to use a local storage layer to get the commits
|
||||
// to ignore, when calculating the object revlist.
|
||||
localStorer := filesystem.NewStorage(
|
||||
osfs.New(r.c.URLs[0]), cache.NewObjectLRUDefault())
|
||||
osfs.New(o.RemoteURL), cache.NewObjectLRUDefault())
|
||||
hashesToPush, err = revlist.ObjectsWithStorageForIgnores(
|
||||
r.s, localStorer, objects, haves)
|
||||
} else {
|
||||
|
@ -314,7 +319,11 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
|||
o.RefSpecs = r.c.Fetch
|
||||
}
|
||||
|
||||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if o.RemoteURL == "" {
|
||||
o.RemoteURL = r.c.URLs[0]
|
||||
}
|
||||
|
||||
s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user