From 83cf1a894e5a3a60ea72fa6b92744cb0705dd145 Mon Sep 17 00:00:00 2001 From: a1012112796 <1012112796@qq.com> Date: Mon, 1 Mar 2021 03:57:45 +0800 Subject: [PATCH] Create tag on ui (#13467) Support create single tag directly support create tag with message from create release ui Signed-off-by: a1012112796 <1012112796@qq.com> Co-authored-by: Lauris BH Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath --- modules/forms/repo_branch_form.go | 1 + modules/forms/repo_form.go | 2 + modules/git/repo_tag_test.go | 2 +- options/locale/locale_en-US.ini | 5 +++ routers/api/v1/repo/release.go | 2 +- routers/repo/branch.go | 16 +++++++- routers/repo/release.go | 25 ++++++++++++- services/mirror/mirror_test.go | 2 +- services/release/release.go | 57 ++++++++++++++++++++++++++--- services/release/release_test.go | 39 ++++++++++++-------- templates/repo/branch_dropdown.tmpl | 11 ++++-- templates/repo/release/new.tmpl | 13 +++++++ web_src/js/index.js | 3 +- 13 files changed, 149 insertions(+), 29 deletions(-) diff --git a/modules/forms/repo_branch_form.go b/modules/forms/repo_branch_form.go index 5c631f20d4..88a069b831 100644 --- a/modules/forms/repo_branch_form.go +++ b/modules/forms/repo_branch_form.go @@ -16,6 +16,7 @@ import ( // NewBranchForm form for creating a new branch type NewBranchForm struct { NewBranchName string `binding:"Required;MaxSize(100);GitRefName"` + CreateTag bool } // Validate validates the fields diff --git a/modules/forms/repo_form.go b/modules/forms/repo_form.go index 48af3450f3..2793acdd5b 100644 --- a/modules/forms/repo_form.go +++ b/modules/forms/repo_form.go @@ -642,7 +642,9 @@ type NewReleaseForm struct { Title string `binding:"Required;MaxSize(255)"` Content string Draft string + TagOnly string Prerelease bool + AddTagMsg bool Files []string } diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go index 1dee29ba57..6feae8d913 100644 --- a/modules/git/repo_tag_test.go +++ b/modules/git/repo_tag_test.go @@ -43,7 +43,7 @@ func TestRepository_GetTag(t *testing.T) { aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0" aTagName := "annotatedTag" - aTagMessage := "my annotated message" + aTagMessage := "my annotated message \n - test two line" bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID) aTagID, _ := bareRepo1.GetTagID(aTagName) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d6c8aa6f71..99f07b9050 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1895,6 +1895,8 @@ release.tag_name_invalid = The tag name is not valid. release.tag_already_exist = This tag name already exists. release.downloads = Downloads release.download_count = Downloads: %s +release.add_tag_msg = Use the title and content of release as tag message. +release.add_tag = Create Tag Only branch.name = Branch Name branch.search = Search branches @@ -1922,6 +1924,9 @@ branch.download = Download Branch '%s' branch.included_desc = This branch is part of the default branch branch.included = Included +tag.create_tag = Create tag %s +tag.create_success = Tag '%s' has been created. + topic.manage_topics = Manage Topics topic.done = Done topic.count_prompt = You can not select more than 25 topics diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index 08d92e6c0a..e9eb4e0f9e 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -179,7 +179,7 @@ func CreateRelease(ctx *context.APIContext) { IsTag: false, Repo: ctx.Repo.Repository, } - if err := releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, nil); err != nil { + if err := releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil { if models.IsErrReleaseAlreadyExist(err) { ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err) } else { diff --git a/routers/repo/branch.go b/routers/repo/branch.go index cf6abc08df..ac6b7a1bed 100644 --- a/routers/repo/branch.go +++ b/routers/repo/branch.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" + release_service "code.gitea.io/gitea/services/release" repo_service "code.gitea.io/gitea/services/repository" ) @@ -383,7 +384,14 @@ func CreateBranch(ctx *context.Context) { } var err error - if ctx.Repo.IsViewBranch { + + if form.CreateTag { + if ctx.Repo.IsViewTag { + err = release_service.CreateNewTag(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName, "") + } else { + err = release_service.CreateNewTag(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName, "") + } + } else if ctx.Repo.IsViewBranch { err = repo_module.CreateNewBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) } else if ctx.Repo.IsViewTag { err = repo_module.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName) @@ -432,6 +440,12 @@ func CreateBranch(ctx *context.Context) { return } + if form.CreateTag { + ctx.Flash.Success(ctx.Tr("repo.tag.create_success", form.NewBranchName)) + ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + util.PathEscapeSegments(form.NewBranchName)) + return + } + ctx.Flash.Success(ctx.Tr("repo.branch.create_success", form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(form.NewBranchName)) } diff --git a/routers/repo/release.go b/routers/repo/release.go index b4370bb09b..d89a173669 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -262,6 +262,29 @@ func NewReleasePost(ctx *context.Context) { return } + msg := "" + if len(form.Title) > 0 && form.AddTagMsg { + msg = form.Title + "\n\n" + form.Content + } + + if len(form.TagOnly) > 0 { + if err = releaseservice.CreateNewTag(ctx.User, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil { + if models.IsErrTagAlreadyExists(err) { + e := err.(models.ErrTagAlreadyExists) + ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName)) + ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) + return + } + + ctx.ServerError("releaseservice.CreateNewTag", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.tag.create_success", form.TagName)) + ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + form.TagName) + return + } + rel = &models.Release{ RepoID: ctx.Repo.Repository.ID, PublisherID: ctx.User.ID, @@ -274,7 +297,7 @@ func NewReleasePost(ctx *context.Context) { IsTag: false, } - if err = releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs); err != nil { + if err = releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil { ctx.Data["Err_TagName"] = true switch { case models.IsErrReleaseAlreadyExist(err): diff --git a/services/mirror/mirror_test.go b/services/mirror/mirror_test.go index ddfb6c676b..57628aa68d 100644 --- a/services/mirror/mirror_test.go +++ b/services/mirror/mirror_test.go @@ -69,7 +69,7 @@ func TestRelease_MirrorDelete(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: true, - }, nil)) + }, nil, "")) err = mirror.GetMirror() assert.NoError(t, err) diff --git a/services/release/release.go b/services/release/release.go index fd821cc813..d04e538c92 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -17,7 +17,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" ) -func createTag(gitRepo *git.Repository, rel *models.Release) error { +func createTag(gitRepo *git.Repository, rel *models.Release, msg string) error { // Only actual create when publish. if !rel.IsDraft { if !gitRepo.IsTagExist(rel.TagName) { @@ -28,7 +28,16 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { // Trim '--' prefix to prevent command line argument vulnerability. rel.TagName = strings.TrimPrefix(rel.TagName, "--") - if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { + if len(msg) > 0 { + if err = gitRepo.CreateAnnotatedTag(rel.TagName, msg, commit.ID.String()); err != nil { + if strings.Contains(err.Error(), "is not a valid tag name") { + return models.ErrInvalidTagName{ + TagName: rel.TagName, + } + } + return err + } + } else if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { if strings.Contains(err.Error(), "is not a valid tag name") { return models.ErrInvalidTagName{ TagName: rel.TagName, @@ -77,7 +86,7 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { } // CreateRelease creates a new release of repository. -func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error { +func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string, msg string) error { isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName) if err != nil { return err @@ -87,7 +96,7 @@ func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs } } - if err = createTag(gitRepo, rel); err != nil { + if err = createTag(gitRepo, rel, msg); err != nil { return err } @@ -107,9 +116,47 @@ func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs return nil } +// CreateNewTag creates a new repository tag +func CreateNewTag(doer *models.User, repo *models.Repository, commit, tagName, msg string) error { + isExist, err := models.IsReleaseExist(repo.ID, tagName) + if err != nil { + return err + } else if isExist { + return models.ErrTagAlreadyExists{ + TagName: tagName, + } + } + + gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + return err + } + defer gitRepo.Close() + + rel := &models.Release{ + RepoID: repo.ID, + PublisherID: doer.ID, + TagName: tagName, + Target: commit, + IsDraft: false, + IsPrerelease: false, + IsTag: true, + } + + if err = createTag(gitRepo, rel, msg); err != nil { + return err + } + + if err = models.InsertRelease(rel); err != nil { + return err + } + + return err +} + // UpdateReleaseOrCreatReleaseFromTag updates information of a release or create release from tag. func UpdateReleaseOrCreatReleaseFromTag(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string, isCreate bool) (err error) { - if err = createTag(gitRepo, rel); err != nil { + if err = createTag(gitRepo, rel, ""); err != nil { return err } rel.LowerTagName = strings.ToLower(rel.TagName) diff --git a/services/release/release_test.go b/services/release/release_test.go index f50fca71ec..deb0618832 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -40,7 +40,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) assert.NoError(t, CreateRelease(gitRepo, &models.Release{ RepoID: repo.ID, @@ -52,7 +52,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) assert.NoError(t, CreateRelease(gitRepo, &models.Release{ RepoID: repo.ID, @@ -64,7 +64,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) assert.NoError(t, CreateRelease(gitRepo, &models.Release{ RepoID: repo.ID, @@ -76,7 +76,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: true, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) assert.NoError(t, CreateRelease(gitRepo, &models.Release{ RepoID: repo.ID, @@ -88,7 +88,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: false, IsPrerelease: true, IsTag: false, - }, nil)) + }, nil, "")) assert.NoError(t, CreateRelease(gitRepo, &models.Release{ RepoID: repo.ID, @@ -100,7 +100,7 @@ func TestRelease_Create(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: true, - }, nil)) + }, nil, "test")) } func TestRelease_Update(t *testing.T) { @@ -125,7 +125,7 @@ func TestRelease_Update(t *testing.T) { IsDraft: false, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) release, err := models.GetRelease(repo.ID, "v1.1.1") assert.NoError(t, err) releaseCreatedUnix := release.CreatedUnix @@ -147,7 +147,7 @@ func TestRelease_Update(t *testing.T) { IsDraft: true, IsPrerelease: false, IsTag: false, - }, nil)) + }, nil, "")) release, err = models.GetRelease(repo.ID, "v1.2.1") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix @@ -169,7 +169,7 @@ func TestRelease_Update(t *testing.T) { IsDraft: false, IsPrerelease: true, IsTag: false, - }, nil)) + }, nil, "")) release, err = models.GetRelease(repo.ID, "v1.3.1") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix @@ -205,12 +205,12 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) assert.NotEmpty(t, release.CreatedUnix) releaseCreatedUnix := release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Note = "Changed note" - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) // Test a changed draft @@ -225,11 +225,11 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) // Test a changed pre-release @@ -244,11 +244,20 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: true, IsTag: false, } - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" release.Note = "Changed note" - assert.NoError(t, createTag(gitRepo, release)) + assert.NoError(t, createTag(gitRepo, release, "")) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) } + +func TestCreateNewTag(t *testing.T) { + assert.NoError(t, models.PrepareTestDatabase()) + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + + assert.NoError(t, CreateNewTag(user, repo, "master", "v2.0", + "v2.0 is released \n\n BUGFIX: .... \n\n 123")) +} diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl index 5dd0553d48..ca805fa587 100644 --- a/templates/repo/branch_dropdown.tmpl +++ b/templates/repo/branch_dropdown.tmpl @@ -24,12 +24,12 @@