Skip to content

Commit 2d2d917

Browse files
authored
Merge branch 'main' into support-everyone-access
2 parents 8e4f7dd + ecd463c commit 2d2d917

File tree

5 files changed

+238
-167
lines changed

5 files changed

+238
-167
lines changed

routers/web/repo/release.go

Lines changed: 115 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"code.gitea.io/gitea/models/unit"
1818
user_model "code.gitea.io/gitea/models/user"
1919
"code.gitea.io/gitea/modules/git"
20-
"code.gitea.io/gitea/modules/log"
2120
"code.gitea.io/gitea/modules/markup/markdown"
2221
"code.gitea.io/gitea/modules/optional"
2322
"code.gitea.io/gitea/modules/setting"
@@ -330,12 +329,42 @@ func LatestRelease(ctx *context.Context) {
330329
ctx.Redirect(release.Link())
331330
}
332331

333-
// NewRelease render creating or edit release page
334-
func NewRelease(ctx *context.Context) {
332+
func newReleaseCommon(ctx *context.Context) {
335333
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
336334
ctx.Data["PageIsReleaseList"] = true
335+
336+
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
337+
if err != nil {
338+
ctx.ServerError("GetTagNamesByRepoID", err)
339+
return
340+
}
341+
ctx.Data["Tags"] = tags
342+
343+
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
344+
assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository)
345+
if err != nil {
346+
ctx.ServerError("GetRepoAssignees", err)
347+
return
348+
}
349+
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
350+
351+
upload.AddUploadContext(ctx, "release")
352+
353+
PrepareBranchList(ctx) // for New Release page
354+
}
355+
356+
// NewRelease render creating or edit release page
357+
func NewRelease(ctx *context.Context) {
358+
newReleaseCommon(ctx)
359+
if ctx.Written() {
360+
return
361+
}
362+
363+
ctx.Data["ShowCreateTagOnlyButton"] = true
364+
365+
// pre-fill the form with the tag name, target branch and the existing release (if exists)
337366
ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch
338-
if tagName := ctx.FormString("tag"); len(tagName) > 0 {
367+
if tagName := ctx.FormString("tag"); tagName != "" {
339368
rel, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, tagName)
340369
if err != nil && !repo_model.IsErrReleaseNotExist(err) {
341370
ctx.ServerError("GetRelease", err)
@@ -344,59 +373,51 @@ func NewRelease(ctx *context.Context) {
344373

345374
if rel != nil {
346375
rel.Repo = ctx.Repo.Repository
347-
if err := rel.LoadAttributes(ctx); err != nil {
376+
if err = rel.LoadAttributes(ctx); err != nil {
348377
ctx.ServerError("LoadAttributes", err)
349378
return
350379
}
351380

381+
ctx.Data["ShowCreateTagOnlyButton"] = false
352382
ctx.Data["tag_name"] = rel.TagName
353-
if rel.Target != "" {
354-
ctx.Data["tag_target"] = rel.Target
355-
}
383+
ctx.Data["tag_target"] = rel.Target
356384
ctx.Data["title"] = rel.Title
357385
ctx.Data["content"] = rel.Note
358386
ctx.Data["attachments"] = rel.Attachments
359387
}
360388
}
361-
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
362-
assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository)
363-
if err != nil {
364-
ctx.ServerError("GetRepoAssignees", err)
365-
return
366-
}
367-
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
368-
369-
upload.AddUploadContext(ctx, "release")
370-
371-
// For New Release page
372-
PrepareBranchList(ctx)
373-
if ctx.Written() {
374-
return
375-
}
376-
377-
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
378-
if err != nil {
379-
ctx.ServerError("GetTagNamesByRepoID", err)
380-
return
381-
}
382-
ctx.Data["Tags"] = tags
383389

384390
ctx.HTML(http.StatusOK, tplReleaseNew)
385391
}
386392

387393
// NewReleasePost response for creating a release
388394
func NewReleasePost(ctx *context.Context) {
395+
newReleaseCommon(ctx)
396+
if ctx.Written() {
397+
return
398+
}
399+
389400
form := web.GetForm(ctx).(*forms.NewReleaseForm)
390-
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
391-
ctx.Data["PageIsReleaseList"] = true
392401

393-
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
394-
if err != nil {
395-
ctx.ServerError("GetTagNamesByRepoID", err)
402+
// first, check whether the release exists, and prepare "ShowCreateTagOnlyButton"
403+
// the logic should be done before the form error check to make the tmpl has correct variables
404+
rel, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, form.TagName)
405+
if err != nil && !repo_model.IsErrReleaseNotExist(err) {
406+
ctx.ServerError("GetRelease", err)
396407
return
397408
}
398-
ctx.Data["Tags"] = tags
399409

410+
// We should still show the "tag only" button if the user clicks it, no matter the release exists or not.
411+
// Because if error occurs, end users need to have the chance to edit the name and submit the form with "tag-only" again.
412+
// It is still not completely right, because there could still be cases like this:
413+
// * user visit "new release" page, see the "tag only" button
414+
// * input something, click other buttons but not "tag only"
415+
// * error occurs, the "new release" page is rendered again, but the "tag only" button is gone
416+
// Such cases are not able to be handled by current code, it needs frontend code to toggle the "tag-only" button if the input changes.
417+
// Or another choice is "always show the tag-only button" if error occurs.
418+
ctx.Data["ShowCreateTagOnlyButton"] = form.TagOnly || rel == nil
419+
420+
// do some form checks
400421
if ctx.HasError() {
401422
ctx.HTML(http.StatusOK, tplReleaseNew)
402423
return
@@ -407,59 +428,49 @@ func NewReleasePost(ctx *context.Context) {
407428
return
408429
}
409430

410-
// Title of release cannot be empty
411-
if len(form.TagOnly) == 0 && len(form.Title) == 0 {
431+
if !form.TagOnly && form.Title == "" {
432+
// if not "tag only", then the title of the release cannot be empty
412433
ctx.RenderWithErr(ctx.Tr("repo.release.title_empty"), tplReleaseNew, &form)
413434
return
414435
}
415436

416-
var attachmentUUIDs []string
417-
if setting.Attachment.Enabled {
418-
attachmentUUIDs = form.Files
419-
}
420-
421-
rel, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, form.TagName)
422-
if err != nil {
423-
if !repo_model.IsErrReleaseNotExist(err) {
424-
ctx.ServerError("GetRelease", err)
425-
return
426-
}
427-
428-
msg := ""
429-
if len(form.Title) > 0 && form.AddTagMsg {
430-
msg = form.Title + "\n\n" + form.Content
437+
handleTagReleaseError := func(err error) {
438+
ctx.Data["Err_TagName"] = true
439+
switch {
440+
case release_service.IsErrTagAlreadyExists(err):
441+
ctx.RenderWithErr(ctx.Tr("repo.branch.tag_collision", form.TagName), tplReleaseNew, &form)
442+
case repo_model.IsErrReleaseAlreadyExist(err):
443+
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
444+
case release_service.IsErrInvalidTagName(err):
445+
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
446+
case release_service.IsErrProtectedTagName(err):
447+
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_protected"), tplReleaseNew, &form)
448+
default:
449+
ctx.ServerError("handleTagReleaseError", err)
431450
}
451+
}
432452

433-
if len(form.TagOnly) > 0 {
434-
if err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
435-
if release_service.IsErrTagAlreadyExists(err) {
436-
e := err.(release_service.ErrTagAlreadyExists)
437-
ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
438-
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL())
439-
return
440-
}
441-
442-
if release_service.IsErrInvalidTagName(err) {
443-
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_invalid"))
444-
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL())
445-
return
446-
}
447-
448-
if release_service.IsErrProtectedTagName(err) {
449-
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
450-
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL())
451-
return
452-
}
453-
454-
ctx.ServerError("release_service.CreateNewTag", err)
455-
return
456-
}
453+
// prepare the git message for creating a new tag
454+
newTagMsg := ""
455+
if form.Title != "" && form.AddTagMsg {
456+
newTagMsg = form.Title + "\n\n" + form.Content
457+
}
457458

458-
ctx.Flash.Success(ctx.Tr("repo.tag.create_success", form.TagName))
459-
ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + util.PathEscapeSegments(form.TagName))
459+
// no release, and tag only
460+
if rel == nil && form.TagOnly {
461+
if err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, newTagMsg); err != nil {
462+
handleTagReleaseError(err)
460463
return
461464
}
465+
ctx.Flash.Success(ctx.Tr("repo.tag.create_success", form.TagName))
466+
ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + util.PathEscapeSegments(form.TagName))
467+
return
468+
}
469+
470+
attachmentUUIDs := util.Iif(setting.Attachment.Enabled, form.Files, nil)
462471

472+
// no existing release, create a new release
473+
if rel == nil {
463474
rel = &repo_model.Release{
464475
RepoID: ctx.Repo.Repository.ID,
465476
Repo: ctx.Repo.Repository,
@@ -469,48 +480,39 @@ func NewReleasePost(ctx *context.Context) {
469480
TagName: form.TagName,
470481
Target: form.Target,
471482
Note: form.Content,
472-
IsDraft: len(form.Draft) > 0,
483+
IsDraft: form.Draft,
473484
IsPrerelease: form.Prerelease,
474485
IsTag: false,
475486
}
476-
477-
if err = release_service.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil {
478-
ctx.Data["Err_TagName"] = true
479-
switch {
480-
case repo_model.IsErrReleaseAlreadyExist(err):
481-
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
482-
case release_service.IsErrInvalidTagName(err):
483-
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
484-
case release_service.IsErrProtectedTagName(err):
485-
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_protected"), tplReleaseNew, &form)
486-
default:
487-
ctx.ServerError("CreateRelease", err)
488-
}
489-
return
490-
}
491-
} else {
492-
if !rel.IsTag {
493-
ctx.Data["Err_TagName"] = true
494-
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
487+
if err = release_service.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, newTagMsg); err != nil {
488+
handleTagReleaseError(err)
495489
return
496490
}
491+
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
492+
return
493+
}
497494

498-
rel.Title = form.Title
499-
rel.Note = form.Content
500-
rel.Target = form.Target
501-
rel.IsDraft = len(form.Draft) > 0
502-
rel.IsPrerelease = form.Prerelease
503-
rel.PublisherID = ctx.Doer.ID
504-
rel.IsTag = false
505-
506-
if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
507-
ctx.Data["Err_TagName"] = true
508-
ctx.ServerError("UpdateRelease", err)
509-
return
510-
}
495+
// tag exists, try to convert it to a real release
496+
// old logic: if the release is not a tag (it is a real release), do not update it on the "new release" page
497+
// add new logic: if tag-only, do not convert the tag to a release
498+
if form.TagOnly || !rel.IsTag {
499+
ctx.Data["Err_TagName"] = true
500+
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
501+
return
511502
}
512-
log.Trace("Release created: %s/%s:%s", ctx.Doer.LowerName, ctx.Repo.Repository.Name, form.TagName)
513503

504+
// convert a tag to a real release (set is_tag=false)
505+
rel.Title = form.Title
506+
rel.Note = form.Content
507+
rel.Target = form.Target
508+
rel.IsDraft = form.Draft
509+
rel.IsPrerelease = form.Prerelease
510+
rel.PublisherID = ctx.Doer.ID
511+
rel.IsTag = false
512+
if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
513+
handleTagReleaseError(err)
514+
return
515+
}
514516
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
515517
}
516518

0 commit comments

Comments
 (0)