+1
appview/pages/pages.go
+1
appview/pages/pages.go
+98
-17
appview/state/repo.go
+98
-17
appview/state/repo.go
···
25
25
"tangled.sh/tangled.sh/core/appview/pages/markup"
26
26
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
27
27
"tangled.sh/tangled.sh/core/appview/pagination"
28
+
"tangled.sh/tangled.sh/core/knotserver"
28
29
"tangled.sh/tangled.sh/core/types"
29
30
30
31
"github.com/bluesky-social/indigo/atproto/data"
···
123
124
user := s.oauth.GetUser(r)
124
125
repoInfo := f.RepoInfo(s, user)
125
126
127
+
forkInfo, err := GetForkInfo(repoInfo, s, f, us, w, user)
128
+
if err != nil {
129
+
log.Printf("Failed to fetch fork information: %v", err)
130
+
return
131
+
}
132
+
133
+
s.pages.RepoIndexPage(w, pages.RepoIndexParams{
134
+
LoggedInUser: user,
135
+
RepoInfo: repoInfo,
136
+
TagMap: tagMap,
137
+
RepoIndexResponse: result,
138
+
CommitsTrunc: commitsTrunc,
139
+
TagsTrunc: tagsTrunc,
140
+
ForkInfo: *forkInfo,
141
+
BranchesTrunc: branchesTrunc,
142
+
EmailToDidOrHandle: EmailToDidOrHandle(s, emails),
143
+
})
144
+
return
145
+
}
146
+
147
+
func GetForkInfo(
148
+
repoInfo repoinfo.RepoInfo,
149
+
s *State,
150
+
f *FullyResolvedRepo,
151
+
us *knotclient.UnsignedClient,
152
+
w http.ResponseWriter,
153
+
user *oauth.User,
154
+
) (*pages.ForkInfo, error) {
155
+
forkInfo := pages.ForkInfo{
156
+
IsFork: repoInfo.Source != nil,
157
+
Status: pages.UpToDate,
158
+
}
159
+
126
160
secret, err := db.GetRegistrationKey(s.db, f.Knot)
127
161
if err != nil {
128
162
log.Printf("failed to get registration key for %s: %s", f.Knot, err)
129
163
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
130
164
}
131
165
132
-
// update the hidden tracking branch to latest
166
+
if !forkInfo.IsFork {
167
+
forkInfo.IsFork = false
168
+
return &forkInfo, nil
169
+
}
170
+
171
+
resp, err := us.Branches(repoInfo.Source.Did, repoInfo.Source.Name)
172
+
if err != nil {
173
+
log.Println("failed to reach knotserver", err)
174
+
return nil, err
175
+
}
176
+
177
+
body, err := io.ReadAll(resp.Body)
178
+
if err != nil {
179
+
log.Printf("Error reading forkResponse forkBody: %v", err)
180
+
return nil, err
181
+
}
182
+
183
+
var result types.RepoBranchesResponse
184
+
err = json.Unmarshal(body, &result)
185
+
if err != nil {
186
+
log.Println("failed to parse forkResponse:", err)
187
+
return nil, err
188
+
}
189
+
190
+
var contains = false
191
+
for _, branch := range result.Branches {
192
+
if branch.Name == f.Ref {
193
+
contains = true
194
+
break
195
+
}
196
+
}
197
+
198
+
if contains == false {
199
+
forkInfo.Status = pages.MissingBranch
200
+
return &forkInfo, nil
201
+
}
202
+
133
203
signedClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev)
134
204
if err != nil {
135
205
log.Printf("failed to create signed client for %s: %s", f.Knot, err)
136
-
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
206
+
return nil, err
137
207
}
138
208
139
209
newHiddenRefResp, err := signedClient.NewHiddenRef(user.Did, repoInfo.Name, f.Ref, f.Ref)
140
210
if err != nil || newHiddenRefResp.StatusCode != http.StatusNoContent {
141
211
log.Printf("failed to update tracking branch: %s", err)
142
-
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
212
+
return nil, err
143
213
}
144
214
145
215
hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref)
146
216
comparison, err := us.Compare(user.Did, repoInfo.Name, f.Ref, hiddenRef)
147
217
if err != nil {
148
-
log.Printf("failed to compare branches: %s", err)
149
-
s.pages.Notice(w, "resubmit-error", err.Error())
218
+
log.Printf("failed to compare branches '%s' and '%s': %s", f.Ref, hiddenRef, err)
219
+
return nil, err
220
+
}
221
+
222
+
if len(comparison.FormatPatch) == 0 {
223
+
return &forkInfo, nil
224
+
}
225
+
226
+
var isAncestor types.AncestorCheckResponse
227
+
forkSyncableResp, err := signedClient.RepoForkSyncable(user.Did, string(f.RepoAt), repoInfo.Name, f.Ref, hiddenRef)
228
+
if err != nil {
229
+
log.Printf("failed to check if fork is syncable: %s", err)
230
+
return nil, err
150
231
}
151
-
log.Println(comparison)
152
232
153
-
s.pages.RepoIndexPage(w, pages.RepoIndexParams{
154
-
LoggedInUser: user,
155
-
RepoInfo: repoInfo,
156
-
TagMap: tagMap,
157
-
RepoIndexResponse: result,
158
-
CommitsTrunc: commitsTrunc,
159
-
TagsTrunc: tagsTrunc,
160
-
BranchesTrunc: branchesTrunc,
161
-
EmailToDidOrHandle: EmailToDidOrHandle(s, emails),
162
-
})
163
-
return
233
+
if err := json.NewDecoder(forkSyncableResp.Body).Decode(&isAncestor); err != nil {
234
+
log.Printf("failed to decode 'isAncestor': %s", err)
235
+
return nil, err
236
+
}
237
+
238
+
if isAncestor.IsAncestor {
239
+
forkInfo.Status = pages.FastForwardable
240
+
} else {
241
+
forkInfo.Status = pages.Conflict
242
+
}
243
+
244
+
return &forkInfo, nil
164
245
}
165
246
166
247
func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) {