mirror of
https://github.com/x-motemen/ghq.git
synced 2026-09-10 07:26:27 -04:00
fix interface of newURL
This commit is contained in:
parent
769b55d91e
commit
2237341b82
|
|
@ -24,7 +24,7 @@ func doList(c *cli.Context) error {
|
|||
}
|
||||
if query != "" {
|
||||
if hasSchemePattern.MatchString(query) || scpLikeURLPattern.MatchString(query) {
|
||||
if url, err := newURL(query, false); err == nil {
|
||||
if url, err := newURL(query, false, false); err == nil {
|
||||
if repo, err := LocalRepositoryFromURL(url); err == nil {
|
||||
query = filepath.ToSlash(repo.RelPath)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func doLook(c *cli.Context) error {
|
|||
}
|
||||
|
||||
if len(reposFound) == 0 {
|
||||
if url, err := newURL(name, false); err == nil {
|
||||
if url, err := newURL(name, false, false); err == nil {
|
||||
repo, err := LocalRepositoryFromURL(url)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
37
getter.go
37
getter.go
|
|
@ -31,46 +31,11 @@ type getter struct {
|
|||
}
|
||||
|
||||
func (g *getter) get(argURL string) error {
|
||||
// If argURL is a "./foo" or "../bar" form,
|
||||
// find repository name trailing after github.com/USER/.
|
||||
argURL = filepath.ToSlash(argURL)
|
||||
parts := strings.Split(argURL, "/")
|
||||
if parts[0] == "." || parts[0] == ".." {
|
||||
if wd, err := os.Getwd(); err == nil {
|
||||
path := filepath.Clean(filepath.Join(wd, filepath.Join(parts...)))
|
||||
|
||||
var localRepoRoot string
|
||||
roots, err := localRepositoryRoots(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range roots {
|
||||
p := strings.TrimPrefix(path, r+string(filepath.Separator))
|
||||
if p != path && (localRepoRoot == "" || len(p) < len(localRepoRoot)) {
|
||||
localRepoRoot = filepath.ToSlash(p)
|
||||
}
|
||||
}
|
||||
|
||||
if localRepoRoot != "" {
|
||||
// Guess it
|
||||
logger.Log("resolved", fmt.Sprintf("relative %q to %q", argURL, "https://"+localRepoRoot))
|
||||
argURL = "https://" + localRepoRoot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u, err := newURL(argURL, false)
|
||||
u, err := newURL(argURL, g.ssh, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not parse URL %q: %w", argURL, err)
|
||||
}
|
||||
|
||||
if g.ssh {
|
||||
// Assume Git repository if `-p` is given.
|
||||
if u, err = convertGitURLHTTPToSSH(u); err != nil {
|
||||
return fmt.Errorf("Could not convert URL %q: %w", u, err)
|
||||
}
|
||||
}
|
||||
|
||||
remote, err := NewRemoteRepository(u)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
72
url.go
72
url.go
|
|
@ -4,11 +4,13 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/Songmu/gitconfig"
|
||||
"github.com/motemen/ghq/logger"
|
||||
)
|
||||
|
||||
// Convert SCP-like URL to SSH URL(e.g. [user@]host.xz:path/to/repo.git/)
|
||||
|
|
@ -20,7 +22,35 @@ var (
|
|||
looksLikeAuthorityPattern = regexp.MustCompile(`[A-Za-z0-9]\.[A-Za-z]+(?::\d{1,5})?$`)
|
||||
)
|
||||
|
||||
func newURL(ref string, forceMe bool) (*url.URL, error) {
|
||||
func newURL(ref string, ssh, forceMe bool) (*url.URL, error) {
|
||||
// If argURL is a "./foo" or "../bar" form,
|
||||
// find repository name trailing after github.com/USER/.
|
||||
ref = filepath.ToSlash(ref)
|
||||
parts := strings.Split(ref, "/")
|
||||
if parts[0] == "." || parts[0] == ".." {
|
||||
if wd, err := os.Getwd(); err == nil {
|
||||
path := filepath.Clean(filepath.Join(wd, filepath.Join(parts...)))
|
||||
|
||||
var localRepoRoot string
|
||||
roots, err := localRepositoryRoots(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range roots {
|
||||
p := strings.TrimPrefix(path, r+string(filepath.Separator))
|
||||
if p != path && (localRepoRoot == "" || len(p) < len(localRepoRoot)) {
|
||||
localRepoRoot = filepath.ToSlash(p)
|
||||
}
|
||||
}
|
||||
|
||||
if localRepoRoot != "" {
|
||||
// Guess it
|
||||
logger.Log("resolved", fmt.Sprintf("relative %q to %q", ref, "https://"+localRepoRoot))
|
||||
ref = "https://" + localRepoRoot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !hasSchemePattern.MatchString(ref) {
|
||||
if scpLikeURLPattern.MatchString(ref) {
|
||||
matched := scpLikeURLPattern.FindStringSubmatch(ref)
|
||||
|
|
@ -42,35 +72,41 @@ func newURL(ref string, forceMe bool) (*url.URL, error) {
|
|||
}
|
||||
}
|
||||
|
||||
url, err := url.Parse(ref)
|
||||
u, err := url.Parse(ref)
|
||||
if err != nil {
|
||||
return url, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !url.IsAbs() {
|
||||
if !strings.Contains(url.Path, "/") {
|
||||
url.Path, err = fillUsernameToPath(url.Path, forceMe)
|
||||
if !u.IsAbs() {
|
||||
if !strings.Contains(u.Path, "/") {
|
||||
u.Path, err = fillUsernameToPath(u.Path, forceMe)
|
||||
if err != nil {
|
||||
return url, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
url.Scheme = "https"
|
||||
url.Host = "github.com"
|
||||
if url.Path[0] != '/' {
|
||||
url.Path = "/" + url.Path
|
||||
u.Scheme = "https"
|
||||
u.Host = "github.com"
|
||||
if u.Path[0] != '/' {
|
||||
u.Path = "/" + u.Path
|
||||
}
|
||||
}
|
||||
|
||||
return url, nil
|
||||
if ssh {
|
||||
// Assume Git repository if `-p` is given.
|
||||
if u, err = convertGitURLHTTPToSSH(u); err != nil {
|
||||
return nil, fmt.Errorf("Could not convert URL %q: %w", u, err)
|
||||
}
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func convertGitURLHTTPToSSH(url *url.URL) (*url.URL, error) {
|
||||
func convertGitURLHTTPToSSH(u *url.URL) (*url.URL, error) {
|
||||
user := "git"
|
||||
if url.User != nil {
|
||||
user = url.User.Username()
|
||||
if u.User != nil {
|
||||
user = u.User.Username()
|
||||
}
|
||||
sshURL := fmt.Sprintf("ssh://%s@%s%s", user, url.Host, url.Path)
|
||||
return url.Parse(sshURL)
|
||||
sshURL := fmt.Sprintf("ssh://%s@%s%s", user, u.Host, u.Path)
|
||||
return u.Parse(sshURL)
|
||||
}
|
||||
|
||||
func detectUserName() (string, error) {
|
||||
|
|
|
|||
10
url_test.go
10
url_test.go
|
|
@ -77,7 +77,7 @@ completeUser = false`)
|
|||
if tc.setup != nil {
|
||||
defer tc.setup()()
|
||||
}
|
||||
repo, err := newURL(tc.url, false)
|
||||
repo, err := newURL(tc.url, false, false)
|
||||
if err != nil {
|
||||
t.Errorf("error should be nil but: %s", err)
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ func TestConvertGitURLHTTPToSSH(t *testing.T) {
|
|||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.url, func(t *testing.T) {
|
||||
httpsURL, err := newURL(tc.url, false)
|
||||
httpsURL, err := newURL(tc.url, false, false)
|
||||
if err != nil {
|
||||
t.Errorf("error should be nil but: %s", err)
|
||||
}
|
||||
|
|
@ -124,15 +124,15 @@ func TestConvertGitURLHTTPToSSH(t *testing.T) {
|
|||
|
||||
func TestNewURL_err(t *testing.T) {
|
||||
invalidURL := "http://foo.com/?foo\nbar"
|
||||
_, err := newURL(invalidURL, false)
|
||||
_, err := newURL(invalidURL, false, false)
|
||||
const wantSub = "net/url: invalid control character in URL"
|
||||
if got := fmt.Sprint(err); !strings.Contains(got, wantSub) {
|
||||
t.Errorf("newURL(%q, false) error = %q; want substring %q", invalidURL, got, wantSub)
|
||||
t.Errorf("newURL(%q, false, false) error = %q; want substring %q", invalidURL, got, wantSub)
|
||||
}
|
||||
defer gitconfig.WithConfig(t, `[[[`)()
|
||||
|
||||
var exitError *exec.ExitError
|
||||
_, err = newURL("peco", false)
|
||||
_, err = newURL("peco", false, false)
|
||||
if !errors.As(err, &exitError) {
|
||||
t.Errorf("error should be occurred but nil")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue