From 798957ad9d360767713b9cf12c26173d0dae4c28 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Tue, 19 Aug 2025 11:47:54 +0100 Subject: [PATCH] appview,knotserver: remove redundant call to DefaultBranch Change-Id: munxpvllmvyunzxmqksqtrtosnvkxxpo --- appview/pages/pages.go | 1 + appview/repo/index.go | 21 +++++++----- appview/repo/repo.go | 4 ++- appview/reporesolver/resolver.go | 57 ++++++++++---------------------- appview/state/profile.go | 19 ----------- knotserver/git/fork.go | 6 ++-- knotserver/handler.go | 4 +-- knotserver/routes.go | 8 ++--- 8 files changed, 44 insertions(+), 76 deletions(-) diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 24c46689..d8d397bf 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -520,6 +520,7 @@ func (p *Pages) RepoIndexPage(w io.Writer, params RepoIndexParams) error { } p.rctx.RepoInfo = params.RepoInfo + p.rctx.RepoInfo.Ref = params.Ref p.rctx.RendererType = markup.RendererTypeRepoMarkdown if params.ReadmeFileName != "" { diff --git a/appview/repo/index.go b/appview/repo/index.go index 3325f080..e6dc16b5 100644 --- a/appview/repo/index.go +++ b/appview/repo/index.go @@ -24,6 +24,7 @@ import ( func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { ref := chi.URLParam(r, "ref") + f, err := rp.repoResolver.Resolve(r) if err != nil { log.Println("failed to fully resolve repo", err) @@ -118,7 +119,7 @@ func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { var forkInfo *types.ForkInfo if user != nil && (repoInfo.Roles.IsOwner() || repoInfo.Roles.IsCollaborator()) { - forkInfo, err = getForkInfo(repoInfo, rp, f, user, signedClient) + forkInfo, err = getForkInfo(repoInfo, rp, f, result.Ref, user, signedClient) if err != nil { log.Printf("Failed to fetch fork information: %v", err) return @@ -126,7 +127,7 @@ func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { } // TODO: a bit dirty - languageInfo, err := rp.getLanguageInfo(f, signedClient, chi.URLParam(r, "ref") == "") + languageInfo, err := rp.getLanguageInfo(f, signedClient, result.Ref, ref == "") if err != nil { log.Printf("failed to compute language percentages: %s", err) // non-fatal @@ -161,18 +162,19 @@ func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { func (rp *Repo) getLanguageInfo( f *reporesolver.ResolvedRepo, signedClient *knotclient.SignedClient, + currentRef string, isDefaultRef bool, ) ([]types.RepoLanguageDetails, error) { // first attempt to fetch from db langs, err := db.GetRepoLanguages( rp.db, db.FilterEq("repo_at", f.RepoAt()), - db.FilterEq("ref", f.Ref), + db.FilterEq("ref", currentRef), ) if err != nil || langs == nil { // non-fatal, fetch langs from ks - ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.Name, f.Ref) + ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.Name, currentRef) if err != nil { return nil, err } @@ -183,7 +185,7 @@ func (rp *Repo) getLanguageInfo( for l, s := range ls.Languages { langs = append(langs, db.RepoLanguage{ RepoAt: f.RepoAt(), - Ref: f.Ref, + Ref: currentRef, IsDefaultRef: isDefaultRef, Language: l, Bytes: s, @@ -234,6 +236,7 @@ func getForkInfo( repoInfo repoinfo.RepoInfo, rp *Repo, f *reporesolver.ResolvedRepo, + currentRef string, user *oauth.User, signedClient *knotclient.SignedClient, ) (*types.ForkInfo, error) { @@ -264,22 +267,22 @@ func getForkInfo( } if !slices.ContainsFunc(result.Branches, func(branch types.Branch) bool { - return branch.Name == f.Ref + return branch.Name == currentRef }) { forkInfo.Status = types.MissingBranch return &forkInfo, nil } - newHiddenRefResp, err := signedClient.NewHiddenRef(user.Did, repoInfo.Name, f.Ref, f.Ref) + newHiddenRefResp, err := signedClient.NewHiddenRef(user.Did, repoInfo.Name, currentRef, currentRef) if err != nil || newHiddenRefResp.StatusCode != http.StatusNoContent { log.Printf("failed to update tracking branch: %s", err) return nil, err } - hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref) + hiddenRef := fmt.Sprintf("hidden/%s/%s", currentRef, currentRef) var status types.AncestorCheckResponse - forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt()), repoInfo.Name, f.Ref, hiddenRef) + forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt()), repoInfo.Name, currentRef, hiddenRef) if err != nil { log.Printf("failed to check if fork is ahead/behind: %s", err) return nil, err diff --git a/appview/repo/repo.go b/appview/repo/repo.go index dbb94440..e28cbc38 100644 --- a/appview/repo/repo.go +++ b/appview/repo/repo.go @@ -1315,6 +1315,8 @@ func (rp *Repo) pipelineSettings(w http.ResponseWriter, r *http.Request) { } func (rp *Repo) SyncRepoFork(w http.ResponseWriter, r *http.Request) { + ref := chi.URLParam(r, "ref") + user := rp.oauth.GetUser(r) f, err := rp.repoResolver.Resolve(r) if err != nil { @@ -1345,7 +1347,7 @@ func (rp *Repo) SyncRepoFork(w http.ResponseWriter, r *http.Request) { forkName := fmt.Sprintf("%s", f.Name) forkSourceUrl := fmt.Sprintf("%s://%s/%s/%s", uri, f.Knot, f.OwnerDid(), f.Repo.Name) - _, err = client.SyncRepoFork(user.Did, forkSourceUrl, forkName, f.Ref) + _, err = client.SyncRepoFork(user.Did, forkSourceUrl, forkName, ref) if err != nil { rp.pages.Notice(w, "repo", "Failed to sync repository fork.") return diff --git a/appview/reporesolver/resolver.go b/appview/reporesolver/resolver.go index bf8b8bbb..f00457f6 100644 --- a/appview/reporesolver/resolver.go +++ b/appview/reporesolver/resolver.go @@ -7,8 +7,8 @@ import ( "fmt" "log" "net/http" - "net/url" "path" + "regexp" "strings" "github.com/bluesky-social/indigo/atproto/identity" @@ -26,9 +26,9 @@ import ( type ResolvedRepo struct { db.Repo - OwnerId identity.Identity - Ref string - CurrentDir string + OwnerId identity.Identity + CurrentDir string + Ref string rr *RepoResolver } @@ -56,29 +56,14 @@ func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { return nil, fmt.Errorf("malformed middleware") } + currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath())) ref := chi.URLParam(r, "ref") - if ref == "" { - us, err := knotclient.NewUnsignedClient(repo.Knot, rr.config.Core.Dev) - if err != nil { - return nil, err - } - - defaultBranch, err := us.DefaultBranch(id.DID.String(), repo.Name) - if err != nil { - return nil, err - } - - ref = defaultBranch.Branch - } - - currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath(), ref)) - return &ResolvedRepo{ Repo: *repo, OwnerId: id, - Ref: ref, CurrentDir: currentDir, + Ref: ref, rr: rr, }, nil @@ -200,12 +185,9 @@ func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { if err != nil { log.Printf("failed to create unsigned client for %s: %v", knot, err) } else { - result, err := us.Branches(f.OwnerDid(), f.Name) - if err != nil { + if result, err := us.Branches(f.OwnerDid(), f.Name); err != nil { log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.Name, err) - } - - if len(result.Branches) == 0 { + } else if len(result.Branches) == 0 { disableFork = true } } @@ -216,7 +198,6 @@ func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { Name: f.Name, RepoAt: repoAt, Description: f.Description, - Ref: f.Ref, IsStarred: isStarred, Knot: knot, Spindle: f.Spindle, @@ -228,6 +209,7 @@ func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { }, DisableFork: disableFork, CurrentDir: f.CurrentDir, + Ref: f.Ref, } if sourceRepo != nil { @@ -251,22 +233,19 @@ func (f *ResolvedRepo) RolesInRepo(u *oauth.User) repoinfo.RolesInRepo { // after the ref. for example: // // /@icyphox.sh/foorepo/blob/main/abc/xyz/ => abc/xyz/ -func extractPathAfterRef(fullPath, ref string) string { +func extractPathAfterRef(fullPath string) string { fullPath = strings.TrimPrefix(fullPath, "/") - ref = url.PathEscape(ref) + // match blob/, tree/, or raw/ followed by any ref and then a slash + // + // captures everything after the final slash + pattern := `(?:blob|tree|raw)/[^/]+/(.*)$` - prefixes := []string{ - fmt.Sprintf("blob/%s/", ref), - fmt.Sprintf("tree/%s/", ref), - fmt.Sprintf("raw/%s/", ref), - } + re := regexp.MustCompile(pattern) + matches := re.FindStringSubmatch(fullPath) - for _, prefix := range prefixes { - idx := strings.Index(fullPath, prefix) - if idx != -1 { - return fullPath[idx+len(prefix):] - } + if len(matches) > 1 { + return matches[1] } return "" diff --git a/appview/state/profile.go b/appview/state/profile.go index 4acca956..f4bc99f7 100644 --- a/appview/state/profile.go +++ b/appview/state/profile.go @@ -89,25 +89,6 @@ func (s *State) profilePage(w http.ResponseWriter, r *http.Request) { log.Printf("failed to create profile timeline for %s: %s", ident.DID.String(), err) } - var didsToResolve []string - for _, r := range collaboratingRepos { - didsToResolve = append(didsToResolve, r.Did) - } - for _, byMonth := range timeline.ByMonth { - for _, pe := range byMonth.PullEvents.Items { - didsToResolve = append(didsToResolve, pe.Repo.Did) - } - for _, ie := range byMonth.IssueEvents.Items { - didsToResolve = append(didsToResolve, ie.Metadata.Repo.Did) - } - for _, re := range byMonth.RepoEvents { - didsToResolve = append(didsToResolve, re.Repo.Did) - if re.Source != nil { - didsToResolve = append(didsToResolve, re.Source.Did) - } - } - } - followers, following, err := db.GetFollowerFollowingCount(s.db, ident.DID.String()) if err != nil { log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err) diff --git a/knotserver/git/fork.go b/knotserver/git/fork.go index a35b5134..5b9a865d 100644 --- a/knotserver/git/fork.go +++ b/knotserver/git/fork.go @@ -27,10 +27,12 @@ func Fork(repoPath, source string) error { return nil } -func (g *GitRepo) Sync(branch string) error { +func (g *GitRepo) Sync() error { + branch := g.h.String() + fetchOpts := &git.FetchOptions{ RefSpecs: []config.RefSpec{ - config.RefSpec(fmt.Sprintf("+refs/heads/%s:refs/heads/%s", branch, branch)), + config.RefSpec("+" + branch + ":" + branch), // +refs/heads/master:refs/heads/master }, } diff --git a/knotserver/handler.go b/knotserver/handler.go index 2c52cc71..ee479d64 100644 --- a/knotserver/handler.go +++ b/knotserver/handler.go @@ -142,8 +142,8 @@ func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, j r.Delete("/", h.RemoveRepo) r.Route("/fork", func(r chi.Router) { r.Post("/", h.RepoFork) - r.Post("/sync/{branch}", h.RepoForkSync) - r.Get("/sync/{branch}", h.RepoForkAheadBehind) + r.Post("/sync/*", h.RepoForkSync) + r.Get("/sync/*", h.RepoForkAheadBehind) }) }) diff --git a/knotserver/routes.go b/knotserver/routes.go index 19ef2c2e..bbbe0443 100644 --- a/knotserver/routes.go +++ b/knotserver/routes.go @@ -710,7 +710,7 @@ func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) { } func (h *Handle) RepoForkAheadBehind(w http.ResponseWriter, r *http.Request) { - l := h.l.With("handler", "RepoForkSync") + l := h.l.With("handler", "RepoForkAheadBehind") data := struct { Did string `json:"did"` @@ -845,20 +845,20 @@ func (h *Handle) RepoForkSync(w http.ResponseWriter, r *http.Request) { name = filepath.Base(source) } - branch := chi.URLParam(r, "branch") + branch := chi.URLParam(r, "*") branch, _ = url.PathUnescape(branch) relativeRepoPath := filepath.Join(did, name) repoPath, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, relativeRepoPath) - gr, err := git.PlainOpen(repoPath) + gr, err := git.Open(repoPath, branch) if err != nil { log.Println(err) notFound(w) return } - err = gr.Sync(branch) + err = gr.Sync() if err != nil { l.Error("error syncing repo fork", "error", err.Error()) writeError(w, err.Error(), http.StatusInternalServerError) -- 2.43.0