mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-17 00:01:00 -04:00
Compare commits
12 Commits
b1eb1676aa
...
6375419468
Author | SHA1 | Date | |
---|---|---|---|
|
6375419468 | ||
|
e0a780d75b | ||
|
a42a838843 | ||
|
811fc9d49c | ||
|
3780795b93 | ||
|
cb01b8691d | ||
|
7586b5815a | ||
|
128d77a3a0 | ||
|
a6a9389c70 | ||
|
32b26181d7 | ||
|
98088befae | ||
|
8995046110 |
@ -53,3 +53,4 @@ wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
|
|||||||
Gary Moon <gary@garymoon.net> (@garymoon)
|
Gary Moon <gary@garymoon.net> (@garymoon)
|
||||||
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
||||||
Denys Konovalov <kontakt@denyskon.de> (@denyskon)
|
Denys Konovalov <kontakt@denyskon.de> (@denyskon)
|
||||||
|
Punit Inani <punitinani1@gmail.com> (@puni9869)
|
||||||
|
@ -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
|
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
|
||||||
// There are several trust models in Gitea
|
// 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 {
|
if !verification.Verified {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the Committer trust model a signature is trusted if it matches the committer
|
// 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.SigningUser.Email == verification.CommittingUser.Email) {
|
||||||
verification.TrustStatus = "trusted"
|
verification.TrustStatus = "trusted"
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we drop to the more nuanced trust models...
|
// 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.SigningUser.Email != verification.CommittingUser.Email) {
|
||||||
verification.TrustStatus = "untrusted"
|
verification.TrustStatus = "untrusted"
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check we actually have a GPG SigningKey
|
// Check we actually have a GPG SigningKey
|
||||||
|
var err error
|
||||||
if verification.SigningKey != nil {
|
if verification.SigningKey != nil {
|
||||||
var isMember bool
|
var isMember bool
|
||||||
if keyMap != nil {
|
if keyMap != nil {
|
||||||
|
@ -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.
|
// 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) {
|
func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) {
|
||||||
if redirect, err = url.Parse(code.RedirectURI); err != nil {
|
redirect, err := url.Parse(code.RedirectURI)
|
||||||
return
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
q := redirect.Query()
|
q := redirect.Query()
|
||||||
if state != "" {
|
if state != "" {
|
||||||
|
@ -15,6 +15,8 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrBranchNotExist represents an error that branch with such name does not exist.
|
// 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()
|
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
|
||||||
|
}
|
||||||
|
@ -16,10 +16,10 @@ type Watch struct {
|
|||||||
Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"`
|
Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddModeColumnToWatch(x *xorm.Engine) (err error) {
|
func AddModeColumnToWatch(x *xorm.Engine) error {
|
||||||
if err = x.Sync2(new(Watch)); err != nil {
|
if err := x.Sync2(new(Watch)); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
_, err = x.Exec("UPDATE `watch` SET `mode` = 1")
|
_, err := x.Exec("UPDATE `watch` SET `mode` = 1")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -23,25 +23,25 @@ func RecalculateStars(x *xorm.Engine) (err error) {
|
|||||||
|
|
||||||
for start := 0; ; start += batchSize {
|
for start := 0; ; start += batchSize {
|
||||||
users := make([]User, 0, batchSize)
|
users := make([]User, 0, batchSize)
|
||||||
if err = sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
|
if err := sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
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 {
|
if _, err := sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err := sess.Commit(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,25 +44,25 @@ func DeleteMigrationCredentials(x *xorm.Engine) (err error) {
|
|||||||
|
|
||||||
for start := 0; ; start += batchSize {
|
for start := 0; ; start += batchSize {
|
||||||
tasks := make([]*Task, 0, batchSize)
|
tasks := make([]*Task, 0, batchSize)
|
||||||
if err = sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
|
if err := sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
if len(tasks) == 0 {
|
if len(tasks) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err = sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
for _, t := range tasks {
|
for _, t := range tasks {
|
||||||
if t.PayloadContent, err = removeCredentials(t.PayloadContent); err != nil {
|
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 {
|
if _, err := sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = sess.Commit(); err != nil {
|
if err := sess.Commit(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error {
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Email string `xorm:"NOT NULL"`
|
Email string `xorm:"NOT NULL"`
|
||||||
@ -26,12 +26,12 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add lower_email and is_primary columns
|
// Add lower_email and is_primary columns
|
||||||
if err = x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
|
if err := x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
|
if _, err := x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmailAddress struct {
|
type EmailAddress struct {
|
||||||
@ -44,8 +44,8 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// change lower_email as unique
|
// change lower_email as unique
|
||||||
if err = x.Sync2(new(EmailAddress)); err != nil {
|
if err := x.Sync2(new(EmailAddress)); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
@ -55,34 +55,33 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
|||||||
|
|
||||||
for start := 0; ; start += batchSize {
|
for start := 0; ; start += batchSize {
|
||||||
users := make([]*User, 0, batchSize)
|
users := make([]*User, 0, batchSize)
|
||||||
if err = sess.Limit(batchSize, start).Find(&users); err != nil {
|
if err := sess.Limit(batchSize, start).Find(&users); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
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 {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
if !exist {
|
if !exist {
|
||||||
if _, err = sess.Insert(&EmailAddress{
|
if _, err := sess.Insert(&EmailAddress{
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
LowerEmail: strings.ToLower(user.Email),
|
LowerEmail: strings.ToLower(user.Email),
|
||||||
IsActivated: user.IsActive,
|
IsActivated: user.IsActive,
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
IsPrimary: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
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
|
// IsOwnedBy returns true when user owns this repository
|
||||||
func (repo *Repository) IsOwnedBy(userID int64) bool {
|
func (repo *Repository) IsOwnedBy(userID int64) bool {
|
||||||
return repo.OwnerID == userID
|
return repo.OwnerID == userID
|
||||||
|
@ -23,8 +23,6 @@ import (
|
|||||||
type DetectedWorkflow struct {
|
type DetectedWorkflow struct {
|
||||||
EntryName string
|
EntryName string
|
||||||
TriggerEvent string
|
TriggerEvent string
|
||||||
Commit *git.Commit
|
|
||||||
Ref string
|
|
||||||
Content []byte
|
Content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +118,6 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
|
|||||||
dwf := &DetectedWorkflow{
|
dwf := &DetectedWorkflow{
|
||||||
EntryName: entry.Name(),
|
EntryName: entry.Name(),
|
||||||
TriggerEvent: evt.Name,
|
TriggerEvent: evt.Name,
|
||||||
Commit: commit,
|
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
workflows = append(workflows, dwf)
|
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 {
|
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||||
// with no special filter parameters
|
acts := evt.Acts()
|
||||||
if len(evt.Acts()) == 0 {
|
activityTypeMatched := false
|
||||||
|
matchTimes := 0
|
||||||
|
|
||||||
|
if vals, ok := acts["types"]; !ok {
|
||||||
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
// 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
|
// 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
|
// all acts conditions should be satisfied
|
||||||
for cond, vals := range evt.Acts() {
|
for cond, vals := range acts {
|
||||||
switch cond {
|
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":
|
case "branches":
|
||||||
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
||||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
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)
|
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 {
|
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
||||||
|
@ -57,6 +57,25 @@ func TestDetectMatched(t *testing.T) {
|
|||||||
yamlOn: "on: pull_request",
|
yamlOn: "on: pull_request",
|
||||||
expected: false,
|
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",
|
desc: "HookEventPullRequest(pull_request) `label_updated` action matches GithubEventPullRequest(pull_request) with `label` activity type",
|
||||||
triggedEvent: webhook_module.HookEventPullRequest,
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
@ -422,10 +422,10 @@ func RepoIDAssignment() func(ctx *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RepoAssignment returns a middleware to handle repository assignment
|
// 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 {
|
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
||||||
log.Trace("RepoAssignment was exec already, skipping second call ...")
|
log.Trace("RepoAssignment was exec already, skipping second call ...")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["repoAssignmentExecuted"] = true
|
ctx.Data["repoAssignmentExecuted"] = true
|
||||||
|
|
||||||
@ -453,7 +453,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
// https://github.com/golang/go/issues/19760
|
// https://github.com/golang/go/issues/19760
|
||||||
if ctx.FormString("go-get") == "1" {
|
if ctx.FormString("go-get") == "1" {
|
||||||
EarlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil {
|
if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil {
|
||||||
@ -466,7 +466,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetUserByName", err)
|
ctx.ServerError("GetUserByName", err)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.Repo.Owner = owner
|
ctx.Repo.Owner = owner
|
||||||
@ -490,7 +490,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
redirectPath += "?" + ctx.Req.URL.RawQuery
|
redirectPath += "?" + ctx.Req.URL.RawQuery
|
||||||
}
|
}
|
||||||
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
|
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get repository.
|
// Get repository.
|
||||||
@ -503,7 +503,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||||
if ctx.FormString("go-get") == "1" {
|
if ctx.FormString("go-get") == "1" {
|
||||||
EarlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.NotFound("GetRepositoryByName", nil)
|
ctx.NotFound("GetRepositoryByName", nil)
|
||||||
} else {
|
} else {
|
||||||
@ -512,13 +512,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetRepositoryByName", err)
|
ctx.ServerError("GetRepositoryByName", err)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
repo.Owner = owner
|
repo.Owner = owner
|
||||||
|
|
||||||
repoAssignment(ctx, repo)
|
repoAssignment(ctx, repo)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Repo.RepoLink = repo.Link()
|
ctx.Repo.RepoLink = repo.Link()
|
||||||
@ -542,12 +542,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetReleaseCountByRepoID", err)
|
ctx.ServerError("GetReleaseCountByRepoID", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
|
ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetReleaseCountByRepoID", err)
|
ctx.ServerError("GetReleaseCountByRepoID", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
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)
|
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CanUserForkRepo", err)
|
ctx.ServerError("CanUserForkRepo", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["CanSignedUserFork"] = canSignedUserFork
|
ctx.Data["CanSignedUserFork"] = canSignedUserFork
|
||||||
|
|
||||||
userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository)
|
userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetForksByUserAndOrgs", err)
|
ctx.ServerError("GetForksByUserAndOrgs", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["UserAndOrgForks"] = userAndOrgForks
|
ctx.Data["UserAndOrgForks"] = userAndOrgForks
|
||||||
|
|
||||||
@ -604,14 +604,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
if repo.IsFork {
|
if repo.IsFork {
|
||||||
RetrieveBaseRepo(ctx, repo)
|
RetrieveBaseRepo(ctx, repo)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.IsGenerated() {
|
if repo.IsGenerated() {
|
||||||
RetrieveTemplateRepo(ctx, repo)
|
RetrieveTemplateRepo(ctx, repo)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +623,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
if !isHomeOrSettings {
|
if !isHomeOrSettings {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink)
|
ctx.Redirect(ctx.Repo.RepoLink)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName))
|
gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName))
|
||||||
@ -636,10 +636,10 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
if !isHomeOrSettings {
|
if !isHomeOrSettings {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink)
|
ctx.Redirect(ctx.Repo.RepoLink)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
|
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
if ctx.Repo.GitRepo != nil {
|
if ctx.Repo.GitRepo != nil {
|
||||||
ctx.Repo.GitRepo.Close()
|
ctx.Repo.GitRepo.Close()
|
||||||
@ -647,7 +647,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
ctx.Repo.GitRepo = gitRepo
|
ctx.Repo.GitRepo = gitRepo
|
||||||
|
|
||||||
// We opened it, we should close it
|
// 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 it's been set to nil then assume someone else has closed it.
|
||||||
if ctx.Repo.GitRepo != nil {
|
if ctx.Repo.GitRepo != nil {
|
||||||
ctx.Repo.GitRepo.Close()
|
ctx.Repo.GitRepo.Close()
|
||||||
@ -657,13 +657,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
// Stop at this point when the repo is empty.
|
// Stop at this point when the repo is empty.
|
||||||
if ctx.Repo.Repository.IsEmpty {
|
if ctx.Repo.Repository.IsEmpty {
|
||||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
|
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetTagNamesByRepoID", err)
|
ctx.ServerError("GetTagNamesByRepoID", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Data["Tags"] = tags
|
ctx.Data["Tags"] = tags
|
||||||
|
|
||||||
@ -677,7 +677,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
|||||||
branchesTotal, err := git_model.CountBranches(ctx, branchOpts)
|
branchesTotal, err := git_model.CountBranches(ctx, branchOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CountBranches", err)
|
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
|
// 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)
|
branchesTotal, err = repo_module.SyncRepoBranches(ctx, ctx.Repo.Repository.ID, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("SyncRepoBranches", err)
|
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)
|
brs, err := git_model.FindBranchNames(ctx, branchOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranches", err)
|
ctx.ServerError("GetBranches", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
// always put default branch on the top
|
// always put default branch on the top
|
||||||
ctx.Data["Branches"] = append(branchOpts.ExcludeBranchNames, brs...)
|
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)
|
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetPendingRepositoryTransfer", err)
|
ctx.ServerError("GetPendingRepositoryTransfer", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repoTransfer.LoadAttributes(ctx); err != nil {
|
if err := repoTransfer.LoadAttributes(ctx); err != nil {
|
||||||
ctx.ServerError("LoadRecipient", err)
|
ctx.ServerError("LoadRecipient", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["RepoTransfer"] = repoTransfer
|
ctx.Data["RepoTransfer"] = repoTransfer
|
||||||
@ -894,7 +894,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
ctx.Repo.IsViewBranch = true
|
ctx.Repo.IsViewBranch = true
|
||||||
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
|
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
|
||||||
ctx.Data["TreePath"] = ""
|
ctx.Data["TreePath"] = ""
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -907,7 +907,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath)
|
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
|
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
// We opened it, we should close it
|
// We opened it, we should close it
|
||||||
cancel = func() {
|
cancel = func() {
|
||||||
@ -944,7 +944,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetBranchCommit", err)
|
ctx.ServerError("GetBranchCommit", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.IsViewBranch = true
|
ctx.Repo.IsViewBranch = true
|
||||||
} else {
|
} else {
|
||||||
@ -956,7 +956,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
|
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)
|
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
|
||||||
ctx.Redirect(link)
|
ctx.Redirect(link)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
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)
|
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranchCommit", err)
|
ctx.ServerError("GetBranchCommit", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||||
|
|
||||||
@ -978,10 +978,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
ctx.NotFound("GetTagCommit", err)
|
ctx.NotFound("GetTagCommit", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.ServerError("GetTagCommit", err)
|
ctx.ServerError("GetTagCommit", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||||
} else if len(refName) >= 7 && len(refName) <= git.SHAFullLength {
|
} 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)
|
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.NotFound("GetCommit", err)
|
ctx.NotFound("GetCommit", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
// If short commit ID add canonical link header
|
// If short commit ID add canonical link header
|
||||||
if len(refName) < git.SHAFullLength {
|
if len(refName) < git.SHAFullLength {
|
||||||
@ -1000,10 +1000,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
|
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
if refType == RepoRefLegacy {
|
if refType == RepoRefLegacy {
|
||||||
@ -1015,7 +1015,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
|||||||
util.PathEscapeSegments(prefix),
|
util.PathEscapeSegments(prefix),
|
||||||
ctx.Repo.BranchNameSubURL(),
|
ctx.Repo.BranchNameSubURL(),
|
||||||
util.PathEscapeSegments(ctx.Repo.TreePath)))
|
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()
|
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetCommitsCount", err)
|
ctx.ServerError("GetCommitsCount", err)
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
|
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
|
||||||
ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache())
|
ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache())
|
||||||
|
@ -6,6 +6,7 @@ package doctor
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"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) {
|
func fixUnitConfig16961(bs []byte, cfg *repo_model.UnitConfig) (fixed bool, err error) {
|
||||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle #16961
|
// Handle #16961
|
||||||
if string(bs) != "&{}" && len(bs) != 0 {
|
if string(bs) != "&{}" && len(bs) != 0 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
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) {
|
func fixExternalWikiConfig16961(bs []byte, cfg *repo_model.ExternalWikiConfig) (fixed bool, err error) {
|
||||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(bs) < 3 {
|
if len(bs) < 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
cfg.ExternalWikiURL = string(bs[2 : len(bs)-1])
|
cfg.ExternalWikiURL = string(bs[2 : len(bs)-1])
|
||||||
return true, nil
|
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) {
|
func fixExternalTrackerConfig16961(bs []byte, cfg *repo_model.ExternalTrackerConfig) (fixed bool, err error) {
|
||||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false, nil
|
||||||
}
|
}
|
||||||
// Handle #16961
|
// Handle #16961
|
||||||
if len(bs) < 3 {
|
if len(bs) < 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.ExternalTrackerURL = string(bytes.Join(parts[:len(parts)-2], []byte{' '}))
|
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) {
|
func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (fixed bool, err error) {
|
||||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle #16961
|
// Handle #16961
|
||||||
if len(bs) < 3 {
|
if len(bs) < 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullRequestsConfig was the following in 1.14
|
// PullRequestsConfig was the following in 1.14
|
||||||
@ -123,37 +124,37 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
|
|||||||
// DefaultMergeStyle MergeStyle
|
// DefaultMergeStyle MergeStyle
|
||||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||||
if len(parts) < 7 {
|
if len(parts) < 7 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseErr error
|
var parseErr error
|
||||||
cfg.IgnoreWhitespaceConflicts, parseErr = parseBool16961(parts[0])
|
cfg.IgnoreWhitespaceConflicts, parseErr = parseBool16961(parts[0])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowMerge, parseErr = parseBool16961(parts[1])
|
cfg.AllowMerge, parseErr = parseBool16961(parts[1])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowRebase, parseErr = parseBool16961(parts[2])
|
cfg.AllowRebase, parseErr = parseBool16961(parts[2])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowRebaseMerge, parseErr = parseBool16961(parts[3])
|
cfg.AllowRebaseMerge, parseErr = parseBool16961(parts[3])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowSquash, parseErr = parseBool16961(parts[4])
|
cfg.AllowSquash, parseErr = parseBool16961(parts[4])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowManualMerge, parseErr = parseBool16961(parts[5])
|
cfg.AllowManualMerge, parseErr = parseBool16961(parts[5])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AutodetectManualMerge, parseErr = parseBool16961(parts[6])
|
cfg.AutodetectManualMerge, parseErr = parseBool16961(parts[6])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.14 unit
|
// 1.14 unit
|
||||||
@ -162,12 +163,12 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(parts) < 9 {
|
if len(parts) < 9 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.DefaultDeleteBranchAfterMerge, parseErr = parseBool16961(parts[7])
|
cfg.DefaultDeleteBranchAfterMerge, parseErr = parseBool16961(parts[7])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.DefaultMergeStyle = repo_model.MergeStyle(string(bytes.Join(parts[8:], []byte{' '})))
|
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) {
|
func fixIssuesConfig16961(bs []byte, cfg *repo_model.IssuesConfig) (fixed bool, err error) {
|
||||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle #16961
|
// Handle #16961
|
||||||
if len(bs) < 3 {
|
if len(bs) < 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return
|
return false, err
|
||||||
}
|
}
|
||||||
var parseErr error
|
var parseErr error
|
||||||
cfg.EnableTimetracker, parseErr = parseBool16961(parts[0])
|
cfg.EnableTimetracker, parseErr = parseBool16961(parts[0])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.AllowOnlyContributorsToTrackTime, parseErr = parseBool16961(parts[1])
|
cfg.AllowOnlyContributorsToTrackTime, parseErr = parseBool16961(parts[1])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
cfg.EnableDependencies, parseErr = parseBool16961(parts[2])
|
cfg.EnableDependencies, parseErr = parseBool16961(parts[2])
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
return
|
return false, errors.Join(err, parseErr)
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
||||||
if len(value) == 0 {
|
if len(value) == 0 {
|
||||||
return
|
return 0, nil
|
||||||
}
|
}
|
||||||
var n int
|
var n int
|
||||||
last := 0
|
last := 0
|
||||||
@ -23,24 +23,24 @@ func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
|||||||
n, err = w.Write(prefix)
|
n, err = w.Write(prefix)
|
||||||
sum += int64(n)
|
sum += int64(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return sum, err
|
||||||
}
|
}
|
||||||
n, err = w.Write(value[last : last+j+1])
|
n, err = w.Write(value[last : last+j+1])
|
||||||
sum += int64(n)
|
sum += int64(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return sum, err
|
||||||
}
|
}
|
||||||
last += j + 1
|
last += j + 1
|
||||||
}
|
}
|
||||||
n, err = w.Write(prefix)
|
n, err = w.Write(prefix)
|
||||||
sum += int64(n)
|
sum += int64(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return sum, err
|
||||||
}
|
}
|
||||||
n, err = w.Write(value[last:])
|
n, err = w.Write(value[last:])
|
||||||
sum += int64(n)
|
sum += int64(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return sum, err
|
||||||
}
|
}
|
||||||
n, err = w.Write([]byte("\n"))
|
n, err = w.Write([]byte("\n"))
|
||||||
sum += int64(n)
|
sum += int64(n)
|
||||||
|
@ -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.
|
// HandleGenericETagTimeCache handles ETag-based caching with Last-Modified caching for a HTTP request.
|
||||||
// It returns true if the request was handled.
|
// 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 {
|
if len(etag) > 0 {
|
||||||
w.Header().Set("Etag", etag)
|
w.Header().Set("Etag", etag)
|
||||||
}
|
}
|
||||||
if !lastModified.IsZero() {
|
if lastModified != nil && !lastModified.IsZero() {
|
||||||
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
|
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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !lastModified.IsZero() {
|
if lastModified != nil && !lastModified.IsZero() {
|
||||||
ifModifiedSince := req.Header.Get("If-Modified-Since")
|
ifModifiedSince := req.Header.Get("If-Modified-Since")
|
||||||
if ifModifiedSince != "" {
|
if ifModifiedSince != "" {
|
||||||
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
|
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
|
||||||
|
@ -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
|
_, _ = 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)
|
buf := make([]byte, mimeDetectionBufferLen)
|
||||||
n, err := util.ReadAtMost(reader, buf)
|
n, err := util.ReadAtMost(reader, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -221,5 +221,8 @@ func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath s
|
|||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
}
|
}
|
||||||
setServeHeadersByFile(r, w, filePath, buf)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -78,7 +77,7 @@ func TestServeContentByReadSeeker(t *testing.T) {
|
|||||||
defer seekReader.Close()
|
defer seekReader.Close()
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
ServeContentByReadSeeker(r, w, "test", time.Time{}, seekReader)
|
ServeContentByReadSeeker(r, w, "test", nil, seekReader)
|
||||||
assert.Equal(t, expectedStatusCode, w.Code)
|
assert.Equal(t, expectedStatusCode, w.Code)
|
||||||
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
||||||
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
|
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
|
||||||
|
@ -138,7 +138,7 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
|
|||||||
|
|
||||||
// Search searches for issues by given conditions.
|
// Search searches for issues by given conditions.
|
||||||
// Returns the matching issue IDs
|
// 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
|
var repoQueriesP []*query.NumericRangeQuery
|
||||||
for _, repoID := range repoIDs {
|
for _, repoID := range repoIDs {
|
||||||
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "repo_id"))
|
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "repo_id"))
|
||||||
|
@ -77,7 +77,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, kw := range keywords {
|
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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
ids := make([]int64, 0, len(res.Hits))
|
ids := make([]int64, 0, len(res.Hits))
|
||||||
|
@ -36,7 +36,7 @@ func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search searches for issues
|
// 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)
|
total, ids, err := issues_model.SearchIssueIDsByKeyword(ctx, kw, repoIDs, limit, start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -140,7 +140,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
|
|||||||
|
|
||||||
// Search searches for issues by given conditions.
|
// Search searches for issues by given conditions.
|
||||||
// Returns the matching issue IDs
|
// 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")
|
kwQuery := elastic.NewMultiMatchQuery(keyword, "title", "content", "comments")
|
||||||
query := elastic.NewBoolQuery()
|
query := elastic.NewBoolQuery()
|
||||||
query = query.Must(kwQuery)
|
query = query.Must(kwQuery)
|
||||||
|
@ -242,12 +242,18 @@ func UpdateIssueIndexer(issue *issues_model.Issue) {
|
|||||||
comments = append(comments, comment.Content)
|
comments = append(comments, comment.Content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
issueType := "issue"
|
||||||
|
if issue.IsPull {
|
||||||
|
issueType = "pull"
|
||||||
|
}
|
||||||
indexerData := &internal.IndexerData{
|
indexerData := &internal.IndexerData{
|
||||||
ID: issue.ID,
|
ID: issue.ID,
|
||||||
RepoID: issue.RepoID,
|
RepoID: issue.RepoID,
|
||||||
Title: issue.Title,
|
State: string(issue.State()),
|
||||||
Content: issue.Content,
|
IssueType: issueType,
|
||||||
Comments: comments,
|
Title: issue.Title,
|
||||||
|
Content: issue.Content,
|
||||||
|
Comments: comments,
|
||||||
}
|
}
|
||||||
log.Debug("Adding to channel: %v", indexerData)
|
log.Debug("Adding to channel: %v", indexerData)
|
||||||
if err := issueIndexerQueue.Push(indexerData); err != nil {
|
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
|
// SearchIssuesByKeyword search issue ids by keywords and repo id
|
||||||
// WARNNING: You have to ensure user have permission to visit repoIDs' issues
|
// 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
|
var issueIDs []int64
|
||||||
indexer := *globalIndexer.Load()
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -50,19 +50,19 @@ func TestBleveSearchIssues(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
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.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{2}, ids)
|
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.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{1}, ids)
|
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.NoError(t, err)
|
||||||
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
|
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.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{1}, ids)
|
assert.EqualValues(t, []int64{1}, ids)
|
||||||
}
|
}
|
||||||
@ -73,19 +73,19 @@ func TestDBSearchIssues(t *testing.T) {
|
|||||||
setting.Indexer.IssueType = "db"
|
setting.Indexer.IssueType = "db"
|
||||||
InitIssueIndexer(true)
|
InitIssueIndexer(true)
|
||||||
|
|
||||||
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
|
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{2}, ids)
|
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.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{1}, ids)
|
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.NoError(t, err)
|
||||||
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
|
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.NoError(t, err)
|
||||||
assert.EqualValues(t, []int64{1}, ids)
|
assert.EqualValues(t, []int64{1}, ids)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ type Indexer interface {
|
|||||||
internal.Indexer
|
internal.Indexer
|
||||||
Index(ctx context.Context, issue []*IndexerData) error
|
Index(ctx context.Context, issue []*IndexerData) error
|
||||||
Delete(ctx context.Context, ids ...int64) 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
|
// 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")
|
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")
|
return nil, fmt.Errorf("indexer is not ready")
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,15 @@ package internal
|
|||||||
|
|
||||||
// IndexerData data stored in the issue indexer
|
// IndexerData data stored in the issue indexer
|
||||||
type IndexerData struct {
|
type IndexerData struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
RepoID int64 `json:"repo_id"`
|
RepoID int64 `json:"repo_id"`
|
||||||
Title string `json:"title"`
|
State string `json:"state"` // open, closed, all
|
||||||
Content string `json:"content"`
|
IssueType string `json:"type"` // issue or pull
|
||||||
Comments []string `json:"comments"`
|
Title string `json:"title"`
|
||||||
IsDelete bool `json:"is_delete"`
|
Content string `json:"content"`
|
||||||
IDs []int64 `json:"ids"`
|
Comments []string `json:"comments"`
|
||||||
|
IsDelete bool `json:"is_delete"`
|
||||||
|
IDs []int64 `json:"ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match represents on search result
|
// Match represents on search result
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
issueIndexerLatestVersion = 0
|
issueIndexerLatestVersion = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ internal.Indexer = &Indexer{}
|
var _ internal.Indexer = &Indexer{}
|
||||||
@ -70,12 +70,19 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
|
|||||||
|
|
||||||
// Search searches for issues by given conditions.
|
// Search searches for issues by given conditions.
|
||||||
// Returns the matching issue IDs
|
// 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))
|
repoFilters := make([]string, 0, len(repoIDs))
|
||||||
for _, repoID := range repoIDs {
|
for _, repoID := range repoIDs {
|
||||||
repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
|
repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
|
||||||
}
|
}
|
||||||
filter := strings.Join(repoFilters, " OR ")
|
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{
|
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
|
||||||
Filter: filter,
|
Filter: filter,
|
||||||
Limit: int64(limit),
|
Limit: int64(limit),
|
||||||
|
@ -211,7 +211,7 @@ func (pm *Manager) nextPID() (start time.Time, pid IDType) {
|
|||||||
pid = IDType(strconv.FormatInt(start.Unix(), 16))
|
pid = IDType(strconv.FormatInt(start.Unix(), 16))
|
||||||
|
|
||||||
if pm.next == 1 {
|
if pm.next == 1 {
|
||||||
return
|
return start, pid
|
||||||
}
|
}
|
||||||
pid = IDType(string(pid) + "-" + strconv.FormatInt(pm.next, 10))
|
pid = IDType(string(pid) + "-" + strconv.FormatInt(pm.next, 10))
|
||||||
return start, pid
|
return start, pid
|
||||||
|
@ -256,3 +256,8 @@ func ToFloat64(number any) (float64, error) {
|
|||||||
}
|
}
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToPointer returns the pointer of a copy of any given value
|
||||||
|
func ToPointer[T any](val T) *T {
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
@ -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`)
|
||||||
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))
|
||||||
|
}
|
||||||
|
@ -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.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.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.new = New Milestone
|
||||||
milestones.closed = Closed %s
|
milestones.closed = Closed %s
|
||||||
milestones.update_ago = Updated %s
|
milestones.update_ago = Updated %s
|
||||||
@ -3232,6 +3234,7 @@ desc = Manage repository packages.
|
|||||||
empty = There are no packages yet.
|
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.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.
|
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 = Type
|
||||||
filter.type.all = All
|
filter.type.all = All
|
||||||
filter.no_result = Your filter produced no results.
|
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.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.registry.info = Choose $branch and $repository from the list below.
|
||||||
alpine.install = To install the package, run the following command:
|
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 = Repository Info
|
||||||
alpine.repository.branches = Branches
|
alpine.repository.branches = Branches
|
||||||
alpine.repository.repositories = Repositories
|
alpine.repository.repositories = Repositories
|
||||||
alpine.repository.architectures = Architectures
|
alpine.repository.architectures = Architectures
|
||||||
cargo.registry = Setup this registry in the Cargo configuration file (for example <code>~/.cargo/config.toml</code>):
|
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.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.repository_site = Repository Site
|
||||||
cargo.details.documentation_site = Documentation Site
|
cargo.details.documentation_site = Documentation Site
|
||||||
chef.registry = Setup this registry in your <code>~/.chef/config.rb</code> file:
|
chef.registry = Setup this registry in your <code>~/.chef/config.rb</code> file:
|
||||||
chef.install = To install the package, run the following command:
|
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.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.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 = Dependencies
|
||||||
composer.dependencies.development = Development Dependencies
|
composer.dependencies.development = Development Dependencies
|
||||||
conan.details.repository = Repository
|
conan.details.repository = Repository
|
||||||
conan.registry = Setup this registry from the command line:
|
conan.registry = Setup this registry from the command line:
|
||||||
conan.install = To install the package using Conan, run the following command:
|
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.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.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.repository_site = Repository Site
|
||||||
conda.details.documentation_site = Documentation Site
|
conda.details.documentation_site = Documentation Site
|
||||||
container.details.type = Image Type
|
container.details.type = Image Type
|
||||||
container.details.platform = Platform
|
container.details.platform = Platform
|
||||||
container.pull = Pull the image from the command line:
|
container.pull = Pull the image from the command line:
|
||||||
container.digest = Digest:
|
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.multi_arch = OS / Arch
|
||||||
container.layers = Image Layers
|
container.layers = Image Layers
|
||||||
container.labels = Labels
|
container.labels = Labels
|
||||||
@ -3298,61 +3294,47 @@ container.labels.key = Key
|
|||||||
container.labels.value = Value
|
container.labels.value = Value
|
||||||
cran.registry = Setup this registry in your <code>Rprofile.site</code> file:
|
cran.registry = Setup this registry in your <code>Rprofile.site</code> file:
|
||||||
cran.install = To install the package, run the following command:
|
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 = Setup this registry from the command line:
|
||||||
debian.registry.info = Choose $distribution and $component from the list below.
|
debian.registry.info = Choose $distribution and $component from the list below.
|
||||||
debian.install = To install the package, run the following command:
|
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 = Repository Info
|
||||||
debian.repository.distributions = Distributions
|
debian.repository.distributions = Distributions
|
||||||
debian.repository.components = Components
|
debian.repository.components = Components
|
||||||
debian.repository.architectures = Architectures
|
debian.repository.architectures = Architectures
|
||||||
generic.download = Download package from the command line:
|
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.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.registry = Setup this registry from the command line:
|
||||||
helm.install = To install the package, run the following command:
|
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.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.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.install2 = Run via command line:
|
||||||
maven.download = To download the dependency, 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.registry = Setup this registry from the command line:
|
||||||
nuget.install = To install the package using NuGet, run the following command:
|
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
|
nuget.dependency.framework = Target Framework
|
||||||
npm.registry = Setup this registry in your project <code>.npmrc</code> file:
|
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.install = To install the package using npm, run the following command:
|
||||||
npm.install2 = or add it to the package.json file:
|
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 = Dependencies
|
||||||
npm.dependencies.development = Development Dependencies
|
npm.dependencies.development = Development Dependencies
|
||||||
npm.dependencies.peer = Peer Dependencies
|
npm.dependencies.peer = Peer Dependencies
|
||||||
npm.dependencies.optional = Optional Dependencies
|
npm.dependencies.optional = Optional Dependencies
|
||||||
npm.details.tag = Tag
|
npm.details.tag = Tag
|
||||||
pub.install = To install the package using Dart, run the following command:
|
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.requires = Requires Python
|
||||||
pypi.install = To install the package using pip, run the following command:
|
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.registry = Setup this registry from the command line:
|
||||||
rpm.install = To install the package, run the following command:
|
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.install = To install the package using gem, run the following command:
|
||||||
rubygems.install2 = or add it to the Gemfile:
|
rubygems.install2 = or add it to the Gemfile:
|
||||||
rubygems.dependencies.runtime = Runtime Dependencies
|
rubygems.dependencies.runtime = Runtime Dependencies
|
||||||
rubygems.dependencies.development = Development Dependencies
|
rubygems.dependencies.development = Development Dependencies
|
||||||
rubygems.required.ruby = Requires Ruby version
|
rubygems.required.ruby = Requires Ruby version
|
||||||
rubygems.required.rubygems = Requires RubyGem 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.registry = Setup this registry from the command line:
|
||||||
swift.install = Add the package in your <code>Package.swift</code> file:
|
swift.install = Add the package in your <code>Package.swift</code> file:
|
||||||
swift.install2 = and run the following command:
|
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.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 = 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.description = If you link a package with a repository, the package is listed in the repository's package list.
|
||||||
settings.link.select = Select Repository
|
settings.link.select = Select Repository
|
||||||
|
210
package-lock.json
generated
210
package-lock.json
generated
@ -30,6 +30,7 @@
|
|||||||
"jquery.are-you-sure": "1.9.0",
|
"jquery.are-you-sure": "1.9.0",
|
||||||
"katex": "0.16.8",
|
"katex": "0.16.8",
|
||||||
"license-checker-webpack-plugin": "0.2.1",
|
"license-checker-webpack-plugin": "0.2.1",
|
||||||
|
"lightningcss-loader": "2.1.0",
|
||||||
"mermaid": "10.2.3",
|
"mermaid": "10.2.3",
|
||||||
"mini-css-extract-plugin": "2.7.6",
|
"mini-css-extract-plugin": "2.7.6",
|
||||||
"minimatch": "9.0.2",
|
"minimatch": "9.0.2",
|
||||||
@ -4010,6 +4011,17 @@
|
|||||||
"node": ">=6"
|
"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": {
|
"node_modules/diff": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||||
@ -6717,6 +6729,204 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"jquery.are-you-sure": "1.9.0",
|
"jquery.are-you-sure": "1.9.0",
|
||||||
"katex": "0.16.8",
|
"katex": "0.16.8",
|
||||||
"license-checker-webpack-plugin": "0.2.1",
|
"license-checker-webpack-plugin": "0.2.1",
|
||||||
|
"lightningcss-loader": "2.1.0",
|
||||||
"mermaid": "10.2.3",
|
"mermaid": "10.2.3",
|
||||||
"mini-css-extract-plugin": "2.7.6",
|
"mini-css-extract-plugin": "2.7.6",
|
||||||
"minimatch": "9.0.2",
|
"minimatch": "9.0.2",
|
||||||
|
@ -129,12 +129,22 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
|||||||
|
|
||||||
baseRef := ""
|
baseRef := ""
|
||||||
headRef := ""
|
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 {
|
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
|
baseRef = pullPayload.PullRequest.Base.Ref
|
||||||
headRef = pullPayload.PullRequest.Head.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{
|
taskContext, err := structpb.NewStruct(map[string]any{
|
||||||
// standard contexts, see https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
// 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.
|
"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.
|
"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.
|
"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_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_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.
|
"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.
|
"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.
|
"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.
|
"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."
|
"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.
|
"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.
|
"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.
|
||||||
|
@ -219,7 +219,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
|||||||
common.ServeContentByReadSeeker(ctx.Base, ctx.Repo.TreePath, lastModified, lfsDataRc)
|
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)
|
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
@ -227,23 +227,23 @@ func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEn
|
|||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTreeEntryByPath", err)
|
ctx.Error(http.StatusInternalServerError, "GetTreeEntryByPath", err)
|
||||||
}
|
}
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.IsDir() || entry.IsSubModule() {
|
if entry.IsDir() || entry.IsSubModule() {
|
||||||
ctx.NotFound("getBlobForEntry", nil)
|
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:])
|
info, _, err := git.Entries([]*git.TreeEntry{entry}).GetCommitsInfo(ctx, ctx.Repo.Commit, path.Dir("/" + ctx.Repo.TreePath)[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetCommitsInfo", err)
|
ctx.Error(http.StatusInternalServerError, "GetCommitsInfo", err)
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(info) == 1 {
|
if len(info) == 1 {
|
||||||
// Not Modified
|
// Not Modified
|
||||||
lastModified = info[0].Commit.Committer.When
|
lastModified = &info[0].Commit.Committer.When
|
||||||
}
|
}
|
||||||
blob = entry.Blob()
|
blob = entry.Blob()
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ func SearchIssues(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
var issueIDs []int64
|
var issueIDs []int64
|
||||||
if len(keyword) > 0 && len(repoIDs) > 0 {
|
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)
|
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -394,7 +394,7 @@ func ListIssues(ctx *context.APIContext) {
|
|||||||
var issueIDs []int64
|
var issueIDs []int64
|
||||||
var labelIDs []int64
|
var labelIDs []int64
|
||||||
if len(keyword) > 0 {
|
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 {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
|
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
|
||||||
return
|
return
|
||||||
|
@ -298,26 +298,26 @@ func ClearIssueLabels(ctx *context.APIContext) {
|
|||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (issue *issues_model.Issue, labels []*issues_model.Label, err error) {
|
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"))
|
issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if issues_model.IsErrIssueNotExist(err) {
|
if issues_model.IsErrIssueNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
|
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 {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetLabelsByIDs", err)
|
ctx.Error(http.StatusInternalServerError, "GetLabelsByIDs", err)
|
||||||
return
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||||
ctx.Status(http.StatusForbidden)
|
ctx.Status(http.StatusForbidden)
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return issue, labels, err
|
return issue, labels, err
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ServeBlob download a git.Blob
|
// 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) {
|
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
|
||||||
return nil
|
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)
|
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)
|
httplib.ServeContentByReadSeeker(ctx.Req, ctx.Resp, filePath, modTime, reader)
|
||||||
}
|
}
|
||||||
|
@ -497,23 +497,23 @@ func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *us
|
|||||||
hasUser, err = user_model.GetUser(user)
|
hasUser, err = user_model.GetUser(user)
|
||||||
if !hasUser || err != nil {
|
if !hasUser || err != nil {
|
||||||
ctx.ServerError("UserLinkAccount", err)
|
ctx.ServerError("UserLinkAccount", err)
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: probably we should respect 'remember' user's choice...
|
// TODO: probably we should respect 'remember' user's choice...
|
||||||
linkAccount(ctx, user, *gothUser, true)
|
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 {
|
} else if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingLogin {
|
||||||
showLinkingLogin(ctx, *gothUser)
|
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
|
// handle error without template
|
||||||
if len(tpl) == 0 {
|
if len(tpl) == 0 {
|
||||||
ctx.ServerError("CreateUser", err)
|
ctx.ServerError("CreateUser", err)
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle error with template
|
// handle error with template
|
||||||
@ -542,7 +542,7 @@ func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *us
|
|||||||
default:
|
default:
|
||||||
ctx.ServerError("CreateUser", err)
|
ctx.ServerError("CreateUser", err)
|
||||||
}
|
}
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
log.Trace("Account created: %s", u.Name)
|
log.Trace("Account created: %s", u.Name)
|
||||||
return true
|
return true
|
||||||
@ -559,7 +559,7 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
|
|||||||
u.SetLastLogin()
|
u.SetLastLogin()
|
||||||
if err := user_model.UpdateUserCols(ctx, u, "is_admin", "is_active", "last_login_unix"); err != nil {
|
if err := user_model.UpdateUserCols(ctx, u, "is_admin", "is_active", "last_login_unix"); err != nil {
|
||||||
ctx.ServerError("UpdateUser", err)
|
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 {
|
if setting.Service.RegisterManualConfirm {
|
||||||
ctx.Data["ManualActivationOnly"] = true
|
ctx.Data["ManualActivationOnly"] = true
|
||||||
ctx.HTML(http.StatusOK, TplActivate)
|
ctx.HTML(http.StatusOK, TplActivate)
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
mailer.SendActivateAccountMail(ctx.Locale, u)
|
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)
|
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/upload"
|
"code.gitea.io/gitea/modules/upload"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/routers/common"
|
"code.gitea.io/gitea/routers/common"
|
||||||
"code.gitea.io/gitea/services/attachment"
|
"code.gitea.io/gitea/services/attachment"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
@ -148,7 +149,7 @@ func ServeAttachment(ctx *context.Context, uuid string) {
|
|||||||
}
|
}
|
||||||
defer fr.Close()
|
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
|
// GetAttachment serve attachments
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
|
// 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) {
|
if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) {
|
||||||
return nil
|
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)
|
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)
|
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
@ -90,23 +90,23 @@ func getBlobForEntry(ctx *context.Context) (blob *git.Blob, lastModified time.Ti
|
|||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetTreeEntryByPath", err)
|
ctx.ServerError("GetTreeEntryByPath", err)
|
||||||
}
|
}
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.IsDir() || entry.IsSubModule() {
|
if entry.IsDir() || entry.IsSubModule() {
|
||||||
ctx.NotFound("getBlobForEntry", nil)
|
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:])
|
info, _, err := git.Entries([]*git.TreeEntry{entry}).GetCommitsInfo(ctx, ctx.Repo.Commit, path.Dir("/" + ctx.Repo.TreePath)[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetCommitsInfo", err)
|
ctx.ServerError("GetCommitsInfo", err)
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(info) == 1 {
|
if len(info) == 1 {
|
||||||
// Not Modified
|
// Not Modified
|
||||||
lastModified = info[0].Commit.Committer.When
|
lastModified = &info[0].Commit.Committer.When
|
||||||
}
|
}
|
||||||
blob = entry.Blob()
|
blob = entry.Blob()
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ func DownloadByID(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
return
|
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)
|
ctx.ServerError("ServeBlob", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ func DownloadByIDOrLFS(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = ServeBlobOrLFS(ctx, blob, time.Time{}); err != nil {
|
if err = ServeBlobOrLFS(ctx, blob, nil); err != nil {
|
||||||
ctx.ServerError("ServeBlob", err)
|
ctx.ServerError("ServeBlob", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,13 +56,13 @@ func CorsHandler() func(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// httpBase implementation git smart HTTP protocol
|
// httpBase implementation git smart HTTP protocol
|
||||||
func httpBase(ctx *context.Context) (h *serviceHandler) {
|
func httpBase(ctx *context.Context) *serviceHandler {
|
||||||
username := ctx.Params(":username")
|
username := ctx.Params(":username")
|
||||||
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
||||||
|
|
||||||
if ctx.FormString("go-get") == "1" {
|
if ctx.FormString("go-get") == "1" {
|
||||||
context.EarlyResponseForGoGetMeta(ctx)
|
context.EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPull, receivePack bool
|
var isPull, receivePack bool
|
||||||
@ -101,7 +101,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
|||||||
owner := ctx.ContextUser
|
owner := ctx.ContextUser
|
||||||
if !owner.IsOrganization() && !owner.IsActive {
|
if !owner.IsOrganization() && !owner.IsActive {
|
||||||
ctx.PlainText(http.StatusForbidden, "Repository cannot be accessed. You cannot push or open issues/pull-requests.")
|
ctx.PlainText(http.StatusForbidden, "Repository cannot be accessed. You cannot push or open issues/pull-requests.")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
repoExist := true
|
repoExist := true
|
||||||
@ -110,19 +110,19 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
|||||||
if repo_model.IsErrRepoNotExist(err) {
|
if repo_model.IsErrRepoNotExist(err) {
|
||||||
if redirectRepoID, err := repo_model.LookupRedirect(owner.ID, reponame); err == nil {
|
if redirectRepoID, err := repo_model.LookupRedirect(owner.ID, reponame); err == nil {
|
||||||
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
repoExist = false
|
repoExist = false
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetRepositoryByName", err)
|
ctx.ServerError("GetRepositoryByName", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow pushing if the repo is archived
|
// Don't allow pushing if the repo is archived
|
||||||
if repoExist && repo.IsArchived && !isPull {
|
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.")
|
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.
|
// Only public pull don't need auth.
|
||||||
@ -136,7 +136,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
|||||||
if isPublicPull {
|
if isPublicPull {
|
||||||
if err := repo.LoadOwner(ctx); err != nil {
|
if err := repo.LoadOwner(ctx); err != nil {
|
||||||
ctx.ServerError("LoadOwner", err)
|
ctx.ServerError("LoadOwner", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
askAuth = askAuth || (repo.Owner.Visibility != structs.VisibleTypePublic)
|
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
|
// TODO: support digit auth - which would be Authorization header with digit
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
|
||||||
ctx.Error(http.StatusUnauthorized)
|
ctx.Error(http.StatusUnauthorized)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repo, auth_model.GetScopeLevelFromAccessMode(accessMode))
|
context.CheckRepoScopedToken(ctx, repo, auth_model.GetScopeLevelFromAccessMode(accessMode))
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && ctx.Data["IsActionsToken"] != true {
|
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 {
|
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
|
// 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")
|
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) {
|
} else if !auth_model.IsErrTwoFactorNotEnrolled(err) {
|
||||||
ctx.ServerError("IsErrTwoFactorNotEnrolled", err)
|
ctx.ServerError("IsErrTwoFactorNotEnrolled", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
|
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
|
||||||
ctx.PlainText(http.StatusForbidden, "Your account is disabled.")
|
ctx.PlainText(http.StatusForbidden, "Your account is disabled.")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
environ = []string{
|
environ = []string{
|
||||||
@ -193,23 +193,23 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
|||||||
task, err := actions_model.GetTaskByID(ctx, taskID)
|
task, err := actions_model.GetTaskByID(ctx, taskID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetTaskByID", err)
|
ctx.ServerError("GetTaskByID", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
if task.RepoID != repo.ID {
|
if task.RepoID != repo.ID {
|
||||||
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if task.IsForkPullRequest {
|
if task.IsForkPullRequest {
|
||||||
if accessMode > perm.AccessModeRead {
|
if accessMode > perm.AccessModeRead {
|
||||||
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
environ = append(environ, fmt.Sprintf("%s=%d", repo_module.EnvActionPerm, perm.AccessModeRead))
|
environ = append(environ, fmt.Sprintf("%s=%d", repo_module.EnvActionPerm, perm.AccessModeRead))
|
||||||
} else {
|
} else {
|
||||||
if accessMode > perm.AccessModeWrite {
|
if accessMode > perm.AccessModeWrite {
|
||||||
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
ctx.PlainText(http.StatusForbidden, "User permission denied")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
environ = append(environ, fmt.Sprintf("%s=%d", repo_module.EnvActionPerm, perm.AccessModeWrite))
|
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)
|
p, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetUserRepoPermission", err)
|
ctx.ServerError("GetUserRepoPermission", err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.CanAccess(accessMode, unitType) {
|
if !p.CanAccess(accessMode, unitType) {
|
||||||
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isPull && repo.IsMirror {
|
if !isPull && repo.IsMirror {
|
||||||
ctx.PlainText(http.StatusForbidden, "mirror repository is read-only")
|
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 !repoExist {
|
||||||
if !receivePack {
|
if !receivePack {
|
||||||
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if isWiki { // you cannot send wiki operation before create the repository
|
if isWiki { // you cannot send wiki operation before create the repository
|
||||||
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
ctx.PlainText(http.StatusNotFound, "Repository not found")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
||||||
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
if !owner.IsOrganization() && !setting.Repository.EnablePushCreateUser {
|
if !owner.IsOrganization() && !setting.Repository.EnablePushCreateUser {
|
||||||
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for users.")
|
ctx.PlainText(http.StatusForbidden, "Push to create is not enabled for users.")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return dummy payload if GET receive-pack
|
// Return dummy payload if GET receive-pack
|
||||||
if ctx.Req.Method == http.MethodGet {
|
if ctx.Req.Method == http.MethodGet {
|
||||||
dummyInfoRefs(ctx)
|
dummyInfoRefs(ctx)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err = repo_service.PushCreateRepo(ctx, ctx.Doer, owner, reponame)
|
repo, err = repo_service.PushCreateRepo(ctx, ctx.Doer, owner, reponame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("pushCreateRepo: %v", err)
|
log.Error("pushCreateRepo: %v", err)
|
||||||
ctx.Status(http.StatusNotFound)
|
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 _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
|
||||||
if repo_model.IsErrUnitTypeNotExist(err) {
|
if repo_model.IsErrUnitTypeNotExist(err) {
|
||||||
ctx.PlainText(http.StatusForbidden, "repository wiki is disabled")
|
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)
|
log.Error("Failed to get the wiki unit in %-v Error: %v", repo, err)
|
||||||
ctx.ServerError("GetUnit(UnitTypeWiki) for "+repo.FullName(), err)
|
ctx.ServerError("GetUnit(UnitTypeWiki) for "+repo.FullName(), err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
|
|||||||
|
|
||||||
var issueIDs []int64
|
var issueIDs []int64
|
||||||
if len(keyword) > 0 {
|
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 err != nil {
|
||||||
if issue_indexer.IsAvailable(ctx) {
|
if issue_indexer.IsAvailable(ctx) {
|
||||||
ctx.ServerError("issueIndexer.Search", err)
|
ctx.ServerError("issueIndexer.Search", err)
|
||||||
@ -1922,9 +1922,12 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
ctx.HTML(http.StatusOK, tplIssueView)
|
ctx.HTML(http.StatusOK, tplIssueView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkBlockedByIssues return canRead and notPermitted
|
||||||
func checkBlockedByIssues(ctx *context.Context, blockers []*issues_model.DependencyInfo) (canRead, notPermitted []*issues_model.DependencyInfo) {
|
func checkBlockedByIssues(ctx *context.Context, blockers []*issues_model.DependencyInfo) (canRead, notPermitted []*issues_model.DependencyInfo) {
|
||||||
var lastRepoID int64
|
var (
|
||||||
var lastPerm access_model.Permission
|
lastRepoID int64
|
||||||
|
lastPerm access_model.Permission
|
||||||
|
)
|
||||||
for i, blocker := range blockers {
|
for i, blocker := range blockers {
|
||||||
// Get the permissions for this repository
|
// Get the permissions for this repository
|
||||||
perm := lastPerm
|
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)
|
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetUserRepoPermission", err)
|
ctx.ServerError("GetUserRepoPermission", err)
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastRepoID = blocker.Repository.ID
|
lastRepoID = blocker.Repository.ID
|
||||||
@ -2463,7 +2466,7 @@ func SearchIssues(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
var issueIDs []int64
|
var issueIDs []int64
|
||||||
if len(keyword) > 0 && len(repoIDs) > 0 {
|
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())
|
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2611,7 +2614,7 @@ func ListIssues(ctx *context.Context) {
|
|||||||
var issueIDs []int64
|
var issueIDs []int64
|
||||||
var labelIDs []int64
|
var labelIDs []int64
|
||||||
if len(keyword) > 0 {
|
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 {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, err.Error())
|
ctx.Error(http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -977,6 +977,18 @@ func renderCode(ctx *context.Context) {
|
|||||||
return
|
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
|
var treeNames []string
|
||||||
paths := make([]string, 0, 5)
|
paths := make([]string, 0, 5)
|
||||||
if len(ctx.Repo.TreePath) > 0 {
|
if len(ctx.Repo.TreePath) > 0 {
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
@ -671,7 +670,7 @@ func WikiRaw(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if entry != nil {
|
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)
|
ctx.ServerError("ServeBlob", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -725,7 +725,7 @@ func issueIDsFromSearch(ctx *context.Context, ctxUser *user_model.User, keyword
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetRepoIDsForIssuesOptions: %w", err)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("SearchIssuesByKeyword: %w", err)
|
return nil, fmt.Errorf("SearchIssuesByKeyword: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -287,9 +287,9 @@ func Action(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
// FIXME: We should check this URL and make sure that it's a valid Gitea URL
|
ctx.JSONOK()
|
||||||
ctx.RedirectToFirst(ctx.FormString("redirect_to"), ctx.ContextUser.HomeLink())
|
|
||||||
}
|
}
|
||||||
|
@ -1256,20 +1256,20 @@ func registerRoutes(m *web.Route) {
|
|||||||
|
|
||||||
m.Group("/blob_excerpt", func() {
|
m.Group("/blob_excerpt", func() {
|
||||||
m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
|
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") {
|
if ctx.FormBool("wiki") {
|
||||||
ctx.Data["PageIsWiki"] = true
|
ctx.Data["PageIsWiki"] = true
|
||||||
repo.MustEnableWiki(ctx)
|
repo.MustEnableWiki(ctx)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
reqRepoCodeReader(ctx)
|
reqRepoCodeReader(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
cancel = context.RepoRef()(ctx)
|
cancel := context.RepoRef()(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.MustBeNotEmpty(ctx)
|
repo.MustBeNotEmpty(ctx)
|
||||||
|
@ -152,7 +152,6 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
} else {
|
} else {
|
||||||
for _, wf := range workflows {
|
for _, wf := range workflows {
|
||||||
if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||||
wf.Ref = ref
|
|
||||||
detectedWorkflows = append(detectedWorkflows, wf)
|
detectedWorkflows = append(detectedWorkflows, wf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +173,6 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
} else {
|
} else {
|
||||||
for _, wf := range baseWorkflows {
|
for _, wf := range baseWorkflows {
|
||||||
if wf.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
if wf.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
||||||
wf.Ref = baseRef
|
|
||||||
detectedWorkflows = append(detectedWorkflows, wf)
|
detectedWorkflows = append(detectedWorkflows, wf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,8 +210,8 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
OwnerID: input.Repo.OwnerID,
|
OwnerID: input.Repo.OwnerID,
|
||||||
WorkflowID: dwf.EntryName,
|
WorkflowID: dwf.EntryName,
|
||||||
TriggerUserID: input.Doer.ID,
|
TriggerUserID: input.Doer.ID,
|
||||||
Ref: dwf.Ref,
|
Ref: ref,
|
||||||
CommitSHA: dwf.Commit.ID.String(),
|
CommitSHA: commit.ID.String(),
|
||||||
IsForkPullRequest: isForkPullRequest,
|
IsForkPullRequest: isForkPullRequest,
|
||||||
Event: input.Event,
|
Event: input.Event,
|
||||||
EventPayload: string(p),
|
EventPayload: string(p),
|
||||||
|
@ -90,7 +90,7 @@ func IsUserHiddenCommentTypeGroupChecked(group string, hiddenCommentTypes *big.I
|
|||||||
commentTypes, ok := hiddenCommentTypeGroups[group]
|
commentTypes, ok := hiddenCommentTypeGroups[group]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Critical("the group map for hidden comment types is out of sync, unknown group: %v", group)
|
log.Critical("the group map for hidden comment types is out of sync, unknown group: %v", group)
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
if hiddenCommentTypes == nil {
|
if hiddenCommentTypes == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -779,7 +779,7 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) {
|
|||||||
for {
|
for {
|
||||||
lineBytes, isFragment, err = input.ReadLine()
|
lineBytes, isFragment, err = input.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return "", err
|
||||||
}
|
}
|
||||||
if wasFragment {
|
if wasFragment {
|
||||||
wasFragment = isFragment
|
wasFragment = isFragment
|
||||||
@ -795,7 +795,7 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) {
|
|||||||
var tail string
|
var tail string
|
||||||
tail, err = input.ReadString('\n')
|
tail, err = input.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return "", err
|
||||||
}
|
}
|
||||||
line += tail
|
line += tail
|
||||||
}
|
}
|
||||||
@ -821,22 +821,21 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
|||||||
_, isFragment, err = input.ReadLine()
|
_, isFragment, err = input.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Now by the definition of ReadLine this cannot be io.EOF
|
// Now by the definition of ReadLine this cannot be io.EOF
|
||||||
err = fmt.Errorf("unable to ReadLine: %w", err)
|
return nil, false, fmt.Errorf("unable to ReadLine: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.Reset()
|
sb.Reset()
|
||||||
lineBytes, isFragment, err = input.ReadLine()
|
lineBytes, isFragment, err = input.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return
|
return lineBytes, isFragment, err
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("unable to ReadLine: %w", err)
|
err = fmt.Errorf("unable to ReadLine: %w", err)
|
||||||
return
|
return nil, false, err
|
||||||
}
|
}
|
||||||
if lineBytes[0] == 'd' {
|
if lineBytes[0] == 'd' {
|
||||||
// End of hunks
|
// End of hunks
|
||||||
return
|
return lineBytes, isFragment, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch lineBytes[0] {
|
switch lineBytes[0] {
|
||||||
@ -853,8 +852,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
|||||||
lineBytes, isFragment, err = input.ReadLine()
|
lineBytes, isFragment, err = input.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Now by the definition of ReadLine this cannot be io.EOF
|
// Now by the definition of ReadLine this cannot be io.EOF
|
||||||
err = fmt.Errorf("unable to ReadLine: %w", err)
|
return nil, false, fmt.Errorf("unable to ReadLine: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
_, _ = sb.Write(lineBytes)
|
_, _ = 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
|
// 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")) {
|
if !bytes.Equal(lineBytes, []byte("\\ No newline at end of file")) {
|
||||||
err = fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
|
return nil, false, fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// Technically this should be the end the file!
|
// 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
|
// 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)
|
curSection.Lines = append(curSection.Lines, diffLine)
|
||||||
default:
|
default:
|
||||||
// This is unexpected
|
// This is unexpected
|
||||||
err = fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
|
return nil, false, fmt.Errorf("unexpected line in hunk: %s", string(lineBytes))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
line := string(lineBytes)
|
line := string(lineBytes)
|
||||||
@ -965,8 +961,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
|||||||
lineBytes, isFragment, err = input.ReadLine()
|
lineBytes, isFragment, err = input.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Now by the definition of ReadLine this cannot be io.EOF
|
// Now by the definition of ReadLine this cannot be io.EOF
|
||||||
err = fmt.Errorf("unable to ReadLine: %w", err)
|
return lineBytes, isFragment, fmt.Errorf("unable to ReadLine: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
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)
|
removed, comment, err = issues_model.ToggleIssueAssignee(ctx, issue, doer, assigneeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return false, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
assignee, err1 := user_model.GetUserByID(ctx, assigneeID)
|
assignee, err := user_model.GetUserByID(ctx, assigneeID)
|
||||||
if err1 != nil {
|
if err != nil {
|
||||||
err = err1
|
return false, nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.NotifyIssueChangeAssignee(ctx, doer, issue, assignee, removed, comment)
|
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 {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment == nil || !isAdd {
|
if comment == nil || !isAdd {
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify all user in this team
|
// notify all user in this team
|
||||||
if err = comment.LoadIssue(ctx); err != nil {
|
if err := comment.LoadIssue(ctx); err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
members, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{
|
members, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{
|
||||||
TeamID: reviewer.ID,
|
TeamID: reviewer.ID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
|
@ -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.
|
// 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
|
oldTitle := issue.Title
|
||||||
issue.Title = title
|
issue.Title = title
|
||||||
|
|
||||||
if err = issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil {
|
if err := issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) {
|
if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) {
|
||||||
if err = issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil {
|
if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ClearLabels clears all of an issue's labels
|
// ClearLabels clears all of an issue's labels
|
||||||
func ClearLabels(issue *issues_model.Issue, doer *user_model.User) (err error) {
|
func ClearLabels(issue *issues_model.Issue, doer *user_model.User) error {
|
||||||
if err = issues_model.ClearIssueLabels(issue, doer); err != nil {
|
if err := issues_model.ClearIssueLabels(issue, doer); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.NotifyIssueClearLabels(db.DefaultContext, doer, issue)
|
notification.NotifyIssueClearLabels(db.DefaultContext, doer, issue)
|
||||||
|
@ -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) {
|
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)
|
review, err := issues_model.GetReviewByID(ctx, reviewID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if review.Type != issues_model.ReviewTypeApprove && review.Type != issues_model.ReviewTypeReject {
|
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
|
// load data for notify
|
||||||
if err = review.LoadAttributes(ctx); err != nil {
|
if err := review.LoadAttributes(ctx); err != nil {
|
||||||
return nil, err
|
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")
|
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 {
|
if err := issues_model.DismissReview(review, isDismiss); err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if dismissPriors {
|
if dismissPriors {
|
||||||
@ -361,11 +361,11 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = review.Issue.LoadPullRequest(ctx); err != nil {
|
if err := review.Issue.LoadPullRequest(ctx); err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
if err = review.Issue.LoadAttributes(ctx); err != nil {
|
if err := review.Issue.LoadAttributes(ctx); err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err = issue_service.CreateComment(ctx, &issues_model.CreateCommentOptions{
|
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,
|
Repo: review.Issue.Repo,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
comment.Review = review
|
comment.Review = review
|
||||||
@ -386,5 +386,5 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
|||||||
|
|
||||||
notification.NotifyPullReviewDismiss(ctx, doer, review, comment)
|
notification.NotifyPullReviewDismiss(ctx, doer, review, comment)
|
||||||
|
|
||||||
return comment, err
|
return comment, nil
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// 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,
|
func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_model.Release,
|
||||||
addAttachmentUUIDs, delAttachmentUUIDs []string, editAttachments map[string]string,
|
addAttachmentUUIDs, delAttachmentUUIDs []string, editAttachments map[string]string,
|
||||||
) (err error) {
|
) error {
|
||||||
if rel.ID == 0 {
|
if rel.ID == 0 {
|
||||||
return errors.New("UpdateRelease only accepts an exist release")
|
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 {
|
if err := committer.Commit(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, uuid := range delAttachmentUUIDs {
|
for _, uuid := range delAttachmentUUIDs {
|
||||||
@ -280,14 +280,14 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod
|
|||||||
|
|
||||||
if !isCreated {
|
if !isCreated {
|
||||||
notification.NotifyUpdateRelease(gitRepo.Ctx, doer, rel)
|
notification.NotifyUpdateRelease(gitRepo.Ctx, doer, rel)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rel.IsDraft {
|
if !rel.IsDraft {
|
||||||
notification.NotifyNewRelease(gitRepo.Ctx, rel)
|
notification.NotifyNewRelease(gitRepo.Ctx, rel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
|
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
|
||||||
|
@ -20,16 +20,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right menu">
|
<div class="right menu">
|
||||||
<form method="post" action="{{.Link}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}&redirect_to={{$.Link}}">
|
<button class="link-action ui basic button gt-mr-0" data-url="{{.Org.HomeLink}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}">
|
||||||
{{$.CsrfTokenHtml}}
|
{{if $.IsFollowing}}
|
||||||
<button type="submit" class="ui basic button gt-mr-0">
|
{{.locale.Tr "user.unfollow"}}
|
||||||
{{if $.IsFollowing}}
|
{{else}}
|
||||||
{{.locale.Tr "user.unfollow"}}
|
{{.locale.Tr "user.follow"}}
|
||||||
{{else}}
|
{{end}}
|
||||||
{{.locale.Tr "user.follow"}}
|
</button>
|
||||||
{{end}}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{{template "base/head" .}}
|
{{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" .}}
|
{{template "shared/user/org_profile_avatar" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "user/overview/header" .}}
|
{{template "user/overview/header" .}}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 class="markup"><pre class="code-block"><code>cargo add {{.PackageDescriptor.Package.Name}}@{{.PackageDescriptor.Version.Version}}</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 class="markup"><pre class="code-block"><code>knife supermarket install {{.PackageDescriptor.Package.Name}} {{.PackageDescriptor.Version.Version}}</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<div class="markup"><pre class="code-block"><code>composer require {{.PackageDescriptor.Package.Name}}:{{.PackageDescriptor.Version.Version}}</code></pre></div>
|
<div class="markup"><pre class="code-block"><code>composer require {{.PackageDescriptor.Package.Name}}:{{.PackageDescriptor.Version.Version}}</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 class="markup"><pre class="code-block"><code>conan install --remote=gitea {{.PackageDescriptor.Package.Name}}/{{.PackageDescriptor.Version.Version}}</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<div class="markup"><pre class="code-block"><code>install.packages("{{.PackageDescriptor.Package.Name}}")</code></pre></div>
|
<div class="markup"><pre class="code-block"><code>install.packages("{{.PackageDescriptor.Package.Name}}")</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,7 @@ sudo apt update</code></pre></div>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@ curl <gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{$.PackageDescripto
|
|||||||
</code></pre></div>
|
</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 class="markup"><pre class="code-block"><code>helm install {{.PackageDescriptor.Package.Name}} {{AppDomain}}/{{.PackageDescriptor.Package.Name}}</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<div class="markup"><pre class="code-block"><code>"{{.PackageDescriptor.Package.Name}}": "{{.PackageDescriptor.Version.Version}}"</code></pre></div>
|
<div class="markup"><pre class="code-block"><code>"{{.PackageDescriptor.Package.Name}}": "{{.PackageDescriptor.Version.Version}}"</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
end</code></pre></div>
|
end</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<div class="markup"><pre class="code-block"><code>swift package resolve</code></pre></div>
|
<div class="markup"><pre class="code-block"><code>swift package resolve</code></pre></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 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>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.cargo.rebuild"}}</button>
|
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.cargo.rebuild"}}</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,53 +1,53 @@
|
|||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<form class="ui form ignore-dirty">
|
<form class="ui form ignore-dirty">
|
||||||
<div class="ui fluid action input">
|
<div class="ui fluid action input">
|
||||||
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
|
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
|
||||||
<select class="ui dropdown" name="type">
|
<select class="ui dropdown" name="type">
|
||||||
<option value="">{{.locale.Tr "packages.filter.type"}}</option>
|
<option value="">{{.locale.Tr "packages.filter.type"}}</option>
|
||||||
<option value="all">{{.locale.Tr "packages.filter.type.all"}}</option>
|
<option value="all">{{.locale.Tr "packages.filter.type.all"}}</option>
|
||||||
{{range $type := .AvailableTypes}}
|
{{range $type := .AvailableTypes}}
|
||||||
<option{{if eq $.PackageType $type}} selected="selected"{{end}} value="{{$type}}">{{$type.Name}}</option>
|
<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>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
</select>
|
||||||
{{template "base/paginate" .}}
|
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
|
||||||
</div>
|
</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>
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{.locale.Tr "packages.versions"}}</strong></p>
|
<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{.locale.Tr "packages.versions"}}</strong></p>
|
||||||
<form class="ui form ignore-dirty">
|
<form class="ui form ignore-dirty">
|
||||||
<div class="ui fluid action input">
|
<div class="ui fluid action input">
|
||||||
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
|
{{template "shared/searchinput" dict "locale" .locale "Value" .Query "AutoFocus" true}}
|
||||||
<select class="ui dropdown" name="sort">
|
<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_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="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_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>
|
<option value="created_desc"{{if or (eq .Sort "") (eq .Sort "created_desc")}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.latest"}}</option>
|
||||||
</select>
|
</select>
|
||||||
{{if eq .PackageDescriptor.Package.Type "container"}}
|
{{if eq .PackageDescriptor.Package.Type "container"}}
|
||||||
<select class="ui dropdown" name="tagged">
|
<select class="ui dropdown" name="tagged">
|
||||||
{{$isTagged := or (eq .Tagged "") (eq .Tagged "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="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>
|
<option value="untagged"{{if not $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.untagged"}}</option>
|
||||||
</select>
|
</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>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "base/paginate" .}}
|
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
|
||||||
</div>
|
</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>
|
||||||
|
@ -1,76 +1,76 @@
|
|||||||
{{if .CanWriteProjects}}
|
{{if .CanWriteProjects}}
|
||||||
<div class="gt-tr">
|
<div class="gt-tr">
|
||||||
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="small-menu-items ui compact tiny menu">
|
<div class="small-menu-items ui compact tiny menu">
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
|
||||||
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
|
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
|
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
|
||||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||||
</a>
|
</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>
|
||||||
<div class="ui right floated secondary filter menu">
|
</div>
|
||||||
<!-- Sort -->
|
<div class="milestone-list">
|
||||||
<div class="ui dropdown type jump item">
|
{{range .Projects}}
|
||||||
<span class="text">
|
<li class="milestone-card">
|
||||||
{{.locale.Tr "repo.issues.filter_sort"}}
|
<h3 class="flex-text-block gt-m-0">
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg .IconName 16}}
|
||||||
</span>
|
<a class="muted" href="{{.Link}}">{{.Title}}</a>
|
||||||
<div class="menu">
|
</h3>
|
||||||
<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>
|
<div class="milestone-toolbar">
|
||||||
<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>
|
<div class="group">
|
||||||
<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 class="flex-text-block">
|
||||||
|
{{svg "octicon-issue-opened" 14}}
|
||||||
|
{{$.locale.PrettyNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-text-block">
|
||||||
|
{{svg "octicon-check" 14}}
|
||||||
|
{{$.locale.PrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||||
</div>
|
<div class="group">
|
||||||
<div class="milestone-list">
|
<a class="flex-text-inline" href="{{.Link}}/edit">{{svg "octicon-pencil" 14}}{{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||||
{{range .Projects}}
|
{{if .IsClosed}}
|
||||||
<li class="milestone-card">
|
<a class="link-action flex-text-inline" href data-url="{{.Link}}/open">{{svg "octicon-check" 14}}{{$.locale.Tr "repo.projects.open"}}</a>
|
||||||
<h3 class="flex-text-block gt-m-0">
|
{{else}}
|
||||||
{{svg .IconName 16}}
|
<a class="link-action flex-text-inline" href data-url="{{.Link}}/close">{{svg "octicon-skip" 14}}{{$.locale.Tr "repo.projects.close"}}</a>
|
||||||
<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}} {{$.locale.Tr "repo.issues.open_title"}}
|
|
||||||
</div>
|
|
||||||
<div class="flex-text-block">
|
|
||||||
{{svg "octicon-check" 14}}
|
|
||||||
{{$.locale.PrettyNumber .NumClosedIssues}} {{$.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>
|
|
||||||
{{end}}
|
{{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}}
|
{{end}}
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{template "base/paginate" .}}
|
{{template "base/paginate" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if $.CanWriteProjects}}
|
{{if $.CanWriteProjects}}
|
||||||
<div class="ui g-modal-confirm delete modal">
|
<div class="ui g-modal-confirm delete modal">
|
||||||
|
@ -1,66 +1,66 @@
|
|||||||
<h2 class="ui dividing header">
|
<h2 class="ui dividing header">
|
||||||
{{if .PageIsEditProjects}}
|
{{if .PageIsEditProjects}}
|
||||||
{{.locale.Tr "repo.projects.edit"}}
|
{{.locale.Tr "repo.projects.edit"}}
|
||||||
<div class="sub header">{{.locale.Tr "repo.projects.edit_subheader"}}</div>
|
<div class="sub header">{{.locale.Tr "repo.projects.edit_subheader"}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{.locale.Tr "repo.projects.new"}}
|
{{.locale.Tr "repo.projects.new"}}
|
||||||
<div class="sub header">{{.locale.Tr "repo.projects.new_subheader"}}</div>
|
<div class="sub header">{{.locale.Tr "repo.projects.new_subheader"}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</h2>
|
</h2>
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<form class="ui form grid" action="{{.Link}}" method="post">
|
<form class="ui form grid" action="{{.Link}}" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="eleven wide column">
|
<div class="eleven wide column">
|
||||||
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
|
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
|
||||||
<div class="field {{if .Err_Title}}error{{end}}">
|
<div class="field {{if .Err_Title}}error{{end}}">
|
||||||
<label>{{.locale.Tr "repo.projects.title"}}</label>
|
<label>{{.locale.Tr "repo.projects.title"}}</label>
|
||||||
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
|
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{.locale.Tr "repo.projects.description"}}</label>
|
<label>{{.locale.Tr "repo.projects.description"}}</label>
|
||||||
<textarea name="content" placeholder="{{.locale.Tr "repo.projects.description_placeholder"}}">{{.content}}</textarea>
|
<textarea name="content" placeholder="{{.locale.Tr "repo.projects.description_placeholder"}}">{{.content}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if not .PageIsEditProjects}}
|
{{if not .PageIsEditProjects}}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{.locale.Tr "repo.projects.template.desc"}}</label>
|
<label>{{.locale.Tr "repo.projects.template.desc"}}</label>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
<input type="hidden" name="board_type" value="{{.type}}">
|
<input type="hidden" name="board_type" value="{{.type}}">
|
||||||
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
|
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{range $element := .BoardTypes}}
|
{{range $element := .BoardTypes}}
|
||||||
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
|
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{.locale.Tr "repo.projects.card_type.desc"}}</label>
|
<label>{{.locale.Tr "repo.projects.card_type.desc"}}</label>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
{{range $element := .CardTypes}}
|
{{range $element := .CardTypes}}
|
||||||
{{if or (eq $.card_type $element.CardType) (and (not $.PageIsEditProjects) (eq $element.CardType 1))}}
|
{{if or (eq $.card_type $element.CardType) (and (not $.PageIsEditProjects) (eq $element.CardType 1))}}
|
||||||
<input type="hidden" name="card_type" value="{{$element.CardType}}">
|
<input type="hidden" name="card_type" value="{{$element.CardType}}">
|
||||||
<div class="default text">{{$.locale.Tr $element.Translation}}</div>
|
<div class="default text">{{$.locale.Tr $element.Translation}}</div>
|
||||||
{{end}}
|
{{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}}
|
{{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>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider"></div>
|
</div>
|
||||||
<div class="ui left">
|
<div class="divider"></div>
|
||||||
<a class="ui cancel button" href="{{$.CancelLink}}">
|
<div class="ui left">
|
||||||
{{.locale.Tr "repo.milestones.cancel"}}
|
<a class="ui cancel button" href="{{$.CancelLink}}">
|
||||||
</a>
|
{{.locale.Tr "repo.milestones.cancel"}}
|
||||||
<button class="ui primary button">
|
</a>
|
||||||
{{if .PageIsEditProjects}}{{.locale.Tr "repo.projects.modify"}}{{else}}{{.locale.Tr "repo.projects.create"}}{{end}}
|
<button class="ui primary button">
|
||||||
</button>
|
{{if .PageIsEditProjects}}{{.locale.Tr "repo.projects.modify"}}{{else}}{{.locale.Tr "repo.projects.create"}}{{end}}
|
||||||
</div>
|
</button>
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
|
@ -1,256 +1,251 @@
|
|||||||
<div role="main" aria-label="{{.Title}}" class="page-content repository projects view-project">
|
<div class="ui two column stackable grid">
|
||||||
<div class="ui container">
|
<div class="column">
|
||||||
<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>
|
</div>
|
||||||
<div class="ui container fluid padded" id="project-board">
|
<div class="column right aligned">
|
||||||
|
{{if .CanWriteProjects}}
|
||||||
<div class="board {{if .CanWriteProjects}}sortable{{end}}">
|
<a class="ui small green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
|
||||||
{{range $board := .Boards}}
|
{{end}}
|
||||||
|
<div class="ui small modal new-board-modal" id="new-board-item">
|
||||||
<div class="ui segment board-column" style="background: {{.Color}} !important;" data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}">
|
<div class="header">
|
||||||
<div class="board-column-header gt-df gt-ac gt-sb">
|
{{$.locale.Tr "repo.projects.column.new"}}
|
||||||
<div class="ui large label board-label gt-py-2">
|
</div>
|
||||||
<div class="ui small circular grey label board-card-cnt">
|
<div class="content">
|
||||||
{{.NumIssues}}
|
<form class="ui form">
|
||||||
</div>
|
<div class="required field">
|
||||||
{{.Title}}
|
<label for="new_board">{{$.locale.Tr "repo.projects.column.new_title"}}</label>
|
||||||
|
<input class="new-board" id="new_board" name="title" required>
|
||||||
</div>
|
</div>
|
||||||
{{if and $.CanWriteProjects (ne .ID 0)}}
|
|
||||||
<div class="ui dropdown jump item">
|
<div class="field color-field">
|
||||||
<div class="not-mobile gt-px-3" tabindex="-1">
|
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
|
||||||
{{svg "octicon-kebab-horizontal"}}
|
<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 class="menu user-menu" tabindex="-1">
|
</div>
|
||||||
<a class="item show-modal button" data-modal="#edit-project-board-modal-{{.ID}}">
|
</div>
|
||||||
{{svg "octicon-pencil"}}
|
|
||||||
|
<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"}}
|
{{$.locale.Tr "repo.projects.column.edit"}}
|
||||||
</a>
|
</div>
|
||||||
{{if not .Default}}
|
<div class="content">
|
||||||
<a class="item show-modal button default-project-board-show"
|
<form class="ui form">
|
||||||
data-modal="#default-project-board-modal-{{.ID}}"
|
<div class="required field">
|
||||||
data-modal-default-project-board-header="{{$.locale.Tr "repo.projects.column.set_default"}}"
|
<label for="new_board_title">{{$.locale.Tr "repo.projects.column.edit_title"}}</label>
|
||||||
data-modal-default-project-board-content="{{$.locale.Tr "repo.projects.column.set_default_desc"}}"
|
<input class="project-board-title" id="new_board_title" name="title" value="{{.Title}}" required>
|
||||||
data-url="{{$.Link}}/{{.ID}}/default">
|
</div>
|
||||||
{{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="field color-field">
|
||||||
<div class="header">
|
<label for="new_board_color">{{$.locale.Tr "repo.projects.column.color"}}</label>
|
||||||
{{$.locale.Tr "repo.projects.column.edit"}}
|
<div class="color picker column">
|
||||||
</div>
|
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_board_color" name="color" value="{{.Color}}">
|
||||||
<div class="content">
|
<div class="column precolors">
|
||||||
<form class="ui form">
|
{{template "repo/issue/label_precolors"}}
|
||||||
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text right actions">
|
<div class="text right actions">
|
||||||
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button>
|
<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>
|
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</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>
|
</div>
|
||||||
</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)}}
|
<div class="ui g-modal-confirm modal" id="delete-board-modal-{{.ID}}">
|
||||||
|
<div class="header">
|
||||||
<!-- start issue card -->
|
{{$.locale.Tr "repo.projects.column.delete"}}
|
||||||
<div class="card board-card" data-issue="{{.ID}}">
|
</div>
|
||||||
{{if eq $.Project.CardType 1}}{{/* Images and Text*/}}
|
<div class="content">
|
||||||
<div class="card-attachment-images">
|
<label>
|
||||||
{{range (index $.issuesAttachmentMap .ID)}}
|
{{$.locale.Tr "repo.projects.column.deletion_desc"}}
|
||||||
<img src="{{.DownloadURL}}" alt="{{.Name}}" />
|
</label>
|
||||||
{{end}}
|
</div>
|
||||||
</div>
|
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
|
||||||
{{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>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
|
||||||
</div>
|
</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}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<!-- stop issue card -->
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
11
templates/repo/code/recently_pushed_new_branches.tmpl
Normal file
11
templates/repo/code/recently_pushed_new_branches.tmpl
Normal 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}}
|
@ -3,6 +3,7 @@
|
|||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
|
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
{{template "repo/code/recently_pushed_new_branches" .}}
|
||||||
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
||||||
<div class="ui repo-description">
|
<div class="ui repo-description">
|
||||||
<div id="repo-desc">
|
<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>
|
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{.locale.Tr "repo.find_file.go_to_file"}}</a>
|
||||||
{{end}}
|
{{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}}>
|
<button class="ui dropdown basic compact jump button gt-mr-2"{{if not .Repository.CanEnableEditor}} disabled{{end}}>
|
||||||
{{.locale.Tr "repo.editor.add_file"}}
|
{{.locale.Tr "repo.editor.add_file"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
|
@ -99,15 +99,13 @@
|
|||||||
{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}}
|
{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}}
|
||||||
<li class="follow">
|
<li class="follow">
|
||||||
{{if $.IsFollowing}}
|
{{if $.IsFollowing}}
|
||||||
<form method="post" action="{{.Link}}?action=unfollow&redirect_to={{$.Link}}">
|
<button class="ui basic red button link-action" data-url="{{.ContextUser.HomeLink}}?action=unfollow">
|
||||||
{{$.CsrfTokenHtml}}
|
{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}
|
||||||
<button type="submit" class="ui basic red button">{{svg "octicon-person"}} {{.locale.Tr "user.unfollow"}}</button>
|
</button>
|
||||||
</form>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<form method="post" action="{{.Link}}?action=follow&redirect_to={{$.Link}}">
|
<button class="ui basic green button link-action" data-url="{{.ContextUser.HomeLink}}?action=follow">
|
||||||
{{$.CsrfTokenHtml}}
|
{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}
|
||||||
<button type="submit" class="ui basic green button">{{svg "octicon-person"}} {{.locale.Tr "user.follow"}}</button>
|
</button>
|
||||||
</form>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<a class="{{if not $.RepoIDs}}active{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&q={{$.Keyword}}">
|
<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>
|
<span>{{CountFmt .TotalIssueCount}}</span>
|
||||||
</a>
|
</a>
|
||||||
{{range .Repos}}
|
{{range .Repos}}
|
||||||
|
@ -8,20 +8,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div role="main" aria-label="{{.Title}}" class="page-content user profile packages">
|
<div role="main" aria-label="{{.Title}}" class="page-content user profile packages">
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<div class="ui stackable grid">
|
<div class="ui stackable grid">
|
||||||
<div class="ui four wide column">
|
<div class="ui four wide column">
|
||||||
{{template "shared/user/profile_big_avatar" .}}
|
{{template "shared/user/profile_big_avatar" .}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui twelve wide column">
|
<div class="ui twelve wide column">
|
||||||
<div class="gt-mb-4">
|
<div class="gt-mb-4">
|
||||||
{{template "user/overview/header" .}}
|
{{template "user/overview/header" .}}
|
||||||
|
</div>
|
||||||
|
{{template "package/shared/versionlist" .}}
|
||||||
</div>
|
</div>
|
||||||
{{template "package/shared/versionlist" .}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.chef.keypair"}}</button>
|
<button class="ui green button">{{$.locale.Tr "packages.owner.settings.chef.keypair"}}</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="field">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,7 +138,7 @@ func TestPullRequestTargetEvent(t *testing.T) {
|
|||||||
|
|
||||||
// load and compare ActionRun
|
// load and compare ActionRun
|
||||||
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID})
|
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)
|
assert.Equal(t, actions_module.GithubEventPullRequestTarget, actionRun.TriggerEvent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -120,9 +120,9 @@ func testCreateBranches(t *testing.T, giteaURL *url.URL) {
|
|||||||
req := NewRequest(t, "GET", redirectURL)
|
req := NewRequest(t, "GET", redirectURL)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
assert.Equal(t,
|
assert.Contains(t,
|
||||||
test.FlashMessage,
|
|
||||||
strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
|
strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
|
||||||
|
test.FlashMessage,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import webpack from 'webpack';
|
|||||||
import {fileURLToPath} from 'node:url';
|
import {fileURLToPath} from 'node:url';
|
||||||
import {readFileSync} from 'node:fs';
|
import {readFileSync} from 'node:fs';
|
||||||
import {env} from 'node:process';
|
import {env} from 'node:process';
|
||||||
|
import {LightningCssMinifyPlugin} from 'lightningcss-loader';
|
||||||
|
|
||||||
const {EsbuildPlugin} = EsBuildLoader;
|
const {EsbuildPlugin} = EsBuildLoader;
|
||||||
const {SourceMapDevToolPlugin, DefinePlugin} = webpack;
|
const {SourceMapDevToolPlugin, DefinePlugin} = webpack;
|
||||||
@ -96,9 +97,10 @@ export default {
|
|||||||
new EsbuildPlugin({
|
new EsbuildPlugin({
|
||||||
target: 'es2015',
|
target: 'es2015',
|
||||||
minify: true,
|
minify: true,
|
||||||
css: true,
|
css: false,
|
||||||
legalComments: 'none',
|
legalComments: 'none',
|
||||||
}),
|
}),
|
||||||
|
new LightningCssMinifyPlugin(),
|
||||||
],
|
],
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
chunks: 'async',
|
chunks: 'async',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user