Compare commits

...

12 Commits

Author SHA1 Message Date
Lunny Xiao
6375419468
Newly pushed branches hints on repository home page (#25715)
This PR will display a pull request creation hint on the repository home
page when there are newly created branches with no pull request. Only
the recent 6 hours and 2 updated branches will be displayed.

Inspired by #14003 
Replace #14003 
Resolves #311
Resolves #13196
Resolves #23743

co-authored by @kolaente
2023-07-08 05:19:00 +02:00
Maxim Slipenko
e0a780d75b
Translate untranslated string in issues list (#25759) 2023-07-07 22:36:39 +00:00
Zettat123
a42a838843
Fix ref for workflows triggered by pull_request_target (#25743)
Follow #25229

At present, when the trigger event is `pull_request_target`, the `ref`
and `sha` of `ActionRun` are set according to the base branch of the
pull request. This makes it impossible for us to find the head branch of
the `ActionRun` directly. In this PR, the `ref` and `sha` will always be
set to the head branch and they will be changed to the base branch when
generating the task context.
2023-07-07 19:22:03 +00:00
silverwind
811fc9d49c
Minify CSS with Lightning CSS (#25754)
Replace esbuild's rudimentary CSS minifier with [Lightning
CSS](https://github.com/parcel-bundler/lightningcss), which results in
around 4% smaller CSS bundle size, index.css goes from 608K to 584K.

The module is quite new but has active use in the Parcel bundler, and as
of yesterday is also under experimental support in Vite, so I trust it
that bugs will be sorted out quickly.

Before: `assets by path css/*.css 959 KiB`
After: `assets by path css/*.css 933 KiB`

I did give this a cursory test and everything seems to be in order.
2023-07-07 18:28:48 +00:00
wxiaoguang
3780795b93
Reformat some templates (#25756)
Only: indent/dedent/newline
2023-07-07 18:06:49 +00:00
techknowlogick
cb01b8691d
Add open/closed field support for issue index (#25708)
A couple of notes:
* Future changes should refactor arguments into a struct
* This filtering only is supported by meilisearch right now
* Issue index number is bumped which will cause a re-index
2023-07-07 17:10:13 +00:00
Zettat123
7586b5815a
Fix activity type match in matchPullRequestEvent (#25746)
Fix #25736 
Caused by #24048

Right now we only check the activity type for `pull_request` event when
`types` is specified or there are no `types` and filter. If a workflow
only specifies filters but no `types` like this:
```
on:
  pull_request:
    branches: [main]
```
the workflow will be triggered even if the activity type is not one of
`[opened, reopened, sync]`. We need to check the activity type in this
case.

Co-authored-by: Giteabot <teabot@gitea.io>
2023-07-07 16:30:07 +00:00
wxiaoguang
128d77a3a0
Following up fixes for "Fix inconsistent user profile layout across tabs" (#25739)
Follow
https://github.com/go-gitea/gitea/pull/25625#issuecomment-1621577816

1. Fix the incorrect "project view" layout
2. Fix the "follow/unfollow" link on "packages" and "projects" tab


Before:


![image](https://github.com/go-gitea/gitea/assets/2114189/3b071235-c186-4097-8a19-dd90dcb2a344)


After:


![image](https://github.com/go-gitea/gitea/assets/2114189/d1d23cd7-28d8-43e3-9f68-03e8a34a9b97)

---------

Co-authored-by: Giteabot <teabot@gitea.io>
2023-07-07 17:27:12 +02:00
hiifong
a6a9389c70
Hide add file button for pull mirrors (#25748)
I think hiding the add file button for mirror repositories that can keep the ui clean.

Before:

![image](https://github.com/go-gitea/gitea/assets/89133723/84ecf1a5-1a92-4bb1-b472-b4988a4441a9)

After:

![image](https://github.com/go-gitea/gitea/assets/89133723/95382e73-286b-4114-9997-456ed77e07ca)
2023-07-07 13:36:14 +00:00
puni9869
32b26181d7
Apply to became a maintainer. (#25745)
Hi Gitea Team, 
I would like to apply as a maintainer.
I don't have that much in-depth knowledge of the codebase, but I would
like to help to review PRs for the beginning in my free time and
contribute in frontend, backend tasks and new proposals.

Here is my PR list:-
https://github.com/go-gitea/gitea/pulls?q=is%3Apr+author%3Apuni9869+is%3Amerged+
2023-07-07 13:49:34 +02:00
wxiaoguang
98088befae
Fix broken translations for package documantion (#25742)
The code was just copied&pasted, it causes problems now.

There are a lot (for every package) broken translations. eg:

```
# en-US
conda.documentation = For more information on the Conda registry, see 
<a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.

# fr-FR (and many languages)
conda.documentation=Pour plus d'informations sur le registre Conda, voir 
<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/fr-fr/packages/conda/">la documentation</a>.
```


To resolve the problem fundamentally, use a general string, and trigger
the re-translating on Crowdin side.


And, it should really really really avoid introducing too much
copied&pasted code .......
2023-07-07 10:47:26 +02:00
6543
8995046110
Less naked returns (#25713)
just a step towards  #25655

and some related refactoring
2023-07-07 05:31:56 +00:00
93 changed files with 1144 additions and 844 deletions

View File

@ -53,3 +53,4 @@ wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
Gary Moon <gary@garymoon.net> (@garymoon)
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
Denys Konovalov <kontakt@denyskon.de> (@denyskon)
Punit Inani <punitinani1@gmail.com> (@puni9869)

View File

@ -455,9 +455,9 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *use
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
// There are several trust models in Gitea
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error), keyMap *map[string]bool) (err error) {
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error), keyMap *map[string]bool) error {
if !verification.Verified {
return
return nil
}
// In the Committer trust model a signature is trusted if it matches the committer
@ -475,7 +475,7 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
verification.SigningUser.Email == verification.CommittingUser.Email) {
verification.TrustStatus = "trusted"
}
return
return nil
}
// Now we drop to the more nuanced trust models...
@ -490,10 +490,11 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
verification.SigningUser.Email != verification.CommittingUser.Email) {
verification.TrustStatus = "untrusted"
}
return
return nil
}
// Check we actually have a GPG SigningKey
var err error
if verification.SigningKey != nil {
var isMember bool
if keyMap != nil {

View File

@ -306,9 +306,10 @@ func (code *OAuth2AuthorizationCode) TableName() string {
}
// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty.
func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (redirect *url.URL, err error) {
if redirect, err = url.Parse(code.RedirectURI); err != nil {
return
func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) {
redirect, err := url.Parse(code.RedirectURI)
if err != nil {
return nil, err
}
q := redirect.Query()
if state != "" {

View File

@ -15,6 +15,8 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
)
// ErrBranchNotExist represents an error that branch with such name does not exist.
@ -378,3 +380,22 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
return committer.Commit()
}
// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created
func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64) (BranchList, error) {
branches := make(BranchList, 0, 2)
subQuery := builder.Select("head_branch").From("pull_request").
InnerJoin("issue", "issue.id = pull_request.issue_id").
Where(builder.Eq{
"pull_request.head_repo_id": repoID,
"issue.is_closed": false,
})
err := db.GetEngine(ctx).
Where("pusher_id=? AND is_deleted=?", userID, false).
And("updated_unix >= ?", time.Now().Add(-time.Hour*6).Unix()).
NotIn("name", subQuery).
OrderBy("branch.updated_unix DESC").
Limit(2).
Find(&branches)
return branches, err
}

View File

@ -16,10 +16,10 @@ type Watch struct {
Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"`
}
func AddModeColumnToWatch(x *xorm.Engine) (err error) {
if err = x.Sync2(new(Watch)); err != nil {
return
func AddModeColumnToWatch(x *xorm.Engine) error {
if err := x.Sync2(new(Watch)); err != nil {
return err
}
_, err = x.Exec("UPDATE `watch` SET `mode` = 1")
_, err := x.Exec("UPDATE `watch` SET `mode` = 1")
return err
}

View File

@ -23,25 +23,25 @@ func RecalculateStars(x *xorm.Engine) (err error) {
for start := 0; ; start += batchSize {
users := make([]User, 0, batchSize)
if err = sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
return
if err := sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
return err
}
if len(users) == 0 {
break
}
if err = sess.Begin(); err != nil {
return
if err := sess.Begin(); err != nil {
return err
}
for _, user := range users {
if _, err = sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
return
if _, err := sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
return err
}
}
if err = sess.Commit(); err != nil {
return
if err := sess.Commit(); err != nil {
return err
}
}

View File

@ -44,25 +44,25 @@ func DeleteMigrationCredentials(x *xorm.Engine) (err error) {
for start := 0; ; start += batchSize {
tasks := make([]*Task, 0, batchSize)
if err = sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
return
if err := sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
return err
}
if len(tasks) == 0 {
break
}
if err = sess.Begin(); err != nil {
return
if err := sess.Begin(); err != nil {
return err
}
for _, t := range tasks {
if t.PayloadContent, err = removeCredentials(t.PayloadContent); err != nil {
return
return err
}
if _, err = sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
return
if _, err := sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
return err
}
}
if err = sess.Commit(); err != nil {
return
if err := sess.Commit(); err != nil {
return err
}
}
return err

View File

@ -9,7 +9,7 @@ import (
"xorm.io/xorm"
)
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error {
type User struct {
ID int64 `xorm:"pk autoincr"`
Email string `xorm:"NOT NULL"`
@ -26,12 +26,12 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
}
// Add lower_email and is_primary columns
if err = x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
return
if err := x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
return err
}
if _, err = x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
return
if _, err := x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
return err
}
type EmailAddress struct {
@ -44,8 +44,8 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
}
// change lower_email as unique
if err = x.Sync2(new(EmailAddress)); err != nil {
return
if err := x.Sync2(new(EmailAddress)); err != nil {
return err
}
sess := x.NewSession()
@ -55,34 +55,33 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
for start := 0; ; start += batchSize {
users := make([]*User, 0, batchSize)
if err = sess.Limit(batchSize, start).Find(&users); err != nil {
return
if err := sess.Limit(batchSize, start).Find(&users); err != nil {
return err
}
if len(users) == 0 {
break
}
for _, user := range users {
var exist bool
exist, err = sess.Where("email=?", user.Email).Table("email_address").Exist()
exist, err := sess.Where("email=?", user.Email).Table("email_address").Exist()
if err != nil {
return
return err
}
if !exist {
if _, err = sess.Insert(&EmailAddress{
if _, err := sess.Insert(&EmailAddress{
UID: user.ID,
Email: user.Email,
LowerEmail: strings.ToLower(user.Email),
IsActivated: user.IsActive,
IsPrimary: true,
}); err != nil {
return
return err
}
} else {
if _, err = sess.Where("email=?", user.Email).Cols("is_primary").Update(&EmailAddress{
if _, err := sess.Where("email=?", user.Email).Cols("is_primary").Update(&EmailAddress{
IsPrimary: true,
}); err != nil {
return
return err
}
}
}

View File

@ -528,6 +528,18 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin
return fmt.Sprintf("%s/%s/compare/%s...%s", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), util.PathEscapeSegments(oldCommitID), util.PathEscapeSegments(newCommitID))
}
func (repo *Repository) ComposeBranchCompareURL(baseRepo *Repository, branchName string) string {
if baseRepo == nil {
baseRepo = repo
}
var cmpBranchEscaped string
if repo.ID != baseRepo.ID {
cmpBranchEscaped = fmt.Sprintf("%s/%s:", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name))
}
cmpBranchEscaped = fmt.Sprintf("%s%s", cmpBranchEscaped, util.PathEscapeSegments(branchName))
return fmt.Sprintf("%s/compare/%s...%s", baseRepo.Link(), util.PathEscapeSegments(baseRepo.DefaultBranch), cmpBranchEscaped)
}
// IsOwnedBy returns true when user owns this repository
func (repo *Repository) IsOwnedBy(userID int64) bool {
return repo.OwnerID == userID

View File

@ -23,8 +23,6 @@ import (
type DetectedWorkflow struct {
EntryName string
TriggerEvent string
Commit *git.Commit
Ref string
Content []byte
}
@ -120,7 +118,6 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
dwf := &DetectedWorkflow{
EntryName: entry.Name(),
TriggerEvent: evt.Name,
Commit: commit,
Content: content,
}
workflows = append(workflows, dwf)
@ -335,44 +332,47 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
}
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
acts := evt.Acts()
activityTypeMatched := false
matchTimes := 0
if vals, ok := acts["types"]; !ok {
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
} else {
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
// Actions with the same name:
// opened, edited, closed, reopened, assigned, unassigned
// Actions need to be converted:
// synchronized -> synchronize
// label_updated -> labeled
// label_cleared -> unlabeled
// Unsupported activity types:
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
action := prPayload.Action
switch action {
case api.HookIssueSynchronized:
action = "synchronize"
case api.HookIssueLabelUpdated:
action = "labeled"
case api.HookIssueLabelCleared:
action = "unlabeled"
}
log.Trace("matching pull_request %s with %v", action, vals)
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
activityTypeMatched = true
matchTimes++
break
}
}
}
matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
for cond, vals := range acts {
switch cond {
case "types":
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
// Actions with the same name:
// opened, edited, closed, reopened, assigned, unassigned
// Actions need to be converted:
// synchronized -> synchronize
// label_updated -> labeled
// label_cleared -> unlabeled
// Unsupported activity types:
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
action := prPayload.Action
switch action {
case api.HookIssueSynchronized:
action = "synchronize"
case api.HookIssueLabelUpdated:
action = "labeled"
case api.HookIssueLabelCleared:
action = "unlabeled"
}
log.Trace("matching pull_request %s with %v", action, vals)
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
matchTimes++
break
}
}
case "branches":
refName := git.RefName(prPayload.PullRequest.Base.Ref)
patterns, err := workflowpattern.CompilePatterns(vals...)
@ -421,7 +421,7 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
log.Warn("pull request event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
return activityTypeMatched && matchTimes == len(evt.Acts())
}
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {

View File

@ -57,6 +57,25 @@ func TestDetectMatched(t *testing.T) {
yamlOn: "on: pull_request",
expected: false,
},
{
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with no activity type",
triggedEvent: webhook_module.HookEventPullRequest,
payload: &api.PullRequestPayload{Action: api.HookIssueClosed},
yamlOn: "on: pull_request",
expected: false,
},
{
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with branches",
triggedEvent: webhook_module.HookEventPullRequest,
payload: &api.PullRequestPayload{
Action: api.HookIssueClosed,
PullRequest: &api.PullRequest{
Base: &api.PRBranchInfo{},
},
},
yamlOn: "on:\n pull_request:\n branches: [main]",
expected: false,
},
{
desc: "HookEventPullRequest(pull_request) `label_updated` action matches GithubEventPullRequest(pull_request) with `label` activity type",
triggedEvent: webhook_module.HookEventPullRequest,

View File

@ -422,10 +422,10 @@ func RepoIDAssignment() func(ctx *Context) {
}
// RepoAssignment returns a middleware to handle repository assignment
func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
func RepoAssignment(ctx *Context) context.CancelFunc {
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
log.Trace("RepoAssignment was exec already, skipping second call ...")
return
return nil
}
ctx.Data["repoAssignmentExecuted"] = true
@ -453,7 +453,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
// https://github.com/golang/go/issues/19760
if ctx.FormString("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
return
return nil
}
if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil {
@ -466,7 +466,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
} else {
ctx.ServerError("GetUserByName", err)
}
return
return nil
}
}
ctx.Repo.Owner = owner
@ -490,7 +490,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
redirectPath += "?" + ctx.Req.URL.RawQuery
}
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
return
return nil
}
// Get repository.
@ -503,7 +503,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
} else if repo_model.IsErrRedirectNotExist(err) {
if ctx.FormString("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
return
return nil
}
ctx.NotFound("GetRepositoryByName", nil)
} else {
@ -512,13 +512,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
} else {
ctx.ServerError("GetRepositoryByName", err)
}
return
return nil
}
repo.Owner = owner
repoAssignment(ctx, repo)
if ctx.Written() {
return
return nil
}
ctx.Repo.RepoLink = repo.Link()
@ -542,12 +542,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
})
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
return
return nil
}
ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
return
return nil
}
ctx.Data["Title"] = owner.Name + "/" + repo.Name
@ -563,14 +563,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("CanUserForkRepo", err)
return
return nil
}
ctx.Data["CanSignedUserFork"] = canSignedUserFork
userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("GetForksByUserAndOrgs", err)
return
return nil
}
ctx.Data["UserAndOrgForks"] = userAndOrgForks
@ -604,14 +604,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if repo.IsFork {
RetrieveBaseRepo(ctx, repo)
if ctx.Written() {
return
return nil
}
}
if repo.IsGenerated() {
RetrieveTemplateRepo(ctx, repo)
if ctx.Written() {
return
return nil
}
}
@ -623,7 +623,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
return
return nil
}
gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName))
@ -636,10 +636,10 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
return
return nil
}
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
return
return nil
}
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
@ -647,7 +647,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Repo.GitRepo = gitRepo
// We opened it, we should close it
cancel = func() {
cancel := func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
@ -657,13 +657,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
// Stop at this point when the repo is empty.
if ctx.Repo.Repository.IsEmpty {
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
return
return cancel
}
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.ServerError("GetTagNamesByRepoID", err)
return
return cancel
}
ctx.Data["Tags"] = tags
@ -677,7 +677,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
branchesTotal, err := git_model.CountBranches(ctx, branchOpts)
if err != nil {
ctx.ServerError("CountBranches", err)
return
return cancel
}
// non empty repo should have at least 1 branch, so this repository's branches haven't been synced yet
@ -685,7 +685,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
branchesTotal, err = repo_module.SyncRepoBranches(ctx, ctx.Repo.Repository.ID, 0)
if err != nil {
ctx.ServerError("SyncRepoBranches", err)
return
return cancel
}
}
@ -694,7 +694,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
brs, err := git_model.FindBranchNames(ctx, branchOpts)
if err != nil {
ctx.ServerError("GetBranches", err)
return
return cancel
}
// always put default branch on the top
ctx.Data["Branches"] = append(branchOpts.ExcludeBranchNames, brs...)
@ -741,12 +741,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("GetPendingRepositoryTransfer", err)
return
return cancel
}
if err := repoTransfer.LoadAttributes(ctx); err != nil {
ctx.ServerError("LoadRecipient", err)
return
return cancel
}
ctx.Data["RepoTransfer"] = repoTransfer
@ -894,7 +894,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
ctx.Data["TreePath"] = ""
return
return nil
}
var (
@ -907,7 +907,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath)
if err != nil {
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
return
return nil
}
// We opened it, we should close it
cancel = func() {
@ -944,7 +944,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.Repository.MarkAsBrokenEmpty()
} else {
ctx.ServerError("GetBranchCommit", err)
return
return cancel
}
ctx.Repo.IsViewBranch = true
} else {
@ -956,7 +956,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
ctx.Redirect(link)
return
return cancel
}
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
@ -966,7 +966,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
if err != nil {
ctx.ServerError("GetBranchCommit", err)
return
return cancel
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
@ -978,10 +978,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound("GetTagCommit", err)
return
return cancel
}
ctx.ServerError("GetTagCommit", err)
return
return cancel
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if len(refName) >= 7 && len(refName) <= git.SHAFullLength {
@ -991,7 +991,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
if err != nil {
ctx.NotFound("GetCommit", err)
return
return cancel
}
// If short commit ID add canonical link header
if len(refName) < git.SHAFullLength {
@ -1000,10 +1000,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
}
} else {
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
return
return cancel
}
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
return
return cancel
}
if refType == RepoRefLegacy {
@ -1015,7 +1015,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
util.PathEscapeSegments(prefix),
ctx.Repo.BranchNameSubURL(),
util.PathEscapeSegments(ctx.Repo.TreePath)))
return
return cancel
}
}
@ -1033,7 +1033,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
if err != nil {
ctx.ServerError("GetCommitsCount", err)
return
return cancel
}
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache())

View File

@ -6,6 +6,7 @@ package doctor
import (
"bytes"
"context"
"errors"
"fmt"
"code.gitea.io/gitea/models/db"
@ -40,12 +41,12 @@ func parseBool16961(bs []byte) (bool, error) {
func fixUnitConfig16961(bs []byte, cfg *repo_model.UnitConfig) (fixed bool, err error) {
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
if err == nil {
return
return false, nil
}
// Handle #16961
if string(bs) != "&{}" && len(bs) != 0 {
return
return false, err
}
return true, nil
@ -54,14 +55,14 @@ func fixUnitConfig16961(bs []byte, cfg *repo_model.UnitConfig) (fixed bool, err
func fixExternalWikiConfig16961(bs []byte, cfg *repo_model.ExternalWikiConfig) (fixed bool, err error) {
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
if err == nil {
return
return false, nil
}
if len(bs) < 3 {
return
return false, err
}
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
return
return false, err
}
cfg.ExternalWikiURL = string(bs[2 : len(bs)-1])
return true, nil
@ -70,20 +71,20 @@ func fixExternalWikiConfig16961(bs []byte, cfg *repo_model.ExternalWikiConfig) (
func fixExternalTrackerConfig16961(bs []byte, cfg *repo_model.ExternalTrackerConfig) (fixed bool, err error) {
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
if err == nil {
return
return false, nil
}
// Handle #16961
if len(bs) < 3 {
return
return false, err
}
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
return
return false, err
}
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
if len(parts) != 3 {
return
return false, err
}
cfg.ExternalTrackerURL = string(bytes.Join(parts[:len(parts)-2], []byte{' '}))
@ -95,16 +96,16 @@ func fixExternalTrackerConfig16961(bs []byte, cfg *repo_model.ExternalTrackerCon
func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (fixed bool, err error) {
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
if err == nil {
return
return false, nil
}
// Handle #16961
if len(bs) < 3 {
return
return false, err
}
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
return
return false, err
}
// PullRequestsConfig was the following in 1.14
@ -123,37 +124,37 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
// DefaultMergeStyle MergeStyle
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
if len(parts) < 7 {
return
return false, err
}
var parseErr error
cfg.IgnoreWhitespaceConflicts, parseErr = parseBool16961(parts[0])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowMerge, parseErr = parseBool16961(parts[1])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowRebase, parseErr = parseBool16961(parts[2])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowRebaseMerge, parseErr = parseBool16961(parts[3])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowSquash, parseErr = parseBool16961(parts[4])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowManualMerge, parseErr = parseBool16961(parts[5])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AutodetectManualMerge, parseErr = parseBool16961(parts[6])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
// 1.14 unit
@ -162,12 +163,12 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
}
if len(parts) < 9 {
return
return false, err
}
cfg.DefaultDeleteBranchAfterMerge, parseErr = parseBool16961(parts[7])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.DefaultMergeStyle = repo_model.MergeStyle(string(bytes.Join(parts[8:], []byte{' '})))
@ -177,34 +178,34 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
func fixIssuesConfig16961(bs []byte, cfg *repo_model.IssuesConfig) (fixed bool, err error) {
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
if err == nil {
return
return false, nil
}
// Handle #16961
if len(bs) < 3 {
return
return false, err
}
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
return
return false, err
}
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
if len(parts) != 3 {
return
return false, err
}
var parseErr error
cfg.EnableTimetracker, parseErr = parseBool16961(parts[0])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.AllowOnlyContributorsToTrackTime, parseErr = parseBool16961(parts[1])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
cfg.EnableDependencies, parseErr = parseBool16961(parts[2])
if parseErr != nil {
return
return false, errors.Join(err, parseErr)
}
return true, nil
}

View File

@ -15,7 +15,7 @@ import (
func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
if len(value) == 0 {
return
return 0, nil
}
var n int
last := 0
@ -23,24 +23,24 @@ func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
n, err = w.Write(prefix)
sum += int64(n)
if err != nil {
return
return sum, err
}
n, err = w.Write(value[last : last+j+1])
sum += int64(n)
if err != nil {
return
return sum, err
}
last += j + 1
}
n, err = w.Write(prefix)
sum += int64(n)
if err != nil {
return
return sum, err
}
n, err = w.Write(value[last:])
sum += int64(n)
if err != nil {
return
return sum, err
}
n, err = w.Write([]byte("\n"))
sum += int64(n)

View File

@ -70,11 +70,11 @@ func checkIfNoneMatchIsValid(req *http.Request, etag string) bool {
// HandleGenericETagTimeCache handles ETag-based caching with Last-Modified caching for a HTTP request.
// It returns true if the request was handled.
func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag string, lastModified time.Time) (handled bool) {
func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag string, lastModified *time.Time) (handled bool) {
if len(etag) > 0 {
w.Header().Set("Etag", etag)
}
if !lastModified.IsZero() {
if lastModified != nil && !lastModified.IsZero() {
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
}
@ -84,7 +84,7 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
return true
}
}
if !lastModified.IsZero() {
if lastModified != nil && !lastModified.IsZero() {
ifModifiedSince := req.Header.Get("If-Modified-Since")
if ifModifiedSince != "" {
t, err := time.Parse(http.TimeFormat, ifModifiedSince)

View File

@ -206,7 +206,7 @@ func ServeContentByReader(r *http.Request, w http.ResponseWriter, filePath strin
_, _ = io.CopyN(w, reader, partialLength) // just like http.ServeContent, not necessary to handle the error
}
func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath string, modTime time.Time, reader io.ReadSeeker) {
func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath string, modTime *time.Time, reader io.ReadSeeker) {
buf := make([]byte, mimeDetectionBufferLen)
n, err := util.ReadAtMost(reader, buf)
if err != nil {
@ -221,5 +221,8 @@ func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath s
buf = buf[:n]
}
setServeHeadersByFile(r, w, filePath, buf)
http.ServeContent(w, r, path.Base(filePath), modTime, reader)
if modTime == nil {
modTime = &time.Time{}
}
http.ServeContent(w, r, path.Base(filePath), *modTime, reader)
}

View File

@ -11,7 +11,6 @@ import (
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -78,7 +77,7 @@ func TestServeContentByReadSeeker(t *testing.T) {
defer seekReader.Close()
w := httptest.NewRecorder()
ServeContentByReadSeeker(r, w, "test", time.Time{}, seekReader)
ServeContentByReadSeeker(r, w, "test", nil, seekReader)
assert.Equal(t, expectedStatusCode, w.Code)
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))

View File

@ -138,7 +138,7 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
// Search searches for issues by given conditions.
// Returns the matching issue IDs
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
var repoQueriesP []*query.NumericRangeQuery
for _, repoID := range repoIDs {
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "repo_id"))

View File

@ -77,7 +77,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
}
for _, kw := range keywords {
res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0)
res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0, "")
assert.NoError(t, err)
ids := make([]int64, 0, len(res.Hits))

View File

@ -36,7 +36,7 @@ func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
}
// Search searches for issues
func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
total, ids, err := issues_model.SearchIssueIDsByKeyword(ctx, kw, repoIDs, limit, start)
if err != nil {
return nil, err

View File

@ -140,7 +140,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
// Search searches for issues by given conditions.
// Returns the matching issue IDs
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
kwQuery := elastic.NewMultiMatchQuery(keyword, "title", "content", "comments")
query := elastic.NewBoolQuery()
query = query.Must(kwQuery)

View File

@ -242,12 +242,18 @@ func UpdateIssueIndexer(issue *issues_model.Issue) {
comments = append(comments, comment.Content)
}
}
issueType := "issue"
if issue.IsPull {
issueType = "pull"
}
indexerData := &internal.IndexerData{
ID: issue.ID,
RepoID: issue.RepoID,
Title: issue.Title,
Content: issue.Content,
Comments: comments,
ID: issue.ID,
RepoID: issue.RepoID,
State: string(issue.State()),
IssueType: issueType,
Title: issue.Title,
Content: issue.Content,
Comments: comments,
}
log.Debug("Adding to channel: %v", indexerData)
if err := issueIndexerQueue.Push(indexerData); err != nil {
@ -278,10 +284,10 @@ func DeleteRepoIssueIndexer(ctx context.Context, repo *repo_model.Repository) {
// SearchIssuesByKeyword search issue ids by keywords and repo id
// WARNNING: You have to ensure user have permission to visit repoIDs' issues
func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword string) ([]int64, error) {
func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword, state string) ([]int64, error) {
var issueIDs []int64
indexer := *globalIndexer.Load()
res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0)
res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0, state)
if err != nil {
return nil, err
}

View File

@ -50,19 +50,19 @@ func TestBleveSearchIssues(t *testing.T) {
time.Sleep(5 * time.Second)
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
assert.NoError(t, err)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
}
@ -73,19 +73,19 @@ func TestDBSearchIssues(t *testing.T) {
setting.Indexer.IssueType = "db"
InitIssueIndexer(true)
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
assert.NoError(t, err)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
}

View File

@ -15,7 +15,7 @@ type Indexer interface {
internal.Indexer
Index(ctx context.Context, issue []*IndexerData) error
Delete(ctx context.Context, ids ...int64) error
Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error)
Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error)
}
// NewDummyIndexer returns a dummy indexer
@ -37,6 +37,6 @@ func (d *dummyIndexer) Delete(ctx context.Context, ids ...int64) error {
return fmt.Errorf("indexer is not ready")
}
func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error) {
func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error) {
return nil, fmt.Errorf("indexer is not ready")
}

View File

@ -5,13 +5,15 @@ package internal
// IndexerData data stored in the issue indexer
type IndexerData struct {
ID int64 `json:"id"`
RepoID int64 `json:"repo_id"`
Title string `json:"title"`
Content string `json:"content"`
Comments []string `json:"comments"`
IsDelete bool `json:"is_delete"`
IDs []int64 `json:"ids"`
ID int64 `json:"id"`
RepoID int64 `json:"repo_id"`
State string `json:"state"` // open, closed, all
IssueType string `json:"type"` // issue or pull
Title string `json:"title"`
Content string `json:"content"`
Comments []string `json:"comments"`
IsDelete bool `json:"is_delete"`
IDs []int64 `json:"ids"`
}
// Match represents on search result

View File

@ -16,7 +16,7 @@ import (
)
const (
issueIndexerLatestVersion = 0
issueIndexerLatestVersion = 1
)
var _ internal.Indexer = &Indexer{}
@ -70,12 +70,19 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
// Search searches for issues by given conditions.
// Returns the matching issue IDs
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
repoFilters := make([]string, 0, len(repoIDs))
for _, repoID := range repoIDs {
repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
}
filter := strings.Join(repoFilters, " OR ")
if state == "open" || state == "closed" {
if filter != "" {
filter = "(" + filter + ") AND state = " + state
} else {
filter = "state = " + state
}
}
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
Filter: filter,
Limit: int64(limit),

View File

@ -211,7 +211,7 @@ func (pm *Manager) nextPID() (start time.Time, pid IDType) {
pid = IDType(strconv.FormatInt(start.Unix(), 16))
if pm.next == 1 {
return
return start, pid
}
pid = IDType(string(pid) + "-" + strconv.FormatInt(pm.next, 10))
return start, pid

View File

@ -256,3 +256,8 @@ func ToFloat64(number any) (float64, error) {
}
return value, nil
}
// ToPointer returns the pointer of a copy of any given value
func ToPointer[T any](val T) *T {
return &val
}

View File

@ -224,3 +224,12 @@ func TestToTitleCase(t *testing.T) {
assert.Equal(t, ToTitleCase(`foo bar baz`), `Foo Bar Baz`)
assert.Equal(t, ToTitleCase(`FOO BAR BAZ`), `Foo Bar Baz`)
}
func TestToPointer(t *testing.T) {
assert.Equal(t, "abc", *ToPointer("abc"))
assert.Equal(t, 123, *ToPointer(123))
abc := "abc"
assert.False(t, &abc == ToPointer(abc))
val123 := 123
assert.False(t, &val123 == ToPointer(val123))
}

View File

@ -1767,6 +1767,8 @@ pulls.auto_merge_canceled_schedule_comment = `canceled auto merging this pull re
pulls.delete.title = Delete this pull request?
pulls.delete.text = Do you really want to delete this pull request? (This will permanently remove all content. Consider closing it instead, if you intend to keep it archived)
pulls.recently_pushed_new_branches = You pushed on branch <strong>%[1]s</strong> %[2]s
milestones.new = New Milestone
milestones.closed = Closed %s
milestones.update_ago = Updated %s
@ -3232,6 +3234,7 @@ desc = Manage repository packages.
empty = There are no packages yet.
empty.documentation = For more information on the package registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
empty.repo = Did you upload a package, but it's not shown here? Go to <a href="%[1]s">package settings</a> and link it to this repo.
registry.documentation = For more information on the %s registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
filter.type = Type
filter.type.all = All
filter.no_result = Your filter produced no results.
@ -3259,38 +3262,31 @@ alpine.registry = Setup this registry by adding the url in your <code>/etc/apk/r
alpine.registry.key = Download the registry public RSA key into the <code>/etc/apk/keys/</code> folder to verify the index signature:
alpine.registry.info = Choose $branch and $repository from the list below.
alpine.install = To install the package, run the following command:
alpine.documentation = For more information on the Alpine registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
alpine.repository = Repository Info
alpine.repository.branches = Branches
alpine.repository.repositories = Repositories
alpine.repository.architectures = Architectures
cargo.registry = Setup this registry in the Cargo configuration file (for example <code>~/.cargo/config.toml</code>):
cargo.install = To install the package using Cargo, run the following command:
cargo.documentation = For more information on the Cargo registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
cargo.details.repository_site = Repository Site
cargo.details.documentation_site = Documentation Site
chef.registry = Setup this registry in your <code>~/.chef/config.rb</code> file:
chef.install = To install the package, run the following command:
chef.documentation = For more information on the Chef registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
composer.registry = Setup this registry in your <code>~/.composer/config.json</code> file:
composer.install = To install the package using Composer, run the following command:
composer.documentation = For more information on the Composer registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
composer.dependencies = Dependencies
composer.dependencies.development = Development Dependencies
conan.details.repository = Repository
conan.registry = Setup this registry from the command line:
conan.install = To install the package using Conan, run the following command:
conan.documentation = For more information on the Conan registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
conda.registry = Setup this registry as a Conda repository in your <code>.condarc</code> file:
conda.install = To install the package using Conda, run the following command:
conda.documentation = For more information on the Conda registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
conda.details.repository_site = Repository Site
conda.details.documentation_site = Documentation Site
container.details.type = Image Type
container.details.platform = Platform
container.pull = Pull the image from the command line:
container.digest = Digest:
container.documentation = For more information on the Container registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
container.multi_arch = OS / Arch
container.layers = Image Layers
container.labels = Labels
@ -3298,61 +3294,47 @@ container.labels.key = Key
container.labels.value = Value
cran.registry = Setup this registry in your <code>Rprofile.site</code> file:
cran.install = To install the package, run the following command:
cran.documentation = For more information on the CRAN registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cran/">the documentation</a>.
debian.registry = Setup this registry from the command line:
debian.registry.info = Choose $distribution and $component from the list below.
debian.install = To install the package, run the following command:
debian.documentation = For more information on the Debian registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
debian.repository = Repository Info
debian.repository.distributions = Distributions
debian.repository.components = Components
debian.repository.architectures = Architectures
generic.download = Download package from the command line:
generic.documentation = For more information on the generic registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
go.install = Install the package from the command line:
go.documentation = For more information on the Go registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
helm.registry = Setup this registry from the command line:
helm.install = To install the package, run the following command:
helm.documentation = For more information on the Helm registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
maven.registry = Setup this registry in your project <code>pom.xml</code> file:
maven.install = To use the package include the following in the <code>dependencies</code> block in the <code>pom.xml</code> file:
maven.install2 = Run via command line:
maven.download = To download the dependency, run via command line:
maven.documentation = For more information on the Maven registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
nuget.registry = Setup this registry from the command line:
nuget.install = To install the package using NuGet, run the following command:
nuget.documentation = For more information on the NuGet registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
nuget.dependency.framework = Target Framework
npm.registry = Setup this registry in your project <code>.npmrc</code> file:
npm.install = To install the package using npm, run the following command:
npm.install2 = or add it to the package.json file:
npm.documentation = For more information on the npm registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
npm.dependencies = Dependencies
npm.dependencies.development = Development Dependencies
npm.dependencies.peer = Peer Dependencies
npm.dependencies.optional = Optional Dependencies
npm.details.tag = Tag
pub.install = To install the package using Dart, run the following command:
pub.documentation = For more information on the Pub registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
pypi.requires = Requires Python
pypi.install = To install the package using pip, run the following command:
pypi.documentation = For more information on the PyPI registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
rpm.registry = Setup this registry from the command line:
rpm.install = To install the package, run the following command:
rpm.documentation = For more information on the RPM registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
rubygems.install = To install the package using gem, run the following command:
rubygems.install2 = or add it to the Gemfile:
rubygems.dependencies.runtime = Runtime Dependencies
rubygems.dependencies.development = Development Dependencies
rubygems.required.ruby = Requires Ruby version
rubygems.required.rubygems = Requires RubyGem version
rubygems.documentation = For more information on the RubyGems registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
swift.registry = Setup this registry from the command line:
swift.install = Add the package in your <code>Package.swift</code> file:
swift.install2 = and run the following command:
swift.documentation = For more information on the Swift registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
vagrant.install = To add a Vagrant box, run the following command:
vagrant.documentation = For more information on the Vagrant registry, see <a target="_blank" rel="noopener noreferrer" href="%s">the documentation</a>.
settings.link = Link this package to a repository
settings.link.description = If you link a package with a repository, the package is listed in the repository's package list.
settings.link.select = Select Repository

210
package-lock.json generated
View File

@ -30,6 +30,7 @@
"jquery.are-you-sure": "1.9.0",
"katex": "0.16.8",
"license-checker-webpack-plugin": "0.2.1",
"lightningcss-loader": "2.1.0",
"mermaid": "10.2.3",
"mini-css-extract-plugin": "2.7.6",
"minimatch": "9.0.2",
@ -4010,6 +4011,17 @@
"node": ">=6"
}
},
"node_modules/detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
"bin": {
"detect-libc": "bin/detect-libc.js"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/diff": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
@ -6717,6 +6729,204 @@
"node": ">=8"
}
},
"node_modules/lightningcss": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.21.5.tgz",
"integrity": "sha512-/pEUPeih2EwIx9n4T82aOG6CInN83tl/mWlw6B5gWLf36UplQi1L+5p3FUHsdt4fXVfOkkh9KIaM3owoq7ss8A==",
"dependencies": {
"detect-libc": "^1.0.3"
},
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"lightningcss-darwin-arm64": "1.21.5",
"lightningcss-darwin-x64": "1.21.5",
"lightningcss-linux-arm-gnueabihf": "1.21.5",
"lightningcss-linux-arm64-gnu": "1.21.5",
"lightningcss-linux-arm64-musl": "1.21.5",
"lightningcss-linux-x64-gnu": "1.21.5",
"lightningcss-linux-x64-musl": "1.21.5",
"lightningcss-win32-x64-msvc": "1.21.5"
}
},
"node_modules/lightningcss-darwin-arm64": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.21.5.tgz",
"integrity": "sha512-z05hyLX85WY0UfhkFUOrWEFqD69lpVAmgl3aDzMKlIZJGygbhbegqb4PV8qfUrKKNBauut/qVNPKZglhTaDDxA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-darwin-x64": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.21.5.tgz",
"integrity": "sha512-MSJhmej/U9MrdPxDk7+FWhO8+UqVoZUHG4VvKT5RQ4RJtqtANTiWiI97LvoVNMtdMnHaKs1Pkji6wHUFxjJsHQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-linux-arm-gnueabihf": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.21.5.tgz",
"integrity": "sha512-xN6+5/JsMrbZHL1lPl+MiNJ3Xza12ueBKPepiyDCFQzlhFRTj7D0LG+cfNTzPBTO8KcYQynLpl1iBB8LGp3Xtw==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-linux-arm64-gnu": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.21.5.tgz",
"integrity": "sha512-KfzFNhC4XTbmG3ma/xcTs/IhCwieW89XALIusKmnV0N618ZDXEB0XjWOYQRCXeK9mfqPdbTBpurEHV/XZtkniQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-linux-arm64-musl": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.21.5.tgz",
"integrity": "sha512-bc0GytQO5Mn9QM6szaZ+31fQHNdidgpM1sSCwzPItz8hg3wOvKl8039rU0veMJV3ZgC9z0ypNRceLrSHeRHmXw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-linux-x64-gnu": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.21.5.tgz",
"integrity": "sha512-JwMbgypPQgc2kW2av3OwzZ8cbrEuIiDiXPJdXRE6aVxu67yHauJawQLqJKTGUhiAhy6iLDG8Wg0a3/ziL+m+Kw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-linux-x64-musl": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.21.5.tgz",
"integrity": "sha512-Ib8b6IQ/OR/VrPU6YBgy4T3QnuHY7DUa95O+nz+cwrTkMSN6fuHcTcIaz4t8TJ6HI5pl3uxUOZjmtls2pyQWow==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-loader": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lightningcss-loader/-/lightningcss-loader-2.1.0.tgz",
"integrity": "sha512-mB+M/lvs/GdXT4yc8ZiNgLUAbYpPI9grDyC3ybz/Zo6s4GZv53iZnLTnkJT/Qm3Sh89dbFUm+omoHFXCfZtcXw==",
"dependencies": {
"browserslist": "^4.21.4",
"lightningcss": "^1.16.0",
"webpack-sources": "^3.2.3"
},
"peerDependencies": {
"webpack": ">=5"
}
},
"node_modules/lightningcss-loader/node_modules/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/lightningcss-win32-x64-msvc": {
"version": "1.21.5",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.21.5.tgz",
"integrity": "sha512-A8cSi8lUpBeVmoF+DqqW7cd0FemDbCuKr490IXdjyeI+KL8adpSKUs8tcqO0OXPh1EoDqK7JNkD/dELmd4Iz5g==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",

View File

@ -29,6 +29,7 @@
"jquery.are-you-sure": "1.9.0",
"katex": "0.16.8",
"license-checker-webpack-plugin": "0.2.1",
"lightningcss-loader": "2.1.0",
"mermaid": "10.2.3",
"mini-css-extract-plugin": "2.7.6",
"minimatch": "9.0.2",

View File

@ -129,12 +129,22 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
baseRef := ""
headRef := ""
ref := t.Job.Run.Ref
sha := t.Job.Run.CommitSHA
if pullPayload, err := t.Job.Run.GetPullRequestEventPayload(); err == nil && pullPayload.PullRequest != nil && pullPayload.PullRequest.Base != nil && pullPayload.PullRequest.Head != nil {
baseRef = pullPayload.PullRequest.Base.Ref
headRef = pullPayload.PullRequest.Head.Ref
// if the TriggerEvent is pull_request_target, ref and sha need to be set according to the base of pull request
// In GitHub's documentation, ref should be the branch or tag that triggered workflow. But when the TriggerEvent is pull_request_target,
// the ref will be the base branch.
if t.Job.Run.TriggerEvent == actions_module.GithubEventPullRequestTarget {
ref = git.BranchPrefix + pullPayload.PullRequest.Base.Name
sha = pullPayload.PullRequest.Base.Sha
}
}
refName := git.RefName(t.Job.Run.Ref)
refName := git.RefName(ref)
taskContext, err := structpb.NewStruct(map[string]any{
// standard contexts, see https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
@ -153,7 +163,7 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
"graphql_url": "", // string, The URL of the GitHub GraphQL API.
"head_ref": headRef, // string, The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.
"job": fmt.Sprint(t.JobID), // string, The job_id of the current job.
"ref": t.Job.Run.Ref, // string, The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by push, this is the branch or tag ref that was pushed. For workflows triggered by pull_request, this is the pull request merge branch. For workflows triggered by release, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is refs/heads/<branch_name>, for pull requests it is refs/pull/<pr_number>/merge, and for tags it is refs/tags/<tag_name>. For example, refs/heads/feature-branch-1.
"ref": ref, // string, The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by push, this is the branch or tag ref that was pushed. For workflows triggered by pull_request, this is the pull request merge branch. For workflows triggered by release, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is refs/heads/<branch_name>, for pull requests it is refs/pull/<pr_number>/merge, and for tags it is refs/tags/<tag_name>. For example, refs/heads/feature-branch-1.
"ref_name": refName.ShortName(), // string, The short ref name of the branch or tag that triggered the workflow run. This value matches the branch or tag name shown on GitHub. For example, feature-branch-1.
"ref_protected": false, // boolean, true if branch protections are configured for the ref that triggered the workflow run.
"ref_type": refName.RefType(), // string, The type of ref that triggered the workflow run. Valid values are branch or tag.
@ -167,7 +177,7 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
"run_attempt": fmt.Sprint(t.Job.Attempt), // string, A unique number for each attempt of a particular workflow run in a repository. This number begins at 1 for the workflow run's first attempt, and increments with each re-run.
"secret_source": "Actions", // string, The source of a secret used in a workflow. Possible values are None, Actions, Dependabot, or Codespaces.
"server_url": setting.AppURL, // string, The URL of the GitHub server. For example: https://github.com.
"sha": t.Job.Run.CommitSHA, // string, The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see "Events that trigger workflows." For example, ffac537e6cbbf934b08745a378932722df287a53.
"sha": sha, // string, The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see "Events that trigger workflows." For example, ffac537e6cbbf934b08745a378932722df287a53.
"token": t.Token, // string, A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the GITHUB_TOKEN secret. For more information, see "Automatic token authentication."
"triggering_actor": "", // string, The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from github.actor. Any workflow re-runs will use the privileges of github.actor, even if the actor initiating the re-run (github.triggering_actor) has different privileges.
"workflow": t.Job.Run.WorkflowID, // string, The name of the workflow. If the workflow file doesn't specify a name, the value of this property is the full path of the workflow file in the repository.

View File

@ -219,7 +219,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
common.ServeContentByReadSeeker(ctx.Base, ctx.Repo.TreePath, lastModified, lfsDataRc)
}
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified time.Time) {
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified *time.Time) {
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
if err != nil {
if git.IsErrNotExist(err) {
@ -227,23 +227,23 @@ func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEn
} else {
ctx.Error(http.StatusInternalServerError, "GetTreeEntryByPath", err)
}
return
return nil, nil, nil
}
if entry.IsDir() || entry.IsSubModule() {
ctx.NotFound("getBlobForEntry", nil)
return
return nil, nil, nil
}
info, _, err := git.Entries([]*git.TreeEntry{entry}).GetCommitsInfo(ctx, ctx.Repo.Commit, path.Dir("/" + ctx.Repo.TreePath)[1:])
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetCommitsInfo", err)
return
return nil, nil, nil
}
if len(info) == 1 {
// Not Modified
lastModified = info[0].Commit.Committer.When
lastModified = &info[0].Commit.Committer.When
}
blob = entry.Blob()

View File

@ -195,7 +195,7 @@ func SearchIssues(ctx *context.APIContext) {
}
var issueIDs []int64
if len(keyword) > 0 && len(repoIDs) > 0 {
if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword); err != nil {
if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword, ctx.FormString("state")); err != nil {
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
return
}
@ -394,7 +394,7 @@ func ListIssues(ctx *context.APIContext) {
var issueIDs []int64
var labelIDs []int64
if len(keyword) > 0 {
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword)
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword, ctx.FormString("state"))
if err != nil {
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
return

View File

@ -298,26 +298,26 @@ func ClearIssueLabels(ctx *context.APIContext) {
ctx.Status(http.StatusNoContent)
}
func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (issue *issues_model.Issue, labels []*issues_model.Label, err error) {
issue, err = issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (*issues_model.Issue, []*issues_model.Label, error) {
issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
if err != nil {
if issues_model.IsErrIssueNotExist(err) {
ctx.NotFound()
} else {
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
}
return
return nil, nil, err
}
labels, err = issues_model.GetLabelsByIDs(form.Labels)
labels, err := issues_model.GetLabelsByIDs(form.Labels)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetLabelsByIDs", err)
return
return nil, nil, err
}
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
ctx.Status(http.StatusForbidden)
return
return nil, nil, nil
}
return issue, labels, err

View File

@ -15,7 +15,7 @@ import (
)
// ServeBlob download a git.Blob
func ServeBlob(ctx *context.Base, filePath string, blob *git.Blob, lastModified time.Time) error {
func ServeBlob(ctx *context.Base, filePath string, blob *git.Blob, lastModified *time.Time) error {
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
return nil
}
@ -38,6 +38,6 @@ func ServeContentByReader(ctx *context.Base, filePath string, size int64, reader
httplib.ServeContentByReader(ctx.Req, ctx.Resp, filePath, size, reader)
}
func ServeContentByReadSeeker(ctx *context.Base, filePath string, modTime time.Time, reader io.ReadSeeker) {
func ServeContentByReadSeeker(ctx *context.Base, filePath string, modTime *time.Time, reader io.ReadSeeker) {
httplib.ServeContentByReadSeeker(ctx.Req, ctx.Resp, filePath, modTime, reader)
}

View File

@ -497,23 +497,23 @@ func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *us
hasUser, err = user_model.GetUser(user)
if !hasUser || err != nil {
ctx.ServerError("UserLinkAccount", err)
return
return false
}
}
// TODO: probably we should respect 'remember' user's choice...
linkAccount(ctx, user, *gothUser, true)
return // user is already created here, all redirects are handled
return false // user is already created here, all redirects are handled
} else if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingLogin {
showLinkingLogin(ctx, *gothUser)
return // user will be created only after linking login
return false // user will be created only after linking login
}
}
// handle error without template
if len(tpl) == 0 {
ctx.ServerError("CreateUser", err)
return
return false
}
// handle error with template
@ -542,7 +542,7 @@ func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *us
default:
ctx.ServerError("CreateUser", err)
}
return
return false
}
log.Trace("Account created: %s", u.Name)
return true
@ -559,7 +559,7 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
u.SetLastLogin()
if err := user_model.UpdateUserCols(ctx, u, "is_admin", "is_active", "last_login_unix"); err != nil {
ctx.ServerError("UpdateUser", err)
return
return false
}
}
@ -577,7 +577,7 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
if setting.Service.RegisterManualConfirm {
ctx.Data["ManualActivationOnly"] = true
ctx.HTML(http.StatusOK, TplActivate)
return
return false
}
mailer.SendActivateAccountMail(ctx.Locale, u)
@ -592,7 +592,7 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
}
return
return false
}
return true

View File

@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/attachment"
repo_service "code.gitea.io/gitea/services/repository"
@ -148,7 +149,7 @@ func ServeAttachment(ctx *context.Context, uuid string) {
}
defer fr.Close()
common.ServeContentByReadSeeker(ctx.Base, attach.Name, attach.CreatedUnix.AsTime(), fr)
common.ServeContentByReadSeeker(ctx.Base, attach.Name, util.ToPointer(attach.CreatedUnix.AsTime()), fr)
}
// GetAttachment serve attachments

View File

@ -20,7 +20,7 @@ import (
)
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified time.Time) error {
func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified *time.Time) error {
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
return nil
}
@ -82,7 +82,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified time.Time
return common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified)
}
func getBlobForEntry(ctx *context.Context) (blob *git.Blob, lastModified time.Time) {
func getBlobForEntry(ctx *context.Context) (blob *git.Blob, lastModified *time.Time) {
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
if err != nil {
if git.IsErrNotExist(err) {
@ -90,23 +90,23 @@ func getBlobForEntry(ctx *context.Context) (blob *git.Blob, lastModified time.Ti
} else {
ctx.ServerError("GetTreeEntryByPath", err)
}
return
return nil, nil
}
if entry.IsDir() || entry.IsSubModule() {
ctx.NotFound("getBlobForEntry", nil)
return
return nil, nil
}
info, _, err := git.Entries([]*git.TreeEntry{entry}).GetCommitsInfo(ctx, ctx.Repo.Commit, path.Dir("/" + ctx.Repo.TreePath)[1:])
if err != nil {
ctx.ServerError("GetCommitsInfo", err)
return
return nil, nil
}
if len(info) == 1 {
// Not Modified
lastModified = info[0].Commit.Committer.When
lastModified = &info[0].Commit.Committer.When
}
blob = entry.Blob()
@ -148,7 +148,7 @@ func DownloadByID(ctx *context.Context) {
}
return
}
if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, time.Time{}); err != nil {
if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, nil); err != nil {
ctx.ServerError("ServeBlob", err)
}
}
@ -164,7 +164,7 @@ func DownloadByIDOrLFS(ctx *context.Context) {
}
return
}
if err = ServeBlobOrLFS(ctx, blob, time.Time{}); err != nil {
if err = ServeBlobOrLFS(ctx, blob, nil); err != nil {
ctx.ServerError("ServeBlob", err)
}
}

View File

@ -56,13 +56,13 @@ func CorsHandler() func(next http.Handler) http.Handler {
}
// httpBase implementation git smart HTTP protocol
func httpBase(ctx *context.Context) (h *serviceHandler) {
func httpBase(ctx *context.Context) *serviceHandler {
username := ctx.Params(":username")
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
if ctx.FormString("go-get") == "1" {
context.EarlyResponseForGoGetMeta(ctx)
return
return nil
}
var isPull, receivePack bool
@ -101,7 +101,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
owner := ctx.ContextUser
if !owner.IsOrganization() && !owner.IsActive {
ctx.PlainText(http.StatusForbidden, "Repository cannot be accessed. You cannot push or open issues/pull-requests.")
return
return nil
}
repoExist := true
@ -110,19 +110,19 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if repo_model.IsErrRepoNotExist(err) {
if redirectRepoID, err := repo_model.LookupRedirect(owner.ID, reponame); err == nil {
context.RedirectToRepo(ctx.Base, redirectRepoID)
return
return nil
}
repoExist = false
} else {
ctx.ServerError("GetRepositoryByName", err)
return
return nil
}
}
// Don't allow pushing if the repo is archived
if repoExist && repo.IsArchived && !isPull {
ctx.PlainText(http.StatusForbidden, "This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.")
return
return nil
}
// Only public pull don't need auth.
@ -136,7 +136,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if isPublicPull {
if err := repo.LoadOwner(ctx); err != nil {
ctx.ServerError("LoadOwner", err)
return
return nil
}
askAuth = askAuth || (repo.Owner.Visibility != structs.VisibleTypePublic)
@ -149,12 +149,12 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
// TODO: support digit auth - which would be Authorization header with digit
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
ctx.Error(http.StatusUnauthorized)
return
return nil
}
context.CheckRepoScopedToken(ctx, repo, auth_model.GetScopeLevelFromAccessMode(accessMode))
if ctx.Written() {
return
return nil
}
if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && ctx.Data["IsActionsToken"] != true {
@ -162,16 +162,16 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if err == nil {
// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
ctx.PlainText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page")
return
return nil
} else if !auth_model.IsErrTwoFactorNotEnrolled(err) {
ctx.ServerError("IsErrTwoFactorNotEnrolled", err)
return
return nil
}
}
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
ctx.PlainText(http.StatusForbidden, "Your account is disabled.")
return
return nil
}
environ = []string{
@ -193,23 +193,23 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
task, err := actions_model.GetTaskByID(ctx, taskID)
if err != nil {
ctx.ServerError("GetTaskByID", err)
return
return nil
}
if task.RepoID != repo.ID {
ctx.PlainText(http.StatusForbidden, "User permission denied")
return
return nil
}
if task.IsForkPullRequest {
if accessMode > perm.AccessModeRead {
ctx.PlainText(http.StatusForbidden, "User permission denied")
return
return nil
}
environ = append(environ, fmt.Sprintf("%s=%d", repo_module.EnvActionPerm, perm.AccessModeRead))
} else {
if accessMode > perm.AccessModeWrite {
ctx.PlainText(http.StatusForbidden, "User permission denied")
return
return nil
}
environ = append(environ, fmt.Sprintf("%s=%d", repo_module.EnvActionPerm, perm.AccessModeWrite))
}
@ -217,18 +217,18 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
p, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
if err != nil {
ctx.ServerError("GetUserRepoPermission", err)
return
return nil
}
if !p.CanAccess(accessMode, unitType) {
ctx.PlainText(http.StatusNotFound, "Repository not found")
return
return nil
}
}
if !isPull && repo.IsMirror {
ctx.PlainText(http.StatusForbidden, "mirror repository is read-only")
return
return nil
}
}
@ -246,34 +246,34 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if !repoExist {
if !receivePack {
ctx.PlainText(http.StatusNotFound, "Repository not found")
return
return nil
}
if isWiki { // you cannot send wiki operation before create the repository
ctx.PlainText(http.StatusNotFound, "Repository not found")
return
return nil
}
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for organizations.")
return
return nil
}
if !owner.IsOrganization() && !setting.Repository.EnablePushCreateUser {
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for users.")
return
return nil
}
// Return dummy payload if GET receive-pack
if ctx.Req.Method == http.MethodGet {
dummyInfoRefs(ctx)
return
return nil
}
repo, err = repo_service.PushCreateRepo(ctx, ctx.Doer, owner, reponame)
if err != nil {
log.Error("pushCreateRepo: %v", err)
ctx.Status(http.StatusNotFound)
return
return nil
}
}
@ -282,11 +282,11 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
if repo_model.IsErrUnitTypeNotExist(err) {
ctx.PlainText(http.StatusForbidden, "repository wiki is disabled")
return
return nil
}
log.Error("Failed to get the wiki unit in %-v Error: %v", repo, err)
ctx.ServerError("GetUnit(UnitTypeWiki) for "+repo.FullName(), err)
return
return nil
}
}

View File

@ -189,7 +189,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
var issueIDs []int64
if len(keyword) > 0 {
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{repo.ID}, keyword)
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{repo.ID}, keyword, ctx.FormString("state"))
if err != nil {
if issue_indexer.IsAvailable(ctx) {
ctx.ServerError("issueIndexer.Search", err)
@ -1922,9 +1922,12 @@ func ViewIssue(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplIssueView)
}
// checkBlockedByIssues return canRead and notPermitted
func checkBlockedByIssues(ctx *context.Context, blockers []*issues_model.DependencyInfo) (canRead, notPermitted []*issues_model.DependencyInfo) {
var lastRepoID int64
var lastPerm access_model.Permission
var (
lastRepoID int64
lastPerm access_model.Permission
)
for i, blocker := range blockers {
// Get the permissions for this repository
perm := lastPerm
@ -1936,7 +1939,7 @@ func checkBlockedByIssues(ctx *context.Context, blockers []*issues_model.Depende
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer)
if err != nil {
ctx.ServerError("GetUserRepoPermission", err)
return
return nil, nil
}
}
lastRepoID = blocker.Repository.ID
@ -2463,7 +2466,7 @@ func SearchIssues(ctx *context.Context) {
}
var issueIDs []int64
if len(keyword) > 0 && len(repoIDs) > 0 {
if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword); err != nil {
if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword, ctx.FormString("state")); err != nil {
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err.Error())
return
}
@ -2611,7 +2614,7 @@ func ListIssues(ctx *context.Context) {
var issueIDs []int64
var labelIDs []int64
if len(keyword) > 0 {
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword)
issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword, ctx.FormString("state"))
if err != nil {
ctx.Error(http.StatusInternalServerError, err.Error())
return

View File

@ -977,6 +977,18 @@ func renderCode(ctx *context.Context) {
return
}
if ctx.Doer != nil {
if err := ctx.Repo.Repository.GetBaseRepo(ctx); err != nil {
ctx.ServerError("GetBaseRepo", err)
return
}
ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, ctx.Repo.Repository.ID, ctx.Doer.ID)
if err != nil {
ctx.ServerError("GetRecentlyPushedBranches", err)
return
}
}
var treeNames []string
paths := make([]string, 0, 5)
if len(ctx.Repo.TreePath) > 0 {

View File

@ -12,7 +12,6 @@ import (
"net/url"
"path/filepath"
"strings"
"time"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
@ -671,7 +670,7 @@ func WikiRaw(ctx *context.Context) {
}
if entry != nil {
if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, entry.Blob(), time.Time{}); err != nil {
if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, entry.Blob(), nil); err != nil {
ctx.ServerError("ServeBlob", err)
}
return

View File

@ -725,7 +725,7 @@ func issueIDsFromSearch(ctx *context.Context, ctxUser *user_model.User, keyword
if err != nil {
return nil, fmt.Errorf("GetRepoIDsForIssuesOptions: %w", err)
}
issueIDsFromSearch, err := issue_indexer.SearchIssuesByKeyword(ctx, searchRepoIDs, keyword)
issueIDsFromSearch, err := issue_indexer.SearchIssuesByKeyword(ctx, searchRepoIDs, keyword, ctx.FormString("state"))
if err != nil {
return nil, fmt.Errorf("SearchIssuesByKeyword: %w", err)
}

View File

@ -287,9 +287,9 @@ func Action(ctx *context.Context) {
}
if err != nil {
ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.FormString("action")), err)
log.Error("Failed to apply action %q: %v", ctx.FormString("action"), err)
ctx.JSONError(fmt.Sprintf("Action %q failed", ctx.FormString("action")))
return
}
// FIXME: We should check this URL and make sure that it's a valid Gitea URL
ctx.RedirectToFirst(ctx.FormString("redirect_to"), ctx.ContextUser.HomeLink())
ctx.JSONOK()
}

View File

@ -1256,20 +1256,20 @@ func registerRoutes(m *web.Route) {
m.Group("/blob_excerpt", func() {
m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
}, func(ctx *context.Context) (cancel gocontext.CancelFunc) {
}, func(ctx *context.Context) gocontext.CancelFunc {
if ctx.FormBool("wiki") {
ctx.Data["PageIsWiki"] = true
repo.MustEnableWiki(ctx)
return
return nil
}
reqRepoCodeReader(ctx)
if ctx.Written() {
return
return nil
}
cancel = context.RepoRef()(ctx)
cancel := context.RepoRef()(ctx)
if ctx.Written() {
return
return cancel
}
repo.MustBeNotEmpty(ctx)

View File

@ -152,7 +152,6 @@ func notify(ctx context.Context, input *notifyInput) error {
} else {
for _, wf := range workflows {
if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget {
wf.Ref = ref
detectedWorkflows = append(detectedWorkflows, wf)
}
}
@ -174,7 +173,6 @@ func notify(ctx context.Context, input *notifyInput) error {
} else {
for _, wf := range baseWorkflows {
if wf.TriggerEvent == actions_module.GithubEventPullRequestTarget {
wf.Ref = baseRef
detectedWorkflows = append(detectedWorkflows, wf)
}
}
@ -212,8 +210,8 @@ func notify(ctx context.Context, input *notifyInput) error {
OwnerID: input.Repo.OwnerID,
WorkflowID: dwf.EntryName,
TriggerUserID: input.Doer.ID,
Ref: dwf.Ref,
CommitSHA: dwf.Commit.ID.String(),
Ref: ref,
CommitSHA: commit.ID.String(),
IsForkPullRequest: isForkPullRequest,
Event: input.Event,
EventPayload: string(p),

View File

@ -90,7 +90,7 @@ func IsUserHiddenCommentTypeGroupChecked(group string, hiddenCommentTypes *big.I
commentTypes, ok := hiddenCommentTypeGroups[group]
if !ok {
log.Critical("the group map for hidden comment types is out of sync, unknown group: %v", group)
return
return false
}
if hiddenCommentTypes == nil {
return false

View File

@ -779,7 +779,7 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) {
for {
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
return
return "", err
}
if wasFragment {
wasFragment = isFragment
@ -795,7 +795,7 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) {
var tail string
tail, err = input.ReadString('\n')
if err != nil {
return
return "", err
}
line += tail
}
@ -821,22 +821,21 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
_, isFragment, err = input.ReadLine()
if err != nil {
// Now by the definition of ReadLine this cannot be io.EOF
err = fmt.Errorf("unable to ReadLine: %w", err)
return
return nil, false, fmt.Errorf("unable to ReadLine: %w", err)
}
}
sb.Reset()
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
if err == io.EOF {
return
return lineBytes, isFragment, err
}
err = fmt.Errorf("unable to ReadLine: %w", err)
return
return nil, false, err
}
if lineBytes[0] == 'd' {
// End of hunks
return
return lineBytes, isFragment, err
}
switch lineBytes[0] {
@ -853,8 +852,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
// Now by the definition of ReadLine this cannot be io.EOF
err = fmt.Errorf("unable to ReadLine: %w", err)
return
return nil, false, fmt.Errorf("unable to ReadLine: %w", err)
}
_, _ = sb.Write(lineBytes)
}
@ -884,8 +882,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
}
// This is used only to indicate that the current file does not have a terminal newline
if !bytes.Equal(lineBytes, []byte("\\ No newline at end of file")) {
err = fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
return
return nil, false, fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
}
// Technically this should be the end the file!
// FIXME: we should be putting a marker at the end of the file if there is no terminal new line
@ -953,8 +950,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
curSection.Lines = append(curSection.Lines, diffLine)
default:
// This is unexpected
err = fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
return
return nil, false, fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
}
line := string(lineBytes)
@ -965,8 +961,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
// Now by the definition of ReadLine this cannot be io.EOF
err = fmt.Errorf("unable to ReadLine: %w", err)
return
return lineBytes, isFragment, fmt.Errorf("unable to ReadLine: %w", err)
}
}
}

View File

@ -46,13 +46,12 @@ func DeleteNotPassedAssignee(ctx context.Context, issue *issues_model.Issue, doe
func ToggleAssignee(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *issues_model.Comment, err error) {
removed, comment, err = issues_model.ToggleIssueAssignee(ctx, issue, doer, assigneeID)
if err != nil {
return
return false, nil, err
}
assignee, err1 := user_model.GetUserByID(ctx, assigneeID)
if err1 != nil {
err = err1
return
assignee, err := user_model.GetUserByID(ctx, assigneeID)
if err != nil {
return false, nil, err
}
notification.NotifyIssueChangeAssignee(ctx, doer, issue, assignee, removed, comment)
@ -236,23 +235,23 @@ func TeamReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *use
}
if err != nil {
return
return nil, err
}
if comment == nil || !isAdd {
return
return nil, nil
}
// notify all user in this team
if err = comment.LoadIssue(ctx); err != nil {
return
if err := comment.LoadIssue(ctx); err != nil {
return nil, err
}
members, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{
TeamID: reviewer.ID,
})
if err != nil {
return
return nil, err
}
for _, member := range members {

View File

@ -49,17 +49,17 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_mo
}
// ChangeTitle changes the title of this issue, as the given user.
func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, title string) (err error) {
func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, title string) error {
oldTitle := issue.Title
issue.Title = title
if err = issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil {
return
if err := issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil {
return err
}
if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) {
if err = issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil {
return
if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil {
return err
}
}

View File

@ -12,9 +12,9 @@ import (
)
// ClearLabels clears all of an issue's labels
func ClearLabels(issue *issues_model.Issue, doer *user_model.User) (err error) {
if err = issues_model.ClearIssueLabels(issue, doer); err != nil {
return
func ClearLabels(issue *issues_model.Issue, doer *user_model.User) error {
if err := issues_model.ClearIssueLabels(issue, doer); err != nil {
return err
}
notification.NotifyIssueClearLabels(db.DefaultContext, doer, issue)

View File

@ -320,7 +320,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos
func DismissReview(ctx context.Context, reviewID, repoID int64, message string, doer *user_model.User, isDismiss, dismissPriors bool) (comment *issues_model.Comment, err error) {
review, err := issues_model.GetReviewByID(ctx, reviewID)
if err != nil {
return
return nil, err
}
if review.Type != issues_model.ReviewTypeApprove && review.Type != issues_model.ReviewTypeReject {
@ -328,7 +328,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
}
// load data for notify
if err = review.LoadAttributes(ctx); err != nil {
if err := review.LoadAttributes(ctx); err != nil {
return nil, err
}
@ -337,8 +337,8 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
return nil, fmt.Errorf("reviews's repository is not the same as the one we expect")
}
if err = issues_model.DismissReview(review, isDismiss); err != nil {
return
if err := issues_model.DismissReview(review, isDismiss); err != nil {
return nil, err
}
if dismissPriors {
@ -361,11 +361,11 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
return nil, nil
}
if err = review.Issue.LoadPullRequest(ctx); err != nil {
return
if err := review.Issue.LoadPullRequest(ctx); err != nil {
return nil, err
}
if err = review.Issue.LoadAttributes(ctx); err != nil {
return
if err := review.Issue.LoadAttributes(ctx); err != nil {
return nil, err
}
comment, err = issue_service.CreateComment(ctx, &issues_model.CreateCommentOptions{
@ -377,7 +377,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
Repo: review.Issue.Repo,
})
if err != nil {
return
return nil, err
}
comment.Review = review
@ -386,5 +386,5 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
notification.NotifyPullReviewDismiss(ctx, doer, review, comment)
return comment, err
return comment, nil
}

View File

@ -187,7 +187,7 @@ func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.R
// editAttachments accept a map of attachment uuid to new attachment name which will be updated with attachments.
func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_model.Release,
addAttachmentUUIDs, delAttachmentUUIDs []string, editAttachments map[string]string,
) (err error) {
) error {
if rel.ID == 0 {
return errors.New("UpdateRelease only accepts an exist release")
}
@ -264,8 +264,8 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod
}
}
if err = committer.Commit(); err != nil {
return
if err := committer.Commit(); err != nil {
return err
}
for _, uuid := range delAttachmentUUIDs {
@ -280,14 +280,14 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod
if !isCreated {
notification.NotifyUpdateRelease(gitRepo.Ctx, doer, rel)
return
return nil
}
if !rel.IsDraft {
notification.NotifyNewRelease(gitRepo.Ctx, rel)
}
return err
return nil
}
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.

View File

@ -20,16 +20,13 @@
</div>
</div>
<div class="right menu">
<form method="post" action="{{.Link}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}&redirect_to={{$.Link}}">
{{$.CsrfTokenHtml}}
<button type="submit" class="ui basic button gt-mr-0">
{{if $.IsFollowing}}
{{.locale.Tr "user.unfollow"}}
{{else}}
{{.locale.Tr "user.follow"}}
{{end}}
</button>
</form>
<button class="link-action ui basic button gt-mr-0" data-url="{{.Org.HomeLink}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}">
{{if $.IsFollowing}}
{{.locale.Tr "user.unfollow"}}
{{else}}
{{.locale.Tr "user.follow"}}
{{end}}
</button>
</div>
</div>

View File

@ -1,5 +1,5 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository packages">
<div role="main" aria-label="{{.Title}}" class="page-content repository projects view-project">
{{template "shared/user/org_profile_avatar" .}}
<div class="ui container">
{{template "user/overview/header" .}}

View File

@ -18,7 +18,7 @@
</div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.alpine.documentation" "https://docs.gitea.io/en-us/packages/alpine/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Alpine" "https://docs.gitea.io/en-us/usage/packages/alpine/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -18,7 +18,7 @@ git-fetch-with-cli = true</code></pre></div>
<div class="markup"><pre class="code-block"><code>cargo add {{.PackageDescriptor.Package.Name}}@{{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.cargo.documentation" "https://docs.gitea.io/en-us/usage/packages/cargo/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Cargo" "https://docs.gitea.io/en-us/usage/packages/cargo/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<div class="markup"><pre class="code-block"><code>knife supermarket install {{.PackageDescriptor.Package.Name}} {{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.chef.documentation" "https://docs.gitea.io/en-us/usage/packages/chef/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Chef" "https://docs.gitea.io/en-us/usage/packages/chef/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -17,7 +17,7 @@
<div class="markup"><pre class="code-block"><code>composer require {{.PackageDescriptor.Package.Name}}:{{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.composer.documentation" "https://docs.gitea.io/en-us/usage/packages/composer/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Composer" "https://docs.gitea.io/en-us/usage/packages/composer/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<div class="markup"><pre class="code-block"><code>conan install --remote=gitea {{.PackageDescriptor.Package.Name}}/{{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.conan.documentation" "https://docs.gitea.io/en-us/usage/packages/conan/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Conan" "https://docs.gitea.io/en-us/usage/packages/conan/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -16,7 +16,7 @@ default_channels:
<div class="markup"><pre class="code-block"><code>conda install{{if $channel}} -c {{$channel}}{{end}} {{.PackageDescriptor.PackageProperties.GetByName "conda.name"}}={{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.conda.documentation" "https://docs.gitea.io/en-us/usage/packages/conda/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Conda" "https://docs.gitea.io/en-us/usage/packages/conda/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -19,7 +19,7 @@
<div class="markup"><pre class="code-block"><code>{{range .PackageDescriptor.Files}}{{if eq .File.LowerName "manifest.json"}}{{.Properties.GetByName "container.digest"}}{{end}}{{end}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.container.documentation" "https://docs.gitea.io/en-us/usage/packages/container/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Container" "https://docs.gitea.io/en-us/usage/packages/container/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<div class="markup"><pre class="code-block"><code>install.packages("{{.PackageDescriptor.Package.Name}}")</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.cran.documentation" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "CRAN" "https://docs.gitea.io/en-us/usage/packages/container/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -16,7 +16,7 @@ sudo apt update</code></pre></div>
</div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.debian.documentation" "https://docs.gitea.io/en-us/packages/debian/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Debian" "https://docs.gitea.io/en-us/usage/packages/debian/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@ curl <gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{$.PackageDescripto
</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.generic.documentation" "https://docs.gitea.io/en-us/usage/packages/generic" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Generic" "https://docs.gitea.io/en-us/usage/packages/generic" | Safe}}</label>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<div class="markup"><pre class="code-block"><code>GOPROXY=<gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{$.PackageDescriptor.Owner.Name}}/go"></gitea-origin-url> go install {{$.PackageDescriptor.Package.Name}}@{{$.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.go.documentation" "https://docs.gitea.io/en-us/usage/packages/go" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Go" "https://docs.gitea.io/en-us/usage/packages/go" | Safe}}</label>
</div>
</div>
</div>

View File

@ -12,7 +12,7 @@ helm repo update</code></pre></div>
<div class="markup"><pre class="code-block"><code>helm install {{.PackageDescriptor.Package.Name}} {{AppDomain}}/{{.PackageDescriptor.Package.Name}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.helm.documentation" "https://docs.gitea.io/en-us/usage/packages/helm/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Helm" "https://docs.gitea.io/en-us/usage/packages/helm/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -40,7 +40,7 @@
<div class="markup"><pre class="code-block"><code>mvn dependency:get -DremoteRepositories=<gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/maven"></gitea-origin-url> -Dartifact={{.PackageDescriptor.Metadata.GroupID}}:{{.PackageDescriptor.Metadata.ArtifactID}}:{{.PackageDescriptor.Version.Version}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.maven.documentation" "https://docs.gitea.io/en-us/usage/packages/maven/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Maven" "https://docs.gitea.io/en-us/usage/packages/maven/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -15,7 +15,7 @@
<div class="markup"><pre class="code-block"><code>&quot;{{.PackageDescriptor.Package.Name}}&quot;: &quot;{{.PackageDescriptor.Version.Version}}&quot;</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.npm.documentation" "https://docs.gitea.io/en-us/usage/packages/npm/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "npm" "https://docs.gitea.io/en-us/usage/packages/npm/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<div class="markup"><pre class="code-block"><code>dotnet add package --source {{.PackageDescriptor.Owner.Name}} --version {{.PackageDescriptor.Version.Version}} {{.PackageDescriptor.Package.Name}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.nuget.documentation" "https://docs.gitea.io/en-us/usage/packages/nuget/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "NuGet" "https://docs.gitea.io/en-us/usage/packages/nuget/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<div class="markup"><pre class="code-block"><code>dart pub add {{.PackageDescriptor.Package.Name}}:{{.PackageDescriptor.Version.Version}} --hosted-url=<gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pub/"></gitea-origin-url></code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.pub.documentation" "https://docs.gitea.io/en-us/usage/packages/pub/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Pub" "https://docs.gitea.io/en-us/usage/packages/pub/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<div class="markup"><pre class="code-block"><code>pip install --index-url <gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pypi/simple/"></gitea-origin-url> {{.PackageDescriptor.Package.Name}}</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.pypi.documentation" "https://docs.gitea.io/en-us/usage/packages/pypi/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "PyPI" "https://docs.gitea.io/en-us/usage/packages/pypi/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -13,7 +13,7 @@
</div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.rpm.documentation" "https://docs.gitea.io/en-us/usage/packages/rpm/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "RPM" "https://docs.gitea.io/en-us/usage/packages/rpm/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -13,7 +13,7 @@
end</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.rubygems.documentation" "https://docs.gitea.io/en-us/usage/packages/rubygems/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "RubyGems" "https://docs.gitea.io/en-us/usage/packages/rubygems/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -17,7 +17,7 @@
<div class="markup"><pre class="code-block"><code>swift package resolve</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.swift.documentation" "https://docs.gitea.io/en-us/usage/packages/swift/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Swift" "https://docs.gitea.io/en-us/usage/packages/swift/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<div class="markup"><pre class="code-block"><code>vagrant box add --box-version {{.PackageDescriptor.Version.Version}} "<gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/vagrant/{{.PackageDescriptor.Package.Name}}"></gitea-origin-url>"</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.vagrant.documentation" "https://docs.gitea.io/en-us/usage/packages/vagrant/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Vagrant" "https://docs.gitea.io/en-us/usage/packages/vagrant/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -18,7 +18,7 @@
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.cargo.rebuild"}}</button>
</form>
<div class="field">
<label>{{.locale.Tr "packages.cargo.documentation" "https://docs.gitea.io/en-us/usage/packages/cargo/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Cargo" "https://docs.gitea.io/en-us/usage/packages/cargo/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -1,53 +1,53 @@
{{template "base/alert" .}}
<form class="ui form ignore-dirty">
<div class="ui fluid action input">
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
<select class="ui dropdown" name="type">
<option value="">{{.locale.Tr "packages.filter.type"}}</option>
<option value="all">{{.locale.Tr "packages.filter.type.all"}}</option>
{{range $type := .AvailableTypes}}
<option{{if eq $.PackageType $type}} selected="selected"{{end}} value="{{$type}}">{{$type.Name}}</option>
{{end}}
</select>
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
<div class="ui {{if .PackageDescriptors}}issue list{{end}}">
{{range .PackageDescriptors}}
<li class="item gt-df gt-py-3">
<div class="issue-item-main">
<div class="issue-item-top-row">
<a class="title" href="{{.FullWebLink}}">{{.Package.Name}}</a>
<span class="ui label">{{svg .Package.Type.SVGName 16}} {{.Package.Type.Name}}</span>
</div>
<div class="desc issue-item-bottom-row">
{{$timeStr := TimeSinceUnix .Version.CreatedUnix $.locale}}
{{$hasRepositoryAccess := false}}
{{if .Repository}}
{{$hasRepositoryAccess = index $.RepositoryAccessMap .Repository.ID}}
{{end}}
{{if $hasRepositoryAccess}}
{{$.locale.Tr "packages.published_by_in" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) .Repository.Link (.Repository.FullName | Escape) | Safe}}
{{else}}
{{$.locale.Tr "packages.published_by" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
{{end}}
</div>
</div>
</li>
{{else}}
{{if not .HasPackages}}
<div class="gt-pt-5 empty center">
{{svg "octicon-package" 48}}
<h2>{{.locale.Tr "packages.empty"}}</h2>
{{if and .Repository .CanWritePackages}}
{{$packagesUrl := URLJoin .Owner.HomeLink "-" "packages"}}
<p>{{.locale.Tr "packages.empty.repo" $packagesUrl | Safe}}</p>
{{end}}
<p>{{.locale.Tr "packages.empty.documentation" "https://docs.gitea.io/en-us/usage/packages/overview/" | Safe}}</p>
</div>
{{else}}
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
{{template "base/alert" .}}
<form class="ui form ignore-dirty">
<div class="ui fluid action input">
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
<select class="ui dropdown" name="type">
<option value="">{{.locale.Tr "packages.filter.type"}}</option>
<option value="all">{{.locale.Tr "packages.filter.type.all"}}</option>
{{range $type := .AvailableTypes}}
<option{{if eq $.PackageType $type}} selected="selected"{{end}} value="{{$type}}">{{$type.Name}}</option>
{{end}}
{{end}}
{{template "base/paginate" .}}
</select>
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
<div class="ui {{if .PackageDescriptors}}issue list{{end}}">
{{range .PackageDescriptors}}
<li class="item gt-df gt-py-3">
<div class="issue-item-main">
<div class="issue-item-top-row">
<a class="title" href="{{.FullWebLink}}">{{.Package.Name}}</a>
<span class="ui label">{{svg .Package.Type.SVGName 16}} {{.Package.Type.Name}}</span>
</div>
<div class="desc issue-item-bottom-row">
{{$timeStr := TimeSinceUnix .Version.CreatedUnix $.locale}}
{{$hasRepositoryAccess := false}}
{{if .Repository}}
{{$hasRepositoryAccess = index $.RepositoryAccessMap .Repository.ID}}
{{end}}
{{if $hasRepositoryAccess}}
{{$.locale.Tr "packages.published_by_in" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) .Repository.Link (.Repository.FullName | Escape) | Safe}}
{{else}}
{{$.locale.Tr "packages.published_by" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
{{end}}
</div>
</div>
</li>
{{else}}
{{if not .HasPackages}}
<div class="gt-pt-5 empty center">
{{svg "octicon-package" 48}}
<h2>{{.locale.Tr "packages.empty"}}</h2>
{{if and .Repository .CanWritePackages}}
{{$packagesUrl := URLJoin .Owner.HomeLink "-" "packages"}}
<p>{{.locale.Tr "packages.empty.repo" $packagesUrl | Safe}}</p>
{{end}}
<p>{{.locale.Tr "packages.empty.documentation" "https://docs.gitea.io/en-us/usage/packages/overview/" | Safe}}</p>
</div>
{{else}}
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
{{end}}
{{end}}
{{template "base/paginate" .}}
</div>

View File

@ -1,37 +1,37 @@
<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{.locale.Tr "packages.versions"}}</strong></p>
<form class="ui form ignore-dirty">
<div class="ui fluid action input">
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
<select class="ui dropdown" name="sort">
<option value="version_asc"{{if eq .Sort "version_asc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.asc"}}</option>
<option value="version_desc"{{if eq .Sort "version_desc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.desc"}}</option>
<option value="created_asc"{{if eq .Sort "created_asc"}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.oldest"}}</option>
<option value="created_desc"{{if or (eq .Sort "") (eq .Sort "created_desc")}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.latest"}}</option>
</select>
{{if eq .PackageDescriptor.Package.Type "container"}}
<select class="ui dropdown" name="tagged">
{{$isTagged := or (eq .Tagged "") (eq .Tagged "tagged")}}
<option value="tagged"{{if $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.tagged"}}</option>
<option value="untagged"{{if not $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.untagged"}}</option>
</select>
{{end}}
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
<div class="ui {{if .PackageDescriptors}}issue list{{end}}">
{{range .PackageDescriptors}}
<li class="item gt-df gt-py-3">
<div class="issue-item-main">
<div class="issue-item-top-row">
<a class="title" href="{{.FullWebLink}}">{{.Version.LowerVersion}}</a>
</div>
<div class="desc issue-item-bottom-row">
{{$.locale.Tr "packages.published_by" (TimeSinceUnix .Version.CreatedUnix $.locale) .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
</div>
</div>
</li>
{{else}}
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{.locale.Tr "packages.versions"}}</strong></p>
<form class="ui form ignore-dirty">
<div class="ui fluid action input">
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
<select class="ui dropdown" name="sort">
<option value="version_asc"{{if eq .Sort "version_asc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.asc"}}</option>
<option value="version_desc"{{if eq .Sort "version_desc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.desc"}}</option>
<option value="created_asc"{{if eq .Sort "created_asc"}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.oldest"}}</option>
<option value="created_desc"{{if or (eq .Sort "") (eq .Sort "created_desc")}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.latest"}}</option>
</select>
{{if eq .PackageDescriptor.Package.Type "container"}}
<select class="ui dropdown" name="tagged">
{{$isTagged := or (eq .Tagged "") (eq .Tagged "tagged")}}
<option value="tagged"{{if $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.tagged"}}</option>
<option value="untagged"{{if not $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.untagged"}}</option>
</select>
{{end}}
{{template "base/paginate" .}}
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
</div>
</form>
<div class="ui {{if .PackageDescriptors}}issue list{{end}}">
{{range .PackageDescriptors}}
<li class="item gt-df gt-py-3">
<div class="issue-item-main">
<div class="issue-item-top-row">
<a class="title" href="{{.FullWebLink}}">{{.Version.LowerVersion}}</a>
</div>
<div class="desc issue-item-bottom-row">
{{$.locale.Tr "packages.published_by" (TimeSinceUnix .Version.CreatedUnix $.locale) .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
</div>
</div>
</li>
{{else}}
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
{{end}}
{{template "base/paginate" .}}
</div>

View File

@ -1,76 +1,76 @@
{{if .CanWriteProjects}}
<div class="gt-tr">
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
</div>
<div class="divider"></div>
{{end}}
{{if .CanWriteProjects}}
<div class="gt-tr">
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
</div>
<div class="divider"></div>
{{end}}
{{template "base/alert" .}}
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
{{svg "octicon-check" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
{{template "base/alert" .}}
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
{{svg "octicon-check" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
</div>
<div class="ui right floated secondary filter menu">
<!-- Sort -->
<div class="ui dropdown type jump item">
<span class="text">
{{.locale.Tr "repo.issues.filter_sort"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="menu">
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=oldest&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=recentupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=leastupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div>
<div class="ui right floated secondary filter menu">
<!-- Sort -->
<div class="ui dropdown type jump item">
<span class="text">
{{.locale.Tr "repo.issues.filter_sort"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="menu">
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=oldest&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=recentupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=leastupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div>
</div>
<div class="milestone-list">
{{range .Projects}}
<li class="milestone-card">
<h3 class="flex-text-block gt-m-0">
{{svg .IconName 16}}
<a class="muted" href="{{.Link}}">{{.Title}}</a>
</h3>
<div class="milestone-toolbar">
<div class="group">
<div class="flex-text-block">
{{svg "octicon-issue-opened" 14}}
{{$.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
</div>
<div class="flex-text-block">
{{svg "octicon-check" 14}}
{{$.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
</div>
</div>
</div>
</div>
<div class="milestone-list">
{{range .Projects}}
<li class="milestone-card">
<h3 class="flex-text-block gt-m-0">
{{svg .IconName 16}}
<a class="muted" href="{{.Link}}">{{.Title}}</a>
</h3>
<div class="milestone-toolbar">
<div class="group">
<div class="flex-text-block">
{{svg "octicon-issue-opened" 14}}
{{$.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
</div>
<div class="flex-text-block">
{{svg "octicon-check" 14}}
{{$.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
</div>
</div>
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
<div class="group">
<a class="flex-text-inline" href="{{.Link}}/edit">{{svg "octicon-pencil" 14}}{{$.locale.Tr "repo.issues.label_edit"}}</a>
{{if .IsClosed}}
<a class="link-action flex-text-inline" href data-url="{{.Link}}/open">{{svg "octicon-check" 14}}{{$.locale.Tr "repo.projects.open"}}</a>
{{else}}
<a class="link-action flex-text-inline" href data-url="{{.Link}}/close">{{svg "octicon-skip" 14}}{{$.locale.Tr "repo.projects.close"}}</a>
{{end}}
<a class="delete-button flex-text-inline" href="#" data-url="{{.Link}}/delete">{{svg "octicon-trash" 14}}{{$.locale.Tr "repo.issues.label_delete"}}</a>
</div>
{{end}}
</div>
{{if .Description}}
<div class="content">
{{.RenderedContent|Str2html}}
</div>
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
<div class="group">
<a class="flex-text-inline" href="{{.Link}}/edit">{{svg "octicon-pencil" 14}}{{$.locale.Tr "repo.issues.label_edit"}}</a>
{{if .IsClosed}}
<a class="link-action flex-text-inline" href data-url="{{.Link}}/open">{{svg "octicon-check" 14}}{{$.locale.Tr "repo.projects.open"}}</a>
{{else}}
<a class="link-action flex-text-inline" href data-url="{{.Link}}/close">{{svg "octicon-skip" 14}}{{$.locale.Tr "repo.projects.close"}}</a>
{{end}}
</li>
<a class="delete-button flex-text-inline" href="#" data-url="{{.Link}}/delete">{{svg "octicon-trash" 14}}{{$.locale.Tr "repo.issues.label_delete"}}</a>
</div>
{{end}}
</div>
{{if .Description}}
<div class="content">
{{.RenderedContent|Str2html}}
</div>
{{end}}
</li>
{{end}}
{{template "base/paginate" .}}
</div>
{{template "base/paginate" .}}
</div>
{{if $.CanWriteProjects}}
<div class="ui g-modal-confirm delete modal">

View File

@ -1,66 +1,66 @@
<h2 class="ui dividing header">
{{if .PageIsEditProjects}}
<h2 class="ui dividing header">
{{if .PageIsEditProjects}}
{{.locale.Tr "repo.projects.edit"}}
<div class="sub header">{{.locale.Tr "repo.projects.edit_subheader"}}</div>
{{else}}
{{.locale.Tr "repo.projects.new"}}
<div class="sub header">{{.locale.Tr "repo.projects.new_subheader"}}</div>
{{end}}
</h2>
{{template "base/alert" .}}
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
</div>
<div class="field">
<label>{{.locale.Tr "repo.projects.description"}}</label>
<textarea name="content" placeholder="{{.locale.Tr "repo.projects.description_placeholder"}}">{{.content}}</textarea>
</div>
{{else}}
{{.locale.Tr "repo.projects.new"}}
<div class="sub header">{{.locale.Tr "repo.projects.new_subheader"}}</div>
{{end}}
</h2>
{{template "base/alert" .}}
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
</div>
<div class="field">
<label>{{.locale.Tr "repo.projects.description"}}</label>
<textarea name="content" placeholder="{{.locale.Tr "repo.projects.description_placeholder"}}">{{.content}}</textarea>
</div>
{{if not .PageIsEditProjects}}
<div class="field">
<label>{{.locale.Tr "repo.projects.template.desc"}}</label>
<div class="ui selection dropdown">
<input type="hidden" name="board_type" value="{{.type}}">
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
<div class="menu">
{{range $element := .BoardTypes}}
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}}
</div>
{{if not .PageIsEditProjects}}
<div class="field">
<label>{{.locale.Tr "repo.projects.template.desc"}}</label>
<div class="ui selection dropdown">
<input type="hidden" name="board_type" value="{{.type}}">
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
<div class="menu">
{{range $element := .BoardTypes}}
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}}
</div>
</div>
{{end}}
</div>
{{end}}
<div class="field">
<label>{{.locale.Tr "repo.projects.card_type.desc"}}</label>
<div class="ui selection dropdown">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{range $element := .CardTypes}}
{{if or (eq $.card_type $element.CardType) (and (not $.PageIsEditProjects) (eq $element.CardType 1))}}
<input type="hidden" name="card_type" value="{{$element.CardType}}">
<div class="default text">{{$.locale.Tr $element.Translation}}</div>
{{end}}
<div class="field">
<label>{{.locale.Tr "repo.projects.card_type.desc"}}</label>
<div class="ui selection dropdown">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{range $element := .CardTypes}}
{{if or (eq $.card_type $element.CardType) (and (not $.PageIsEditProjects) (eq $element.CardType 1))}}
<input type="hidden" name="card_type" value="{{$element.CardType}}">
<div class="default text">{{$.locale.Tr $element.Translation}}</div>
{{end}}
{{end}}
<div class="menu">
{{range $element := .CardTypes}}
<div class="item" data-id="{{$element.CardType}}" data-value="{{$element.CardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}}
<div class="menu">
{{range $element := .CardTypes}}
<div class="item" data-id="{{$element.CardType}}" data-value="{{$element.CardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}}
</div>
</div>
</div>
</div>
<div class="divider"></div>
<div class="ui left">
<a class="ui cancel button" href="{{$.CancelLink}}">
{{.locale.Tr "repo.milestones.cancel"}}
</a>
<button class="ui primary button">
{{if .PageIsEditProjects}}{{.locale.Tr "repo.projects.modify"}}{{else}}{{.locale.Tr "repo.projects.create"}}{{end}}
</button>
</div>
</form>
</div>
<div class="divider"></div>
<div class="ui left">
<a class="ui cancel button" href="{{$.CancelLink}}">
{{.locale.Tr "repo.milestones.cancel"}}
</a>
<button class="ui primary button">
{{if .PageIsEditProjects}}{{.locale.Tr "repo.projects.modify"}}{{else}}{{.locale.Tr "repo.projects.create"}}{{end}}
</button>
</div>
</form>

View File

@ -1,256 +1,251 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository projects view-project">
<div class="ui container">
<div class="ui two column stackable grid">
<div class="column">
</div>
<div class="column right aligned">
{{if .CanWriteProjects}}
<a class="ui small green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
{{end}}
<div class="ui small modal new-board-modal" id="new-board-item">
<div class="header">
{{$.locale.Tr "repo.projects.column.new"}}
</div>
<div class="content">
<form class="ui form">
<div class="required field">
<label for="new_board">{{$.locale.Tr "repo.projects.column.new_title"}}</label>
<input class="new-board" id="new_board" name="title" required>
</div>
<div class="field color-field">
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
<div class="color picker column">
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_board_color_picker" name="color">
<div class="column precolors">
{{template "repo/issue/label_precolors"}}
</div>
</div>
</div>
<div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button>
<button data-url="{{$.Link}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<div class="ui two column stackable grid">
<div class="column">
<h2 class="project-title">{{$.Project.Title}}</h2>
<div class="content project-description">{{$.Project.RenderedContent|Str2html}}</div>
</div>
{{if $.CanWriteProjects}}
<div class="column right aligned">
<div class="ui compact right mini menu">
<a class="item" href="{{$.Link}}/edit?redirect=project">
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>
{{if .Project.IsClosed}}
<a class="item link-action" href data-url="{{$.Link}}/open">
{{svg "octicon-check"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.projects.open"}}</span>
</a>
{{else}}
<a class="item link-action" href data-url="{{$.Link}}/close">
{{svg "octicon-skip"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.projects.close"}}</span>
</a>
{{end}}
<a class="item delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.Project.ID}}">
{{svg "octicon-trash"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_delete"}}</span>
</a>
</div>
</div>
{{end}}
</div>
<div class="divider"></div>
<div class="ui two column stackable grid">
<div class="column">
</div>
<div class="ui container fluid padded" id="project-board">
<div class="board {{if .CanWriteProjects}}sortable{{end}}">
{{range $board := .Boards}}
<div class="ui segment board-column" style="background: {{.Color}} !important;" data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}">
<div class="board-column-header gt-df gt-ac gt-sb">
<div class="ui large label board-label gt-py-2">
<div class="ui small circular grey label board-card-cnt">
{{.NumIssues}}
</div>
{{.Title}}
<div class="column right aligned">
{{if .CanWriteProjects}}
<a class="ui small green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
{{end}}
<div class="ui small modal new-board-modal" id="new-board-item">
<div class="header">
{{$.locale.Tr "repo.projects.column.new"}}
</div>
<div class="content">
<form class="ui form">
<div class="required field">
<label for="new_board">{{$.locale.Tr "repo.projects.column.new_title"}}</label>
<input class="new-board" id="new_board" name="title" required>
</div>
{{if and $.CanWriteProjects (ne .ID 0)}}
<div class="ui dropdown jump item">
<div class="not-mobile gt-px-3" tabindex="-1">
{{svg "octicon-kebab-horizontal"}}
<div class="field color-field">
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
<div class="color picker column">
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_board_color_picker" name="color">
<div class="column precolors">
{{template "repo/issue/label_precolors"}}
</div>
<div class="menu user-menu" tabindex="-1">
<a class="item show-modal button" data-modal="#edit-project-board-modal-{{.ID}}">
{{svg "octicon-pencil"}}
</div>
</div>
<div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button>
<button data-url="{{$.Link}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<div class="ui two column stackable grid">
<div class="column">
<h2 class="project-title">{{$.Project.Title}}</h2>
<div class="content project-description">{{$.Project.RenderedContent|Str2html}}</div>
</div>
{{if $.CanWriteProjects}}
<div class="column right aligned">
<div class="ui compact right mini menu">
<a class="item" href="{{$.Link}}/edit?redirect=project">
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>
{{if .Project.IsClosed}}
<a class="item link-action" href data-url="{{$.Link}}/open">
{{svg "octicon-check"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.projects.open"}}</span>
</a>
{{else}}
<a class="item link-action" href data-url="{{$.Link}}/close">
{{svg "octicon-skip"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.projects.close"}}</span>
</a>
{{end}}
<a class="item delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.Project.ID}}">
{{svg "octicon-trash"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_delete"}}</span>
</a>
</div>
</div>
{{end}}
</div>
<div class="divider"></div>
<div id="project-board">
<div class="board {{if .CanWriteProjects}}sortable{{end}}">
{{range $board := .Boards}}
<div class="ui segment board-column" style="background: {{.Color}} !important;" data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}">
<div class="board-column-header gt-df gt-ac gt-sb">
<div class="ui large label board-label gt-py-2">
<div class="ui small circular grey label board-card-cnt">
{{.NumIssues}}
</div>
{{.Title}}
</div>
{{if and $.CanWriteProjects (ne .ID 0)}}
<div class="ui dropdown jump item">
<div class="not-mobile gt-px-3" tabindex="-1">
{{svg "octicon-kebab-horizontal"}}
</div>
<div class="menu user-menu" tabindex="-1">
<a class="item show-modal button" data-modal="#edit-project-board-modal-{{.ID}}">
{{svg "octicon-pencil"}}
{{$.locale.Tr "repo.projects.column.edit"}}
</a>
{{if not .Default}}
<a class="item show-modal button default-project-board-show"
data-modal="#default-project-board-modal-{{.ID}}"
data-modal-default-project-board-header="{{$.locale.Tr "repo.projects.column.set_default"}}"
data-modal-default-project-board-content="{{$.locale.Tr "repo.projects.column.set_default_desc"}}"
data-url="{{$.Link}}/{{.ID}}/default">
{{svg "octicon-pin"}}
{{$.locale.Tr "repo.projects.column.set_default"}}
</a>
{{else}}
<a class="item show-modal button default-project-board-show"
data-modal="#default-project-board-modal-{{.ID}}"
data-modal-default-project-board-header="{{$.locale.Tr "repo.projects.column.unset_default"}}"
data-modal-default-project-board-content="{{$.locale.Tr "repo.projects.column.unset_default_desc"}}"
data-url="{{$.Link}}/{{.ID}}/unsetdefault">
{{svg "octicon-pin-slash"}}
{{$.locale.Tr "repo.projects.column.unset_default"}}
</a>
{{end}}
<a class="item show-modal button show-delete-column-modal"
data-modal="#delete-board-modal-{{.ID}}"
data-url="{{$.Link}}/{{.ID}}"
>
{{svg "octicon-trash"}}
{{$.locale.Tr "repo.projects.column.delete"}}
</a>
<div class="ui small modal edit-project-board" id="edit-project-board-modal-{{.ID}}">
<div class="header">
{{$.locale.Tr "repo.projects.column.edit"}}
</a>
{{if not .Default}}
<a class="item show-modal button default-project-board-show"
data-modal="#default-project-board-modal-{{.ID}}"
data-modal-default-project-board-header="{{$.locale.Tr "repo.projects.column.set_default"}}"
data-modal-default-project-board-content="{{$.locale.Tr "repo.projects.column.set_default_desc"}}"
data-url="{{$.Link}}/{{.ID}}/default">
{{svg "octicon-pin"}}
{{$.locale.Tr "repo.projects.column.set_default"}}
</a>
{{else}}
<a class="item show-modal button default-project-board-show"
data-modal="#default-project-board-modal-{{.ID}}"
data-modal-default-project-board-header="{{$.locale.Tr "repo.projects.column.unset_default"}}"
data-modal-default-project-board-content="{{$.locale.Tr "repo.projects.column.unset_default_desc"}}"
data-url="{{$.Link}}/{{.ID}}/unsetdefault">
{{svg "octicon-pin-slash"}}
{{$.locale.Tr "repo.projects.column.unset_default"}}
</a>
{{end}}
<a class="item show-modal button show-delete-column-modal"
data-modal="#delete-board-modal-{{.ID}}"
data-url="{{$.Link}}/{{.ID}}"
>
{{svg "octicon-trash"}}
{{$.locale.Tr "repo.projects.column.delete"}}
</a>
</div>
<div class="content">
<form class="ui form">
<div class="required field">
<label for="new_board_title">{{$.locale.Tr "repo.projects.column.edit_title"}}</label>
<input class="project-board-title" id="new_board_title" name="title" value="{{.Title}}" required>
</div>
<div class="ui small modal edit-project-board" id="edit-project-board-modal-{{.ID}}">
<div class="header">
{{$.locale.Tr "repo.projects.column.edit"}}
</div>
<div class="content">
<form class="ui form">
<div class="required field">
<label for="new_board_title">{{$.locale.Tr "repo.projects.column.edit_title"}}</label>
<input class="project-board-title" id="new_board_title" name="title" value="{{.Title}}" required>
</div>
<div class="field color-field">
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
<div class="color picker column">
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_board_color" name="color" value="{{.Color}}">
<div class="column precolors">
{{template "repo/issue/label_precolors"}}
</div>
<div class="field color-field">
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
<div class="color picker column">
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_board_color" name="color" value="{{.Color}}">
<div class="column precolors">
{{template "repo/issue/label_precolors"}}
</div>
</div>
</div>
<div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button>
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
</div>
</form>
</div>
</div>
<div class="ui g-modal-confirm modal default-project-board-modal" id="default-project-board-modal-{{.ID}}">
<div class="header">
<span id="default-project-board-header"></span>
</div>
<div class="content">
<label id="default-project-board-content"></label>
</div>
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
</div>
<div class="ui g-modal-confirm modal" id="delete-board-modal-{{.ID}}">
<div class="header">
{{$.locale.Tr "repo.projects.column.delete"}}
</div>
<div class="content">
<label>
{{$.locale.Tr "repo.projects.column.deletion_desc"}}
</label>
</div>
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
<div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button>
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
</div>
</form>
</div>
</div>
</div>
{{end}}
</div>
<div class="divider"></div>
<div class="ui cards board" data-url="{{$.Link}}/{{.ID}}" data-project="{{$.Project.ID}}" data-board="{{.ID}}" id="board_{{.ID}}">
<div class="ui g-modal-confirm modal default-project-board-modal" id="default-project-board-modal-{{.ID}}">
<div class="header">
<span id="default-project-board-header"></span>
</div>
<div class="content">
<label id="default-project-board-content"></label>
</div>
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
</div>
{{range (index $.IssuesMap .ID)}}
<!-- start issue card -->
<div class="card board-card" data-issue="{{.ID}}">
{{if eq $.Project.CardType 1}}{{/* Images and Text*/}}
<div class="card-attachment-images">
{{range (index $.issuesAttachmentMap .ID)}}
<img src="{{.DownloadURL}}" alt="{{.Name}}" />
{{end}}
</div>
{{end}}
<div class="content gt-p-0">
<div class="header">
<span class="gt-dif gt-ac gt-vm">
{{template "shared/issueicon" .}}
</span>
<a class="project-board-title gt-vm" href="{{.Link}}">
{{.Title}}
</a>
</div>
<div class="meta gt-my-2">
<span class="text light grey">
{{.Repo.FullName}}#{{.Index}}
{{$timeStr := TimeSinceUnix .GetLastEventTimestamp $.locale}}
{{if .OriginalAuthor}}
{{$.locale.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
{{else if gt .Poster.ID 0}}
{{$.locale.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}}
{{else}}
{{$.locale.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
{{end}}
</span>
</div>
{{- if .MilestoneID}}
<div class="meta gt-my-2">
<a class="milestone" href="{{$.RepoLink}}/milestone/{{.MilestoneID}}">
{{svg "octicon-milestone" 16 "gt-mr-2 gt-vm"}}
<span class="gt-vm">{{.Milestone.Name}}</span>
</a>
</div>
{{- end}}
{{- range index $.LinkedPRs .ID}}
<div class="meta gt-my-2">
<a href="{{$.RepoLink}}/pulls/{{.Index}}">
<span class="gt-m-0 text {{if .PullRequest.HasMerged}}purple{{else if .IsClosed}}red{{else}}green{{end}}">{{svg "octicon-git-merge" 16 "gt-mr-2 gt-vm"}}</span>
<span class="gt-vm">{{.Title}} <span class="text light grey">#{{.Index}}</span></span>
</a>
</div>
{{- end}}
</div>
{{if or .Labels .Assignees}}
<div class="extra content labels-list gt-p-0 gt-pt-2">
{{range .Labels}}
<a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel $.Context .}}</a>
{{end}}
<div class="right floated">
{{range .Assignees}}
<a target="_blank" href="{{.HomeLink}}" data-tooltip-content="{{$.locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{avatar $.Context . 28 "mini gt-mr-3"}}</a>
{{end}}
<div class="ui g-modal-confirm modal" id="delete-board-modal-{{.ID}}">
<div class="header">
{{$.locale.Tr "repo.projects.column.delete"}}
</div>
<div class="content">
<label>
{{$.locale.Tr "repo.projects.column.deletion_desc"}}
</label>
</div>
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
</div>
</div>
{{end}}
</div>
<!-- stop issue card -->
{{end}}
</div>
<div class="divider"></div>
<div class="ui cards board" data-url="{{$.Link}}/{{.ID}}" data-project="{{$.Project.ID}}" data-board="{{.ID}}" id="board_{{.ID}}">
{{range (index $.IssuesMap .ID)}}
<!-- start issue card -->
<div class="card board-card" data-issue="{{.ID}}">
{{if eq $.Project.CardType 1}}{{/* Images and Text*/}}
<div class="card-attachment-images">
{{range (index $.issuesAttachmentMap .ID)}}
<img src="{{.DownloadURL}}" alt="{{.Name}}" />
{{end}}
</div>
{{end}}
<div class="content gt-p-0">
<div class="header">
<span class="gt-dif gt-ac gt-vm">
{{template "shared/issueicon" .}}
</span>
<a class="project-board-title gt-vm" href="{{.Link}}">
{{.Title}}
</a>
</div>
<div class="meta gt-my-2">
<span class="text light grey">
{{.Repo.FullName}}#{{.Index}}
{{$timeStr := TimeSinceUnix .GetLastEventTimestamp $.locale}}
{{if .OriginalAuthor}}
{{$.locale.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
{{else if gt .Poster.ID 0}}
{{$.locale.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}}
{{else}}
{{$.locale.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
{{end}}
</span>
</div>
{{- if .MilestoneID}}
<div class="meta gt-my-2">
<a class="milestone" href="{{$.RepoLink}}/milestone/{{.MilestoneID}}">
{{svg "octicon-milestone" 16 "gt-mr-2 gt-vm"}}
<span class="gt-vm">{{.Milestone.Name}}</span>
</a>
</div>
{{- end}}
{{- range index $.LinkedPRs .ID}}
<div class="meta gt-my-2">
<a href="{{$.RepoLink}}/pulls/{{.Index}}">
<span class="gt-m-0 text {{if .PullRequest.HasMerged}}purple{{else if .IsClosed}}red{{else}}green{{end}}">{{svg "octicon-git-merge" 16 "gt-mr-2 gt-vm"}}</span>
<span class="gt-vm">{{.Title}} <span class="text light grey">#{{.Index}}</span></span>
</a>
</div>
{{- end}}
</div>
{{if or .Labels .Assignees}}
<div class="extra content labels-list gt-p-0 gt-pt-2">
{{range .Labels}}
<a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel $.Context .}}</a>
{{end}}
<div class="right floated">
{{range .Assignees}}
<a target="_blank" href="{{.HomeLink}}" data-tooltip-content="{{$.locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{avatar $.Context . 28 "mini gt-mr-3"}}</a>
{{end}}
</div>
</div>
{{end}}
</div>
</div>
{{end}}
</div>
<!-- stop issue card -->
{{end}}
</div>
</div>
{{end}}
</div>
</div>

View File

@ -0,0 +1,11 @@
{{range .RecentlyPushedNewBranches}}
<div class="ui positive message gt-df gt-ac">
<div class="gt-f1">
{{$timeSince := TimeSince .UpdatedUnix.AsTime $.locale}}
{{$.locale.Tr "repo.pulls.recently_pushed_new_branches" (PathEscapeSegments .Name) $timeSince | Safe}}
</div>
<a aria-role="button" class="ui compact positive button gt-m-0" href="{{$.Repository.ComposeBranchCompareURL $.Repository.BaseRepo (PathEscapeSegments .Name)}}">
{{$.locale.Tr "repo.pulls.compare_changes"}}
</a>
</div>
{{end}}

View File

@ -3,6 +3,7 @@
{{template "repo/header" .}}
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
{{template "base/alert" .}}
{{template "repo/code/recently_pushed_new_branches" .}}
{{if and (not .HideRepoInfo) (not .IsBlame)}}
<div class="ui repo-description">
<div id="repo-desc">
@ -83,7 +84,7 @@
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{.locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}}
{{if and .CanWriteCode .IsViewBranch (not .Repository.IsArchived) (not .IsViewFile)}}
{{if and .CanWriteCode .IsViewBranch (not .Repository.IsMirror) (not .Repository.IsArchived) (not .IsViewFile)}}
<button class="ui dropdown basic compact jump button gt-mr-2"{{if not .Repository.CanEnableEditor}} disabled{{end}}>
{{.locale.Tr "repo.editor.add_file"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}

View File

@ -99,15 +99,13 @@
{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}}
<li class="follow">
{{if $.IsFollowing}}
<form method="post" action="{{.Link}}?action=unfollow&redirect_to={{$.Link}}">
{{$.CsrfTokenHtml}}
<button type="submit" class="ui basic red button">{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}</button>
</form>
<button class="ui basic red button link-action" data-url="{{.ContextUser.HomeLink}}?action=unfollow">
{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}
</button>
{{else}}
<form method="post" action="{{.Link}}?action=follow&redirect_to={{$.Link}}">
{{$.CsrfTokenHtml}}
<button type="submit" class="ui basic green button">{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}</button>
</form>
<button class="ui basic green button link-action" data-url="{{.ContextUser.HomeLink}}?action=follow">
{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}
</button>
{{end}}
</li>
{{end}}

View File

@ -33,7 +33,7 @@
</a>
<div class="divider"></div>
<a class="{{if not $.RepoIDs}}active{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&q={{$.Keyword}}">
<span class="text truncate">All</span>
<span class="text truncate">{{.locale.Tr "all"}}</span>
<span>{{CountFmt .TotalIssueCount}}</span>
</a>
{{range .Repos}}

View File

@ -8,20 +8,20 @@
</div>
</div>
{{else}}
<div role="main" aria-label="{{.Title}}" class="page-content user profile packages">
<div class="ui container">
<div class="ui stackable grid">
<div class="ui four wide column">
{{template "shared/user/profile_big_avatar" .}}
</div>
<div class="ui twelve wide column">
<div class="gt-mb-4">
{{template "user/overview/header" .}}
<div role="main" aria-label="{{.Title}}" class="page-content user profile packages">
<div class="ui container">
<div class="ui stackable grid">
<div class="ui four wide column">
{{template "shared/user/profile_big_avatar" .}}
</div>
<div class="ui twelve wide column">
<div class="gt-mb-4">
{{template "user/overview/header" .}}
</div>
{{template "package/shared/versionlist" .}}
</div>
{{template "package/shared/versionlist" .}}
</div>
</div>
</div>
</div>
{{end}}
{{template "base/footer" .}}

View File

@ -16,7 +16,7 @@
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.chef.keypair"}}</button>
</form>
<div class="field">
<label>{{.locale.Tr "packages.chef.documentation" "https://docs.gitea.io/en-us/usage/packages/chef/" | Safe}}</label>
<label>{{.locale.Tr "packages.registry.documentation" "Chef" "https://docs.gitea.io/en-us/usage/packages/chef/" | Safe}}</label>
</div>
</div>
</div>

View File

@ -138,7 +138,7 @@ func TestPullRequestTargetEvent(t *testing.T) {
// load and compare ActionRun
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID})
assert.Equal(t, addWorkflowToBaseResp.Commit.SHA, actionRun.CommitSHA)
assert.Equal(t, addFileToForkedResp.Commit.SHA, actionRun.CommitSHA)
assert.Equal(t, actions_module.GithubEventPullRequestTarget, actionRun.TriggerEvent)
})
}

View File

@ -120,9 +120,9 @@ func testCreateBranches(t *testing.T, giteaURL *url.URL) {
req := NewRequest(t, "GET", redirectURL)
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
assert.Equal(t,
test.FlashMessage,
assert.Contains(t,
strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
test.FlashMessage,
)
}
}

View File

@ -11,6 +11,7 @@ import webpack from 'webpack';
import {fileURLToPath} from 'node:url';
import {readFileSync} from 'node:fs';
import {env} from 'node:process';
import {LightningCssMinifyPlugin} from 'lightningcss-loader';
const {EsbuildPlugin} = EsBuildLoader;
const {SourceMapDevToolPlugin, DefinePlugin} = webpack;
@ -96,9 +97,10 @@ export default {
new EsbuildPlugin({
target: 'es2015',
minify: true,
css: true,
css: false,
legalComments: 'none',
}),
new LightningCssMinifyPlugin(),
],
splitChunks: {
chunks: 'async',