mirror of
https://github.com/go-gitea/gitea
synced 2025-01-19 14:14:26 +00:00
34dfc25b83
close #33086 * Add a special value for "SSH_USER" setting: `(DOER_USERNAME)` * Improve parseRepositoryURL and add tests (now it doesn't have hard dependency on some setting values) Many changes are just adding "ctx" and "doer" argument to functions. By the way, improve app.example.ini, remove all `%(key)s` syntax, it only makes messy and no user really cares about it. Document: https://gitea.com/gitea/docs/pulls/138
102 lines
3.0 KiB
Go
102 lines
3.0 KiB
Go
// Copyright 2021 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package git
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
giturl "code.gitea.io/gitea/modules/git/url"
|
|
"code.gitea.io/gitea/modules/util"
|
|
)
|
|
|
|
// GetRemoteAddress returns remote url of git repository in the repoPath with special remote name
|
|
func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) {
|
|
var cmd *Command
|
|
if DefaultFeatures().CheckVersionAtLeast("2.7") {
|
|
cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName)
|
|
} else {
|
|
cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
|
|
}
|
|
|
|
result, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if len(result) > 0 {
|
|
result = result[:len(result)-1]
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetRemoteURL returns the url of a specific remote of the repository.
|
|
func GetRemoteURL(ctx context.Context, repoPath, remoteName string) (*giturl.GitURL, error) {
|
|
addr, err := GetRemoteAddress(ctx, repoPath, remoteName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return giturl.ParseGitURL(addr)
|
|
}
|
|
|
|
// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
|
|
type ErrInvalidCloneAddr struct {
|
|
Host string
|
|
IsURLError bool
|
|
IsInvalidPath bool
|
|
IsProtocolInvalid bool
|
|
IsPermissionDenied bool
|
|
LocalPath bool
|
|
}
|
|
|
|
// IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
|
|
func IsErrInvalidCloneAddr(err error) bool {
|
|
_, ok := err.(*ErrInvalidCloneAddr)
|
|
return ok
|
|
}
|
|
|
|
func (err *ErrInvalidCloneAddr) Error() string {
|
|
if err.IsInvalidPath {
|
|
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
|
|
}
|
|
if err.IsProtocolInvalid {
|
|
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
|
|
}
|
|
if err.IsPermissionDenied {
|
|
return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
|
|
}
|
|
if err.IsURLError {
|
|
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
|
|
}
|
|
|
|
return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
|
|
}
|
|
|
|
func (err *ErrInvalidCloneAddr) Unwrap() error {
|
|
return util.ErrInvalidArgument
|
|
}
|
|
|
|
// ParseRemoteAddr checks if given remote address is valid,
|
|
// and returns composed URL with needed username and password.
|
|
func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
|
|
remoteAddr = strings.TrimSpace(remoteAddr)
|
|
// Remote address can be HTTP/HTTPS/Git URL or local path.
|
|
if strings.HasPrefix(remoteAddr, "http://") ||
|
|
strings.HasPrefix(remoteAddr, "https://") ||
|
|
strings.HasPrefix(remoteAddr, "git://") {
|
|
u, err := url.Parse(remoteAddr)
|
|
if err != nil {
|
|
return "", &ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
|
|
}
|
|
if len(authUsername)+len(authPassword) > 0 {
|
|
u.User = url.UserPassword(authUsername, authPassword)
|
|
}
|
|
remoteAddr = u.String()
|
|
}
|
|
|
|
return remoteAddr, nil
|
|
}
|