diff options
author | Anthony Wang | 2023-02-11 23:52:36 +0000 |
---|---|---|
committer | Anthony Wang | 2023-02-11 23:52:36 +0000 |
commit | e61e9fba59d6e6f0eb86869e07d9d52867384132 (patch) | |
tree | c6072319ab1b1429eb4132c9797ab4c6d6ffd760 /models | |
parent | 1a54d5e8970f2ff6ffe3aeaa19b3917f5e7dc9fd (diff) | |
parent | 1cb8d14bf71e0b8637c9eaa10808b4fd05139f45 (diff) |
Merge remote-tracking branch 'origin/main' into forgejo-federation
Diffstat (limited to 'models')
-rw-r--r-- | models/activities/action.go | 51 | ||||
-rw-r--r-- | models/activities/action_test.go | 2 | ||||
-rw-r--r-- | models/activities/notification.go | 16 | ||||
-rw-r--r-- | models/issues/comment.go | 33 | ||||
-rw-r--r-- | models/issues/issue.go | 2 | ||||
-rw-r--r-- | models/issues/issue_xref.go | 14 | ||||
-rw-r--r-- | models/issues/pull.go | 12 | ||||
-rw-r--r-- | models/issues/pull_list.go | 14 | ||||
-rw-r--r-- | models/organization/org.go | 20 | ||||
-rw-r--r-- | models/organization/org_test.go | 16 | ||||
-rw-r--r-- | models/packages/descriptor.go | 8 | ||||
-rw-r--r-- | models/packages/package.go | 12 | ||||
-rw-r--r-- | models/packages/package_property.go | 6 | ||||
-rw-r--r-- | models/project/project.go | 1 | ||||
-rw-r--r-- | models/repo/release.go | 5 | ||||
-rw-r--r-- | models/repo/repo.go | 2 |
16 files changed, 162 insertions, 52 deletions
diff --git a/models/activities/action.go b/models/activities/action.go index 4baedbfe1..8e7492c00 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -223,6 +223,49 @@ func (a *Action) GetRepoAbsoluteLink() string { return setting.AppURL + url.PathEscape(a.GetRepoUserName()) + "/" + url.PathEscape(a.GetRepoName()) } +// GetCommentHTMLURL returns link to action comment. +func (a *Action) GetCommentHTMLURL() string { + return a.getCommentHTMLURL(db.DefaultContext) +} + +func (a *Action) loadComment(ctx context.Context) (err error) { + if a.CommentID == 0 || a.Comment != nil { + return nil + } + a.Comment, err = issues_model.GetCommentByID(ctx, a.CommentID) + return err +} + +func (a *Action) getCommentHTMLURL(ctx context.Context) string { + if a == nil { + return "#" + } + _ = a.loadComment(ctx) + if a.Comment != nil { + return a.Comment.HTMLURL() + } + if len(a.GetIssueInfos()) == 0 { + return "#" + } + // Return link to issue + issueIDString := a.GetIssueInfos()[0] + issueID, err := strconv.ParseInt(issueIDString, 10, 64) + if err != nil { + return "#" + } + + issue, err := issues_model.GetIssueByID(ctx, issueID) + if err != nil { + return "#" + } + + if err = issue.LoadRepo(ctx); err != nil { + return "#" + } + + return issue.HTMLURL() +} + // GetCommentLink returns link to action comment. func (a *Action) GetCommentLink() string { return a.getCommentLink(db.DefaultContext) @@ -232,11 +275,9 @@ func (a *Action) getCommentLink(ctx context.Context) string { if a == nil { return "#" } - if a.Comment == nil && a.CommentID != 0 { - a.Comment, _ = issues_model.GetCommentByID(ctx, a.CommentID) - } + _ = a.loadComment(ctx) if a.Comment != nil { - return a.Comment.HTMLURL() + return a.Comment.Link() } if len(a.GetIssueInfos()) == 0 { return "#" @@ -257,7 +298,7 @@ func (a *Action) getCommentLink(ctx context.Context) string { return "#" } - return issue.HTMLURL() + return issue.Link() } // GetBranch returns the action's repository branch. diff --git a/models/activities/action_test.go b/models/activities/action_test.go index 29312bd48..f37e58f68 100644 --- a/models/activities/action_test.go +++ b/models/activities/action_test.go @@ -36,7 +36,7 @@ func TestAction_GetRepoLink(t *testing.T) { expected := path.Join(setting.AppSubURL, owner.Name, repo.Name) assert.Equal(t, expected, action.GetRepoLink()) assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink()) - assert.Equal(t, comment.HTMLURL(), action.GetCommentLink()) + assert.Equal(t, comment.HTMLURL(), action.GetCommentHTMLURL()) } func TestGetFeeds(t *testing.T) { diff --git a/models/activities/notification.go b/models/activities/notification.go index f153eb058..75276a044 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -459,6 +459,22 @@ func (n *Notification) HTMLURL() string { return "" } +// Link formats a relative URL-string to the notification +func (n *Notification) Link() string { + switch n.Source { + case NotificationSourceIssue, NotificationSourcePullRequest: + if n.Comment != nil { + return n.Comment.Link() + } + return n.Issue.Link() + case NotificationSourceCommit: + return n.Repository.Link() + "/commit/" + url.PathEscape(n.CommitID) + case NotificationSourceRepository: + return n.Repository.Link() + } + return "" +} + // APIURL formats a URL-string to the notification func (n *Notification) APIURL() string { return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) diff --git a/models/issues/comment.go b/models/issues/comment.go index 82c702a88..2eefaffd8 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -393,21 +393,40 @@ func (c *Comment) HTMLURL() string { log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } + return c.Issue.HTMLURL() + c.hashLink() +} + +// Link formats a relative URL-string to the issue-comment +func (c *Comment) Link() string { + err := c.LoadIssue(db.DefaultContext) + if err != nil { // Silently dropping errors :unamused: + log.Error("LoadIssue(%d): %v", c.IssueID, err) + return "" + } + err = c.Issue.LoadRepo(db.DefaultContext) + if err != nil { // Silently dropping errors :unamused: + log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) + return "" + } + return c.Issue.Link() + c.hashLink() +} + +func (c *Comment) hashLink() string { if c.Type == CommentTypeCode { if c.ReviewID == 0 { - return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) + return "/files#" + c.HashTag() } if c.Review == nil { if err := c.LoadReview(); err != nil { log.Warn("LoadReview(%d): %v", c.ReviewID, err) - return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) + return "/files#" + c.HashTag() } } if c.Review.Type <= ReviewTypePending { - return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) + return "/files#" + c.HashTag() } } - return fmt.Sprintf("%s#%s", c.Issue.HTMLURL(), c.HashTag()) + return "#" + c.HashTag() } // APIURL formats a API-string to the issue-comment @@ -710,8 +729,8 @@ func (c *Comment) UnsignedLine() uint64 { return uint64(c.Line) } -// CodeCommentURL returns the url to a comment in code -func (c *Comment) CodeCommentURL() string { +// CodeCommentLink returns the url to a comment in code +func (c *Comment) CodeCommentLink() string { err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) @@ -722,7 +741,7 @@ func (c *Comment) CodeCommentURL() string { log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } - return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) + return fmt.Sprintf("%s/files#%s", c.Issue.Link(), c.HashTag()) } // LoadPushCommits Load push commits diff --git a/models/issues/issue.go b/models/issues/issue.go index 806016b57..63e153d7b 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -421,7 +421,7 @@ func (issue *Issue) HTMLURL() string { return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index) } -// Link returns the Link URL to this issue. +// Link returns the issue's relative URL. func (issue *Issue) Link() string { var path string if issue.IsPull { diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go index 21ee24210..a1086f9e8 100644 --- a/models/issues/issue_xref.go +++ b/models/issues/issue_xref.go @@ -277,26 +277,26 @@ func CommentTypeIsRef(t CommentType) bool { return t == CommentTypeCommentRef || t == CommentTypePullRef || t == CommentTypeIssueRef } -// RefCommentHTMLURL returns the HTML URL for the comment that created this reference -func (c *Comment) RefCommentHTMLURL() string { +// RefCommentLink returns the relative URL for the comment that created this reference +func (c *Comment) RefCommentLink() string { // Edge case for when the reference is inside the title or the description of the referring issue if c.RefCommentID == 0 { - return c.RefIssueHTMLURL() + return c.RefIssueLink() } if err := c.LoadRefComment(); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefComment(%d): %v", c.RefCommentID, err) return "" } - return c.RefComment.HTMLURL() + return c.RefComment.Link() } -// RefIssueHTMLURL returns the HTML URL of the issue where this reference was created -func (c *Comment) RefIssueHTMLURL() string { +// RefIssueLink returns the relative URL of the issue where this reference was created +func (c *Comment) RefIssueLink() string { if err := c.LoadRefIssue(); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefIssue(%d): %v", c.RefCommentID, err) return "" } - return c.RefIssue.HTMLURL() + return c.RefIssue.Link() } // RefIssueTitle returns the title of the issue where this reference was created diff --git a/models/issues/pull.go b/models/issues/pull.go index 044fb5fa0..3f8b0bc7a 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -759,8 +759,8 @@ func GetPullRequestsByHeadBranch(ctx context.Context, headBranch string, headRep return prs, nil } -// GetBaseBranchHTMLURL returns the HTML URL of the base branch -func (pr *PullRequest) GetBaseBranchHTMLURL() string { +// GetBaseBranchLink returns the relative URL of the base branch +func (pr *PullRequest) GetBaseBranchLink() string { if err := pr.LoadBaseRepo(db.DefaultContext); err != nil { log.Error("LoadBaseRepo: %v", err) return "" @@ -768,11 +768,11 @@ func (pr *PullRequest) GetBaseBranchHTMLURL() string { if pr.BaseRepo == nil { return "" } - return pr.BaseRepo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(pr.BaseBranch) + return pr.BaseRepo.Link() + "/src/branch/" + util.PathEscapeSegments(pr.BaseBranch) } -// GetHeadBranchHTMLURL returns the HTML URL of the head branch -func (pr *PullRequest) GetHeadBranchHTMLURL() string { +// GetHeadBranchLink returns the relative URL of the head branch +func (pr *PullRequest) GetHeadBranchLink() string { if pr.Flow == PullRequestFlowAGit { return "" } @@ -784,7 +784,7 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string { if pr.HeadRepo == nil { return "" } - return pr.HeadRepo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(pr.HeadBranch) + return pr.HeadRepo.Link() + "/src/branch/" + util.PathEscapeSegments(pr.HeadBranch) } // UpdateAllowEdits update if PR can be edited from maintainers diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index 007c2fd90..f4efd916c 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -13,6 +13,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" "xorm.io/xorm" ) @@ -175,7 +176,18 @@ func (prs PullRequestList) loadAttributes(ctx context.Context) error { } for _, pr := range prs { pr.Issue = set[pr.IssueID] - pr.Issue.PullRequest = pr // panic here means issueIDs and prs are not in sync + /* + Old code: + pr.Issue.PullRequest = pr // panic here means issueIDs and prs are not in sync + + It's worth panic because it's almost impossible to happen under normal use. + But in integration testing, an asynchronous task could read a database that has been reset. + So returning an error would make more sense, let the caller has a choice to ignore it. + */ + if pr.Issue == nil { + return fmt.Errorf("issues and prs may be not in sync: cannot find issue %v for pr %v: %w", pr.IssueID, pr.ID, util.ErrNotExist) + } + pr.Issue.PullRequest = pr } return nil } diff --git a/models/organization/org.go b/models/organization/org.go index 05eaead60..852facf70 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -110,22 +110,14 @@ func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) { return CanCreateOrgRepo(db.DefaultContext, org.ID, uid) } -func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) { - return GetTeam(ctx, org.ID, name) -} - // GetTeam returns named team of organization. -func (org *Organization) GetTeam(name string) (*Team, error) { - return org.getTeam(db.DefaultContext, name) -} - -func (org *Organization) getOwnerTeam(ctx context.Context) (*Team, error) { - return org.getTeam(ctx, OwnerTeamName) +func (org *Organization) GetTeam(ctx context.Context, name string) (*Team, error) { + return GetTeam(ctx, org.ID, name) } // GetOwnerTeam returns owner team of organization. -func (org *Organization) GetOwnerTeam() (*Team, error) { - return org.getOwnerTeam(db.DefaultContext) +func (org *Organization) GetOwnerTeam(ctx context.Context) (*Team, error) { + return org.GetTeam(ctx, OwnerTeamName) } // FindOrgTeams returns all teams of a given organization @@ -342,7 +334,7 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) { } // GetOrgByName returns organization by given name. -func GetOrgByName(name string) (*Organization, error) { +func GetOrgByName(ctx context.Context, name string) (*Organization, error) { if len(name) == 0 { return nil, ErrOrgNotExist{0, name} } @@ -350,7 +342,7 @@ func GetOrgByName(name string) (*Organization, error) { LowerName: strings.ToLower(name), Type: user_model.UserTypeOrganization, } - has, err := db.GetEngine(db.DefaultContext).Get(u) + has, err := db.GetEngine(ctx).Get(u) if err != nil { return nil, err } else if !has { diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 0a3836592..cfa304d7b 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -61,28 +61,28 @@ func TestUser_IsOrgMember(t *testing.T) { func TestUser_GetTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - team, err := org.GetTeam("team1") + team, err := org.GetTeam(db.DefaultContext, "team1") assert.NoError(t, err) assert.Equal(t, org.ID, team.OrgID) assert.Equal(t, "team1", team.LowerName) - _, err = org.GetTeam("does not exist") + _, err = org.GetTeam(db.DefaultContext, "does not exist") assert.True(t, organization.IsErrTeamNotExist(err)) nonOrg := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 2}) - _, err = nonOrg.GetTeam("team") + _, err = nonOrg.GetTeam(db.DefaultContext, "team") assert.True(t, organization.IsErrTeamNotExist(err)) } func TestUser_GetOwnerTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - team, err := org.GetOwnerTeam() + team, err := org.GetOwnerTeam(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, org.ID, team.OrgID) nonOrg := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 2}) - _, err = nonOrg.GetOwnerTeam() + _, err = nonOrg.GetOwnerTeam(db.DefaultContext) assert.True(t, organization.IsErrTeamNotExist(err)) } @@ -115,15 +115,15 @@ func TestUser_GetMembers(t *testing.T) { func TestGetOrgByName(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - org, err := organization.GetOrgByName("user3") + org, err := organization.GetOrgByName(db.DefaultContext, "user3") assert.NoError(t, err) assert.EqualValues(t, 3, org.ID) assert.Equal(t, "user3", org.Name) - _, err = organization.GetOrgByName("user2") // user2 is an individual + _, err = organization.GetOrgByName(db.DefaultContext, "user2") // user2 is an individual assert.True(t, organization.IsErrOrgNotExist(err)) - _, err = organization.GetOrgByName("") // corner case + _, err = organization.GetOrgByName(db.DefaultContext, "") // corner case assert.True(t, organization.IsErrOrgNotExist(err)) } diff --git a/models/packages/descriptor.go b/models/packages/descriptor.go index 3b36ee226..f4be21e74 100644 --- a/models/packages/descriptor.go +++ b/models/packages/descriptor.go @@ -11,6 +11,8 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/packages/cargo" + "code.gitea.io/gitea/modules/packages/chef" "code.gitea.io/gitea/modules/packages/composer" "code.gitea.io/gitea/modules/packages/conan" "code.gitea.io/gitea/modules/packages/conda" @@ -63,7 +65,7 @@ type PackageFileDescriptor struct { // PackageWebLink returns the package web link func (pd *PackageDescriptor) PackageWebLink() string { - return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName)) + return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HomeLink(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName)) } // FullWebLink returns the package version web link @@ -129,6 +131,10 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc var metadata interface{} switch p.Type { + case TypeCargo: + metadata = &cargo.Metadata{} + case TypeChef: + metadata = &chef.Metadata{} case TypeComposer: metadata = &composer.Metadata{} case TypeConan: diff --git a/models/packages/package.go b/models/packages/package.go index 0015953d8..32f30fab9 100644 --- a/models/packages/package.go +++ b/models/packages/package.go @@ -30,6 +30,8 @@ type Type string // List of supported packages const ( + TypeCargo Type = "cargo" + TypeChef Type = "chef" TypeComposer Type = "composer" TypeConan Type = "conan" TypeConda Type = "conda" @@ -46,6 +48,8 @@ const ( ) var TypeList = []Type{ + TypeCargo, + TypeChef, TypeComposer, TypeConan, TypeConda, @@ -64,6 +68,10 @@ var TypeList = []Type{ // Name gets the name of the package type func (pt Type) Name() string { switch pt { + case TypeCargo: + return "Cargo" + case TypeChef: + return "Chef" case TypeComposer: return "Composer" case TypeConan: @@ -97,6 +105,10 @@ func (pt Type) Name() string { // SVGName gets the name of the package type svg image func (pt Type) SVGName() string { switch pt { + case TypeCargo: + return "gitea-cargo" + case TypeChef: + return "gitea-chef" case TypeComposer: return "gitea-composer" case TypeConan: diff --git a/models/packages/package_property.go b/models/packages/package_property.go index 1b7f253d5..e03b12c9d 100644 --- a/models/packages/package_property.go +++ b/models/packages/package_property.go @@ -58,6 +58,12 @@ func GetPropertiesByName(ctx context.Context, refType PropertyType, refID int64, return pps, db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Find(&pps) } +// UpdateProperty updates a property +func UpdateProperty(ctx context.Context, pp *PackageProperty) error { + _, err := db.GetEngine(ctx).ID(pp.ID).Update(pp) + return err +} + // DeleteAllProperties deletes all properties of a ref func DeleteAllProperties(ctx context.Context, refType PropertyType, refID int64) error { _, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Delete(&PackageProperty{}) diff --git a/models/project/project.go b/models/project/project.go index 273823ac9..9074fd0c1 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -116,6 +116,7 @@ func (p *Project) LoadRepo(ctx context.Context) (err error) { return err } +// Link returns the project's relative URL. func (p *Project) Link() string { if p.OwnerID > 0 { err := p.LoadOwner(db.DefaultContext) diff --git a/models/repo/release.go b/models/repo/release.go index 08b429f5e..abf91bc4b 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -130,6 +130,11 @@ func (r *Release) HTMLURL() string { return r.Repo.HTMLURL() + "/releases/tag/" + util.PathEscapeSegments(r.TagName) } +// Link the relative url for a release on the web UI. release must have attributes loaded +func (r *Release) Link() string { + return r.Repo.Link() + "/releases/tag/" + util.PathEscapeSegments(r.TagName) +} + // IsReleaseExist returns true if release with given tag name already exists. func IsReleaseExist(ctx context.Context, repoID int64, tagName string) (bool, error) { if len(tagName) == 0 { diff --git a/models/repo/repo.go b/models/repo/repo.go index 01b4c961d..ccc4b8bb1 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -481,7 +481,7 @@ func (repo *Repository) RepoPath() string { return RepoPath(repo.OwnerName, repo.Name) } -// Link returns the repository link +// Link returns the repository relative url func (repo *Repository) Link() string { return setting.AppSubURL + "/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name) } |