forked from tangled.org/core
this repo has no description

appview: add stacking to NewPull form

Changed files
+96 -74
appview
pages
state
+6 -3
appview/pages/templates/repo/pulls/fragments/pullCompareBranches.html
···
{{ define "repo/pulls/fragments/pullCompareBranches" }}
<div id="patch-upload">
-
<label for="targetBranch" class="dark:text-white"
-
>select a branch</label
-
>
<div class="flex flex-wrap gap-2 items-center">
<select
name="sourceBranch"
···
{{ end }}
</select>
</div>
</div>
<p class="mt-4">
···
{{ define "repo/pulls/fragments/pullCompareBranches" }}
<div id="patch-upload">
+
<label for="targetBranch" class="dark:text-white">select a branch</label>
<div class="flex flex-wrap gap-2 items-center">
<select
name="sourceBranch"
···
{{ end }}
</select>
</div>
+
</div>
+
+
<div class="flex items-center gap-2">
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
</div>
<p class="mt-4">
+7 -1
appview/pages/templates/repo/pulls/fragments/pullCompareForks.html
···
<label for="forkSelect" class="dark:text-white"
>select a fork to compare</label
>
-
<div class="flex flex-wrap gap-4 items-center mb-4">
<div class="flex flex-wrap gap-2 items-center">
<select
id="forkSelect"
···
</div>
</div>
</div>
<p class="mt-4">
Title and description are optional; if left out, they will be extracted
from the first commit.
···
<label for="forkSelect" class="dark:text-white"
>select a fork to compare</label
>
+
<div class="flex flex-wrap gap-4 items-center">
<div class="flex flex-wrap gap-2 items-center">
<select
id="forkSelect"
···
</div>
</div>
</div>
+
+
<div class="flex items-center gap-2">
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
+
</div>
+
<p class="mt-4">
Title and description are optional; if left out, they will be extracted
from the first commit.
+59 -61
appview/pages/templates/repo/pulls/new.html
···
{{ define "repoContent" }}
<form
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
-
class="mt-6 space-y-6"
hx-indicator="#create-pull-spinner"
hx-swap="none"
>
-
<div class="flex flex-col gap-4">
-
<label>configure your pull request</label>
-
-
<p>First, choose a target branch on {{ .RepoInfo.FullName }}.</p>
-
<div class="pb-2">
<select
-
required
-
name="targetBranch"
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
-
>
-
<option disabled selected>target branch</option>
-
{{ range .Branches }}
-
<option value="{{ .Reference.Name }}" class="py-1" {{if .IsDefault}}selected{{end}}>
-
{{ .Reference.Name }}
-
</option>
-
{{ end }}
</select>
</div>
-
<p>Next, choose a pull strategy.</p>
-
<nav class="flex space-x-4 items-end">
-
<button
-
type="button"
-
class="px-3 py-2 pb-2 btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML"
-
>
-
paste patch
-
</button>
-
-
{{ if .RepoInfo.Roles.IsPushAllowed }}
-
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
-
or
-
</span>
-
<button
-
type="button"
-
class="px-3 py-2 pb-2 btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML"
-
>
-
compare branches
-
</button>
-
{{ end }}
-
-
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
-
or
-
</span>
-
<button
-
type="button"
-
class="px-3 py-2 pb-2 btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML"
-
>
-
compare forks
-
</button>
-
</nav>
-
<section id="patch-strategy">
-
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
-
</section>
-
<p id="patch-preview"></p>
-
<div id="patch-error" class="error dark:text-red-300"></div>
<div>
<label for="title" class="dark:text-white">write a title</label>
···
{{ define "repoContent" }}
<form
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
hx-indicator="#create-pull-spinner"
hx-swap="none"
>
+
<div class="flex flex-col gap-6">
+
<div class="flex gap-2 items-center">
+
<p>First, choose a target branch on {{ .RepoInfo.FullName }}:</p>
+
<div>
<select
+
required
+
name="targetBranch"
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
>
+
<option disabled selected>target branch</option>
+
{{ range .Branches }}
+
<option value="{{ .Reference.Name }}" class="py-1" {{if .IsDefault}}selected{{end}}>
+
{{ .Reference.Name }}
+
</option>
+
{{ end }}
</select>
+
</div>
</div>
+
<div class="flex flex-col gap-2">
+
<p>Next, choose a pull strategy.</p>
+
<nav class="flex space-x-4 items-center">
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
>
+
paste patch
+
</button>
+
{{ if .RepoInfo.Roles.IsPushAllowed }}
+
<span class="text-sm text-gray-500 dark:text-gray-400">
+
or
+
</span>
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
>
+
compare branches
+
</button>
+
{{ end }}
+
<span class="text-sm text-gray-500 dark:text-gray-400">
+
or
+
</span>
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
>
+
compare forks
+
</button>
+
</nav>
+
<section id="patch-strategy" class="flex flex-col gap-2">
+
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
+
</section>
+
<div id="patch-error" class="error dark:text-red-300"></div>
+
</div>
<div>
<label for="title" class="dark:text-white">write a title</label>
+24 -9
appview/state/pull.go
···
isBranchBased := isPushAllowed && sourceBranch != "" && fromFork == ""
isForkBased := fromFork != "" && sourceBranch != ""
isPatchBased := patch != "" && !isBranchBased && !isForkBased
if isPatchBased && !patchutil.IsFormatPatch(patch) {
if title == "" {
···
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
return
}
-
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch)
} else if isForkBased {
if !caps.PullRequests.ForkSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
return
}
-
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch)
} else if isPatchBased {
if !caps.PullRequests.PatchSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
return
}
-
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch)
}
return
}
}
-
func (s *State) handleBranchBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *oauth.User, title, body, targetBranch, sourceBranch string) {
pullSource := &db.PullSource{
Branch: sourceBranch,
}
···
return
}
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource)
}
-
func (s *State) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *oauth.User, title, body, targetBranch, patch string) {
if !patchutil.IsPatchValid(patch) {
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
return
}
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", nil, nil)
}
-
func (s *State) handleForkBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *oauth.User, forkRepo string, title, body, targetBranch, sourceBranch string) {
fork, err := db.GetForkByDid(s.db, user.Did, forkRepo)
if errors.Is(err, sql.ErrNoRows) {
s.pages.Notice(w, "pull", "No such fork.")
···
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, &db.PullSource{
Branch: sourceBranch,
RepoAt: &forkAtUri,
-
}, &tangled.RepoPull_Source{Branch: sourceBranch, Repo: &fork.AtUri})
}
func (s *State) createPullRequest(
···
sourceRev string,
pullSource *db.PullSource,
recordPullSource *tangled.RepoPull_Source,
) {
tx, err := s.db.BeginTx(r.Context(), nil)
if err != nil {
log.Println("failed to start tx")
···
isBranchBased := isPushAllowed && sourceBranch != "" && fromFork == ""
isForkBased := fromFork != "" && sourceBranch != ""
isPatchBased := patch != "" && !isBranchBased && !isForkBased
+
isStacked := r.FormValue("isStacked") == "on"
if isPatchBased && !patchutil.IsFormatPatch(patch) {
if title == "" {
···
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
return
}
+
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch, isStacked)
} else if isForkBased {
if !caps.PullRequests.ForkSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
return
}
+
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch, isStacked)
} else if isPatchBased {
if !caps.PullRequests.PatchSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
return
}
+
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch, isStacked)
}
return
}
}
+
func (s *State) handleBranchBasedPull(
+
w http.ResponseWriter,
+
r *http.Request,
+
f *FullyResolvedRepo,
+
user *oauth.User,
+
title,
+
body,
+
targetBranch,
+
sourceBranch string,
+
isStacked bool,
+
) {
pullSource := &db.PullSource{
Branch: sourceBranch,
}
···
return
}
+
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource, isStacked)
}
+
func (s *State) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
if !patchutil.IsPatchValid(patch) {
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
return
}
+
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", nil, nil, isStacked)
}
+
func (s *State) handleForkBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *oauth.User, forkRepo string, title, body, targetBranch, sourceBranch string, isStacked bool) {
fork, err := db.GetForkByDid(s.db, user.Did, forkRepo)
if errors.Is(err, sql.ErrNoRows) {
s.pages.Notice(w, "pull", "No such fork.")
···
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, &db.PullSource{
Branch: sourceBranch,
RepoAt: &forkAtUri,
+
}, &tangled.RepoPull_Source{Branch: sourceBranch, Repo: &fork.AtUri}, isStacked)
}
func (s *State) createPullRequest(
···
sourceRev string,
pullSource *db.PullSource,
recordPullSource *tangled.RepoPull_Source,
+
isStacked bool,
) {
+
if isStacked {
+
}
+
tx, err := s.db.BeginTx(r.Context(), nil)
if err != nil {
log.Println("failed to start tx")