mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	Add single release page and latest redirect (#11102)
* Add single release and latest release routes Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update API and move latest search to models Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
This commit is contained in:
		@@ -80,6 +80,11 @@ func (r *Release) TarURL() string {
 | 
				
			|||||||
	return fmt.Sprintf("%s/archive/%s.tar.gz", r.Repo.HTMLURL(), r.TagName)
 | 
						return fmt.Sprintf("%s/archive/%s.tar.gz", r.Repo.HTMLURL(), r.TagName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HTMLURL the url for a release on the web UI. release must have attributes loaded
 | 
				
			||||||
 | 
					func (r *Release) HTMLURL() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%s/releases/tag/%s", r.Repo.HTMLURL(), r.TagName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// APIFormat convert a Release to api.Release
 | 
					// APIFormat convert a Release to api.Release
 | 
				
			||||||
func (r *Release) APIFormat() *api.Release {
 | 
					func (r *Release) APIFormat() *api.Release {
 | 
				
			||||||
	assets := make([]*api.Attachment, 0)
 | 
						assets := make([]*api.Attachment, 0)
 | 
				
			||||||
@@ -93,6 +98,7 @@ func (r *Release) APIFormat() *api.Release {
 | 
				
			|||||||
		Title:        r.Title,
 | 
							Title:        r.Title,
 | 
				
			||||||
		Note:         r.Note,
 | 
							Note:         r.Note,
 | 
				
			||||||
		URL:          r.APIURL(),
 | 
							URL:          r.APIURL(),
 | 
				
			||||||
 | 
							HTMLURL:      r.HTMLURL(),
 | 
				
			||||||
		TarURL:       r.TarURL(),
 | 
							TarURL:       r.TarURL(),
 | 
				
			||||||
		ZipURL:       r.ZipURL(),
 | 
							ZipURL:       r.ZipURL(),
 | 
				
			||||||
		IsDraft:      r.IsDraft,
 | 
							IsDraft:      r.IsDraft,
 | 
				
			||||||
@@ -217,6 +223,28 @@ func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, er
 | 
				
			|||||||
	return rels, sess.Find(&rels)
 | 
						return rels, sess.Find(&rels)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetLatestReleaseByRepoID returns the latest release for a repository
 | 
				
			||||||
 | 
					func GetLatestReleaseByRepoID(repoID int64) (*Release, error) {
 | 
				
			||||||
 | 
						cond := builder.NewCond().
 | 
				
			||||||
 | 
							And(builder.Eq{"repo_id": repoID}).
 | 
				
			||||||
 | 
							And(builder.Eq{"is_draft": false}).
 | 
				
			||||||
 | 
							And(builder.Eq{"is_prerelease": false}).
 | 
				
			||||||
 | 
							And(builder.Eq{"is_tag": false})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rel := new(Release)
 | 
				
			||||||
 | 
						has, err := x.
 | 
				
			||||||
 | 
							Desc("created_unix", "id").
 | 
				
			||||||
 | 
							Where(cond).
 | 
				
			||||||
 | 
							Get(rel)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						} else if !has {
 | 
				
			||||||
 | 
							return nil, ErrReleaseNotExist{0, "latest"}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rel, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
 | 
					// GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
 | 
				
			||||||
func GetReleasesByRepoIDAndNames(ctx DBContext, repoID int64, tagNames []string) (rels []*Release, err error) {
 | 
					func GetReleasesByRepoIDAndNames(ctx DBContext, repoID int64, tagNames []string) (rels []*Release, err error) {
 | 
				
			||||||
	err = ctx.e.
 | 
						err = ctx.e.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ type Release struct {
 | 
				
			|||||||
	Title        string `json:"name"`
 | 
						Title        string `json:"name"`
 | 
				
			||||||
	Note         string `json:"body"`
 | 
						Note         string `json:"body"`
 | 
				
			||||||
	URL          string `json:"url"`
 | 
						URL          string `json:"url"`
 | 
				
			||||||
 | 
						HTMLURL      string `json:"html_url"`
 | 
				
			||||||
	TarURL       string `json:"tarball_url"`
 | 
						TarURL       string `json:"tarball_url"`
 | 
				
			||||||
	ZipURL       string `json:"zipball_url"`
 | 
						ZipURL       string `json:"zipball_url"`
 | 
				
			||||||
	IsDraft      bool   `json:"draft"`
 | 
						IsDraft      bool   `json:"draft"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,6 +131,65 @@ func Releases(ctx *context.Context) {
 | 
				
			|||||||
	ctx.HTML(200, tplReleases)
 | 
						ctx.HTML(200, tplReleases)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SingleRelease renders a single release's page
 | 
				
			||||||
 | 
					func SingleRelease(ctx *context.Context) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = ctx.Tr("repo.release.releases")
 | 
				
			||||||
 | 
						ctx.Data["PageIsReleaseList"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases)
 | 
				
			||||||
 | 
						ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						release, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("tag"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("GetReleasesByRepoID", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = models.GetReleaseAttachments(release)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("GetReleaseAttachments", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						release.Publisher, err = models.GetUserByID(release.PublisherID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if models.IsErrUserNotExist(err) {
 | 
				
			||||||
 | 
								release.Publisher = models.NewGhostUser()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								ctx.ServerError("GetUserByID", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := calReleaseNumCommitsBehind(ctx.Repo, release, make(map[string]int64)); err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("calReleaseNumCommitsBehind", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						release.Note = markdown.RenderString(release.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["Releases"] = []*models.Release{release}
 | 
				
			||||||
 | 
						ctx.HTML(200, tplReleases)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LatestRelease redirects to the latest release
 | 
				
			||||||
 | 
					func LatestRelease(ctx *context.Context) {
 | 
				
			||||||
 | 
						release, err := models.GetLatestReleaseByRepoID(ctx.Repo.Repository.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if models.IsErrReleaseNotExist(err) {
 | 
				
			||||||
 | 
								ctx.NotFound("LatestRelease", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx.ServerError("GetLatestReleaseByRepoID", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := release.LoadAttributes(); err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("LoadAttributes", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Redirect(release.HTMLURL())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewRelease render creating release page
 | 
					// NewRelease render creating release page
 | 
				
			||||||
func NewRelease(ctx *context.Context) {
 | 
					func NewRelease(ctx *context.Context) {
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
 | 
						ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -805,7 +805,9 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
				
			|||||||
	// Releases
 | 
						// Releases
 | 
				
			||||||
	m.Group("/:username/:reponame", func() {
 | 
						m.Group("/:username/:reponame", func() {
 | 
				
			||||||
		m.Group("/releases", func() {
 | 
							m.Group("/releases", func() {
 | 
				
			||||||
			m.Get("/", repo.MustBeNotEmpty, repo.Releases)
 | 
								m.Get("/", repo.Releases)
 | 
				
			||||||
 | 
								m.Get("/tag/:tag", repo.SingleRelease)
 | 
				
			||||||
 | 
								m.Get("/latest", repo.LatestRelease)
 | 
				
			||||||
		}, repo.MustBeNotEmpty, context.RepoRef())
 | 
							}, repo.MustBeNotEmpty, context.RepoRef())
 | 
				
			||||||
		m.Group("/releases", func() {
 | 
							m.Group("/releases", func() {
 | 
				
			||||||
			m.Get("/new", repo.NewRelease)
 | 
								m.Get("/new", repo.NewRelease)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@
 | 
				
			|||||||
							</div>
 | 
												</div>
 | 
				
			||||||
						{{else}}
 | 
											{{else}}
 | 
				
			||||||
							<h3>
 | 
												<h3>
 | 
				
			||||||
								<a href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}">{{.Title}}</a>
 | 
													<a href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{.Title}}</a>
 | 
				
			||||||
								{{if $.CanCreateRelease}}<small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName | EscapePound}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)</small>{{end}}
 | 
													{{if $.CanCreateRelease}}<small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName | EscapePound}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)</small>{{end}}
 | 
				
			||||||
							</h3>
 | 
												</h3>
 | 
				
			||||||
							<p class="text grey">
 | 
												<p class="text grey">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13107,6 +13107,10 @@
 | 
				
			|||||||
          "type": "boolean",
 | 
					          "type": "boolean",
 | 
				
			||||||
          "x-go-name": "IsDraft"
 | 
					          "x-go-name": "IsDraft"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "html_url": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "HTMLURL"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "id": {
 | 
					        "id": {
 | 
				
			||||||
          "type": "integer",
 | 
					          "type": "integer",
 | 
				
			||||||
          "format": "int64",
 | 
					          "format": "int64",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user