tangled
alpha
login
or
join now
tjh.dev
/
test
forked from
tangled.org/core
0
fork
atom
Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork
atom
overview
issues
pulls
pipelines
appview: pulls: make target branch picking generic
anirudh.fi
11 months ago
6379061a
c2e3b7a7
verified
This commit was signed with the committer's
known signature
.
anirudh.fi
SSH Key Fingerprint:
SHA256:cz35vdbiWEzCNEfuL9fMC2JVIhtXavXBHrRjv8gxpAk=
+107
-104
7 changed files
expand all
collapse all
unified
split
appview
pages
pages.go
templates
fragments
pullCompareBranches.html
pullCompareForks.html
pullCompareForksBranches.html
repo
pulls
new.html
pull.html
state
pull.go
-1
appview/pages/pages.go
···
575
575
type RepoNewPullParams struct {
576
576
LoggedInUser *auth.User
577
577
RepoInfo RepoInfo
578
578
-
Forks []db.Repo
579
578
Branches []types.Branch
580
579
Active string
581
580
}
+17
-32
appview/pages/templates/fragments/pullCompareBranches.html
···
1
1
{{ define "fragments/pullCompareBranches" }}
2
2
-
3
3
-
<div id="patch-upload">
4
4
-
<label for="targetBranch" class="dark:text-white">configure branches</label>
5
5
-
<div class="flex flex-wrap gap-2 items-center">
6
6
-
<select
7
7
-
required
8
8
-
name="targetBranch"
9
9
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
2
2
+
<div id="patch-upload">
3
3
+
<label for="targetBranch" class="dark:text-white"
4
4
+
>select a branch</label
10
5
>
11
11
-
<option disabled selected>target branch</option>
12
12
-
{{ range .Branches }}
13
13
-
<option value="{{ .Reference.Name }}" class="py-1">
14
14
-
{{ .Reference.Name }}
15
15
-
</option>
16
16
-
{{ end }}
17
17
-
</select>
18
18
-
19
19
-
{{ i "move-left" "w-5 h-5" }}
20
20
-
21
21
-
<select
22
22
-
name="sourceBranch"
23
23
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
24
24
-
>
25
25
-
<option disabled selected>source branch</option>
26
26
-
{{ range .Branches }}
27
27
-
<option value="{{ .Reference.Name }}" class="py-1">
28
28
-
{{ .Reference.Name }}
29
29
-
</option>
30
30
-
{{ end }}
31
31
-
</select>
32
32
-
</div>
33
33
-
34
34
-
</div>
6
6
+
<div class="flex flex-wrap gap-2 items-center">
7
7
+
<select
8
8
+
name="sourceBranch"
9
9
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
10
10
+
>
11
11
+
<option disabled selected>source branch</option>
12
12
+
{{ range .Branches }}
13
13
+
<option value="{{ .Reference.Name }}" class="py-1">
14
14
+
{{ .Reference.Name }}
15
15
+
</option>
16
16
+
{{ end }}
17
17
+
</select>
18
18
+
</div>
19
19
+
</div>
35
20
{{ end }}
+32
-25
appview/pages/templates/fragments/pullCompareForks.html
···
3
3
<label for="forkSelect" class="dark:text-white"
4
4
>select a fork to compare</label
5
5
>
6
6
-
<div class="flex flex-wrap gap-2 items-center mb-4">
7
7
-
<select
8
8
-
id="forkSelect"
9
9
-
name="fork"
10
10
-
required
11
11
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
12
12
-
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
13
13
-
hx-target="#branch-selection"
14
14
-
hx-vals='{"fork": this.value}'
15
15
-
hx-swap="innerHTML"
16
16
-
onchange="document.getElementById('hiddenForkInput').value = this.value;"
17
17
-
>
18
18
-
<option disabled selected>select a fork</option>
19
19
-
{{ range .Forks }}
20
20
-
<option value="{{ .Name }}" class="py-1">
21
21
-
{{ .Name }}
22
22
-
</option>
23
23
-
{{ end }}
24
24
-
</select>
25
25
-
26
26
-
<input type="hidden" id="hiddenForkInput" name="fork" value="">
27
27
-
</div>
6
6
+
<div class="flex flex-wrap gap-4 items-center mb-4">
7
7
+
<div class="flex flex-wrap gap-2 items-center">
8
8
+
<select
9
9
+
id="forkSelect"
10
10
+
name="fork"
11
11
+
required
12
12
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
13
13
+
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
14
14
+
hx-target="#branch-selection"
15
15
+
hx-vals='{"fork": this.value}'
16
16
+
hx-swap="innerHTML"
17
17
+
onchange="document.getElementById('hiddenForkInput').value = this.value;"
18
18
+
>
19
19
+
<option disabled selected>select a fork</option>
20
20
+
{{ range .Forks }}
21
21
+
<option value="{{ .Name }}" class="py-1">
22
22
+
{{ .Name }}
23
23
+
</option>
24
24
+
{{ end }}
25
25
+
</select>
28
26
29
29
-
<div id="branch-selection" class="mt-2">
30
30
-
<div class="text-sm text-gray-500 dark:text-gray-400">
31
31
-
Select a fork first to view available branches
27
27
+
<input
28
28
+
type="hidden"
29
29
+
id="hiddenForkInput"
30
30
+
name="fork"
31
31
+
value=""
32
32
+
/>
33
33
+
</div>
34
34
+
35
35
+
<div id="branch-selection">
36
36
+
<div class="text-sm text-gray-500 dark:text-gray-400">
37
37
+
Select a fork first to view available branches
38
38
+
</div>
32
39
</div>
33
40
</div>
34
41
</div>
-16
appview/pages/templates/fragments/pullCompareForksBranches.html
···
1
1
{{ define "fragments/pullCompareForksBranches" }}
2
2
<div class="flex flex-wrap gap-2 items-center">
3
3
<select
4
4
-
required
5
5
-
name="targetBranch"
6
6
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
7
7
-
>
8
8
-
<option disabled selected>target branch</option>
9
9
-
{{ range .TargetBranches }}
10
10
-
<option value="{{ .Reference.Name }}" class="py-1">
11
11
-
{{ .Reference.Name }}
12
12
-
</option>
13
13
-
{{ end }}
14
14
-
</select>
15
15
-
16
16
-
{{ i "move-left" "w-5 h-5" }}
17
17
-
18
18
-
19
19
-
<select
20
4
name="sourceBranch"
21
5
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
22
6
>
+30
-5
appview/pages/templates/repo/pulls/new.html
···
36
36
</div>
37
37
38
38
39
39
-
<label>choose your pull strategy</label>
40
40
-
<nav class="flex space-x-4">
39
39
+
<label>configure your pull request</label>
40
40
+
41
41
+
<p>First, choose a target branch on {{ .RepoInfo.FullName }}.</p>
42
42
+
<div class="pb-2">
43
43
+
<select
44
44
+
required
45
45
+
name="targetBranch"
46
46
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
47
47
+
>
48
48
+
<option disabled selected>target branch</option>
49
49
+
{{ range .Branches }}
50
50
+
<option value="{{ .Reference.Name }}" class="py-1">
51
51
+
{{ .Reference.Name }}
52
52
+
</option>
53
53
+
{{ end }}
54
54
+
</select>
55
55
+
</div>
56
56
+
57
57
+
<p>Then, choose a pull strategy.</p>
58
58
+
<nav class="flex space-x-4 items-end">
41
59
<button
42
60
type="button"
43
61
class="px-3 py-2 pb-2 btn"
···
67
49
</button>
68
50
69
51
{{ if .RepoInfo.Roles.IsPushAllowed }}
52
52
+
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
53
53
+
or
54
54
+
</span>
70
55
<button
71
56
type="button"
72
57
class="px-3 py-2 pb-2 btn"
···
80
59
compare branches
81
60
</button>
82
61
{{ end }}
62
62
+
63
63
+
<span class="text-sm text-gray-500 dark:text-gray-400 pb-2">
64
64
+
or
65
65
+
</span>
83
66
<button
84
67
type="button"
85
68
class="px-3 py-2 pb-2 btn"
···
95
70
</button>
96
71
</nav>
97
72
98
98
-
<section id="patch-strategy">
73
73
+
<section id="patch-strategy">
99
74
{{ template "fragments/pullPatchUpload" . }}
100
75
</section>
101
76
102
102
-
<div class="flex justify-start items-center gap-2">
77
77
+
<div class="flex justify-start items-center gap-2 mt-4">
103
78
<button type="submit" class="btn flex items-center gap-2">
104
79
{{ i "git-pull-request-create" "w-4 h-4" }}
105
80
create pull
106
81
</button>
107
107
-
</div>
82
82
+
</div>
108
83
109
84
</div>
110
85
<div id="pull" class="error dark:text-red-300"></div>
+6
-1
appview/pages/templates/repo/pulls/pull.html
···
50
50
{{ if not .Pull.IsSameRepoBranch }}
51
51
<a href="/{{ $owner }}/{{ .PullSourceRepo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .PullSourceRepo.Name }}</a>
52
52
{{ end }}
53
53
+
54
54
+
{{ $fullRepo := .RepoInfo.FullName }}
55
55
+
{{ if not .Pull.IsSameRepoBranch }}
56
56
+
{{ $fullRepo = printf "%s/%s" $owner .PullSourceRepo.Name }}
57
57
+
{{ end }}
53
58
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
54
54
-
<a href="/{{ $owner }}/{{ .PullSourceRepo.Name }}/tree/{{ .Pull.PullSource.Branch }}" class="no-underline hover:underline">{{ .Pull.PullSource.Branch }}</a>
59
59
+
<a href="/{{ $fullRepo }}/tree/{{ .Pull.PullSource.Branch }}" class="no-underline hover:underline">{{ .Pull.PullSource.Branch }}</a>
55
60
</span>
56
61
</span>
57
62
{{ end }}
+22
-24
appview/state/pull.go
···
501
501
return
502
502
}
503
503
504
504
-
forks, err := db.GetForksByDid(s.db, user.Did)
505
505
-
if err != nil {
506
506
-
log.Println("failed to get forks", err)
507
507
-
return
508
508
-
}
509
509
-
510
504
switch r.Method {
511
505
case http.MethodGet:
512
506
us, err := NewUnsignedClient(f.Knot, s.config.Dev)
···
532
538
s.pages.RepoNewPull(w, pages.RepoNewPullParams{
533
539
LoggedInUser: user,
534
540
RepoInfo: f.RepoInfo(s, user),
535
535
-
Forks: forks,
536
541
Branches: result.Branches,
537
542
})
538
543
case http.MethodPost:
···
542
549
sourceBranch := r.FormValue("sourceBranch")
543
550
patch := r.FormValue("patch")
544
551
545
545
-
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
546
546
-
isBranchBased := isPushAllowed && sourceBranch != "" && fromFork == ""
547
547
-
isPatchBased := patch != ""
548
548
-
isForkBased := fromFork != "" && sourceBranch != ""
549
549
-
550
550
-
if !isBranchBased && !isPatchBased && !isForkBased {
551
551
-
s.pages.Notice(w, "pull", "Neither source branch nor patch supplied.")
552
552
-
return
553
553
-
}
554
554
-
555
555
-
if isBranchBased && isPatchBased {
556
556
-
s.pages.Notice(w, "pull", "Cannot select both patch and source branch.")
557
557
-
return
558
558
-
}
559
559
-
552
552
+
// Validate required fields for all PR types
560
553
if title == "" || body == "" || targetBranch == "" {
561
554
s.pages.Notice(w, "pull", "Title, body and target branch are required.")
562
555
return
563
556
}
564
557
558
558
+
// Determine PR type based on input parameters
559
559
+
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
560
560
+
isBranchBased := isPushAllowed && sourceBranch != "" && fromFork == ""
561
561
+
isForkBased := fromFork != "" && sourceBranch != ""
562
562
+
isPatchBased := patch != "" && !isBranchBased && !isForkBased
563
563
+
564
564
+
// Validate we have at least one valid PR creation method
565
565
+
if !isBranchBased && !isPatchBased && !isForkBased {
566
566
+
s.pages.Notice(w, "pull", "Neither source branch nor patch supplied.")
567
567
+
return
568
568
+
}
569
569
+
570
570
+
// Can't mix branch-based and patch-based approaches
571
571
+
if isBranchBased && patch != "" {
572
572
+
s.pages.Notice(w, "pull", "Cannot select both patch and source branch.")
573
573
+
return
574
574
+
}
575
575
+
576
576
+
// Handle the PR creation based on the type
565
577
if isBranchBased {
566
578
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch)
567
567
-
} else if isPatchBased {
568
568
-
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch)
569
579
} else if isForkBased {
570
580
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch)
581
581
+
} else if isPatchBased {
582
582
+
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch)
571
583
}
572
584
return
573
585
}