mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-29 15:13:53 +03:00
f90928507a
Git has a cool feature called git notes. It allows adding a text to a commit without changing the commit itself. Forgejo already displays git notes. With this PR you can also now change git notes. <details> <summary>Screenshots</summary> ![grafik](/attachments/53a9546b-c4db-4b07-92ae-eb15b209b21d) ![grafik](/attachments/1bd96f2c-6178-45d2-93d7-d19c7cbe5898) ![grafik](/attachments/9ea73623-25d1-4628-a43f-f5ecbd431788) ![grafik](/attachments/efea0c9e-43c6-4441-bb7e-948177bf9021) </details> ## Checklist The [developer guide](https://forgejo.org/docs/next/developer/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [x] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. <!--start release-notes-assistant--> ## Release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - Features - [PR](https://codeberg.org/forgejo/forgejo/pulls/4753): <!--number 4753 --><!--line 0 --><!--description QWxsb3cgY2hhbmdpbmcgZ2l0IG5vdGVz-->Allow changing git notes<!--description--> <!--end release-notes-assistant--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4753 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: JakobDev <jakobdev@gmx.de> Co-committed-by: JakobDev <jakobdev@gmx.de>
209 lines
5.5 KiB
Go
209 lines
5.5 KiB
Go
// Copyright 2021 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repo
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"code.gitea.io/gitea/modules/git"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
"code.gitea.io/gitea/modules/web"
|
|
"code.gitea.io/gitea/services/context"
|
|
"code.gitea.io/gitea/services/convert"
|
|
)
|
|
|
|
// GetNote Get a note corresponding to a single commit from a repository
|
|
func GetNote(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/git/notes/{sha} repository repoGetNote
|
|
// ---
|
|
// summary: Get a note corresponding to a single commit from a repository
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: sha
|
|
// in: path
|
|
// description: a git ref or commit sha
|
|
// type: string
|
|
// required: true
|
|
// - name: verification
|
|
// in: query
|
|
// description: include verification for every commit (disable for speedup, default 'true')
|
|
// type: boolean
|
|
// - name: files
|
|
// in: query
|
|
// description: include a list of affected files for every commit (disable for speedup, default 'true')
|
|
// type: boolean
|
|
// responses:
|
|
// "200":
|
|
// "$ref": "#/responses/Note"
|
|
// "422":
|
|
// "$ref": "#/responses/validationError"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
|
|
sha := ctx.Params(":sha")
|
|
if !git.IsValidRefPattern(sha) {
|
|
ctx.Error(http.StatusUnprocessableEntity, "no valid ref or sha", fmt.Sprintf("no valid ref or sha: %s", sha))
|
|
return
|
|
}
|
|
getNote(ctx, sha)
|
|
}
|
|
|
|
func getNote(ctx *context.APIContext, identifier string) {
|
|
if ctx.Repo.GitRepo == nil {
|
|
ctx.InternalServerError(fmt.Errorf("no open git repo"))
|
|
return
|
|
}
|
|
|
|
commitID, err := ctx.Repo.GitRepo.ConvertToGitID(identifier)
|
|
if err != nil {
|
|
if git.IsErrNotExist(err) {
|
|
ctx.NotFound(err)
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "ConvertToSHA1", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
var note git.Note
|
|
if err := git.GetNote(ctx, ctx.Repo.GitRepo, commitID.String(), ¬e); err != nil {
|
|
if git.IsErrNotExist(err) {
|
|
ctx.NotFound(identifier)
|
|
return
|
|
}
|
|
ctx.Error(http.StatusInternalServerError, "GetNote", err)
|
|
return
|
|
}
|
|
|
|
verification := ctx.FormString("verification") == "" || ctx.FormBool("verification")
|
|
files := ctx.FormString("files") == "" || ctx.FormBool("files")
|
|
|
|
cmt, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, note.Commit, nil,
|
|
convert.ToCommitOptions{
|
|
Stat: true,
|
|
Verification: verification,
|
|
Files: files,
|
|
})
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "ToCommit", err)
|
|
return
|
|
}
|
|
apiNote := api.Note{Message: string(note.Message), Commit: cmt}
|
|
ctx.JSON(http.StatusOK, apiNote)
|
|
}
|
|
|
|
// SetNote Sets a note corresponding to a single commit from a repository
|
|
func SetNote(ctx *context.APIContext) {
|
|
// swagger:operation POST /repos/{owner}/{repo}/git/notes/{sha} repository repoSetNote
|
|
// ---
|
|
// summary: Set a note corresponding to a single commit from a repository
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: sha
|
|
// in: path
|
|
// description: a git ref or commit sha
|
|
// type: string
|
|
// required: true
|
|
// - name: body
|
|
// in: body
|
|
// schema:
|
|
// "$ref": "#/definitions/NoteOptions"
|
|
// responses:
|
|
// "200":
|
|
// "$ref": "#/responses/Note"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
// "422":
|
|
// "$ref": "#/responses/validationError"
|
|
sha := ctx.Params(":sha")
|
|
if !git.IsValidRefPattern(sha) {
|
|
ctx.Error(http.StatusUnprocessableEntity, "no valid ref or sha", fmt.Sprintf("no valid ref or sha: %s", sha))
|
|
return
|
|
}
|
|
|
|
form := web.GetForm(ctx).(*api.NoteOptions)
|
|
|
|
err := git.SetNote(ctx, ctx.Repo.GitRepo, sha, form.Message, ctx.Doer.Name, ctx.Doer.GetEmail())
|
|
if err != nil {
|
|
if git.IsErrNotExist(err) {
|
|
ctx.NotFound(sha)
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "SetNote", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
getNote(ctx, sha)
|
|
}
|
|
|
|
// RemoveNote Removes a note corresponding to a single commit from a repository
|
|
func RemoveNote(ctx *context.APIContext) {
|
|
// swagger:operation DELETE /repos/{owner}/{repo}/git/notes/{sha} repository repoRemoveNote
|
|
// ---
|
|
// summary: Removes a note corresponding to a single commit from a repository
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: sha
|
|
// in: path
|
|
// description: a git ref or commit sha
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "204":
|
|
// "$ref": "#/responses/empty"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
// "422":
|
|
// "$ref": "#/responses/validationError"
|
|
sha := ctx.Params(":sha")
|
|
if !git.IsValidRefPattern(sha) {
|
|
ctx.Error(http.StatusUnprocessableEntity, "no valid ref or sha", fmt.Sprintf("no valid ref or sha: %s", sha))
|
|
return
|
|
}
|
|
|
|
err := git.RemoveNote(ctx, ctx.Repo.GitRepo, sha)
|
|
if err != nil {
|
|
if git.IsErrNotExist(err) {
|
|
ctx.NotFound(sha)
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "RemoveNote", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
ctx.Status(http.StatusNoContent)
|
|
}
|