+2
-1
appview/db/db.go
+2
-1
appview/db/db.go
···
264
return err
265
})
266
267
+
runMigration(db, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error {
268
_, err := tx.Exec(`
269
alter table pulls add column source_branch text;
270
alter table pulls add column source_repo_at text;
271
+
alter table pull_submissions add column source_rev text;
272
`)
273
return err
274
})
+15
-8
appview/db/pulls.go
+15
-8
appview/db/pulls.go
···
83
RoundNumber int
84
Patch string
85
Comments []PullComment
86
87
// meta
88
Created time.Time
···
222
}
223
224
_, err = tx.Exec(`
225
-
insert into pull_submissions (pull_id, repo_at, round_number, patch)
226
-
values (?, ?, ?, ?)
227
-
`, pull.PullId, pull.RepoAt, 0, pull.Submissions[0].Patch)
228
if err != nil {
229
return err
230
}
···
395
396
submissionsQuery := `
397
select
398
-
id, pull_id, repo_at, round_number, patch, created
399
from
400
pull_submissions
401
where
···
412
for submissionsRows.Next() {
413
var submission PullSubmission
414
var submissionCreatedStr string
415
err := submissionsRows.Scan(
416
&submission.ID,
417
&submission.PullId,
···
419
&submission.RoundNumber,
420
&submission.Patch,
421
&submissionCreatedStr,
422
)
423
if err != nil {
424
return nil, err
···
430
}
431
submission.Created = submissionCreatedTime
432
433
submissionsMap[submission.ID] = &submission
434
}
435
if err = submissionsRows.Close(); err != nil {
···
604
return err
605
}
606
607
-
func ResubmitPull(e Execer, pull *Pull, newPatch string) error {
608
newRoundNumber := len(pull.Submissions)
609
_, err := e.Exec(`
610
-
insert into pull_submissions (pull_id, repo_at, round_number, patch)
611
-
values (?, ?, ?, ?)
612
-
`, pull.PullId, pull.RepoAt, newRoundNumber, newPatch)
613
614
return err
615
}
···
83
RoundNumber int
84
Patch string
85
Comments []PullComment
86
+
SourceRev string // include the rev that was used to create this submission: only for branch PRs
87
88
// meta
89
Created time.Time
···
223
}
224
225
_, err = tx.Exec(`
226
+
insert into pull_submissions (pull_id, repo_at, round_number, patch, source_rev)
227
+
values (?, ?, ?, ?, ?)
228
+
`, pull.PullId, pull.RepoAt, 0, pull.Submissions[0].Patch, pull.Submissions[0].SourceRev)
229
if err != nil {
230
return err
231
}
···
396
397
submissionsQuery := `
398
select
399
+
id, pull_id, repo_at, round_number, patch, created, source_rev
400
from
401
pull_submissions
402
where
···
413
for submissionsRows.Next() {
414
var submission PullSubmission
415
var submissionCreatedStr string
416
+
var submissionSourceRev sql.NullString
417
err := submissionsRows.Scan(
418
&submission.ID,
419
&submission.PullId,
···
421
&submission.RoundNumber,
422
&submission.Patch,
423
&submissionCreatedStr,
424
+
&submissionSourceRev,
425
)
426
if err != nil {
427
return nil, err
···
433
}
434
submission.Created = submissionCreatedTime
435
436
+
if submissionSourceRev.Valid {
437
+
submission.SourceRev = submissionSourceRev.String
438
+
}
439
+
440
submissionsMap[submission.ID] = &submission
441
}
442
if err = submissionsRows.Close(); err != nil {
···
611
return err
612
}
613
614
+
func ResubmitPull(e Execer, pull *Pull, newPatch, sourceRev string) error {
615
newRoundNumber := len(pull.Submissions)
616
_, err := e.Exec(`
617
+
insert into pull_submissions (pull_id, repo_at, round_number, patch, source_rev)
618
+
values (?, ?, ?, ?, ?)
619
+
`, pull.PullId, pull.RepoAt, newRoundNumber, newPatch, sourceRev)
620
621
return err
622
}
+31
-11
appview/pages/pages.go
+31
-11
appview/pages/pages.go
···
586
return p.executeRepo("repo/pulls/pulls", w, params)
587
}
588
589
type RepoSinglePullParams struct {
590
-
LoggedInUser *auth.User
591
-
RepoInfo RepoInfo
592
-
Active string
593
-
DidHandleMap map[string]string
594
-
Pull *db.Pull
595
-
MergeCheck types.MergeCheckResponse
596
}
597
598
func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error {
···
627
}
628
629
type PullActionsParams struct {
630
-
LoggedInUser *auth.User
631
-
RepoInfo RepoInfo
632
-
Pull *db.Pull
633
-
RoundNumber int
634
-
MergeCheck types.MergeCheckResponse
635
}
636
637
func (p *Pages) PullActionsFragment(w io.Writer, params PullActionsParams) error {
···
586
return p.executeRepo("repo/pulls/pulls", w, params)
587
}
588
589
+
type ResubmitResult uint64
590
+
591
+
const (
592
+
ShouldResubmit ResubmitResult = iota
593
+
ShouldNotResubmit
594
+
Unknown
595
+
)
596
+
597
+
func (r ResubmitResult) Yes() bool {
598
+
return r == ShouldResubmit
599
+
}
600
+
func (r ResubmitResult) No() bool {
601
+
return r == ShouldNotResubmit
602
+
}
603
+
func (r ResubmitResult) Unknown() bool {
604
+
return r == Unknown
605
+
}
606
+
607
type RepoSinglePullParams struct {
608
+
LoggedInUser *auth.User
609
+
RepoInfo RepoInfo
610
+
Active string
611
+
DidHandleMap map[string]string
612
+
Pull *db.Pull
613
+
MergeCheck types.MergeCheckResponse
614
+
ResubmitCheck ResubmitResult
615
}
616
617
func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error {
···
646
}
647
648
type PullActionsParams struct {
649
+
LoggedInUser *auth.User
650
+
RepoInfo RepoInfo
651
+
Pull *db.Pull
652
+
RoundNumber int
653
+
MergeCheck types.MergeCheckResponse
654
+
ResubmitCheck ResubmitResult
655
}
656
657
func (p *Pages) PullActionsFragment(w io.Writer, params PullActionsParams) error {
+13
-1
appview/pages/templates/fragments/pullActions.html
+13
-1
appview/pages/templates/fragments/pullActions.html
···
10
{{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
11
{{ $isLastRound := eq $roundNumber $lastIdx }}
12
{{ $isSameRepoBranch := .Pull.IsSameRepoBranch }}
13
<div class="relative w-fit">
14
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
15
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2">
···
37
{{ end }}
38
39
{{ if and $isPullAuthor $isOpen $isLastRound }}
40
<button id="resubmitBtn"
41
{{ if $isSameRepoBranch }}
42
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
···
47
{{ end }}
48
49
hx-disabled-elt="#resubmitBtn"
50
-
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed">
51
{{ i "rotate-ccw" "w-4 h-4" }}
52
<span>resubmit</span>
53
</button>
···
10
{{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
11
{{ $isLastRound := eq $roundNumber $lastIdx }}
12
{{ $isSameRepoBranch := .Pull.IsSameRepoBranch }}
13
+
{{ $isUpToDate := .ResubmitCheck.No }}
14
<div class="relative w-fit">
15
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
16
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2">
···
38
{{ end }}
39
40
{{ if and $isPullAuthor $isOpen $isLastRound }}
41
+
{{ $disabled := "" }}
42
+
{{ if $isUpToDate }}
43
+
{{ $disabled = "disabled" }}
44
+
{{ end }}
45
<button id="resubmitBtn"
46
{{ if $isSameRepoBranch }}
47
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
···
52
{{ end }}
53
54
hx-disabled-elt="#resubmitBtn"
55
+
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed" {{ $disabled }}
56
+
57
+
{{ if $disabled }}
58
+
title="Update this branch to resubmit this pull request"
59
+
{{ else }}
60
+
title="Resubmit this pull request"
61
+
{{ end }}
62
+
>
63
{{ i "rotate-ccw" "w-4 h-4" }}
64
<span>resubmit</span>
65
</button>
+14
-1
appview/pages/templates/repo/pulls/pull.html
+14
-1
appview/pages/templates/repo/pulls/pull.html
···
135
136
{{ if eq $lastIdx .RoundNumber }}
137
{{ block "mergeStatus" $ }} {{ end }}
138
{{ end }}
139
140
{{ if $.LoggedInUser }}
141
-
{{ template "fragments/pullActions" (dict "LoggedInUser" $.LoggedInUser "Pull" $.Pull "RepoInfo" $.RepoInfo "RoundNumber" .RoundNumber "MergeCheck" $.MergeCheck) }}
142
{{ else }}
143
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
144
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
···
209
</div>
210
{{ end }}
211
{{ end }}
···
135
136
{{ if eq $lastIdx .RoundNumber }}
137
{{ block "mergeStatus" $ }} {{ end }}
138
+
{{ block "resubmitStatus" $ }} {{ end }}
139
{{ end }}
140
141
{{ if $.LoggedInUser }}
142
+
{{ template "fragments/pullActions" (dict "LoggedInUser" $.LoggedInUser "Pull" $.Pull "RepoInfo" $.RepoInfo "RoundNumber" .RoundNumber "MergeCheck" $.MergeCheck "ResubmitCheck" $.ResubmitCheck) }}
143
{{ else }}
144
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
145
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
···
210
</div>
211
{{ end }}
212
{{ end }}
213
+
214
+
{{ define "resubmitStatus" }}
215
+
{{ if .ResubmitCheck.Yes }}
216
+
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
217
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
218
+
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
219
+
{{ i "triangle-alert" "w-4 h-4" }}
220
+
<span class="font-medium">this branch has been updated, consider resubmitting</span>
221
+
</div>
222
+
</div>
223
+
{{ end }}
224
+
{{ end }}
+91
-28
appview/state/pull.go
+91
-28
appview/state/pull.go
···
50
}
51
52
mergeCheckResponse := s.mergeCheck(f, pull)
53
54
s.pages.PullActionsFragment(w, pages.PullActionsParams{
55
-
LoggedInUser: user,
56
-
RepoInfo: f.RepoInfo(s, user),
57
-
Pull: pull,
58
-
RoundNumber: roundNumber,
59
-
MergeCheck: mergeCheckResponse,
60
})
61
return
62
}
···
105
}
106
107
mergeCheckResponse := s.mergeCheck(f, pull)
108
109
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
110
-
LoggedInUser: user,
111
-
RepoInfo: f.RepoInfo(s, user),
112
-
DidHandleMap: didHandleMap,
113
-
Pull: pull,
114
-
MergeCheck: mergeCheckResponse,
115
})
116
}
117
···
175
return mergeCheckResponse
176
}
177
178
func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) {
179
user := s.auth.GetUser(r)
180
f, err := fullyResolvedRepo(r)
···
457
sourceBranch := r.FormValue("sourceBranch")
458
patch := r.FormValue("patch")
459
460
-
if patch == "" {
461
-
if isPushAllowed && sourceBranch == "" {
462
-
s.pages.Notice(w, "pull", "Neither source branch nor patch supplied.")
463
-
return
464
-
}
465
-
s.pages.Notice(w, "pull", "Patch is empty.")
466
return
467
}
468
469
-
if patch != "" && sourceBranch != "" {
470
s.pages.Notice(w, "pull", "Cannot select both patch and source branch.")
471
return
472
}
···
477
}
478
479
// TODO: check if knot has this capability
480
var pullSource *db.PullSource
481
-
if sourceBranch != "" && isPushAllowed {
482
pullSource = &db.PullSource{
483
Branch: sourceBranch,
484
}
485
// generate a patch using /compare
486
ksClient, err := NewUnsignedClient(f.Knot, s.config.Dev)
487
if err != nil {
···
489
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
490
return
491
}
492
-
493
-
log.Println(targetBranch, sourceBranch)
494
495
resp, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
496
switch resp.StatusCode {
···
510
err = json.Unmarshal(respBody, &diffTreeResponse)
511
if err != nil {
512
log.Println("failed to unmarshal diff tree response", err)
513
-
log.Println(string(respBody))
514
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
515
}
516
517
patch = diffTreeResponse.DiffTree.Patch
518
}
519
520
-
log.Println(patch)
521
-
522
// Validate patch format
523
if !isPatchValid(patch) {
524
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
535
536
rkey := s.TID()
537
initialSubmission := db.PullSubmission{
538
-
Patch: patch,
539
}
540
err = db.NewPull(tx, &db.Pull{
541
Title: title,
···
573
TargetRepo: string(f.RepoAt),
574
TargetBranch: targetBranch,
575
Patch: patch,
576
},
577
},
578
})
···
613
return
614
case http.MethodPost:
615
patch := r.FormValue("patch")
616
617
// this pull is a branch based pull
618
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
619
if pull.IsSameRepoBranch() && isPushAllowed {
620
sourceBranch := pull.PullSource.Branch
621
targetBranch := pull.TargetBranch
622
// extract patch by performing compare
623
ksClient, err := NewUnsignedClient(f.Knot, s.config.Dev)
624
if err != nil {
···
627
return
628
}
629
630
-
log.Println(targetBranch, sourceBranch)
631
-
632
resp, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
633
switch resp.StatusCode {
634
case 404:
···
647
err = json.Unmarshal(respBody, &diffTreeResponse)
648
if err != nil {
649
log.Println("failed to unmarshal diff tree response", err)
650
-
log.Println(string(respBody))
651
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
652
}
653
654
patch = diffTreeResponse.DiffTree.Patch
655
}
656
···
664
return
665
}
666
667
// Validate patch format
668
if !isPatchValid(patch) {
669
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
···
678
}
679
defer tx.Rollback()
680
681
-
err = db.ResubmitPull(tx, pull, patch)
682
if err != nil {
683
log.Println("failed to create pull request", err)
684
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
···
705
TargetRepo: string(f.RepoAt),
706
TargetBranch: pull.TargetBranch,
707
Patch: patch, // new patch
708
},
709
},
710
})
···
50
}
51
52
mergeCheckResponse := s.mergeCheck(f, pull)
53
+
var resubmitResult pages.ResubmitResult
54
+
if user.Did == pull.OwnerDid {
55
+
resubmitResult = s.resubmitCheck(f, pull)
56
+
}
57
58
s.pages.PullActionsFragment(w, pages.PullActionsParams{
59
+
LoggedInUser: user,
60
+
RepoInfo: f.RepoInfo(s, user),
61
+
Pull: pull,
62
+
RoundNumber: roundNumber,
63
+
MergeCheck: mergeCheckResponse,
64
+
ResubmitCheck: resubmitResult,
65
})
66
return
67
}
···
110
}
111
112
mergeCheckResponse := s.mergeCheck(f, pull)
113
+
var resubmitResult pages.ResubmitResult
114
+
if user.Did == pull.OwnerDid {
115
+
resubmitResult = s.resubmitCheck(f, pull)
116
+
}
117
118
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
119
+
LoggedInUser: user,
120
+
RepoInfo: f.RepoInfo(s, user),
121
+
DidHandleMap: didHandleMap,
122
+
Pull: pull,
123
+
MergeCheck: mergeCheckResponse,
124
+
ResubmitCheck: resubmitResult,
125
})
126
}
127
···
185
return mergeCheckResponse
186
}
187
188
+
func (s *State) resubmitCheck(f *FullyResolvedRepo, pull *db.Pull) pages.ResubmitResult {
189
+
if pull.State == db.PullMerged {
190
+
return pages.Unknown
191
+
}
192
+
193
+
if pull.PullSource == nil {
194
+
return pages.Unknown
195
+
}
196
+
197
+
us, err := NewUnsignedClient(f.Knot, s.config.Dev)
198
+
if err != nil {
199
+
log.Printf("failed to setup signed client for %s; ignoring: %v", f.Knot, err)
200
+
return pages.Unknown
201
+
}
202
+
203
+
resp, err := us.Branch(f.OwnerDid(), f.RepoName, pull.PullSource.Branch)
204
+
if err != nil {
205
+
log.Println("failed to reach knotserver", err)
206
+
return pages.Unknown
207
+
}
208
+
209
+
body, err := io.ReadAll(resp.Body)
210
+
if err != nil {
211
+
log.Printf("Error reading response body: %v", err)
212
+
return pages.Unknown
213
+
}
214
+
215
+
var result types.RepoBranchResponse
216
+
err = json.Unmarshal(body, &result)
217
+
if err != nil {
218
+
log.Println("failed to parse response:", err)
219
+
return pages.Unknown
220
+
}
221
+
222
+
if pull.Submissions[pull.LastRoundNumber()].SourceRev != result.Branch.Hash {
223
+
log.Println(pull.Submissions[pull.LastRoundNumber()].SourceRev, result.Branch.Hash)
224
+
return pages.ShouldResubmit
225
+
} else {
226
+
return pages.ShouldNotResubmit
227
+
}
228
+
}
229
+
230
func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) {
231
user := s.auth.GetUser(r)
232
f, err := fullyResolvedRepo(r)
···
509
sourceBranch := r.FormValue("sourceBranch")
510
patch := r.FormValue("patch")
511
512
+
isBranchBased := isPushAllowed && (sourceBranch != "")
513
+
isPatchBased := patch != ""
514
+
515
+
if !isBranchBased && !isPatchBased {
516
+
s.pages.Notice(w, "pull", "Neither source branch nor patch supplied.")
517
return
518
}
519
520
+
if isBranchBased && isPatchBased {
521
s.pages.Notice(w, "pull", "Cannot select both patch and source branch.")
522
return
523
}
···
528
}
529
530
// TODO: check if knot has this capability
531
+
var sourceRev string
532
var pullSource *db.PullSource
533
+
var recordPullSource *tangled.RepoPull_Source
534
+
if isBranchBased {
535
pullSource = &db.PullSource{
536
Branch: sourceBranch,
537
}
538
+
recordPullSource = &tangled.RepoPull_Source{
539
+
Branch: sourceBranch,
540
+
}
541
// generate a patch using /compare
542
ksClient, err := NewUnsignedClient(f.Knot, s.config.Dev)
543
if err != nil {
···
545
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
546
return
547
}
548
549
resp, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
550
switch resp.StatusCode {
···
564
err = json.Unmarshal(respBody, &diffTreeResponse)
565
if err != nil {
566
log.Println("failed to unmarshal diff tree response", err)
567
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
568
}
569
570
+
sourceRev = diffTreeResponse.DiffTree.Rev2
571
patch = diffTreeResponse.DiffTree.Patch
572
}
573
574
// Validate patch format
575
if !isPatchValid(patch) {
576
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
587
588
rkey := s.TID()
589
initialSubmission := db.PullSubmission{
590
+
Patch: patch,
591
+
SourceRev: sourceRev,
592
}
593
err = db.NewPull(tx, &db.Pull{
594
Title: title,
···
626
TargetRepo: string(f.RepoAt),
627
TargetBranch: targetBranch,
628
Patch: patch,
629
+
Source: recordPullSource,
630
},
631
},
632
})
···
667
return
668
case http.MethodPost:
669
patch := r.FormValue("patch")
670
+
var sourceRev string
671
+
var recordPullSource *tangled.RepoPull_Source
672
673
// this pull is a branch based pull
674
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
675
if pull.IsSameRepoBranch() && isPushAllowed {
676
sourceBranch := pull.PullSource.Branch
677
targetBranch := pull.TargetBranch
678
+
recordPullSource = &tangled.RepoPull_Source{
679
+
Branch: sourceBranch,
680
+
}
681
// extract patch by performing compare
682
ksClient, err := NewUnsignedClient(f.Knot, s.config.Dev)
683
if err != nil {
···
686
return
687
}
688
689
resp, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
690
switch resp.StatusCode {
691
case 404:
···
704
err = json.Unmarshal(respBody, &diffTreeResponse)
705
if err != nil {
706
log.Println("failed to unmarshal diff tree response", err)
707
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
708
}
709
710
+
sourceRev = diffTreeResponse.DiffTree.Rev2
711
patch = diffTreeResponse.DiffTree.Patch
712
}
713
···
721
return
722
}
723
724
+
if sourceRev == pull.Submissions[pull.LastRoundNumber()].SourceRev {
725
+
s.pages.Notice(w, "resubmit-error", "This branch has not changed since the last submission.")
726
+
return
727
+
}
728
+
729
// Validate patch format
730
if !isPatchValid(patch) {
731
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
···
740
}
741
defer tx.Rollback()
742
743
+
err = db.ResubmitPull(tx, pull, patch, sourceRev)
744
if err != nil {
745
log.Println("failed to create pull request", err)
746
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
···
767
TargetRepo: string(f.RepoAt),
768
TargetBranch: pull.TargetBranch,
769
Patch: patch, // new patch
770
+
Source: recordPullSource,
771
},
772
},
773
})
+15
appview/state/signer.go
+15
appview/state/signer.go
···
287
return us.client.Do(req)
288
}
289
290
+
func (us *UnsignedClient) Branch(ownerDid, repoName, branch string) (*http.Response, error) {
291
+
const (
292
+
Method = "GET"
293
+
)
294
+
295
+
endpoint := fmt.Sprintf("/%s/%s/branches/%s", ownerDid, repoName, branch)
296
+
297
+
req, err := us.newRequest(Method, endpoint, nil)
298
+
if err != nil {
299
+
return nil, err
300
+
}
301
+
302
+
return us.client.Do(req)
303
+
}
304
+
305
func (us *UnsignedClient) DefaultBranch(ownerDid, repoName string) (*http.Response, error) {
306
const (
307
Method = "GET"
-2
knotserver/git/diff.go
-2
knotserver/git/diff.go
+13
knotserver/git/git.go
+13
knotserver/git/git.go
···
238
return branches, nil
239
}
240
241
+
func (g *GitRepo) Branch(name string) (*plumbing.Reference, error) {
242
+
ref, err := g.r.Reference(plumbing.NewBranchReferenceName(name), false)
243
+
if err != nil {
244
+
return nil, fmt.Errorf("branch: %w", err)
245
+
}
246
+
247
+
if !ref.Name().IsBranch() {
248
+
return nil, fmt.Errorf("branch: %s is not a branch", ref.Name())
249
+
}
250
+
251
+
return ref, nil
252
+
}
253
+
254
func (g *GitRepo) SetDefaultBranch(branch string) error {
255
ref := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.NewBranchReferenceName(branch))
256
return g.r.Storer.SetReference(ref)
+1
knotserver/handler.go
+1
knotserver/handler.go
+31
knotserver/routes.go
+31
knotserver/routes.go
···
456
return
457
}
458
459
+
func (h *Handle) Branch(w http.ResponseWriter, r *http.Request) {
460
+
path, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, didPath(r))
461
+
branchName := chi.URLParam(r, "branch")
462
+
l := h.l.With("handler", "Branch")
463
+
464
+
gr, err := git.PlainOpen(path)
465
+
if err != nil {
466
+
notFound(w)
467
+
return
468
+
}
469
+
470
+
ref, err := gr.Branch(branchName)
471
+
if err != nil {
472
+
l.Error("getting branches", "error", err.Error())
473
+
writeError(w, err.Error(), http.StatusInternalServerError)
474
+
return
475
+
}
476
+
477
+
resp := types.RepoBranchResponse{
478
+
Branch: types.Branch{
479
+
Reference: types.Reference{
480
+
Name: ref.Name().Short(),
481
+
Hash: ref.Hash().String(),
482
+
},
483
+
},
484
+
}
485
+
486
+
writeJSON(w, resp)
487
+
return
488
+
}
489
+
490
func (h *Handle) Keys(w http.ResponseWriter, r *http.Request) {
491
l := h.l.With("handler", "Keys")
492
+4
types/repo.go
+4
types/repo.go