+28
-4
appview/state/pull.go
+28
-4
appview/state/pull.go
···
558
sourceBranch := r.FormValue("sourceBranch")
559
patch := r.FormValue("patch")
560
561
-
// Validate required fields for all PR types
562
-
if title == "" || body == "" || targetBranch == "" {
563
-
s.pages.Notice(w, "pull", "Title, body and target branch are required.")
564
return
565
}
566
567
us, err := NewUnsignedClient(f.Knot, s.config.Dev)
568
if err != nil {
569
-
log.Println("failed to create unsigned client to %s: %v", f.Knot, err)
570
s.pages.Notice(w, "pull", "Failed to create a pull request. Try again later.")
571
return
572
}
···
816
}
817
818
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pullId))
819
}
820
821
func (s *State) PatchUploadFragment(w http.ResponseWriter, r *http.Request) {
···
558
sourceBranch := r.FormValue("sourceBranch")
559
patch := r.FormValue("patch")
560
561
+
if targetBranch == "" {
562
+
s.pages.Notice(w, "pull", "Target branch is required.")
563
return
564
}
565
566
us, err := NewUnsignedClient(f.Knot, s.config.Dev)
567
if err != nil {
568
+
log.Printf("failed to create unsigned client to %s: %v", f.Knot, err)
569
s.pages.Notice(w, "pull", "Failed to create a pull request. Try again later.")
570
return
571
}
···
815
}
816
817
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pullId))
818
+
}
819
+
820
+
func (s *State) ValidatePatch(w http.ResponseWriter, r *http.Request) {
821
+
_, err := fullyResolvedRepo(r)
822
+
if err != nil {
823
+
log.Println("failed to get repo and knot", err)
824
+
return
825
+
}
826
+
827
+
patch := r.FormValue("patch")
828
+
if patch == "" {
829
+
s.pages.Notice(w, "patch-error", "Patch is required.")
830
+
return
831
+
}
832
+
833
+
if patch == "" || !patchutil.IsPatchValid(patch) {
834
+
s.pages.Notice(w, "patch-error", "Invalid patch format. Please provide a valid git diff or format-patch.")
835
+
return
836
+
}
837
+
838
+
if patchutil.IsFormatPatch(patch) {
839
+
s.pages.Notice(w, "patch-preview", "Format patch detected. Title and description are optional; if left out, they will be extracted from the first commit.")
840
+
} else {
841
+
s.pages.Notice(w, "patch-preview", "Regular diff detected. Please provide a title and description.")
842
+
}
843
}
844
845
func (s *State) PatchUploadFragment(w http.ResponseWriter, r *http.Request) {
+1
appview/state/router.go
+1
appview/state/router.go
···
96
r.With(AuthMiddleware(s)).Route("/new", func(r chi.Router) {
97
r.Get("/", s.NewPull)
98
r.Get("/patch-upload", s.PatchUploadFragment)
99
r.Get("/compare-branches", s.CompareBranchesFragment)
100
r.Get("/compare-forks", s.CompareForksFragment)
101
r.Get("/fork-branches", s.CompareForksBranchesFragment)
···
96
r.With(AuthMiddleware(s)).Route("/new", func(r chi.Router) {
97
r.Get("/", s.NewPull)
98
r.Get("/patch-upload", s.PatchUploadFragment)
99
+
r.Post("/validate-patch", s.ValidatePatch)
100
r.Get("/compare-branches", s.CompareBranchesFragment)
101
r.Get("/compare-forks", s.CompareForksFragment)
102
r.Get("/fork-branches", s.CompareForksBranchesFragment)
+10
-5
input.css
+10
-5
input.css
···
35
font-size: 15px;
36
}
37
@supports (font-variation-settings: normal) {
38
-
html {
39
-
font-feature-settings: 'ss01' 1, 'kern' 1, 'liga' 1, 'cv05' 1, 'tnum' 1;
40
-
}
41
}
42
43
a {
···
48
@apply block mb-2 text-gray-900 text-sm font-bold py-2 uppercase dark:text-gray-100;
49
}
50
input {
51
-
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400;
52
}
53
textarea {
54
-
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400;
55
}
56
details summary::-webkit-details-marker {
57
display: none;
···
35
font-size: 15px;
36
}
37
@supports (font-variation-settings: normal) {
38
+
html {
39
+
font-feature-settings:
40
+
"ss01" 1,
41
+
"kern" 1,
42
+
"liga" 1,
43
+
"cv05" 1,
44
+
"tnum" 1;
45
+
}
46
}
47
48
a {
···
53
@apply block mb-2 text-gray-900 text-sm font-bold py-2 uppercase dark:text-gray-100;
54
}
55
input {
56
+
@apply border border-gray-400 block rounded bg-gray-50 focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400;
57
}
58
textarea {
59
+
@apply border border-gray-400 block rounded bg-gray-50 focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400;
60
}
61
details summary::-webkit-details-marker {
62
display: none;
-3
patchutil/patchutil.go
-3
patchutil/patchutil.go