Add commit fields to web file editor

This commit is contained in:
2026-06-08 15:29:39 -05:00
parent c025fbe946
commit f2d8743b6b
4 changed files with 61 additions and 11 deletions
+44 -8
View File
@@ -75,10 +75,12 @@ type webBlobData struct {
}
type webEditData struct {
Repo Repository
Ref string
Path string
Content string
Repo Repository
Ref string
Path string
Content string
CommitMessage string
CommitDescription string
}
type webTreeEntry struct {
@@ -337,6 +339,9 @@ var webTemplates = template.Must(template.New("web").Funcs(template.FuncMap{
<p><label>Branch<br><input name="ref" value="{{$d.Ref}}"></label></p>
<p><label>Path<br><input name="path" value="{{$d.Path}}" size="80"></label></p>
<p><label>Content<br><textarea name="content" rows="24" cols="100">{{$d.Content}}</textarea></label></p>
<h2>Commit</h2>
<p><label>Commit message<br><input name="commit_message" value="{{$d.CommitMessage}}" size="80"></label></p>
<p><label>Extended description<br><textarea name="commit_description" rows="4" cols="80">{{$d.CommitDescription}}</textarea></label></p>
<p><button type="submit">commit changes</button></p>
</form>
{{end}}
@@ -964,7 +969,7 @@ func (s *Server) webRepoEdit(w http.ResponseWriter, r *http.Request, owner, name
content = c
}
}
s.renderWeb(w, r, "Edit File", webEditData{Repo: repo, Ref: ref, Path: p, Content: content}, errMsg)
s.renderWeb(w, r, "Edit File", webEditData{Repo: repo, Ref: ref, Path: p, Content: content, CommitMessage: defaultEditCommitMessage(p)}, errMsg)
}
func (s *Server) webRepoEditPost(w http.ResponseWriter, r *http.Request, owner, name string) {
@@ -993,7 +998,12 @@ func (s *Server) webRepoEditPost(w http.ResponseWriter, r *http.Request, owner,
s.webRepoEdit(w, r, owner, name, err.Error())
return
}
if err := s.commitEditedFile(repo, ref, p, r.FormValue("content"), user); err != nil {
message, description, err := editCommitFields(p, r.FormValue("commit_message"), r.FormValue("commit_description"))
if err != nil {
s.webRepoEdit(w, r, owner, name, err.Error())
return
}
if err := s.commitEditedFile(repo, ref, p, r.FormValue("content"), message, description, user); err != nil {
s.webRepoEdit(w, r, owner, name, err.Error())
return
}
@@ -1664,7 +1674,29 @@ func renderMarkdown(s string) (template.HTML, error) {
return template.HTML(buf.String()), nil
}
func (s *Server) commitEditedFile(repo Repository, ref, p, content string, user User) error {
func defaultEditCommitMessage(p string) string {
if p == "" {
return "Create file"
}
return "Edit " + p
}
func editCommitFields(p, message, description string) (string, string, error) {
message = strings.TrimSpace(message)
description = strings.TrimSpace(description)
if message == "" {
message = defaultEditCommitMessage(p)
}
if strings.ContainsAny(message, "\x00\r\n") {
return "", "", errors.New("commit message must be a single line")
}
if strings.Contains(description, "\x00") {
return "", "", errors.New("commit description is invalid")
}
return message, description, nil
}
func (s *Server) commitEditedFile(repo Repository, ref, p, content, message, description string, user User) error {
if !branchRE.MatchString(ref) {
return errors.New("invalid branch")
}
@@ -1702,7 +1734,11 @@ func (s *Server) commitEditedFile(repo Repository, ref, p, content string, user
if err := gitRunOutput(work, "add", filepath.FromSlash(p)); err != nil {
return err
}
if err := gitRunOutput(work, "commit", "-m", "Edit "+p); err != nil {
args := []string{"commit", "-m", message}
if description != "" {
args = append(args, "-m", description)
}
if err := gitRunOutput(work, args...); err != nil {
if strings.Contains(err.Error(), "nothing to commit") {
return nil
}
+15 -1
View File
@@ -197,7 +197,17 @@ func TestWebRepoPagesCreateEditAndForkRules(t *testing.T) {
expectLoadRepo(mock, "alice", "demo", repo)
expectBearerUser(mock, "tok", user)
rr = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodPost, "/alice/demo/edit", strings.NewReader("_csrf="+csrf.Value+"&ref=main&path=web.txt&content=from+web"))
req = httptest.NewRequest(http.MethodGet, "/alice/demo/edit?ref=main&path=README.md", nil)
req.AddCookie(&http.Cookie{Name: webAuthCookie, Value: "tok"})
s.ServeHTTP(rr, req)
if rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), "Commit message") || !strings.Contains(rr.Body.String(), "Extended description") || !strings.Contains(rr.Body.String(), "Edit README.md") {
t.Fatalf("edit page status=%d body=%s", rr.Code, rr.Body.String())
}
expectLoadRepo(mock, "alice", "demo", repo)
expectBearerUser(mock, "tok", user)
rr = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodPost, "/alice/demo/edit", strings.NewReader("_csrf="+csrf.Value+"&ref=main&path=web.txt&content=from+web&commit_message=Custom+web+commit&commit_description=Detailed+body"))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.AddCookie(csrf)
req.AddCookie(&http.Cookie{Name: webAuthCookie, Value: "tok"})
@@ -209,6 +219,10 @@ func TestWebRepoPagesCreateEditAndForkRules(t *testing.T) {
if err != nil || !strings.Contains(content, "from web") {
t.Fatalf("edited file content=%q err=%v", content, err)
}
commits, err := gitCommitHistory(bare, "main", 1)
if err != nil || len(commits) != 1 || commits[0].Subject != "Custom web commit" || !strings.Contains(commits[0].Body, "Detailed body") {
t.Fatalf("edited commit history=%#v err=%v", commits, err)
}
privateRepo := repo
privateRepo.Visibility = "private"