···
11
+
"tangled.sh/tangled.sh/core/appview/commitverify"
12
+
"tangled.sh/tangled.sh/core/appview/db"
13
+
"tangled.sh/tangled.sh/core/appview/oauth"
14
+
"tangled.sh/tangled.sh/core/appview/pages"
15
+
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
16
+
"tangled.sh/tangled.sh/core/appview/reporesolver"
17
+
"tangled.sh/tangled.sh/core/knotclient"
18
+
"tangled.sh/tangled.sh/core/types"
20
+
"github.com/go-chi/chi/v5"
23
+
func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) {
24
+
ref := chi.URLParam(r, "ref")
25
+
f, err := rp.repoResolver.Resolve(r)
27
+
log.Println("failed to fully resolve repo", err)
31
+
us, err := knotclient.NewUnsignedClient(f.Knot, rp.config.Core.Dev)
33
+
log.Printf("failed to create unsigned client for %s", f.Knot)
34
+
rp.pages.Error503(w)
38
+
result, err := us.Index(f.OwnerDid(), f.RepoName, ref)
40
+
rp.pages.Error503(w)
41
+
log.Println("failed to reach knotserver", err)
45
+
tagMap := make(map[string][]string)
46
+
for _, tag := range result.Tags {
49
+
hash = tag.Tag.Target.String()
51
+
tagMap[hash] = append(tagMap[hash], tag.Name)
54
+
for _, branch := range result.Branches {
56
+
tagMap[hash] = append(tagMap[hash], branch.Name)
59
+
slices.SortFunc(result.Branches, func(a, b types.Branch) int {
60
+
if a.Name == result.Ref {
69
+
if a.Commit != nil && b.Commit != nil {
70
+
if a.Commit.Committer.When.Before(b.Commit.Committer.When) {
76
+
return strings.Compare(a.Name, b.Name) * -1
79
+
commitCount := len(result.Commits)
80
+
branchCount := len(result.Branches)
81
+
tagCount := len(result.Tags)
82
+
fileCount := len(result.Files)
84
+
commitCount, branchCount, tagCount = balanceIndexItems(commitCount, branchCount, tagCount, fileCount)
85
+
commitsTrunc := result.Commits[:min(commitCount, len(result.Commits))]
86
+
tagsTrunc := result.Tags[:min(tagCount, len(result.Tags))]
87
+
branchesTrunc := result.Branches[:min(branchCount, len(result.Branches))]
89
+
emails := uniqueEmails(commitsTrunc)
90
+
emailToDidMap, err := db.GetEmailToDid(rp.db, emails, true)
92
+
log.Println("failed to get email to did map", err)
95
+
vc, err := commitverify.GetVerifiedObjectCommits(rp.db, emailToDidMap, commitsTrunc)
100
+
user := rp.oauth.GetUser(r)
101
+
repoInfo := f.RepoInfo(user)
103
+
secret, err := db.GetRegistrationKey(rp.db, f.Knot)
105
+
log.Printf("failed to get registration key for %s: %s", f.Knot, err)
106
+
rp.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
109
+
signedClient, err := knotclient.NewSignedClient(f.Knot, secret, rp.config.Core.Dev)
111
+
log.Printf("failed to create signed client for %s: %s", f.Knot, err)
115
+
var forkInfo *types.ForkInfo
116
+
if user != nil && (repoInfo.Roles.IsOwner() || repoInfo.Roles.IsCollaborator()) {
117
+
forkInfo, err = getForkInfo(repoInfo, rp, f, user, signedClient)
119
+
log.Printf("Failed to fetch fork information: %v", err)
124
+
repoLanguages, err := signedClient.RepoLanguages(f.OwnerDid(), f.RepoName, ref)
126
+
log.Printf("failed to compute language percentages: %s", err)
130
+
rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
131
+
LoggedInUser: user,
132
+
RepoInfo: repoInfo,
134
+
RepoIndexResponse: *result,
135
+
CommitsTrunc: commitsTrunc,
136
+
TagsTrunc: tagsTrunc,
137
+
ForkInfo: forkInfo,
138
+
BranchesTrunc: branchesTrunc,
139
+
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
140
+
VerifiedCommits: vc,
141
+
Languages: repoLanguages,
147
+
repoInfo repoinfo.RepoInfo,
149
+
f *reporesolver.ResolvedRepo,
151
+
signedClient *knotclient.SignedClient,
152
+
) (*types.ForkInfo, error) {
157
+
forkInfo := types.ForkInfo{
158
+
IsFork: repoInfo.Source != nil,
159
+
Status: types.UpToDate,
162
+
if !forkInfo.IsFork {
163
+
forkInfo.IsFork = false
164
+
return &forkInfo, nil
167
+
us, err := knotclient.NewUnsignedClient(repoInfo.Source.Knot, rp.config.Core.Dev)
169
+
log.Printf("failed to create unsigned client for %s", repoInfo.Source.Knot)
173
+
result, err := us.Branches(repoInfo.Source.Did, repoInfo.Source.Name)
175
+
log.Println("failed to reach knotserver", err)
179
+
if !slices.ContainsFunc(result.Branches, func(branch types.Branch) bool {
180
+
return branch.Name == f.Ref
182
+
forkInfo.Status = types.MissingBranch
183
+
return &forkInfo, nil
186
+
newHiddenRefResp, err := signedClient.NewHiddenRef(user.Did, repoInfo.Name, f.Ref, f.Ref)
187
+
if err != nil || newHiddenRefResp.StatusCode != http.StatusNoContent {
188
+
log.Printf("failed to update tracking branch: %s", err)
192
+
hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref)
194
+
var status types.AncestorCheckResponse
195
+
forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt), repoInfo.Name, f.Ref, hiddenRef)
197
+
log.Printf("failed to check if fork is ahead/behind: %s", err)
201
+
if err := json.NewDecoder(forkSyncableResp.Body).Decode(&status); err != nil {
202
+
log.Printf("failed to decode fork status: %s", err)
206
+
forkInfo.Status = status.Status
207
+
return &forkInfo, nil