rin
Public Open-source lightweight git hosting.
repo_files.go · 131 lines · 4.2 KB
Raw
1 package handlers
2
3 import (
4 "fmt"
5 "net/url"
6 "strings"
7
8 "polar/internal/git"
9 "polar/internal/web/middleware"
10
11 "github.com/gofiber/fiber/v2"
12 )
13
14 // RepoNewFilePage renders the web form for creating a file.
15 // GET /:owner/:repo/new-file
16 func (h *Handler) RepoNewFilePage(c *fiber.Ctx) error {
17 return h.renderFileForm(c, "file")
18 }
19
20 // RepoNewFolderPage renders the form for creating a folder. Git cannot store
21 // empty directories, so the folder is tracked through a .gitkeep placeholder.
22 // GET /:owner/:repo/new-folder
23 func (h *Handler) RepoNewFolderPage(c *fiber.Ctx) error {
24 return h.renderFileForm(c, "folder")
25 }
26
27 func (h *Handler) renderFileForm(c *fiber.Ctx, mode string) error {
28 r, diskPath, err := h.loadAuthorizedRepo(c, true)
29 if err != nil {
30 return nil
31 }
32
33 titleKey := "file.new_file"
34 if mode == "folder" {
35 titleKey = "file.new_folder"
36 }
37
38 ref := strings.TrimSpace(c.Query("ref"))
39 if ref == "" {
40 ref, _ = git.EnsureDefaultBranch(c.UserContext(), diskPath, r.DefaultBranch)
41 }
42 subPath := strings.Trim(strings.ReplaceAll(c.Query("path"), "\\", "/"), "/")
43
44 data := h.baseData(c, h.tr(c, titleKey))
45 data["Repo"] = r
46 data["Ref"] = ref
47 data["SubPath"] = subPath
48 data["Mode"] = mode
49 data["ActiveTab"] = "code"
50 data["CanWrite"] = true
51 data["Branches"], _ = git.ListBranches(c.UserContext(), diskPath)
52 return h.render(c, fiber.StatusOK, "file_new", data)
53 }
54
55 // RepoCreateFileSubmit commits a new file to the selected branch.
56 // POST /:owner/:repo/new-file
57 func (h *Handler) RepoCreateFileSubmit(c *fiber.Ctx) error {
58 r, diskPath, err := h.loadAuthorizedRepo(c, true)
59 if err != nil {
60 return nil
61 }
62 u := middleware.CurrentUser(c)
63
64 ref := strings.TrimSpace(c.FormValue("ref"))
65 if ref == "" || !git.BranchExists(c.UserContext(), diskPath, ref) {
66 ref, _ = git.EnsureDefaultBranch(c.UserContext(), diskPath, r.DefaultBranch)
67 }
68
69 filePath := strings.TrimSpace(c.FormValue("path"))
70 message := strings.TrimSpace(c.FormValue("message"))
71 content := c.FormValue("content")
72
73 backTo := fmt.Sprintf("/%s/%s/new-file?ref=%s", r.OwnerUsername, r.Name, url.QueryEscape(ref))
74
75 clean, cerr := git.CleanSubPath(filePath)
76 if cerr != nil || clean == "" {
77 h.setFlashT(c, "flash.path_invalid")
78 return c.Redirect(backTo, fiber.StatusSeeOther)
79 }
80 if blob, rerr := git.ReadBlob(c.UserContext(), diskPath, ref, clean); rerr == nil && blob != nil {
81 h.setFlashT(c, "flash.file_exists")
82 return c.Redirect(backTo+"&path="+url.QueryEscape(clean), fiber.StatusSeeOther)
83 }
84 if message == "" {
85 message = "Add " + clean
86 }
87 if _, werr := git.WriteFileCommit(c.UserContext(), diskPath, ref, clean, []byte(content), message, u.Username, u.Email); werr != nil {
88 h.setFlashT(c, "flash.file_create_failed")
89 return c.Redirect(backTo+"&path="+url.QueryEscape(clean), fiber.StatusSeeOther)
90 }
91
92 h.setFlashT(c, "flash.file_created")
93 return c.Redirect(fmt.Sprintf("/%s/%s/blob/%s/%s", r.OwnerUsername, r.Name, ref, clean), fiber.StatusSeeOther)
94 }
95
96 // RepoCreateFolderSubmit commits a .gitkeep placeholder so the new folder is
97 // tracked by git.
98 // POST /:owner/:repo/new-folder
99 func (h *Handler) RepoCreateFolderSubmit(c *fiber.Ctx) error {
100 r, diskPath, err := h.loadAuthorizedRepo(c, true)
101 if err != nil {
102 return nil
103 }
104 u := middleware.CurrentUser(c)
105
106 ref := strings.TrimSpace(c.FormValue("ref"))
107 if ref == "" || !git.BranchExists(c.UserContext(), diskPath, ref) {
108 ref, _ = git.EnsureDefaultBranch(c.UserContext(), diskPath, r.DefaultBranch)
109 }
110
111 folder := strings.TrimSpace(c.FormValue("path"))
112 message := strings.TrimSpace(c.FormValue("message"))
113
114 backTo := fmt.Sprintf("/%s/%s/new-folder?ref=%s", r.OwnerUsername, r.Name, url.QueryEscape(ref))
115
116 clean, cerr := git.CleanSubPath(folder)
117 if cerr != nil || clean == "" {
118 h.setFlashT(c, "flash.path_invalid")
119 return c.Redirect(backTo, fiber.StatusSeeOther)
120 }
121 if message == "" {
122 message = "Create folder " + clean
123 }
124 if _, werr := git.WriteFileCommit(c.UserContext(), diskPath, ref, clean+"/.gitkeep", nil, message, u.Username, u.Email); werr != nil {
125 h.setFlashT(c, "flash.folder_create_failed")
126 return c.Redirect(backTo, fiber.StatusSeeOther)
127 }
128
129 h.setFlashT(c, "flash.folder_created")
130 return c.Redirect(fmt.Sprintf("/%s/%s/tree/%s/%s", r.OwnerUsername, r.Name, ref, clean), fiber.StatusSeeOther)
131 }
132