mirror of
https://gitea.com/gitea/tea.git
synced 2026-04-25 17:53:37 +02:00
refactor: code cleanup across codebase (#947)
## Summary - Extract duplicate \`getReleaseByTag\` into shared \`cmd/releases/utils.go\` - Replace \`log.Fatal\` calls with proper error returns in config and login commands; \`GetLoginByToken\`/\`GetLoginsByHost\`/\`GetLoginByHost\` now return errors - Remove dead \`portChan\` channel in \`modules/auth/oauth.go\` - Fix YAML integer detection to use \`strconv.ParseInt\` (correctly handles negatives and large ints) - Fix \`path.go\` error handling to use \`errors.As\` + \`syscall.ENOTDIR\` instead of string comparison - Extract repeated credential helper key into local variable in \`SetupHelper\` - Use existing \`isRemoteDeleted()\` in \`pull_clean.go\` instead of duplicating the logic - Fix ~30 error message casing violations to follow Go conventions - Use \`fmt.Errorf\` consistently instead of string concatenation in \`generic.go\` Reviewed-on: https://gitea.com/gitea/tea/pulls/947 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-by: Bo-Yi Wu (吳柏毅) <appleboy.tw@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Co-committed-by: Nicolas <bircni@icloud.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd/flags"
|
"code.gitea.io/tea/cmd/flags"
|
||||||
|
"code.gitea.io/tea/cmd/releases"
|
||||||
"code.gitea.io/tea/modules/context"
|
"code.gitea.io/tea/modules/context"
|
||||||
|
|
||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
@@ -37,15 +38,15 @@ func runReleaseAttachmentCreate(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
client := ctx.Login.Client()
|
client := ctx.Login.Client()
|
||||||
|
|
||||||
if ctx.Args().Len() < 2 {
|
if ctx.Args().Len() < 2 {
|
||||||
return fmt.Errorf("No release tag or assets specified.\nUsage:\t%s", ctx.Command.UsageText)
|
return fmt.Errorf("no release tag or assets specified.\nUsage:\t%s", ctx.Command.UsageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
tag := ctx.Args().First()
|
tag := ctx.Args().First()
|
||||||
if len(tag) == 0 {
|
if len(tag) == 0 {
|
||||||
return fmt.Errorf("Release tag needed to create attachment")
|
return fmt.Errorf("release tag needed to create attachment")
|
||||||
}
|
}
|
||||||
|
|
||||||
release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
release, err := releases.GetReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd/flags"
|
"code.gitea.io/tea/cmd/flags"
|
||||||
|
"code.gitea.io/tea/cmd/releases"
|
||||||
"code.gitea.io/tea/modules/context"
|
"code.gitea.io/tea/modules/context"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
@@ -42,12 +43,12 @@ func runReleaseAttachmentDelete(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
client := ctx.Login.Client()
|
client := ctx.Login.Client()
|
||||||
|
|
||||||
if ctx.Args().Len() < 2 {
|
if ctx.Args().Len() < 2 {
|
||||||
return fmt.Errorf("No release tag or attachment names specified.\nUsage:\t%s", ctx.Command.UsageText)
|
return fmt.Errorf("no release tag or attachment names specified.\nUsage:\t%s", ctx.Command.UsageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
tag := ctx.Args().First()
|
tag := ctx.Args().First()
|
||||||
if len(tag) == 0 {
|
if len(tag) == 0 {
|
||||||
return fmt.Errorf("Release tag needed to delete attachment")
|
return fmt.Errorf("release tag needed to delete attachment")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Bool("confirm") {
|
if !ctx.Bool("confirm") {
|
||||||
@@ -55,7 +56,7 @@ func runReleaseAttachmentDelete(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
release, err := releases.GetReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ func runReleaseAttachmentDelete(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if attachment == nil {
|
if attachment == nil {
|
||||||
return fmt.Errorf("Release does not have attachment named '%s'", name)
|
return fmt.Errorf("release does not have attachment named '%s'", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = client.DeleteReleaseAttachment(ctx.Owner, ctx.Repo, release.ID, attachment.ID)
|
_, err = client.DeleteReleaseAttachment(ctx.Owner, ctx.Repo, release.ID, attachment.ID)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd/flags"
|
"code.gitea.io/tea/cmd/flags"
|
||||||
|
"code.gitea.io/tea/cmd/releases"
|
||||||
"code.gitea.io/tea/modules/context"
|
"code.gitea.io/tea/modules/context"
|
||||||
"code.gitea.io/tea/modules/print"
|
"code.gitea.io/tea/modules/print"
|
||||||
|
|
||||||
@@ -42,10 +43,10 @@ func RunReleaseAttachmentList(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
tag := ctx.Args().First()
|
tag := ctx.Args().First()
|
||||||
if len(tag) == 0 {
|
if len(tag) == 0 {
|
||||||
return fmt.Errorf("Release tag needed to list attachments")
|
return fmt.Errorf("release tag needed to list attachments")
|
||||||
}
|
}
|
||||||
|
|
||||||
release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
release, err := releases.GetReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -59,21 +60,3 @@ func RunReleaseAttachmentList(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
return print.ReleaseAttachmentsList(attachments, ctx.Output)
|
return print.ReleaseAttachmentsList(attachments, ctx.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReleaseByTag(owner, repo, tag string, client *gitea.Client) (*gitea.Release, error) {
|
|
||||||
rl, _, err := client.ListReleases(owner, repo, gitea.ListReleasesOptions{
|
|
||||||
ListOptions: gitea.ListOptions{Page: -1},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rl) == 0 {
|
|
||||||
return nil, fmt.Errorf("Repo does not have any release")
|
|
||||||
}
|
|
||||||
for _, r := range rl {
|
|
||||||
if r.TagName == tag {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Release tag does not exist")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -76,9 +76,13 @@ func runRepoClone(ctx stdctx.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
owner, repo = utils.GetOwnerAndRepo(url.Path, login.User)
|
owner, repo = utils.GetOwnerAndRepo(url.Path, login.User)
|
||||||
if url.Host != "" {
|
if url.Host != "" {
|
||||||
login = config.GetLoginByHost(url.Host)
|
var lookupErr error
|
||||||
|
login, lookupErr = config.GetLoginByHost(url.Host)
|
||||||
|
if lookupErr != nil {
|
||||||
|
return lookupErr
|
||||||
|
}
|
||||||
if login == nil {
|
if login == nil {
|
||||||
return fmt.Errorf("No login configured matching host '%s', run `tea login add` first", url.Host)
|
return fmt.Errorf("no login configured matching host '%s', run 'tea login add' first", url.Host)
|
||||||
}
|
}
|
||||||
debug.Printf("Matched login '%s' for host '%s'", login.Name, url.Host)
|
debug.Printf("Matched login '%s' for host '%s'", login.Name, url.Host)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func runAddComment(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
args := ctx.Args()
|
args := ctx.Args()
|
||||||
if args.Len() == 0 {
|
if args.Len() == 0 {
|
||||||
return fmt.Errorf("Please specify issue / pr index")
|
return fmt.Errorf("please specify issue / pr index")
|
||||||
}
|
}
|
||||||
|
|
||||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func (f CsvFlag) GetValues(cmd *cli.Command) ([]string, error) {
|
|||||||
if f.AvailableFields != nil && val != "" {
|
if f.AvailableFields != nil && val != "" {
|
||||||
for _, field := range selection {
|
for _, field := range selection {
|
||||||
if !utils.Contains(f.AvailableFields, field) {
|
if !utils.Contains(f.AvailableFields, field) {
|
||||||
return nil, fmt.Errorf("Invalid field '%s'", field)
|
return nil, fmt.Errorf("invalid field '%s'", field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package flags
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
@@ -167,7 +168,7 @@ func ParseState(stateStr string) (gitea.StateType, error) {
|
|||||||
case "closed":
|
case "closed":
|
||||||
return gitea.StateClosed, nil
|
return gitea.StateClosed, nil
|
||||||
default:
|
default:
|
||||||
return "", errors.New("unknown state '" + stateStr + "'")
|
return "", fmt.Errorf("unknown state '%s'", stateStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +185,6 @@ func ParseIssueKind(kindStr string, defaultKind gitea.IssueType) (gitea.IssueTyp
|
|||||||
case "pull", "pulls", "pr":
|
case "pull", "pulls", "pr":
|
||||||
return gitea.IssueTypePull, nil
|
return gitea.IssueTypePull, nil
|
||||||
default:
|
default:
|
||||||
return "", errors.New("unknown kind '" + kindStr + "'")
|
return "", fmt.Errorf("unknown kind '%s'", kindStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ func GetIssuePRCreateFlags(ctx *context.TeaContext) (*gitea.CreateIssueOption, e
|
|||||||
}
|
}
|
||||||
ms, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, milestoneName)
|
ms, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, milestoneName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Milestone '%s' not found", milestoneName)
|
return nil, fmt.Errorf("milestone '%s' not found", milestoneName)
|
||||||
}
|
}
|
||||||
opts.Milestone = ms.ID
|
opts.Milestone = ms.ID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,5 +37,5 @@ func runLabels(ctx context.Context, cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runLabelsDetails(cmd *cli.Command) error {
|
func runLabelsDetails(cmd *cli.Command) error {
|
||||||
return fmt.Errorf("Not yet implemented")
|
return fmt.Errorf("not yet implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ package login
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"fmt"
|
||||||
"log"
|
|
||||||
|
|
||||||
"code.gitea.io/tea/modules/config"
|
"code.gitea.io/tea/modules/config"
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ var CmdLoginDelete = cli.Command{
|
|||||||
func RunLoginDelete(_ context.Context, cmd *cli.Command) error {
|
func RunLoginDelete(_ context.Context, cmd *cli.Command) error {
|
||||||
logins, err := config.GetLogins()
|
logins, err := config.GetLogins()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var name string
|
var name string
|
||||||
@@ -37,7 +36,7 @@ func RunLoginDelete(_ context.Context, cmd *cli.Command) error {
|
|||||||
} else if len(logins) == 1 {
|
} else if len(logins) == 1 {
|
||||||
name = logins[0].Name
|
name = logins[0].Name
|
||||||
} else {
|
} else {
|
||||||
return errors.New("Please specify a login name")
|
return fmt.Errorf("please specify a login name")
|
||||||
}
|
}
|
||||||
|
|
||||||
return config.DeleteLogin(name)
|
return config.DeleteLogin(name)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package login
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ func runLoginEdit(_ context.Context, _ *cli.Command) error {
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
log.Fatal(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return open.Start(config.GetConfigPath())
|
return open.Start(config.GetConfigPath())
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -93,7 +92,7 @@ var CmdLoginHelper = cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(wants["host"]) == 0 {
|
if len(wants["host"]) == 0 {
|
||||||
log.Fatal("Hostname is required")
|
return fmt.Errorf("hostname is required")
|
||||||
} else if len(wants["protocol"]) == 0 {
|
} else if len(wants["protocol"]) == 0 {
|
||||||
wants["protocol"] = "http"
|
wants["protocol"] = "http"
|
||||||
}
|
}
|
||||||
@@ -104,20 +103,24 @@ var CmdLoginHelper = cli.Command{
|
|||||||
var lookupErr error
|
var lookupErr error
|
||||||
userConfig, lookupErr = config.GetLoginByName(loginName)
|
userConfig, lookupErr = config.GetLoginByName(loginName)
|
||||||
if lookupErr != nil {
|
if lookupErr != nil {
|
||||||
log.Fatal(lookupErr)
|
return lookupErr
|
||||||
}
|
}
|
||||||
if userConfig == nil {
|
if userConfig == nil {
|
||||||
log.Fatalf("Login '%s' not found", loginName)
|
return fmt.Errorf("login '%s' not found", loginName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
userConfig = config.GetLoginByHost(wants["host"])
|
var lookupErr error
|
||||||
|
userConfig, lookupErr = config.GetLoginByHost(wants["host"])
|
||||||
|
if lookupErr != nil {
|
||||||
|
return lookupErr
|
||||||
|
}
|
||||||
if userConfig == nil {
|
if userConfig == nil {
|
||||||
log.Fatalf("No login found for host '%s'", wants["host"])
|
return fmt.Errorf("no login found for host '%s'", wants["host"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(userConfig.GetAccessToken()) == 0 {
|
if len(userConfig.GetAccessToken()) == 0 {
|
||||||
log.Fatal("User not set")
|
return fmt.Errorf("user not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := url.Parse(userConfig.URL)
|
host, err := url.Parse(userConfig.URL)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func runReleaseCreate(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if resp != nil && resp.StatusCode == http.StatusConflict {
|
if resp != nil && resp.StatusCode == http.StatusConflict {
|
||||||
return fmt.Errorf("There already is a release for this tag")
|
return fmt.Errorf("there is already a release for this tag")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func runReleaseDelete(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range ctx.Args().Slice() {
|
for _, tag := range ctx.Args().Slice() {
|
||||||
release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
release, err := GetReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func runReleaseEdit(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range ctx.Args().Slice() {
|
for _, tag := range ctx.Args().Slice() {
|
||||||
release, err := getReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
release, err := GetReleaseByTag(ctx.Owner, ctx.Repo, tag, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package releases
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
stdctx "context"
|
stdctx "context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd/flags"
|
"code.gitea.io/tea/cmd/flags"
|
||||||
"code.gitea.io/tea/modules/context"
|
"code.gitea.io/tea/modules/context"
|
||||||
@@ -48,21 +47,3 @@ func RunReleasesList(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
return print.ReleasesList(releases, ctx.Output)
|
return print.ReleasesList(releases, ctx.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReleaseByTag(owner, repo, tag string, client *gitea.Client) (*gitea.Release, error) {
|
|
||||||
rl, _, err := client.ListReleases(owner, repo, gitea.ListReleasesOptions{
|
|
||||||
ListOptions: gitea.ListOptions{Page: -1},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rl) == 0 {
|
|
||||||
return nil, fmt.Errorf("Repo does not have any release")
|
|
||||||
}
|
|
||||||
for _, r := range rl {
|
|
||||||
if r.TagName == tag {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Release tag does not exist")
|
|
||||||
}
|
|
||||||
|
|||||||
29
cmd/releases/utils.go
Normal file
29
cmd/releases/utils.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package releases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/sdk/gitea"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetReleaseByTag finds a release by its tag name.
|
||||||
|
func GetReleaseByTag(owner, repo, tag string, client *gitea.Client) (*gitea.Release, error) {
|
||||||
|
rl, _, err := client.ListReleases(owner, repo, gitea.ListReleasesOptions{
|
||||||
|
ListOptions: gitea.ListOptions{Page: -1},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rl) == 0 {
|
||||||
|
return nil, fmt.Errorf("repo does not have any release")
|
||||||
|
}
|
||||||
|
for _, r := range rl {
|
||||||
|
if r.TagName == tag {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("release tag does not exist")
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ func runReposSearch(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
org, resp, err := client.GetOrg(teaCmd.String("owner"))
|
org, resp, err := client.GetOrg(teaCmd.String("owner"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if resp == nil || resp.StatusCode != http.StatusNotFound {
|
if resp == nil || resp.StatusCode != http.StatusNotFound {
|
||||||
return fmt.Errorf("Could not find owner: %w", err)
|
return fmt.Errorf("could not find owner: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if owner is no org, its a user
|
// if owner is no org, its a user
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func runTrackedTimesAdd(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Args().Len() < 2 {
|
if ctx.Args().Len() < 2 {
|
||||||
return fmt.Errorf("No issue or duration specified.\nUsage:\t%s", ctx.Command.UsageText)
|
return fmt.Errorf("no issue or duration specified.\nUsage:\t%s", ctx.Command.UsageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, err := utils.ArgToIndex(ctx.Args().First())
|
issue, err := utils.ArgToIndex(ctx.Args().First())
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func runTrackedTimesDelete(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
client := ctx.Login.Client()
|
client := ctx.Login.Client()
|
||||||
|
|
||||||
if ctx.Args().Len() < 2 {
|
if ctx.Args().Len() < 2 {
|
||||||
return fmt.Errorf("No issue or time ID specified.\nUsage:\t%s", ctx.Command.UsageText)
|
return fmt.Errorf("no issue or time ID specified.\nUsage:\t%s", ctx.Command.UsageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, err := utils.ArgToIndex(ctx.Args().First())
|
issue, err := utils.ArgToIndex(ctx.Args().First())
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func runTrackedTimesReset(_ stdctx.Context, cmd *cli.Command) error {
|
|||||||
client := ctx.Login.Client()
|
client := ctx.Login.Client()
|
||||||
|
|
||||||
if ctx.Args().Len() != 1 {
|
if ctx.Args().Len() != 1 {
|
||||||
return fmt.Errorf("No issue specified.\nUsage:\t%s", ctx.Command.UsageText)
|
return fmt.Errorf("no issue specified.\nUsage:\t%s", ctx.Command.UsageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, err := utils.ArgToIndex(ctx.Args().First())
|
issue, err := utils.ArgToIndex(ctx.Args().First())
|
||||||
|
|||||||
@@ -226,7 +226,6 @@ func startLocalServerAndOpenBrowser(authURL, expectedState string, opts OAuthOpt
|
|||||||
codeChan := make(chan string, 1)
|
codeChan := make(chan string, 1)
|
||||||
stateChan := make(chan string, 1)
|
stateChan := make(chan string, 1)
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
portChan := make(chan int, 1)
|
|
||||||
|
|
||||||
// Parse the redirect URL to get the path
|
// Parse the redirect URL to get the path
|
||||||
parsedURL, err := url.Parse(opts.RedirectURL)
|
parsedURL, err := url.Parse(opts.RedirectURL)
|
||||||
@@ -311,7 +310,6 @@ func startLocalServerAndOpenBrowser(authURL, expectedState string, opts OAuthOpt
|
|||||||
if port == 0 {
|
if port == 0 {
|
||||||
addr := listener.Addr().(*net.TCPAddr)
|
addr := listener.Addr().(*net.TCPAddr)
|
||||||
port = addr.Port
|
port = addr.Port
|
||||||
portChan <- port
|
|
||||||
|
|
||||||
// Update redirect URL with actual port
|
// Update redirect URL with actual port
|
||||||
parsedURL.Host = fmt.Sprintf("%s:%d", hostname, port)
|
parsedURL.Host = fmt.Sprintf("%s:%d", hostname, port)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -74,7 +73,8 @@ func GetConfigPath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("unable to get or create config file")
|
fmt.Fprintln(os.Stderr, "unable to get or create config file")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return configFilePath
|
return configFilePath
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -132,7 +131,7 @@ func GetDefaultLogin() (*Login, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(config.Logins) == 0 {
|
if len(config.Logins) == 0 {
|
||||||
return nil, errors.New("No available login")
|
return nil, errors.New("no available login")
|
||||||
}
|
}
|
||||||
for _, l := range config.Logins {
|
for _, l := range config.Logins {
|
||||||
if l.Default {
|
if l.Default {
|
||||||
@@ -178,50 +177,51 @@ func GetLoginByName(name string) (*Login, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetLoginByToken get login by token
|
// GetLoginByToken get login by token
|
||||||
func GetLoginByToken(token string) *Login {
|
func GetLoginByToken(token string) (*Login, error) {
|
||||||
if token == "" {
|
if token == "" {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
err := loadConfig()
|
if err := loadConfig(); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range config.Logins {
|
for _, l := range config.Logins {
|
||||||
if l.Token == token {
|
if l.Token == token {
|
||||||
return &l
|
return &l, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLoginByHost finds a login by it's server URL
|
// GetLoginByHost finds a login by its server URL
|
||||||
func GetLoginByHost(host string) *Login {
|
func GetLoginByHost(host string) (*Login, error) {
|
||||||
logins := GetLoginsByHost(host)
|
logins, err := GetLoginsByHost(host)
|
||||||
if len(logins) > 0 {
|
if err != nil {
|
||||||
return logins[0]
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil
|
if len(logins) > 0 {
|
||||||
|
return logins[0], nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLoginsByHost returns all logins matching a host
|
// GetLoginsByHost returns all logins matching a host
|
||||||
func GetLoginsByHost(host string) []*Login {
|
func GetLoginsByHost(host string) ([]*Login, error) {
|
||||||
err := loadConfig()
|
if err := loadConfig(); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches []*Login
|
var matches []*Login
|
||||||
for i := range config.Logins {
|
for i := range config.Logins {
|
||||||
loginURL, err := url.Parse(config.Logins[i].URL)
|
loginURL, err := url.Parse(config.Logins[i].URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if loginURL.Host == host {
|
if loginURL.Host == host {
|
||||||
matches = append(matches, &config.Logins[i])
|
matches = append(matches, &config.Logins[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matches
|
return matches, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLogin delete a login by name from config
|
// DeleteLogin delete a login by name from config
|
||||||
@@ -417,12 +417,13 @@ func doOAuthRefresh(l *Login) (*oauth2.Token, error) {
|
|||||||
func (l *Login) Client(options ...gitea.ClientOption) *gitea.Client {
|
func (l *Login) Client(options ...gitea.ClientOption) *gitea.Client {
|
||||||
// Refresh OAuth token if expired or near expiry
|
// Refresh OAuth token if expired or near expiry
|
||||||
if err := l.RefreshOAuthTokenIfNeeded(); err != nil {
|
if err := l.RefreshOAuthTokenIfNeeded(); err != nil {
|
||||||
log.Fatalf("Failed to refresh token: %s\nPlease use 'tea login oauth-refresh %s' to manually refresh the token.\n", err, l.Name)
|
fmt.Fprintf(os.Stderr, "Failed to refresh token: %s\nPlease use 'tea login oauth-refresh %s' to manually refresh the token.\n", err, l.Name)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{}
|
||||||
if l.Insecure {
|
if l.Insecure {
|
||||||
cookieJar, _ := cookiejar.New(nil)
|
cookieJar, _ := cookiejar.New(nil) // New with nil options never returns an error
|
||||||
|
|
||||||
httpClient = &http.Client{
|
httpClient = &http.Client{
|
||||||
Jar: cookieJar,
|
Jar: cookieJar,
|
||||||
@@ -443,12 +444,18 @@ func (l *Login) Client(options ...gitea.ClientOption) *gitea.Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if l.SSHCertPrincipal != "" {
|
if l.SSHCertPrincipal != "" {
|
||||||
l.askForSSHPassphrase()
|
if err := l.askForSSHPassphrase(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to read SSH passphrase: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
options = append(options, gitea.UseSSHCert(l.SSHCertPrincipal, l.SSHKey, l.SSHPassphrase))
|
options = append(options, gitea.UseSSHCert(l.SSHCertPrincipal, l.SSHKey, l.SSHPassphrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.SSHKeyFingerprint != "" {
|
if l.SSHKeyFingerprint != "" {
|
||||||
l.askForSSHPassphrase()
|
if err := l.askForSSHPassphrase(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to read SSH passphrase: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
options = append(options, gitea.UseSSHPubkey(l.SSHKeyFingerprint, l.SSHKey, l.SSHPassphrase))
|
options = append(options, gitea.UseSSHPubkey(l.SSHKeyFingerprint, l.SSHKey, l.SSHPassphrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,25 +463,25 @@ func (l *Login) Client(options ...gitea.ClientOption) *gitea.Client {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
var versionError *gitea.ErrUnknownVersion
|
var versionError *gitea.ErrUnknownVersion
|
||||||
if !errors.As(err, &versionError) {
|
if !errors.As(err, &versionError) {
|
||||||
log.Fatal(err)
|
fmt.Fprintf(os.Stderr, "Failed to create Gitea client: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "WARNING: could not detect gitea version: %s\nINFO: set gitea version: to last supported one\n", versionError)
|
fmt.Fprintf(os.Stderr, "WARNING: could not detect gitea version: %s\nINFO: set gitea version: to last supported one\n", versionError)
|
||||||
}
|
}
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) askForSSHPassphrase() {
|
func (l *Login) askForSSHPassphrase() error {
|
||||||
if ok, err := utils.IsKeyEncrypted(l.SSHKey); ok && err == nil && l.SSHPassphrase == "" {
|
if ok, err := utils.IsKeyEncrypted(l.SSHKey); ok && err == nil && l.SSHPassphrase == "" {
|
||||||
if err := huh.NewInput().
|
return huh.NewInput().
|
||||||
Title("ssh-key is encrypted please enter the passphrase: ").
|
Title("ssh-key is encrypted please enter the passphrase: ").
|
||||||
Validate(huh.ValidateNotEmpty()).
|
Validate(huh.ValidateNotEmpty()).
|
||||||
EchoMode(huh.EchoModePassword).
|
EchoMode(huh.EchoModePassword).
|
||||||
Value(&l.SSHPassphrase).
|
Value(&l.SSHPassphrase).
|
||||||
WithTheme(theme.GetTheme()).
|
WithTheme(theme.GetTheme()).
|
||||||
Run(); err != nil {
|
Run()
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSSHHost returns SSH host name
|
// GetSSHHost returns SSH host name
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository")
|
var errNotAGiteaRepo = errors.New("no Gitea login found; you might want to specify --repo (and --login) to work outside of a repository")
|
||||||
|
|
||||||
// ErrCommandCanceled is returned when the user explicitly cancels an interactive prompt.
|
// ErrCommandCanceled is returned when the user explicitly cancels an interactive prompt.
|
||||||
var ErrCommandCanceled = errors.New("command canceled")
|
var ErrCommandCanceled = errors.New("command canceled")
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ func (r TeaRepo) TeaFindBranchBySha(sha, repoURL string) (b *git_config.Branch,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if remote == nil {
|
if remote == nil {
|
||||||
return nil, fmt.Errorf("No remote found for '%s'", repoURL)
|
return nil, fmt.Errorf("no remote found for '%s'", repoURL)
|
||||||
}
|
}
|
||||||
remoteName := remote.Config().Name
|
remoteName := remote.Config().Name
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ func (r TeaRepo) TeaFindBranchByName(branchName, repoURL string) (b *git_config.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if remote == nil {
|
if remote == nil {
|
||||||
return nil, fmt.Errorf("No remote found for '%s'", repoURL)
|
return nil, fmt.Errorf("no remote found for '%s'", repoURL)
|
||||||
}
|
}
|
||||||
remoteName := remote.Config().Name
|
remoteName := remote.Config().Name
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func CreateLogin() error {
|
|||||||
}
|
}
|
||||||
_, err := url.Parse(s)
|
_, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Invalid URL: %v", err)
|
return fmt.Errorf("invalid URL: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
@@ -69,7 +69,7 @@ func CreateLogin() error {
|
|||||||
}
|
}
|
||||||
for _, login := range logins {
|
for _, login := range logins {
|
||||||
if login.Name == name {
|
if login.Name == name {
|
||||||
return fmt.Errorf("Login with name '%s' already exists", name)
|
return fmt.Errorf("login with name '%s' already exists", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -154,7 +154,7 @@ func CreateLogin() error {
|
|||||||
Value(&tokenScopes).
|
Value(&tokenScopes).
|
||||||
Validate(func(s []string) error {
|
Validate(func(s []string) error {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return errors.New("At least one scope is required")
|
return errors.New("at least one scope is required")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func getPullIndex(ctx *context.TeaContext, branch string) (int64, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if len(prs) == 0 {
|
if len(prs) == 0 {
|
||||||
return 0, fmt.Errorf("No open PRs found")
|
return 0, fmt.Errorf("no open PRs found")
|
||||||
}
|
}
|
||||||
opts.ListOptions.Page++
|
opts.ListOptions.Page++
|
||||||
prOptions := make([]string, 0)
|
prOptions := make([]string, 0)
|
||||||
|
|||||||
@@ -150,8 +150,7 @@ func outputYaml(f io.Writer, headers []string, values [][]string) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
valueNode := &yaml.Node{Kind: yaml.ScalarNode, Value: val}
|
valueNode := &yaml.Node{Kind: yaml.ScalarNode, Value: val}
|
||||||
intVal, _ := strconv.Atoi(val)
|
if _, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||||||
if strconv.Itoa(intVal) == val {
|
|
||||||
valueNode.Tag = "!!int"
|
valueNode.Tag = "!!int"
|
||||||
} else {
|
} else {
|
||||||
valueNode.Tag = "!!str"
|
valueNode.Tag = "!!str"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
func CreateIssue(login *config.Login, repoOwner, repoName string, opts gitea.CreateIssueOption) error {
|
func CreateIssue(login *config.Login, repoOwner, repoName string, opts gitea.CreateIssueOption) error {
|
||||||
// title is required
|
// title is required
|
||||||
if len(opts.Title) == 0 {
|
if len(opts.Title) == 0 {
|
||||||
return fmt.Errorf("Title is required")
|
return fmt.Errorf("title is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, _, err := login.Client().CreateIssue(repoOwner, repoName, opts)
|
issue, _, err := login.Client().CreateIssue(repoOwner, repoName, opts)
|
||||||
|
|||||||
@@ -20,12 +20,13 @@ import (
|
|||||||
func SetupHelper(login config.Login) (ok bool, err error) {
|
func SetupHelper(login config.Login) (ok bool, err error) {
|
||||||
// Check that the URL is not blank
|
// Check that the URL is not blank
|
||||||
if login.URL == "" {
|
if login.URL == "" {
|
||||||
return false, fmt.Errorf("Invalid gitea url")
|
return false, fmt.Errorf("invalid Gitea URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all helper to URL in git config
|
// get all helper to URL in git config
|
||||||
|
helperKey := fmt.Sprintf("credential.%s.helper", login.URL)
|
||||||
var currentHelpers []byte
|
var currentHelpers []byte
|
||||||
if currentHelpers, err = exec.Command("git", "config", "--global", "--get-all", fmt.Sprintf("credential.%s.helper", login.URL)).Output(); err != nil {
|
if currentHelpers, err = exec.Command("git", "config", "--global", "--get-all", helperKey).Output(); err != nil {
|
||||||
currentHelpers = []byte{}
|
currentHelpers = []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +38,10 @@ func SetupHelper(login config.Login) (ok bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add tea helper
|
// Add tea helper
|
||||||
if _, err = exec.Command("git", "config", "--global", fmt.Sprintf("credential.%s.helper", login.URL), "").Output(); err != nil {
|
if _, err = exec.Command("git", "config", "--global", helperKey, "").Output(); err != nil {
|
||||||
return false, fmt.Errorf("git config --global %s, error: %s", fmt.Sprintf("credential.%s.helper", login.URL), err)
|
return false, fmt.Errorf("git config --global %s, error: %s", helperKey, err)
|
||||||
} else if _, err = exec.Command("git", "config", "--global", "--add", fmt.Sprintf("credential.%s.helper", login.URL), "!tea login helper").Output(); err != nil {
|
} else if _, err = exec.Command("git", "config", "--global", "--add", helperKey, "!tea login helper").Output(); err != nil {
|
||||||
return false, fmt.Errorf("git config --global --add %s %s, error: %s", fmt.Sprintf("credential.%s.helper", login.URL), "!tea login helper", err)
|
return false, fmt.Errorf("git config --global --add %s %s, error: %s", helperKey, "!tea login helper", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
@@ -62,7 +63,11 @@ func CreateLogin(name, token, user, passwd, otp, scopes, sshKey, giteaURL, sshCe
|
|||||||
}
|
}
|
||||||
// ... if we already use this token
|
// ... if we already use this token
|
||||||
if shouldCheckTokenUniqueness(token, sshAgent, sshKey, sshCertPrincipal, sshKeyFingerprint) {
|
if shouldCheckTokenUniqueness(token, sshAgent, sshKey, sshCertPrincipal, sshKeyFingerprint) {
|
||||||
if login := config.GetLoginByToken(token); login != nil {
|
login, err := config.GetLoginByToken(token)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if login != nil {
|
||||||
return fmt.Errorf("token already been used, delete login '%s' first", login.Name)
|
return fmt.Errorf("token already been used, delete login '%s' first", login.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
func CreateMilestone(login *config.Login, repoOwner, repoName, title, description string, deadline *time.Time, state gitea.StateType) error {
|
func CreateMilestone(login *config.Login, repoOwner, repoName, title, description string, deadline *time.Time, state gitea.StateType) error {
|
||||||
// title is required
|
// title is required
|
||||||
if len(title) == 0 {
|
if len(title) == 0 {
|
||||||
return fmt.Errorf("Title is required")
|
return fmt.Errorf("title is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
mile, _, err := login.Client().CreateMilestone(repoOwner, repoName, gitea.CreateMilestoneOption{
|
mile, _, err := login.Client().CreateMilestone(repoOwner, repoName, gitea.CreateMilestoneOption{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||||||
|
|
||||||
// if remote head branch is already deleted, pr.Head.Ref points to "pulls/<idx>/head"
|
// if remote head branch is already deleted, pr.Head.Ref points to "pulls/<idx>/head"
|
||||||
remoteBranch := pr.Head.Ref
|
remoteBranch := pr.Head.Ref
|
||||||
remoteDeleted := remoteBranch == fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
remoteDeleted := isRemoteDeleted(pr)
|
||||||
if remoteDeleted {
|
if remoteDeleted {
|
||||||
remoteBranch = pr.Head.Name // this still holds the original branch name
|
remoteBranch = pr.Head.Name // this still holds the original branch name
|
||||||
fmt.Printf("Remote branch '%s' already deleted.\n", remoteBranch)
|
fmt.Printf("Remote branch '%s' already deleted.\n", remoteBranch)
|
||||||
@@ -62,9 +62,9 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||||||
}
|
}
|
||||||
if branch == nil {
|
if branch == nil {
|
||||||
if ignoreSHA {
|
if ignoreSHA {
|
||||||
return fmt.Errorf("Remote branch %s not found in local repo", remoteBranch)
|
return fmt.Errorf("remote branch %s not found in local repo", remoteBranch)
|
||||||
}
|
}
|
||||||
return fmt.Errorf(`Remote branch %s not found in local repo.
|
return fmt.Errorf(`remote branch %s not found in local repo.
|
||||||
Either you don't track this PR, or the local branch has diverged from the remote.
|
Either you don't track this PR, or the local branch has diverged from the remote.
|
||||||
If you still want to continue & are sure you don't loose any important commits,
|
If you still want to continue & are sure you don't loose any important commits,
|
||||||
call me again with the --ignore-sha flag`, remoteBranch)
|
call me again with the --ignore-sha flag`, remoteBranch)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func PullMerge(login *config.Login, repoOwner, repoName string, index int64, opt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !success {
|
if !success {
|
||||||
return fmt.Errorf("Failed to merge PR. Is it still open?")
|
return fmt.Errorf("failed to merge PR, is it still open?")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PathExists returns whether the given file or directory exists or not
|
// PathExists returns whether the given file or directory exists or not
|
||||||
@@ -38,18 +39,19 @@ func exists(path string, expectDir bool) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
return false, nil
|
return false, nil
|
||||||
} else if err.(*os.PathError).Err.Error() == "not a directory" {
|
}
|
||||||
// some middle segment of path is a file, cannot traverse
|
var pathErr *os.PathError
|
||||||
// FIXME: catches error on linux; go does not provide a way to catch this properly..
|
if errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.ENOTDIR) {
|
||||||
|
// a middle segment of path is a file, cannot traverse
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
isDir := f.IsDir()
|
isDir := f.IsDir()
|
||||||
if isDir && !expectDir {
|
if isDir && !expectDir {
|
||||||
return false, errors.New("A directory with the same name exists")
|
return false, errors.New("a directory with the same name exists")
|
||||||
} else if !isDir && expectDir {
|
} else if !isDir && expectDir {
|
||||||
return false, errors.New("A file with the same name exists")
|
return false, errors.New("a file with the same name exists")
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,17 +21,17 @@ func ValidateAuthenticationMethod(
|
|||||||
// Normalize URL
|
// Normalize URL
|
||||||
serverURL, err := NormalizeURL(giteaURL)
|
serverURL, err := NormalizeURL(giteaURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unable to parse URL: %s", err)
|
return nil, fmt.Errorf("unable to parse URL: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !sshAgent && sshCertPrincipal == "" && sshKey == "" {
|
if !sshAgent && sshCertPrincipal == "" && sshKey == "" {
|
||||||
// .. if we have enough information to authenticate
|
// .. if we have enough information to authenticate
|
||||||
if len(token) == 0 && (len(user)+len(passwd)) == 0 {
|
if len(token) == 0 && (len(user)+len(passwd)) == 0 {
|
||||||
return nil, fmt.Errorf("No token set")
|
return nil, fmt.Errorf("no token set")
|
||||||
} else if len(user) != 0 && len(passwd) == 0 {
|
} else if len(user) != 0 && len(passwd) == 0 {
|
||||||
return nil, fmt.Errorf("No password set")
|
return nil, fmt.Errorf("no password set")
|
||||||
} else if len(user) == 0 && len(passwd) != 0 {
|
} else if len(user) == 0 && len(passwd) != 0 {
|
||||||
return nil, fmt.Errorf("No user set")
|
return nil, fmt.Errorf("no user set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return serverURL, nil
|
return serverURL, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user