@@ -17,7 +17,6 @@ import (
17
17
"code.gitea.io/gitea/models/unit"
18
18
user_model "code.gitea.io/gitea/models/user"
19
19
"code.gitea.io/gitea/modules/git"
20
- "code.gitea.io/gitea/modules/log"
21
20
"code.gitea.io/gitea/modules/markup/markdown"
22
21
"code.gitea.io/gitea/modules/optional"
23
22
"code.gitea.io/gitea/modules/setting"
@@ -330,12 +329,42 @@ func LatestRelease(ctx *context.Context) {
330
329
ctx .Redirect (release .Link ())
331
330
}
332
331
333
- // NewRelease render creating or edit release page
334
- func NewRelease (ctx * context.Context ) {
332
+ func newReleaseCommon (ctx * context.Context ) {
335
333
ctx .Data ["Title" ] = ctx .Tr ("repo.release.new_release" )
336
334
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)
337
366
ctx .Data ["tag_target" ] = ctx .Repo .Repository .DefaultBranch
338
- if tagName := ctx .FormString ("tag" ); len ( tagName ) > 0 {
367
+ if tagName := ctx .FormString ("tag" ); tagName != "" {
339
368
rel , err := repo_model .GetRelease (ctx , ctx .Repo .Repository .ID , tagName )
340
369
if err != nil && ! repo_model .IsErrReleaseNotExist (err ) {
341
370
ctx .ServerError ("GetRelease" , err )
@@ -344,59 +373,51 @@ func NewRelease(ctx *context.Context) {
344
373
345
374
if rel != nil {
346
375
rel .Repo = ctx .Repo .Repository
347
- if err : = rel .LoadAttributes (ctx ); err != nil {
376
+ if err = rel .LoadAttributes (ctx ); err != nil {
348
377
ctx .ServerError ("LoadAttributes" , err )
349
378
return
350
379
}
351
380
381
+ ctx .Data ["ShowCreateTagOnlyButton" ] = false
352
382
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
356
384
ctx .Data ["title" ] = rel .Title
357
385
ctx .Data ["content" ] = rel .Note
358
386
ctx .Data ["attachments" ] = rel .Attachments
359
387
}
360
388
}
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
383
389
384
390
ctx .HTML (http .StatusOK , tplReleaseNew )
385
391
}
386
392
387
393
// NewReleasePost response for creating a release
388
394
func NewReleasePost (ctx * context.Context ) {
395
+ newReleaseCommon (ctx )
396
+ if ctx .Written () {
397
+ return
398
+ }
399
+
389
400
form := web .GetForm (ctx ).(* forms.NewReleaseForm )
390
- ctx .Data ["Title" ] = ctx .Tr ("repo.release.new_release" )
391
- ctx .Data ["PageIsReleaseList" ] = true
392
401
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 )
396
407
return
397
408
}
398
- ctx .Data ["Tags" ] = tags
399
409
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
400
421
if ctx .HasError () {
401
422
ctx .HTML (http .StatusOK , tplReleaseNew )
402
423
return
@@ -407,59 +428,49 @@ func NewReleasePost(ctx *context.Context) {
407
428
return
408
429
}
409
430
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
412
433
ctx .RenderWithErr (ctx .Tr ("repo.release.title_empty" ), tplReleaseNew , & form )
413
434
return
414
435
}
415
436
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 )
431
450
}
451
+ }
432
452
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
+ }
457
458
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 )
460
463
return
461
464
}
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 )
462
471
472
+ // no existing release, create a new release
473
+ if rel == nil {
463
474
rel = & repo_model.Release {
464
475
RepoID : ctx .Repo .Repository .ID ,
465
476
Repo : ctx .Repo .Repository ,
@@ -469,48 +480,39 @@ func NewReleasePost(ctx *context.Context) {
469
480
TagName : form .TagName ,
470
481
Target : form .Target ,
471
482
Note : form .Content ,
472
- IsDraft : len ( form .Draft ) > 0 ,
483
+ IsDraft : form .Draft ,
473
484
IsPrerelease : form .Prerelease ,
474
485
IsTag : false ,
475
486
}
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 )
495
489
return
496
490
}
491
+ ctx .Redirect (ctx .Repo .RepoLink + "/releases" )
492
+ return
493
+ }
497
494
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
511
502
}
512
- log .Trace ("Release created: %s/%s:%s" , ctx .Doer .LowerName , ctx .Repo .Repository .Name , form .TagName )
513
503
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
+ }
514
516
ctx .Redirect (ctx .Repo .RepoLink + "/releases" )
515
517
}
516
518
0 commit comments