mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-26 09:09:36 -05:00
enhancement: add signoff option in commit form (#14516)
Signed-off-by: a1012112796 <1012112796@qq.com>
This commit is contained in:
parent
f761c82c94
commit
f19da14c34
11 changed files with 51 additions and 8 deletions
|
@ -698,6 +698,7 @@ type EditRepoFileForm struct {
|
||||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||||
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
||||||
LastCommit string
|
LastCommit string
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
@ -733,6 +734,7 @@ type UploadRepoFileForm struct {
|
||||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||||
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
||||||
Files []string
|
Files []string
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
@ -766,6 +768,7 @@ type DeleteRepoFileForm struct {
|
||||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||||
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
NewBranchName string `binding:"GitRefName;MaxSize(100)"`
|
||||||
LastCommit string
|
LastCommit string
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
|
|
@ -25,6 +25,7 @@ type DeleteRepoFileOptions struct {
|
||||||
Author *IdentityOptions
|
Author *IdentityOptions
|
||||||
Committer *IdentityOptions
|
Committer *IdentityOptions
|
||||||
Dates *CommitDateOptions
|
Dates *CommitDateOptions
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRepoFile deletes a file in the given repository
|
// DeleteRepoFile deletes a file in the given repository
|
||||||
|
@ -199,9 +200,9 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
|
||||||
// Now commit the tree
|
// Now commit the tree
|
||||||
var commitHash string
|
var commitHash string
|
||||||
if opts.Dates != nil {
|
if opts.Dates != nil {
|
||||||
commitHash, err = t.CommitTreeWithDate(author, committer, treeHash, message, opts.Dates.Author, opts.Dates.Committer)
|
commitHash, err = t.CommitTreeWithDate(author, committer, treeHash, message, opts.Signoff, opts.Dates.Author, opts.Dates.Committer)
|
||||||
} else {
|
} else {
|
||||||
commitHash, err = t.CommitTree(author, committer, treeHash, message)
|
commitHash, err = t.CommitTree(author, committer, treeHash, message, opts.Signoff)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -185,12 +185,12 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ref string) (string, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitTree creates a commit from a given tree for the user with provided message
|
// CommitTree creates a commit from a given tree for the user with provided message
|
||||||
func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, treeHash string, message string) (string, error) {
|
func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, treeHash string, message string, signoff bool) (string, error) {
|
||||||
return t.CommitTreeWithDate(author, committer, treeHash, message, time.Now(), time.Now())
|
return t.CommitTreeWithDate(author, committer, treeHash, message, signoff, time.Now(), time.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitTreeWithDate creates a commit from a given tree for the user with provided message
|
// CommitTreeWithDate creates a commit from a given tree for the user with provided message
|
||||||
func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *models.User, treeHash string, message string, authorDate, committerDate time.Time) (string, error) {
|
func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *models.User, treeHash string, message string, signoff bool, authorDate, committerDate time.Time) (string, error) {
|
||||||
authorSig := author.NewGitSig()
|
authorSig := author.NewGitSig()
|
||||||
committerSig := committer.NewGitSig()
|
committerSig := committer.NewGitSig()
|
||||||
|
|
||||||
|
@ -236,6 +236,13 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *models
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if signoff {
|
||||||
|
// Signed-off-by
|
||||||
|
_, _ = messageBytes.WriteString("\n")
|
||||||
|
_, _ = messageBytes.WriteString("Signed-off-by: ")
|
||||||
|
_, _ = messageBytes.WriteString(committerSig.String())
|
||||||
|
}
|
||||||
|
|
||||||
env = append(env,
|
env = append(env,
|
||||||
"GIT_COMMITTER_NAME="+committerSig.Name,
|
"GIT_COMMITTER_NAME="+committerSig.Name,
|
||||||
"GIT_COMMITTER_EMAIL="+committerSig.Email,
|
"GIT_COMMITTER_EMAIL="+committerSig.Email,
|
||||||
|
|
|
@ -51,6 +51,7 @@ type UpdateRepoFileOptions struct {
|
||||||
Author *IdentityOptions
|
Author *IdentityOptions
|
||||||
Committer *IdentityOptions
|
Committer *IdentityOptions
|
||||||
Dates *CommitDateOptions
|
Dates *CommitDateOptions
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func detectEncodingAndBOM(entry *git.TreeEntry, repo *models.Repository) (string, bool) {
|
func detectEncodingAndBOM(entry *git.TreeEntry, repo *models.Repository) (string, bool) {
|
||||||
|
@ -417,9 +418,9 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
|
||||||
// Now commit the tree
|
// Now commit the tree
|
||||||
var commitHash string
|
var commitHash string
|
||||||
if opts.Dates != nil {
|
if opts.Dates != nil {
|
||||||
commitHash, err = t.CommitTreeWithDate(author, committer, treeHash, message, opts.Dates.Author, opts.Dates.Committer)
|
commitHash, err = t.CommitTreeWithDate(author, committer, treeHash, message, opts.Signoff, opts.Dates.Author, opts.Dates.Committer)
|
||||||
} else {
|
} else {
|
||||||
commitHash, err = t.CommitTree(author, committer, treeHash, message)
|
commitHash, err = t.CommitTree(author, committer, treeHash, message, opts.Signoff)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -24,6 +24,7 @@ type UploadRepoFileOptions struct {
|
||||||
TreePath string
|
TreePath string
|
||||||
Message string
|
Message string
|
||||||
Files []string // In UUID format.
|
Files []string // In UUID format.
|
||||||
|
Signoff bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type uploadInfo struct {
|
type uploadInfo struct {
|
||||||
|
@ -143,7 +144,7 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
|
||||||
committer := doer
|
committer := doer
|
||||||
|
|
||||||
// Now commit the tree
|
// Now commit the tree
|
||||||
commitHash, err := t.CommitTree(author, committer, treeHash, opts.Message)
|
commitHash, err := t.CommitTree(author, committer, treeHash, opts.Message, opts.Signoff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ type FileOptions struct {
|
||||||
Author Identity `json:"author"`
|
Author Identity `json:"author"`
|
||||||
Committer Identity `json:"committer"`
|
Committer Identity `json:"committer"`
|
||||||
Dates CommitDateOptions `json:"dates"`
|
Dates CommitDateOptions `json:"dates"`
|
||||||
|
// Add a Signed-off-by trailer by the committer at the end of the commit log message.
|
||||||
|
Signoff bool `json:"signoff"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileOptions options for creating files
|
// CreateFileOptions options for creating files
|
||||||
|
|
|
@ -874,6 +874,7 @@ editor.add = Add '%s'
|
||||||
editor.update = Update '%s'
|
editor.update = Update '%s'
|
||||||
editor.delete = Delete '%s'
|
editor.delete = Delete '%s'
|
||||||
editor.commit_message_desc = Add an optional extended description…
|
editor.commit_message_desc = Add an optional extended description…
|
||||||
|
editor.signoff_desc = Add a Signed-off-by trailer by the committer at the end of the commit log message.
|
||||||
editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
|
editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
|
||||||
editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
|
editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
|
||||||
editor.create_new_branch_np = Create a <strong>new branch</strong> for this commit.
|
editor.create_new_branch_np = Create a <strong>new branch</strong> for this commit.
|
||||||
|
|
|
@ -235,6 +235,7 @@ func CreateFile(ctx *context.APIContext) {
|
||||||
Author: apiOpts.Dates.Author,
|
Author: apiOpts.Dates.Author,
|
||||||
Committer: apiOpts.Dates.Committer,
|
Committer: apiOpts.Dates.Committer,
|
||||||
},
|
},
|
||||||
|
Signoff: apiOpts.Signoff,
|
||||||
}
|
}
|
||||||
if opts.Dates.Author.IsZero() {
|
if opts.Dates.Author.IsZero() {
|
||||||
opts.Dates.Author = time.Now()
|
opts.Dates.Author = time.Now()
|
||||||
|
@ -323,6 +324,7 @@ func UpdateFile(ctx *context.APIContext) {
|
||||||
Author: apiOpts.Dates.Author,
|
Author: apiOpts.Dates.Author,
|
||||||
Committer: apiOpts.Dates.Committer,
|
Committer: apiOpts.Dates.Committer,
|
||||||
},
|
},
|
||||||
|
Signoff: apiOpts.Signoff,
|
||||||
}
|
}
|
||||||
if opts.Dates.Author.IsZero() {
|
if opts.Dates.Author.IsZero() {
|
||||||
opts.Dates.Author = time.Now()
|
opts.Dates.Author = time.Now()
|
||||||
|
@ -449,6 +451,7 @@ func DeleteFile(ctx *context.APIContext) {
|
||||||
Author: apiOpts.Dates.Author,
|
Author: apiOpts.Dates.Author,
|
||||||
Committer: apiOpts.Dates.Committer,
|
Committer: apiOpts.Dates.Committer,
|
||||||
},
|
},
|
||||||
|
Signoff: apiOpts.Signoff,
|
||||||
}
|
}
|
||||||
if opts.Dates.Author.IsZero() {
|
if opts.Dates.Author.IsZero() {
|
||||||
opts.Dates.Author = time.Now()
|
opts.Dates.Author = time.Now()
|
||||||
|
|
|
@ -240,6 +240,7 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||||
Message: message,
|
Message: message,
|
||||||
Content: strings.ReplaceAll(form.Content, "\r", ""),
|
Content: strings.ReplaceAll(form.Content, "\r", ""),
|
||||||
IsNewFile: isNewFile,
|
IsNewFile: isNewFile,
|
||||||
|
Signoff: form.Signoff,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
// This is where we handle all the errors thrown by repofiles.CreateOrUpdateRepoFile
|
// This is where we handle all the errors thrown by repofiles.CreateOrUpdateRepoFile
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
|
@ -442,6 +443,7 @@ func DeleteFilePost(ctx *context.Context) {
|
||||||
NewBranch: branchName,
|
NewBranch: branchName,
|
||||||
TreePath: ctx.Repo.TreePath,
|
TreePath: ctx.Repo.TreePath,
|
||||||
Message: message,
|
Message: message,
|
||||||
|
Signoff: form.Signoff,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
|
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
|
||||||
if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
|
if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
|
||||||
|
@ -650,6 +652,7 @@ func UploadFilePost(ctx *context.Context) {
|
||||||
TreePath: form.TreePath,
|
TreePath: form.TreePath,
|
||||||
Message: message,
|
Message: message,
|
||||||
Files: form.Files,
|
Files: form.Files,
|
||||||
|
Signoff: form.Signoff,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if models.IsErrLFSFileLocked(err) {
|
if models.IsErrLFSFileLocked(err) {
|
||||||
ctx.Data["Err_TreePath"] = true
|
ctx.Data["Err_TreePath"] = true
|
||||||
|
|
|
@ -14,6 +14,12 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.editor.commit_message_desc"}}" rows="5">{{.commit_message}}</textarea>
|
<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.editor.commit_message_desc"}}" rows="5">{{.commit_message}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="signoff" type="checkbox" tabindex="0" class="hidden">
|
||||||
|
<label>{{.i18n.Tr "repo.editor.signoff_desc"}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="quick-pull-choice js-quick-pull-choice">
|
<div class="quick-pull-choice js-quick-pull-choice">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui radio checkbox {{if not .CanCommitToBranch.CanCommitToBranch}}disabled{{end}}">
|
<div class="ui radio checkbox {{if not .CanCommitToBranch.CanCommitToBranch}}disabled{{end}}">
|
||||||
|
|
|
@ -12023,6 +12023,11 @@
|
||||||
"description": "new_branch (optional) will make a new branch from `branch` before creating the file",
|
"description": "new_branch (optional) will make a new branch from `branch` before creating the file",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "NewBranchName"
|
"x-go-name": "NewBranchName"
|
||||||
|
},
|
||||||
|
"signoff": {
|
||||||
|
"description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "Signoff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -12731,6 +12736,11 @@
|
||||||
"description": "sha is the SHA for the file that already exists",
|
"description": "sha is the SHA for the file that already exists",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "SHA"
|
"x-go-name": "SHA"
|
||||||
|
},
|
||||||
|
"signoff": {
|
||||||
|
"description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "Signoff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -15762,6 +15772,11 @@
|
||||||
"description": "sha is the SHA for the file that already exists",
|
"description": "sha is the SHA for the file that already exists",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "SHA"
|
"x-go-name": "SHA"
|
||||||
|
},
|
||||||
|
"signoff": {
|
||||||
|
"description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "Signoff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
|
Loading…
Reference in a new issue