mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 19:11:25 +01:00
fix: tighten error classification and pull request selection
Only Gitea's archived-repository messages mean the repository is archived, so an archived label is no longer reported as one. Refused POSTs to the organization, team, user and SSH key collections name the resource they would have created, and the existing pull request is looked up with escaped branch names. pullSelector without an argument refuses an explicit --repo, like gh: the checked-out branch says nothing about another repository. Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
7 files changed
+41
-23
No files matched your search
@@ -295,10 +295,11 @@ func argumentName(cmd *cobra.Command, argument string) string {
|
||||
if group == cmd {
|
||||
return text
|
||||
}
|
||||
if noun := group.Name(); noun == "pr" {
|
||||
return "pull request " + text
|
||||
noun := group.Name()
|
||||
if noun == "pr" {
|
||||
noun = "pull request"
|
||||
}
|
||||
return group.Name() + " " + text
|
||||
return noun + " " + text
|
||||
}
|
||||
|
||||
// localFlagsChanged reports whether any command-specific flag was supplied.
|
||||
|
||||
@@ -5,6 +5,7 @@ package app
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -58,10 +59,10 @@ func (f downloadFlags) destination(name string) (path string, skip bool, err err
|
||||
}
|
||||
path = f.output
|
||||
if path == "" || isDirectory(path) {
|
||||
if name != filepath.Base(name) || name == "." || name == ".." || strings.ContainsAny(name, `/\`) {
|
||||
if name == "" || name == "." || name == ".." || strings.ContainsAny(name, `/\`) {
|
||||
return "", false, clierr.Wrap(clierr.Usage, fmt.Errorf("cannot use %q as a file name; pass --output", name))
|
||||
}
|
||||
path = filepath.Join(cmpOrDot(path, f.dir), name)
|
||||
path = filepath.Join(cmp.Or(path, f.dir, "."), name)
|
||||
}
|
||||
if _, err := os.Lstat(path); err == nil {
|
||||
if f.skipExisting {
|
||||
@@ -76,15 +77,6 @@ func (f downloadFlags) destination(name string) (path string, skip bool, err err
|
||||
return path, false, nil
|
||||
}
|
||||
|
||||
func cmpOrDot(values ...string) string {
|
||||
for _, value := range values {
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return "."
|
||||
}
|
||||
|
||||
func isDirectory(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
return (err == nil && info.IsDir()) || strings.HasSuffix(path, string(filepath.Separator)) || strings.HasSuffix(path, "/")
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -206,7 +207,7 @@ func existsHint(ctx context.Context, apiErr *transport.APIError, conflict *servi
|
||||
var pull struct {
|
||||
URL string `json:"html_url"`
|
||||
}
|
||||
if apiErr.Lookup(ctx, "repos/"+conflict.Scope+"/pulls/"+base+"/"+head, &pull) == http.StatusOK && pull.URL != "" {
|
||||
if apiErr.Lookup(ctx, "repos/"+conflict.Scope+"/pulls/"+url.PathEscape(base)+"/"+url.PathEscape(head), &pull) == http.StatusOK && pull.URL != "" {
|
||||
return "see " + pull.URL
|
||||
}
|
||||
case "wiki page":
|
||||
|
||||
+14
-7
@@ -74,11 +74,14 @@ func parseRefURL(raw string, kind refKind) (ref, error) {
|
||||
return ref{}, invalid
|
||||
}
|
||||
segments := strings.Split(strings.Trim(u.Path, "/"), "/")
|
||||
positive := func(i int) int64 {
|
||||
if i >= len(segments) {
|
||||
return 0
|
||||
at := func(i int) string {
|
||||
if i < len(segments) {
|
||||
return segments[i]
|
||||
}
|
||||
n, err := strconv.ParseInt(segments[i], 10, 64)
|
||||
return ""
|
||||
}
|
||||
positive := func(i int) int64 {
|
||||
n, err := strconv.ParseInt(at(i), 10, 64)
|
||||
if err != nil || n < 1 {
|
||||
return 0
|
||||
}
|
||||
@@ -88,12 +91,12 @@ func parseRefURL(raw string, kind refKind) (ref, error) {
|
||||
for i := 2; i < len(segments); i++ {
|
||||
result := ref{}
|
||||
switch {
|
||||
case kind == runRef && segments[i] == "actions" && i+2 < len(segments) && segments[i+1] == "runs" && positive(i+2) > 0:
|
||||
case kind == runRef && at(i) == "actions" && at(i+1) == "runs" && positive(i+2) > 0:
|
||||
result.Number = positive(i + 2)
|
||||
if i+4 < len(segments) && segments[i+3] == "jobs" {
|
||||
if at(i+3) == "jobs" {
|
||||
result.Job = positive(i + 4)
|
||||
}
|
||||
case kind != runRef && (segments[i] == "issues" || segments[i] == "pulls") && positive(i+1) > 0:
|
||||
case kind != runRef && (at(i) == "issues" || at(i) == "pulls") && positive(i+1) > 0:
|
||||
result.Number = positive(i + 1)
|
||||
default:
|
||||
continue
|
||||
@@ -188,6 +191,10 @@ func (a *application) sameRepository(first, second string) bool {
|
||||
// checked-out branch.
|
||||
func (a *application) pullSelector(cmd *cobra.Command, args []string) (target, int64, error) {
|
||||
if len(args) == 0 || args[0] == "" {
|
||||
// The checked-out branch says nothing about a repository chosen with --repo.
|
||||
if a.options.repo != "" {
|
||||
return target{}, 0, clierr.Wrap(clierr.Usage, errors.New("pass a pull request number, URL or branch with --repo"))
|
||||
}
|
||||
return a.currentPull(cmd.Context())
|
||||
}
|
||||
raw := args[0]
|
||||
|
||||
@@ -135,6 +135,11 @@ func TestPullSelectorDefaultsToTheCheckedOutBranch(t *testing.T) {
|
||||
require.Equal(t, tc.want, n)
|
||||
})
|
||||
}
|
||||
a, _ := refApplication(t, branch("feat/two", nil))
|
||||
a.options.repo = "alice/project"
|
||||
_, _, err := a.pullSelector(commandContext(), nil)
|
||||
require.Equal(t, clierr.Usage, clierr.ExitCode(err))
|
||||
require.EqualError(t, err, "pass a pull request number, URL or branch with --repo")
|
||||
}
|
||||
|
||||
func TestPullSelectorAcceptsNumbersURLsAndBranches(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user