Monorepo for Tangled tangled.org

knotserver: routes: add handler/route to check if fork is syncable

authored by brookjeynes.dev and committed by Tangled a597918f 1235c6c5

Changed files
+70 -1
knotserver
+1
knotserver/handler.go
··· 129 129 r.Route("/fork", func(r chi.Router) { 130 130 r.Post("/", h.RepoFork) 131 131 r.Post("/sync/{branch}", h.RepoForkSync) 132 + r.Get("/sync/{branch}", h.RepoForkSyncable) 132 133 }) 133 134 }) 134 135
+69 -1
knotserver/routes.go
··· 631 631 w.WriteHeader(http.StatusNoContent) 632 632 } 633 633 634 + func (h *Handle) RepoForkSyncable(w http.ResponseWriter, r *http.Request) { 635 + l := h.l.With("handler", "RepoForkSync") 636 + 637 + data := struct { 638 + Did string `json:"did"` 639 + Source string `json:"source"` 640 + Name string `json:"name,omitempty"` 641 + HiddenRef string `json:"hiddenref"` 642 + }{} 643 + 644 + if err := json.NewDecoder(r.Body).Decode(&data); err != nil { 645 + writeError(w, "invalid request body", http.StatusBadRequest) 646 + return 647 + } 648 + 649 + did := data.Did 650 + source := data.Source 651 + 652 + if did == "" || source == "" { 653 + l.Error("invalid request body, empty did or name") 654 + w.WriteHeader(http.StatusBadRequest) 655 + return 656 + } 657 + 658 + var name string 659 + if data.Name != "" { 660 + name = data.Name 661 + } else { 662 + name = filepath.Base(source) 663 + } 664 + 665 + branch := chi.URLParam(r, "branch") 666 + branch, _ = url.PathUnescape(branch) 667 + 668 + relativeRepoPath := filepath.Join(did, name) 669 + repoPath, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, relativeRepoPath) 670 + 671 + gr, err := git.PlainOpen(repoPath) 672 + if err != nil { 673 + log.Println(err) 674 + notFound(w) 675 + return 676 + } 677 + 678 + forkCommit, err := gr.ResolveRevision(branch) 679 + if err != nil { 680 + l.Error("error resolving ref revision", "msg", err.Error()) 681 + writeError(w, fmt.Sprintf("error resolving revision %s", branch), http.StatusBadRequest) 682 + return 683 + } 684 + 685 + sourceCommit, err := gr.ResolveRevision(data.HiddenRef) 686 + if err != nil { 687 + l.Error("error resolving hidden ref revision", "msg", err.Error()) 688 + writeError(w, fmt.Sprintf("error resolving revision %s", data.HiddenRef), http.StatusBadRequest) 689 + return 690 + } 691 + 692 + isAncestor, err := forkCommit.IsAncestor(sourceCommit) 693 + if err != nil { 694 + log.Printf("error resolving whether %s is ancestor of %s: %s", branch, data.HiddenRef, err) 695 + return 696 + } 697 + 698 + w.Header().Set("Content-Type", "application/json") 699 + json.NewEncoder(w).Encode(types.AncestorCheckResponse{IsAncestor: isAncestor}) 700 + } 701 + 634 702 func (h *Handle) RepoForkSync(w http.ResponseWriter, r *http.Request) { 635 703 l := h.l.With("handler", "RepoForkSync") 636 704 ··· 676 744 677 745 err = gr.Sync(branch) 678 746 if err != nil { 679 - l.Error("syncing repo fork", "error", err.Error()) 747 + l.Error("error syncing repo fork", "error", err.Error()) 680 748 writeError(w, err.Error(), http.StatusInternalServerError) 681 749 return 682 750 }