-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a739c78
commit 85782b3
Showing
19 changed files
with
229 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ import ( | |
user_model "code.gitea.io/gitea/models/user" | ||
"code.gitea.io/gitea/modules/base" | ||
"code.gitea.io/gitea/modules/git" | ||
gitUrl "code.gitea.io/gitea/modules/git/url" | ||
"code.gitea.io/gitea/modules/httplib" | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/markup" | ||
|
@@ -635,14 +636,26 @@ type CloneLink struct { | |
} | ||
|
||
// ComposeHTTPSCloneURL returns HTTPS clone URL based on given owner and repository name. | ||
func ComposeHTTPSCloneURL(owner, repo string) string { | ||
return fmt.Sprintf("%s%s/%s.git", setting.AppURL, url.PathEscape(owner), url.PathEscape(repo)) | ||
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string { | ||
return fmt.Sprintf("%s%s/%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), url.PathEscape(repo)) | ||
} | ||
|
||
func ComposeSSHCloneURL(ownerName, repoName string) string { | ||
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string { | ||
sshUser := setting.SSH.User | ||
sshDomain := setting.SSH.Domain | ||
|
||
if sshUser == "(DOER_USERNAME)" { | ||
// Some users use SSH reverse-proxy and need to use the current signed-in username as the SSH user | ||
// to make the SSH reverse-proxy could prepare the user's public keys ahead. | ||
// For most cases we have the correct "doer", then use it as the SSH user. | ||
// If we can't get the doer, then use the built-in SSH user. | ||
if doer != nil { | ||
sshUser = doer.Name | ||
} else { | ||
sshUser = setting.SSH.BuiltinServerUser | ||
} | ||
} | ||
|
||
// non-standard port, it must use full URI | ||
if setting.SSH.Port != 22 { | ||
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port)) | ||
|
@@ -660,21 +673,20 @@ func ComposeSSHCloneURL(ownerName, repoName string) string { | |
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName)) | ||
} | ||
|
||
func (repo *Repository) cloneLink(isWiki bool) *CloneLink { | ||
repoName := repo.Name | ||
if isWiki { | ||
repoName += ".wiki" | ||
} | ||
|
||
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string) *CloneLink { | ||
cl := new(CloneLink) | ||
cl.SSH = ComposeSSHCloneURL(repo.OwnerName, repoName) | ||
cl.HTTPS = ComposeHTTPSCloneURL(repo.OwnerName, repoName) | ||
cl.SSH = ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName) | ||
cl.HTTPS = ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName) | ||
return cl | ||
} | ||
|
||
// CloneLink returns clone URLs of repository. | ||
func (repo *Repository) CloneLink() (cl *CloneLink) { | ||
return repo.cloneLink(false) | ||
func (repo *Repository) CloneLink(ctx context.Context, doer *user_model.User) (cl *CloneLink) { | ||
return repo.cloneLink(ctx, doer, repo.Name) | ||
} | ||
|
||
func (repo *Repository) CloneLinkGeneral(ctx context.Context) (cl *CloneLink) { | ||
return repo.cloneLink(ctx, nil /* no doer, use a general git user */, repo.Name) | ||
} | ||
|
||
// GetOriginalURLHostname returns the hostname of a URL or the URL | ||
|
@@ -770,47 +782,66 @@ func GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*Repo | |
return &repo, err | ||
} | ||
|
||
// getRepositoryURLPathSegments returns segments (owner, reponame) extracted from a url | ||
func getRepositoryURLPathSegments(repoURL string) []string { | ||
if strings.HasPrefix(repoURL, setting.AppURL) { | ||
return strings.Split(strings.TrimPrefix(repoURL, setting.AppURL), "/") | ||
func parseRepositoryURL(ctx context.Context, repoURL string) (ret struct { | ||
OwnerName, RepoName, RemainingPath string | ||
}, | ||
) { | ||
// possible urls for git: | ||
// https://my.domain/sub-path/<owner>/<repo>[.git] | ||
// git+ssh://[email protected]/<owner>/<repo>[.git] | ||
// ssh://[email protected]/<owner>/<repo>[.git] | ||
// [email protected]:<owner>/<repo>[.git] | ||
|
||
fillPathParts := func(s string) { | ||
s = strings.TrimPrefix(s, "/") | ||
fields := strings.SplitN(s, "/", 3) | ||
if len(fields) >= 2 { | ||
ret.OwnerName = fields[0] | ||
ret.RepoName = strings.TrimSuffix(fields[1], ".git") | ||
if len(fields) == 3 { | ||
ret.RemainingPath = "/" + fields[2] | ||
} | ||
} | ||
} | ||
|
||
sshURLVariants := [4]string{ | ||
setting.SSH.Domain + ":", | ||
setting.SSH.User + "@" + setting.SSH.Domain + ":", | ||
"git+ssh://" + setting.SSH.Domain + "/", | ||
"git+ssh://" + setting.SSH.User + "@" + setting.SSH.Domain + "/", | ||
parsed, err := gitUrl.ParseGitURL(repoURL) | ||
if err != nil { | ||
return ret | ||
} | ||
|
||
for _, sshURL := range sshURLVariants { | ||
if strings.HasPrefix(repoURL, sshURL) { | ||
return strings.Split(strings.TrimPrefix(repoURL, sshURL), "/") | ||
if parsed.URL.Scheme == "http" || parsed.URL.Scheme == "https" { | ||
if !httplib.IsCurrentGiteaSiteURL(ctx, repoURL) { | ||
return ret | ||
} | ||
fillPathParts(strings.TrimPrefix(parsed.URL.Path, setting.AppSubURL)) | ||
return ret | ||
} | ||
if parsed.URL.Scheme == "ssh" || parsed.URL.Scheme == "git+ssh" { | ||
domainApp := setting.Domain | ||
domainCur := httplib.GuessCurrentHostDomain(ctx) | ||
urlDomain, _, _ := net.SplitHostPort(parsed.URL.Host) | ||
urlDomain = util.IfZero(urlDomain, parsed.URL.Host) | ||
if urlDomain == "" { | ||
return ret | ||
} | ||
// check whether URL domain is the App domain | ||
domainMatches := domainApp == urlDomain | ||
// check whether URL domain is current domain from context | ||
domainMatches = domainMatches || (domainCur != "" && domainCur == urlDomain) | ||
if domainMatches { | ||
fillPathParts(parsed.URL.Path) | ||
} | ||
return ret | ||
} | ||
|
||
return nil | ||
return ret | ||
} | ||
|
||
// GetRepositoryByURL returns the repository by given url | ||
func GetRepositoryByURL(ctx context.Context, repoURL string) (*Repository, error) { | ||
// possible urls for git: | ||
// https://my.domain/sub-path/<owner>/<repo>.git | ||
// https://my.domain/sub-path/<owner>/<repo> | ||
// git+ssh://[email protected]/<owner>/<repo>.git | ||
// git+ssh://[email protected]/<owner>/<repo> | ||
// [email protected]:<owner>/<repo>.git | ||
// [email protected]:<owner>/<repo> | ||
|
||
pathSegments := getRepositoryURLPathSegments(repoURL) | ||
|
||
if len(pathSegments) != 2 { | ||
ret := parseRepositoryURL(ctx, repoURL) | ||
if ret.OwnerName == "" { | ||
return nil, fmt.Errorf("unknown or malformed repository URL") | ||
} | ||
|
||
ownerName := pathSegments[0] | ||
repoName := strings.TrimSuffix(pathSegments[1], ".git") | ||
return GetRepositoryByOwnerAndName(ctx, ownerName, repoName) | ||
return GetRepositoryByOwnerAndName(ctx, ret.OwnerName, ret.RepoName) | ||
} | ||
|
||
// GetRepositoryByID returns the repository by given id if exists. | ||
|
Oops, something went wrong.