diff --git a/appview/db/pulls.go b/appview/db/pulls.go
index 637b42fb..71f8ce7e 100644
--- a/appview/db/pulls.go
+++ b/appview/db/pulls.go
@@ -1063,6 +1063,28 @@ func (stack Stack) StrictlyBelow(pull *Pull) Stack {
return nil
}
+// all pulls above this pull (including self) in this stack
+func (stack Stack) Above(pull *Pull) Stack {
+ position := stack.Position(pull)
+
+ if position < 0 {
+ return nil
+ }
+
+ return stack[:position+1]
+}
+
+// all pulls below this pull (excluding self) in this stack
+func (stack Stack) StrictlyAbove(pull *Pull) Stack {
+ above := stack.Above(pull)
+
+ if len(above) > 0 {
+ return above[:len(above)-1]
+ }
+
+ return nil
+}
+
// the combined format-patches of all the newest submissions in this stack
func (stack Stack) CombinedPatch() string {
// go in reverse order because the bottom of the stack is the last element in the slice
diff --git a/appview/pages/pages.go b/appview/pages/pages.go
index 34976175..863588a5 100644
--- a/appview/pages/pages.go
+++ b/appview/pages/pages.go
@@ -743,6 +743,7 @@ type RepoSinglePullParams struct {
Active string
DidHandleMap map[string]string
Pull *db.Pull
+ Stack db.Stack
MergeCheck types.MergeCheckResponse
ResubmitCheck ResubmitResult
}
@@ -757,6 +758,7 @@ type RepoPullPatchParams struct {
DidHandleMap map[string]string
RepoInfo repoinfo.RepoInfo
Pull *db.Pull
+ Stack db.Stack
Diff *types.NiceDiff
Round int
Submission *db.PullSubmission
diff --git a/appview/pages/templates/repo/pulls/fragments/pullHeader.html b/appview/pages/templates/repo/pulls/fragments/pullHeader.html
index 3b9dbe9a..863dec16 100644
--- a/appview/pages/templates/repo/pulls/fragments/pullHeader.html
+++ b/appview/pages/templates/repo/pulls/fragments/pullHeader.html
@@ -1,68 +1,105 @@
{{ define "repo/pulls/fragments/pullHeader" }}
-
-
- {{ .Pull.Title }}
- #{{ .Pull.PullId }}
-
-
+
+ {{ block "pullState" .Pull }} {{ end }}
+
+ #{{ .Pull.PullId }}
+ {{ .Pull.Title }}
+
+
-{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-{{ $icon := "ban" }}
-
-{{ if .Pull.State.IsOpen }}
- {{ $bgColor = "bg-green-600 dark:bg-green-700" }}
- {{ $icon = "git-pull-request" }}
-{{ else if .Pull.State.IsMerged }}
- {{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
- {{ $icon = "git-merge" }}
-{{ end }}
-
-
+
-
- {{ i $icon "w-4 h-4 mr-1.5 text-white" }}
- {{ .Pull.State.String }}
-
-
- opened by
- {{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
- {{ $owner }}
-
-
-
-
- targeting
-
- {{ .Pull.TargetBranch }}
-
-
- {{ if not .Pull.IsPatchBased }}
- from
-
- {{ if .Pull.IsForkBased }}
- {{ if .Pull.PullSource.Repo }}
- {{ $owner }}/{{ .Pull.PullSource.Repo.Name }}:
- {{- else -}}
- [deleted fork]
- {{- end -}}
- {{- end -}}
- {{- .Pull.PullSource.Branch -}}
-
- {{ end }}
+
+ opened by
+ {{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
+ {{ $owner }}
+
+
+
+
+ targeting
+
+ {{ .Pull.TargetBranch }}
+
+ {{ if not .Pull.IsPatchBased }}
+ from
+
+ {{ if .Pull.IsForkBased }}
+ {{ if .Pull.PullSource.Repo }}
+ {{ $owner }}/{{ .Pull.PullSource.Repo.Name }}:
+ {{- else -}}
+ [deleted fork]
+ {{- end -}}
+ {{- end -}}
+ {{- .Pull.PullSource.Branch -}}
+
+ {{ end }}
+
{{ if .Pull.Body }}
-
- {{ .Pull.Body | markdown }}
-
+
+ {{ .Pull.Body | markdown }}
+
{{ end }}
-
+
+
+{{ end }}
+
+{{ define "singlePullHeader" }}
+{{ end }}
+
+{{ define "stackedPullHeader" }}
+
+ {{ block "stackedPullHeaderAbove" . }} {{ end }}
+
+ {{ block "singlePullHeader" . }} {{ end }}
+
+ {{ block "stackedPullHeaderBelow" . }} {{ end }}
+
+{{ end }}
+
+{{ define "stackedPullHeaderAbove" }}
+ {{ if .Pull.IsStacked }}
+ {{ $above := .Stack.StrictlyAbove .Pull }}
+
+ {{ range $pull := $above }}
+
+ {{ block "summarizedHeader" (list $pull $) }} {{ end }}
+
+ {{ end }}
+
+ {{ end }}
+{{ end }}
+
+{{ define "stackedPullHeaderBelow" }}
+ {{ if .Pull.IsStacked }}
+ {{ $below := .Stack.StrictlyBelow .Pull }}
+
+ {{ range $pull := $below }}
+
+ {{ block "summarizedHeader" (list $pull $) }} {{ end }}
+
+ {{ end }}
+
+ {{ end }}
+{{ end }}
+{{ define "pullState" }}
+ {{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+ {{ $icon := "ban" }}
+
+ {{ if .State.IsOpen }}
+ {{ $bgColor = "bg-green-600 dark:bg-green-700" }}
+ {{ $icon = "git-pull-request" }}
+ {{ else if .State.IsMerged }}
+ {{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
+ {{ $icon = "git-merge" }}
+ {{ end }}
+
+ {{ i $icon "w-4 h-4 mr-1.5 text-white" }}
+ {{ .State.String }}
+
{{ end }}
diff --git a/appview/pages/templates/repo/pulls/fragments/pullStack.html b/appview/pages/templates/repo/pulls/fragments/pullStack.html
new file mode 100644
index 00000000..aed7ece8
--- /dev/null
+++ b/appview/pages/templates/repo/pulls/fragments/pullStack.html
@@ -0,0 +1,47 @@
+{{ define "repo/pulls/fragments/pullStack" }}
+
+ {{ range $pull := .Stack }}
+ {{ $isCurrent := false }}
+ {{ with $.Pull }}
+ {{ $isCurrent = eq $pull.PullId $.Pull.PullId }}
+ {{ end }}
+
+ {{ block "summarizedHeader" (list $pull $) }} {{ end }}
+ {{ if $isCurrent }}
+ {{ i "arrow-left" "w-4 h-4" }}
+ {{ end }}
+
+ {{ end }}
+
+{{ end }}
+
+{{ define "summarizedHeader" }}
+ {{ $pull := index . 0 }}
+ {{ $root := index . 1 }}
+
+
+ {{ block "summarizedPullState" $pull }} {{ end }}
+
+ #{{ $pull.PullId }}
+ {{ $pull.Title }}
+
+
+
+{{ end }}
+
+{{ define "summarizedPullState" }}
+ {{ $fgColor := "text-gray-600 dark:text-gray-300" }}
+ {{ $icon := "ban" }}
+
+ {{ if .State.IsOpen }}
+ {{ $fgColor = "text-green-600 dark:text-green-500" }}
+ {{ $icon = "git-pull-request" }}
+ {{ else if .State.IsMerged }}
+ {{ $fgColor = "text-purple-600 dark:text-purple-500" }}
+ {{ $icon = "git-merge" }}
+ {{ end }}
+
+ {{ $style := printf "w-4 h-4 %s" $fgColor }}
+
+ {{ i $icon $style }}
+{{ end }}
diff --git a/appview/pages/templates/repo/pulls/pull.html b/appview/pages/templates/repo/pulls/pull.html
index 46eadd3c..5dcaac97 100644
--- a/appview/pages/templates/repo/pulls/pull.html
+++ b/appview/pages/templates/repo/pulls/pull.html
@@ -11,7 +11,14 @@
{{ define "repoContent" }}
- {{ template "repo/pulls/fragments/pullHeader" . }}
+ {{ template "repo/pulls/fragments/pullHeader" . }}
+
+ {{ if .Pull.IsStacked }}
+
+
STACK
+ {{ template "repo/pulls/fragments/pullStack" . }}
+
+ {{ end }}
{{ end }}
{{ define "repoAfter" }}
diff --git a/appview/state/pull.go b/appview/state/pull.go
index 037af84e..3954206f 100644
--- a/appview/state/pull.go
+++ b/appview/state/pull.go
@@ -136,6 +136,7 @@ func (s *State) RepoSinglePull(w http.ResponseWriter, r *http.Request) {
RepoInfo: f.RepoInfo(s, user),
DidHandleMap: didHandleMap,
Pull: pull,
+ Stack: stack,
MergeCheck: mergeCheckResponse,
ResubmitCheck: resubmitResult,
})
@@ -303,6 +304,8 @@ func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) {
return
}
+ stack, _ := r.Context().Value("stack").(db.Stack)
+
roundId := chi.URLParam(r, "round")
roundIdInt, err := strconv.Atoi(roundId)
if err != nil || roundIdInt >= len(pull.Submissions) {
@@ -329,6 +332,7 @@ func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) {
DidHandleMap: didHandleMap,
RepoInfo: f.RepoInfo(s, user),
Pull: pull,
+ Stack: stack,
Round: roundIdInt,
Submission: pull.Submissions[roundIdInt],
Diff: &diff,
@@ -1647,13 +1651,17 @@ func (s *State) resubmitStackedPullHelper(
if op, ok := origById[np.ChangeId]; ok {
// pull exists in both stacks
// TODO: can we avoid reparse?
- origFiles, _, _ := gitdiff.Parse(strings.NewReader(op.LatestPatch()))
- newFiles, _, _ := gitdiff.Parse(strings.NewReader(np.LatestPatch()))
+ origFiles, origHeaderStr, _ := gitdiff.Parse(strings.NewReader(op.LatestPatch()))
+ newFiles, newHeaderStr, _ := gitdiff.Parse(strings.NewReader(np.LatestPatch()))
+
+ origHeader, _ := gitdiff.ParsePatchHeader(origHeaderStr)
+ newHeader, _ := gitdiff.ParsePatchHeader(newHeaderStr)
patchutil.SortPatch(newFiles)
patchutil.SortPatch(origFiles)
- if patchutil.Equal(newFiles, origFiles) {
+ // text content of patch may be identical, but a jj rebase might have forwarded it
+ if patchutil.Equal(newFiles, origFiles) && origHeader.SHA == newHeader.SHA {
unchanged[op.ChangeId] = struct{}{}
} else {
updated[op.ChangeId] = struct{}{}