Skip to content

Commit 4cd7d59

Browse files
committed
fix
1 parent a739c78 commit 4cd7d59

File tree

19 files changed

+229
-101
lines changed

19 files changed

+229
-101
lines changed

custom/conf/app.example.ini

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ RUN_USER = ; git
103103
;REDIRECT_OTHER_PORT = false
104104
;PORT_TO_REDIRECT = 80
105105
;;
106-
;; expect PROXY protocol header on connections to https redirector.
107-
;REDIRECTOR_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)s
106+
;; expect PROXY protocol header on connections to https redirector, defaults to USE_PROXY_PROTOCOL
107+
;REDIRECTOR_USE_PROXY_PROTOCOL =
108108
;; Minimum and maximum supported TLS versions
109109
;SSL_MIN_VERSION=TLSv1.2
110110
;SSL_MAX_VERSION=
@@ -129,12 +129,13 @@ RUN_USER = ; git
129129
;; your SSH server node is not the same as HTTP node. For different protocol, the default
130130
;; values are different. If `PROTOCOL` is `http+unix`, the default value is `http://unix/`.
131131
;; If `PROTOCOL` is `fcgi` or `fcgi+unix`, the default value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
132-
;; If listen on `0.0.0.0`, the default value is `%(PROTOCOL)s://localhost:%(HTTP_PORT)s/`, Otherwise the default
133-
;; value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
134-
;LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
132+
;; If listen on `0.0.0.0`, the default value is `%(PROTOCOL)s://localhost:%(HTTP_PORT)s/`.
133+
;; Otherwise the default value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
134+
;; Most users don't need (and shouldn't) set this value.
135+
;LOCAL_ROOT_URL =
135136
;;
136-
;; When making local connections pass the PROXY protocol header.
137-
;LOCAL_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)s
137+
;; When making local connections pass the PROXY protocol header, defaults to USE_PROXY_PROTOCOL
138+
;LOCAL_USE_PROXY_PROTOCOL =
138139
;;
139140
;; Disable SSH feature when not available
140141
;DISABLE_SSH = false
@@ -146,22 +147,26 @@ RUN_USER = ; git
146147
;SSH_SERVER_USE_PROXY_PROTOCOL = false
147148
;;
148149
;; Username to use for the builtin SSH server. If blank, then it is the value of RUN_USER.
149-
;BUILTIN_SSH_SERVER_USER = %(RUN_USER)s
150+
;BUILTIN_SSH_SERVER_USER =
150151
;;
151-
;; Domain name to be exposed in clone URL
152-
;SSH_DOMAIN = %(DOMAIN)s
152+
;; Domain name to be exposed in clone URL, defaults to DOMAIN or the domain part of ROOT_URL
153+
;SSH_DOMAIN =
153154
;;
154-
;; SSH username displayed in clone URLs.
155-
;SSH_USER = %(BUILTIN_SSH_SERVER_USER)s
155+
;; SSH username displayed in clone URLs. It defaults to BUILTIN_SSH_SERVER_USER or RUN_USER.
156+
;; If it is set to "(DOER_USERNAME)", it will use current signed-in user's username.
157+
;; This option is only for some advanced users who have configured their SSH reverse-proxy
158+
;; and need to use different usernames for git SSH clone.
159+
;; Most users should just leave it blank.
160+
;SSH_USER =
156161
;;
157162
;; The network interface the builtin SSH server should listen on
158163
;SSH_LISTEN_HOST =
159164
;;
160165
;; Port number to be exposed in clone URL
161166
;SSH_PORT = 22
162167
;;
163-
;; The port number the builtin SSH server should listen on
164-
;SSH_LISTEN_PORT = %(SSH_PORT)s
168+
;; The port number the builtin SSH server should listen on, defaults to SSH_PORT
169+
;SSH_LISTEN_PORT =
165170
;;
166171
;; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
167172
;SSH_ROOT_PATH =
@@ -188,7 +193,7 @@ RUN_USER = ; git
188193
;;
189194
;; For the built-in SSH server, choose the keypair to offer as the host key
190195
;; The private key should be at SSH_SERVER_HOST_KEY and the public SSH_SERVER_HOST_KEY.pub
191-
;; relative paths are made absolute relative to the %(APP_DATA_PATH)s
196+
;; relative paths are made absolute relative to the APP_DATA_PATH
192197
;SSH_SERVER_HOST_KEYS=ssh/gitea.rsa, ssh/gogs.rsa
193198
;;
194199
;; Directory to create temporary files in when testing public keys using ssh-keygen,
@@ -582,7 +587,7 @@ ENABLED = true
582587
[log]
583588
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
584589
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
585-
;; Root path for the log files - defaults to %(GITEA_WORK_DIR)/log
590+
;; Root path for the log files - defaults to "GITEA_WORK_DIR/log"
586591
;ROOT_PATH =
587592
;;
588593
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -682,8 +687,8 @@ LEVEL = Info
682687
;; The path of git executable. If empty, Gitea searches through the PATH environment.
683688
;PATH =
684689
;;
685-
;; The HOME directory for Git
686-
;HOME_PATH = %(APP_DATA_PATH)s/home
690+
;; The HOME directory for Git, defaults to "APP_DATA_PATH/home"
691+
;HOME_PATH =
687692
;;
688693
;; Disables highlight of added and removed changes
689694
;DISABLE_DIFF_HIGHLIGHT = false
@@ -946,8 +951,8 @@ LEVEL = Info
946951
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
947952
;[repository]
948953
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
949-
;; Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)s/gitea-repositories.
950-
;; A relative path is interpreted as _`AppWorkPath`_/%(ROOT)s
954+
;; Root path for storing all repository data. By default, it is set to "APP_DATA_PATH/gitea-repositories".
955+
;; A relative path is interpreted by using "APP_DATA_PATH" as the base path.
951956
;ROOT =
952957
;;
953958
;; The script type this server supports. Usually this is `bash`, but some users report that only `sh` is available.
@@ -1506,7 +1511,8 @@ LEVEL = Info
15061511
;TYPE = persistable-channel
15071512
;;
15081513
;; data-dir for storing persistable queues and level queues, individual queues will default to `queues/common` meaning the queue is shared.
1509-
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
1514+
;; Relative paths will be made absolute against "APP_DATA_PATH"
1515+
;DATADIR = queues/
15101516
;;
15111517
;; Default queue length before a channel queue will block
15121518
;LENGTH = 100000

models/migrations/v1_21/v276.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func getRemoteAddress(ownerName, repoName, remoteName string) (string, error) {
172172
return "", fmt.Errorf("get remote %s's address of %s/%s failed: %v", remoteName, ownerName, repoName, err)
173173
}
174174

175-
u, err := giturl.Parse(remoteURL)
175+
u, err := giturl.ParseGitURL(remoteURL)
176176
if err != nil {
177177
return "", err
178178
}

models/repo/repo.go

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
user_model "code.gitea.io/gitea/models/user"
2121
"code.gitea.io/gitea/modules/base"
2222
"code.gitea.io/gitea/modules/git"
23+
gitUrl "code.gitea.io/gitea/modules/git/url"
2324
"code.gitea.io/gitea/modules/httplib"
2425
"code.gitea.io/gitea/modules/log"
2526
"code.gitea.io/gitea/modules/markup"
@@ -635,14 +636,26 @@ type CloneLink struct {
635636
}
636637

637638
// ComposeHTTPSCloneURL returns HTTPS clone URL based on given owner and repository name.
638-
func ComposeHTTPSCloneURL(owner, repo string) string {
639-
return fmt.Sprintf("%s%s/%s.git", setting.AppURL, url.PathEscape(owner), url.PathEscape(repo))
639+
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string {
640+
return fmt.Sprintf("%s%s/%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), url.PathEscape(repo))
640641
}
641642

642-
func ComposeSSHCloneURL(ownerName, repoName string) string {
643+
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string {
643644
sshUser := setting.SSH.User
644645
sshDomain := setting.SSH.Domain
645646

647+
if sshUser == "(DOER_USERNAME)" {
648+
// Some users use SSH reverse-proxy and need to use the current signed-in username as the SSH user
649+
// to make the SSH reverse-proxy could prepare the user's public keys ahead.
650+
// For most cases we have the correct "doer", then use it as the SSH user.
651+
// If we can't get the doer, then use the built-in SSH user.
652+
if doer != nil {
653+
sshUser = doer.Name
654+
} else {
655+
sshUser = setting.SSH.BuiltinServerUser
656+
}
657+
}
658+
646659
// non-standard port, it must use full URI
647660
if setting.SSH.Port != 22 {
648661
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port))
@@ -660,21 +673,20 @@ func ComposeSSHCloneURL(ownerName, repoName string) string {
660673
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
661674
}
662675

663-
func (repo *Repository) cloneLink(isWiki bool) *CloneLink {
664-
repoName := repo.Name
665-
if isWiki {
666-
repoName += ".wiki"
667-
}
668-
676+
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string) *CloneLink {
669677
cl := new(CloneLink)
670-
cl.SSH = ComposeSSHCloneURL(repo.OwnerName, repoName)
671-
cl.HTTPS = ComposeHTTPSCloneURL(repo.OwnerName, repoName)
678+
cl.SSH = ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName)
679+
cl.HTTPS = ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName)
672680
return cl
673681
}
674682

675683
// CloneLink returns clone URLs of repository.
676-
func (repo *Repository) CloneLink() (cl *CloneLink) {
677-
return repo.cloneLink(false)
684+
func (repo *Repository) CloneLink(ctx context.Context, doer *user_model.User) (cl *CloneLink) {
685+
return repo.cloneLink(ctx, doer, repo.Name)
686+
}
687+
688+
func (repo *Repository) CloneLinkGeneral(ctx context.Context) (cl *CloneLink) {
689+
return repo.cloneLink(ctx, nil /* no doer, use a general git user */, repo.Name)
678690
}
679691

680692
// GetOriginalURLHostname returns the hostname of a URL or the URL
@@ -770,47 +782,66 @@ func GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*Repo
770782
return &repo, err
771783
}
772784

773-
// getRepositoryURLPathSegments returns segments (owner, reponame) extracted from a url
774-
func getRepositoryURLPathSegments(repoURL string) []string {
775-
if strings.HasPrefix(repoURL, setting.AppURL) {
776-
return strings.Split(strings.TrimPrefix(repoURL, setting.AppURL), "/")
785+
func parseRepositoryURL(ctx context.Context, repoURL string) (ret struct {
786+
OwnerName, RepoName, RemainingPath string
787+
},
788+
) {
789+
// possible urls for git:
790+
// https://my.domain/sub-path/<owner>/<repo>[.git]
791+
// git+ssh://[email protected]/<owner>/<repo>[.git]
792+
// ssh://[email protected]/<owner>/<repo>[.git]
793+
// [email protected]:<owner>/<repo>[.git]
794+
795+
fillPathParts := func(s string) {
796+
s = strings.TrimPrefix(s, "/")
797+
fields := strings.SplitN(s, "/", 3)
798+
if len(fields) >= 2 {
799+
ret.OwnerName = fields[0]
800+
ret.RepoName = strings.TrimSuffix(fields[1], ".git")
801+
if len(fields) == 3 {
802+
ret.RemainingPath = "/" + fields[2]
803+
}
804+
}
777805
}
778806

779-
sshURLVariants := [4]string{
780-
setting.SSH.Domain + ":",
781-
setting.SSH.User + "@" + setting.SSH.Domain + ":",
782-
"git+ssh://" + setting.SSH.Domain + "/",
783-
"git+ssh://" + setting.SSH.User + "@" + setting.SSH.Domain + "/",
807+
parsed, err := gitUrl.ParseGitURL(repoURL)
808+
if err != nil {
809+
return ret
784810
}
785-
786-
for _, sshURL := range sshURLVariants {
787-
if strings.HasPrefix(repoURL, sshURL) {
788-
return strings.Split(strings.TrimPrefix(repoURL, sshURL), "/")
811+
if parsed.URL.Scheme == "http" || parsed.URL.Scheme == "https" {
812+
if !httplib.IsCurrentGiteaSiteURL(ctx, repoURL) {
813+
return ret
814+
}
815+
fillPathParts(strings.TrimPrefix(parsed.URL.Path, setting.AppSubURL))
816+
return ret
817+
}
818+
if parsed.URL.Scheme == "ssh" || parsed.URL.Scheme == "git+ssh" {
819+
domainApp := setting.Domain
820+
domainCur := httplib.GuessCurrentHostDomain(ctx)
821+
urlDomain, _, _ := net.SplitHostPort(parsed.URL.Host)
822+
urlDomain = util.IfZero(urlDomain, parsed.URL.Host)
823+
if urlDomain == "" {
824+
return ret
789825
}
826+
// check whether URL domain is the App domain
827+
domainMatches := domainApp == urlDomain
828+
// check whether URL domain is current domain from context
829+
domainMatches = domainMatches || (domainCur != "" && domainCur == urlDomain)
830+
if domainMatches {
831+
fillPathParts(parsed.URL.Path)
832+
}
833+
return ret
790834
}
791-
792-
return nil
835+
return ret
793836
}
794837

795838
// GetRepositoryByURL returns the repository by given url
796839
func GetRepositoryByURL(ctx context.Context, repoURL string) (*Repository, error) {
797-
// possible urls for git:
798-
// https://my.domain/sub-path/<owner>/<repo>.git
799-
// https://my.domain/sub-path/<owner>/<repo>
800-
// git+ssh://[email protected]/<owner>/<repo>.git
801-
// git+ssh://[email protected]/<owner>/<repo>
802-
// [email protected]:<owner>/<repo>.git
803-
// [email protected]:<owner>/<repo>
804-
805-
pathSegments := getRepositoryURLPathSegments(repoURL)
806-
807-
if len(pathSegments) != 2 {
840+
ret := parseRepositoryURL(ctx, repoURL)
841+
if ret.OwnerName == "" {
808842
return nil, fmt.Errorf("unknown or malformed repository URL")
809843
}
810-
811-
ownerName := pathSegments[0]
812-
repoName := strings.TrimSuffix(pathSegments[1], ".git")
813-
return GetRepositoryByOwnerAndName(ctx, ownerName, repoName)
844+
return GetRepositoryByOwnerAndName(ctx, ret.OwnerName, ret.RepoName)
814845
}
815846

816847
// GetRepositoryByID returns the repository by given id if exists.

0 commit comments

Comments
 (0)