Skip to content

Commit c6b7d60

Browse files
fix broken hooks
1 parent de61df2 commit c6b7d60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+271
-167
lines changed

cmd/hook.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ Gitea or set your environment appropriately.`, "")
181181
// the environment is set by serv command
182182
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
183183
username := os.Getenv(repo_module.EnvRepoUsername)
184+
groupID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvRepoGroupID), 10, 64)
184185
reponame := os.Getenv(repo_module.EnvRepoName)
185186
userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
186187
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
@@ -254,7 +255,7 @@ Gitea or set your environment appropriately.`, "")
254255
hookOptions.OldCommitIDs = oldCommitIDs
255256
hookOptions.NewCommitIDs = newCommitIDs
256257
hookOptions.RefFullNames = refFullNames
257-
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
258+
extra := private.HookPreReceive(ctx, username, reponame, groupID, hookOptions)
258259
if extra.HasError() {
259260
return fail(ctx, extra.UserMsg, "HookPreReceive(batch) failed: %v", extra.Error)
260261
}
@@ -277,7 +278,7 @@ Gitea or set your environment appropriately.`, "")
277278

278279
fmt.Fprintf(out, " Checking %d references\n", count)
279280

280-
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
281+
extra := private.HookPreReceive(ctx, username, reponame, groupID, hookOptions)
281282
if extra.HasError() {
282283
return fail(ctx, extra.UserMsg, "HookPreReceive(last) failed: %v", extra.Error)
283284
}
@@ -350,6 +351,7 @@ Gitea or set your environment appropriately.`, "")
350351
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
351352
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
352353
pusherName := os.Getenv(repo_module.EnvPusherName)
354+
groupID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvRepoGroupID), 10, 64)
353355

354356
hookOptions := private.HookOptions{
355357
UserName: pusherName,
@@ -399,7 +401,7 @@ Gitea or set your environment appropriately.`, "")
399401
hookOptions.OldCommitIDs = oldCommitIDs
400402
hookOptions.NewCommitIDs = newCommitIDs
401403
hookOptions.RefFullNames = refFullNames
402-
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
404+
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, groupID, hookOptions)
403405
if extra.HasError() {
404406
_ = dWriter.Close()
405407
hookPrintResults(results)
@@ -414,7 +416,7 @@ Gitea or set your environment appropriately.`, "")
414416
if count == 0 {
415417
if wasEmpty && masterPushed {
416418
// We need to tell the repo to reset the default branch to master
417-
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
419+
extra := private.SetDefaultBranch(ctx, repoUser, repoName, groupID, "master")
418420
if extra.HasError() {
419421
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
420422
}
@@ -432,7 +434,7 @@ Gitea or set your environment appropriately.`, "")
432434

433435
fmt.Fprintf(out, " Processing %d references\n", count)
434436

435-
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
437+
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, groupID, hookOptions)
436438
if resp == nil {
437439
_ = dWriter.Close()
438440
hookPrintResults(results)
@@ -445,7 +447,7 @@ Gitea or set your environment appropriately.`, "")
445447

446448
if wasEmpty && masterPushed {
447449
// We need to tell the repo to reset the default branch to master
448-
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
450+
extra := private.SetDefaultBranch(ctx, repoUser, repoName, groupID, "master")
449451
if extra.HasError() {
450452
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
451453
}
@@ -513,6 +515,7 @@ Gitea or set your environment appropriately.`, "")
513515
repoName := os.Getenv(repo_module.EnvRepoName)
514516
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
515517
pusherName := os.Getenv(repo_module.EnvPusherName)
518+
groupID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvRepoGroupID), 10, 64)
516519

517520
// 1. Version and features negotiation.
518521
// S: PKT-LINE(version=1\0push-options atomic...) / PKT-LINE(version=1\n)
@@ -626,7 +629,7 @@ Gitea or set your environment appropriately.`, "")
626629
}
627630

628631
// 3. run hook
629-
resp, extra := private.HookProcReceive(ctx, repoUser, repoName, hookOptions)
632+
resp, extra := private.HookProcReceive(ctx, repoUser, repoName, groupID, hookOptions)
630633
if extra.HasError() {
631634
return fail(ctx, extra.UserMsg, "HookProcReceive failed: %v", extra.Error)
632635
}

models/issues/issue_xref.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func (issue *Issue) getCrossReferences(stdCtx context.Context, ctx *crossReferen
148148
refRepo = ctx.OrigIssue.Repo
149149
} else {
150150
// Issues in other repositories
151-
refRepo, err = repo_model.GetRepositoryByOwnerAndName(stdCtx, ref.Owner, ref.Name)
151+
refRepo, err = repo_model.GetRepositoryByOwnerAndName(stdCtx, ref.Owner, ref.Name, ref.GroupID)
152152
if err != nil {
153153
if repo_model.IsErrRepoNotExist(err) {
154154
continue

models/migrations/v1_25/v322.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ func AddGroupColumnsToRepositoryTable(x *xorm.Engine) error {
1515
IgnoreIndices: false,
1616
}, new(Repository))
1717
return err
18+
1819
}

models/repo/repo.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -831,11 +831,12 @@ func (err ErrRepoNotExist) Unwrap() error {
831831
}
832832

833833
// GetRepositoryByOwnerAndName returns the repository by given owner name and repo name
834-
func GetRepositoryByOwnerAndName(ctx context.Context, ownerName, repoName string) (*Repository, error) {
834+
func GetRepositoryByOwnerAndName(ctx context.Context, ownerName, repoName string, groupID int64) (*Repository, error) {
835835
var repo Repository
836836
has, err := db.GetEngine(ctx).Table("repository").Select("repository.*").
837837
Join("INNER", "`user`", "`user`.id = repository.owner_id").
838838
Where("repository.lower_name = ?", strings.ToLower(repoName)).
839+
And("`repository`.group_id = ?", groupID).
839840
And("`user`.lower_name = ?", strings.ToLower(ownerName)).
840841
Get(&repo)
841842
if err != nil {
@@ -847,10 +848,11 @@ func GetRepositoryByOwnerAndName(ctx context.Context, ownerName, repoName string
847848
}
848849

849850
// GetRepositoryByName returns the repository by given name under user if exists.
850-
func GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*Repository, error) {
851+
func GetRepositoryByName(ctx context.Context, ownerID, groupID int64, name string) (*Repository, error) {
851852
var repo Repository
852853
has, err := db.GetEngine(ctx).
853854
Where("`owner_id`=?", ownerID).
855+
And("`group_id`=?", groupID).
854856
And("`lower_name`=?", strings.ToLower(name)).
855857
NoAutoCondition().
856858
Get(&repo)
@@ -868,7 +870,7 @@ func GetRepositoryByURL(ctx context.Context, repoURL string) (*Repository, error
868870
if err != nil || ret.OwnerName == "" {
869871
return nil, errors.New("unknown or malformed repository URL")
870872
}
871-
return GetRepositoryByOwnerAndName(ctx, ret.OwnerName, ret.RepoName)
873+
return GetRepositoryByOwnerAndName(ctx, ret.OwnerName, ret.RepoName, ret.GroupID)
872874
}
873875

874876
// GetRepositoryByURLRelax also accepts an SSH clone URL without user part

modules/git/url/url.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"net"
1010
stdurl "net/url"
11+
"strconv"
1112
"strings"
1213

1314
"code.gitea.io/gitea/modules/httplib"
@@ -102,6 +103,7 @@ type RepositoryURL struct {
102103

103104
// if the URL belongs to current Gitea instance, then the below fields have values
104105
OwnerName string
106+
GroupID int64
105107
RepoName string
106108
RemainingPath string
107109
}
@@ -121,24 +123,35 @@ func ParseRepositoryURL(ctx context.Context, repoURL string) (*RepositoryURL, er
121123
ret := &RepositoryURL{}
122124
ret.GitURL = parsed
123125

124-
fillPathParts := func(s string) {
126+
fillPathParts := func(s string) error {
125127
s = strings.TrimPrefix(s, "/")
126-
fields := strings.SplitN(s, "/", 3)
128+
fields := strings.SplitN(s, "/", 4)
129+
var pathErr error
127130
if len(fields) >= 2 {
128131
ret.OwnerName = fields[0]
129-
ret.RepoName = strings.TrimSuffix(fields[1], ".git")
130-
if len(fields) == 3 {
132+
if len(fields) >= 3 {
133+
ret.GroupID, pathErr = strconv.ParseInt(fields[1], 10, 64)
134+
if pathErr != nil {
135+
return pathErr
136+
}
137+
ret.RepoName = strings.TrimSuffix(fields[2], ".git")
138+
ret.RemainingPath = "/" + fields[3]
139+
} else {
140+
ret.RepoName = strings.TrimSuffix(fields[1], ".git")
131141
ret.RemainingPath = "/" + fields[2]
132142
}
133143
}
144+
return nil
134145
}
135146

136147
switch parsed.URL.Scheme {
137148
case "http", "https":
138149
if !httplib.IsCurrentGiteaSiteURL(ctx, repoURL) {
139150
return ret, nil
140151
}
141-
fillPathParts(strings.TrimPrefix(parsed.URL.Path, setting.AppSubURL))
152+
if err = fillPathParts(strings.TrimPrefix(parsed.URL.Path, setting.AppSubURL)); err != nil {
153+
return nil, err
154+
}
142155
case "ssh", "git+ssh":
143156
domainSSH := setting.SSH.Domain
144157
domainCur := httplib.GuessCurrentHostDomain(ctx)
@@ -152,7 +165,9 @@ func ParseRepositoryURL(ctx context.Context, repoURL string) (*RepositoryURL, er
152165
// check whether URL domain is current domain from context
153166
domainMatches = domainMatches || (domainCur != "" && domainCur == urlDomain)
154167
if domainMatches {
155-
fillPathParts(parsed.URL.Path)
168+
if err = fillPathParts(parsed.URL.Path); err != nil {
169+
return nil, err
170+
}
156171
}
157172
}
158173
return ret, nil
@@ -161,7 +176,11 @@ func ParseRepositoryURL(ctx context.Context, repoURL string) (*RepositoryURL, er
161176
// MakeRepositoryWebLink generates a web link (http/https) for a git repository (by guessing sometimes)
162177
func MakeRepositoryWebLink(repoURL *RepositoryURL) string {
163178
if repoURL.OwnerName != "" {
164-
return setting.AppSubURL + "/" + repoURL.OwnerName + "/" + repoURL.RepoName
179+
var groupSegment string
180+
if repoURL.GroupID > 0 {
181+
groupSegment = strconv.FormatInt(repoURL.GroupID, 10) + "/"
182+
}
183+
return setting.AppSubURL + "/" + repoURL.OwnerName + "/" + groupSegment + repoURL.RepoName
165184
}
166185

167186
// now, let's guess, for example:

modules/markup/html.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
6060
v.shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
6161

6262
// anyHashPattern splits url containing SHA into parts
63-
v.anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~%./\w]+)?(\?[-+~%.\w&=]+)?(#[-+~%.\w]+)?`)
63+
v.anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,6}([0-9a-f]{40,64})(/[-+~%./\w]+)?(\?[-+~%.\w&=]+)?(#[-+~%.\w]+)?`)
6464

6565
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
66-
v.comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
66+
v.comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,6}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
6767

6868
// fullURLPattern matches full URL like "mailto:...", "https://..." and "ssh+git://..."
6969
v.fullURLPattern = regexp.MustCompile(`^[a-z][-+\w]+:`)
@@ -79,13 +79,13 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
7979
v.emojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
8080

8181
// example: https://domain/org/repo/pulls/27#hash
82-
v.issueFullPattern = regexp.MustCompile(`https?://(?:\S+/)[\w_.-]+/[\w_.-]+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`)
82+
v.issueFullPattern = regexp.MustCompile(`https?://(?:\S+/)[\w_.-]+/([\w_.-]+/)?[\w_.-]+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`)
8383

8484
// example: https://domain/org/repo/pulls/27/files#hash
85-
v.filesChangedFullPattern = regexp.MustCompile(`https?://(?:\S+/)[\w_.-]+/[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b`)
85+
v.filesChangedFullPattern = regexp.MustCompile(`https?://(?:\S+/)[\w_.-]+/([\w_.-]+/)?[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b`)
8686

8787
// codePreviewPattern matches "http://domain/.../{owner}/{repo}/src/commit/{commit}/{filepath}#L10-L20"
88-
v.codePreviewPattern = regexp.MustCompile(`https?://\S+/([^\s/]+)/([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)`)
88+
v.codePreviewPattern = regexp.MustCompile(`https?://\S+/([^\s/]+)/([^\s/]+/)?([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)`)
8989

9090
// cleans: "<foo/bar", "<any words/", ("<html", "<head", "<script", "<style", "<?", "<%")
9191
v.tagCleaner = regexp.MustCompile(`(?i)<(/?\w+/\w+|/[\w ]+/|/?(html|head|script|style|%|\?)\b)`)

modules/markup/html_codepreview.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
type RenderCodePreviewOptions struct {
1919
FullURL string
2020
OwnerName string
21+
GroupID int64
2122
RepoName string
2223
CommitID string
2324
FilePath string
@@ -34,10 +35,14 @@ func renderCodeBlock(ctx *RenderContext, node *html.Node) (urlPosStart, urlPosSt
3435
opts := RenderCodePreviewOptions{
3536
FullURL: node.Data[m[0]:m[1]],
3637
OwnerName: node.Data[m[2]:m[3]],
37-
RepoName: node.Data[m[4]:m[5]],
38-
CommitID: node.Data[m[6]:m[7]],
39-
FilePath: node.Data[m[8]:m[9]],
4038
}
39+
if len(m) >= 12 {
40+
opts.GroupID, _ = strconv.ParseInt(node.Data[m[4]:m[5]], 10, 64)
41+
opts.RepoName, opts.CommitID, opts.FilePath = node.Data[m[6]:m[7]], node.Data[m[8]:m[9]], node.Data[m[10]:m[11]]
42+
} else {
43+
opts.RepoName, opts.CommitID, opts.FilePath = node.Data[m[4]:m[5]], node.Data[m[6]:m[7]], node.Data[m[8]:m[9]]
44+
}
45+
4146
if !httplib.IsCurrentGiteaSiteURL(ctx, opts.FullURL) {
4247
return 0, 0, "", nil
4348
}

modules/markup/html_issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
type RenderIssueIconTitleOptions struct {
2323
OwnerName string
2424
RepoName string
25+
GroupID int64
2526
LinkHref string
2627
IssueIndex int64
2728
}

modules/private/hook.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,16 @@ type HookProcReceiveRefResult struct {
8282
HeadBranch string
8383
}
8484

85-
func newInternalRequestAPIForHooks(ctx context.Context, hookName, ownerName, repoName string, opts HookOptions) *httplib.Request {
86-
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/%s/%s/%s", hookName, url.PathEscape(ownerName), url.PathEscape(repoName))
85+
func genGroupSegment(groupID int64) string {
86+
var groupSegment string
87+
if groupID > 0 {
88+
groupSegment = fmt.Sprintf("%d/", groupID)
89+
}
90+
return groupSegment
91+
}
92+
93+
func newInternalRequestAPIForHooks(ctx context.Context, hookName, ownerName, repoName string, groupID int64, opts HookOptions) *httplib.Request {
94+
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/%s/%s/%s%s", hookName, url.PathEscape(ownerName), genGroupSegment(groupID), url.PathEscape(repoName))
8795
req := newInternalRequestAPI(ctx, reqURL, "POST", opts)
8896
// This "timeout" applies to http.Client's timeout: A Timeout of zero means no timeout.
8997
// This "timeout" was previously set to `time.Duration(60+len(opts.OldCommitIDs))` seconds, but it caused unnecessary timeout failures.
@@ -93,28 +101,29 @@ func newInternalRequestAPIForHooks(ctx context.Context, hookName, ownerName, rep
93101
}
94102

95103
// HookPreReceive check whether the provided commits are allowed
96-
func HookPreReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) ResponseExtra {
97-
req := newInternalRequestAPIForHooks(ctx, "pre-receive", ownerName, repoName, opts)
104+
func HookPreReceive(ctx context.Context, ownerName, repoName string, groupID int64, opts HookOptions) ResponseExtra {
105+
req := newInternalRequestAPIForHooks(ctx, "pre-receive", ownerName, repoName, groupID, opts)
98106
_, extra := requestJSONResp(req, &ResponseText{})
99107
return extra
100108
}
101109

102110
// HookPostReceive updates services and users
103-
func HookPostReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookPostReceiveResult, ResponseExtra) {
104-
req := newInternalRequestAPIForHooks(ctx, "post-receive", ownerName, repoName, opts)
111+
func HookPostReceive(ctx context.Context, ownerName, repoName string, groupID int64, opts HookOptions) (*HookPostReceiveResult, ResponseExtra) {
112+
req := newInternalRequestAPIForHooks(ctx, "post-receive", ownerName, repoName, groupID, opts)
105113
return requestJSONResp(req, &HookPostReceiveResult{})
106114
}
107115

108116
// HookProcReceive proc-receive hook
109-
func HookProcReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookProcReceiveResult, ResponseExtra) {
110-
req := newInternalRequestAPIForHooks(ctx, "proc-receive", ownerName, repoName, opts)
117+
func HookProcReceive(ctx context.Context, ownerName, repoName string, groupID int64, opts HookOptions) (*HookProcReceiveResult, ResponseExtra) {
118+
req := newInternalRequestAPIForHooks(ctx, "proc-receive", ownerName, repoName, groupID, opts)
111119
return requestJSONResp(req, &HookProcReceiveResult{})
112120
}
113121

114122
// SetDefaultBranch will set the default branch to the provided branch for the provided repository
115-
func SetDefaultBranch(ctx context.Context, ownerName, repoName, branch string) ResponseExtra {
116-
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/set-default-branch/%s/%s/%s",
123+
func SetDefaultBranch(ctx context.Context, ownerName, repoName string, groupID int64, branch string) ResponseExtra {
124+
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/set-default-branch/%s/%s/%s%s",
117125
url.PathEscape(ownerName),
126+
genGroupSegment(groupID),
118127
url.PathEscape(repoName),
119128
url.PathEscape(branch),
120129
)

0 commit comments

Comments
 (0)