@@ -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 
388394func  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