gore runs everything
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178package module
import ( "context" "encoding/json" "fmt" "io" "net/http" "os" "path" "strings"
"golang.org/x/mod/module" "golang.org/x/sync/errgroup")
type latestResp struct { Version string `json:"Version"`}
type resolvedModule struct { Module string Version string GoMod []byte}
func proxyRequest(importPath, suffix string) (*http.Request, error) { proxyBase := "https://proxy.golang.org" if gp := os.Getenv("GOPROXY"); gp != "" { if strings.ContainsRune(gp, ',') || strings.ContainsRune(gp, '|') || gp == "off" || gp == "direct" { return nil, fmt.Errorf("only GOPROXY=<url> is supported by gore, not %q", gp) } proxyBase = strings.TrimSuffix(gp, "/") } escapedSuffix, err := module.EscapeVersion(suffix) if err != nil { return nil, err } if escapedSuffix != "@latest" { escapedSuffix = "@v/" + escapedSuffix } escapedImportPath, err := module.EscapePath(importPath) if err != nil { return nil, err } fmt.Println("proxyRequest", proxyBase+"/"+escapedImportPath+"/"+escapedSuffix) req, err := http.NewRequest("GET", proxyBase+"/"+escapedImportPath+"/"+escapedSuffix, nil) if err != nil { return nil, err } // TODO: dynamic version here pls req.Header.Set("User-Agent", "gore runs everything") return req, nil}
func moduleInfo(ctx context.Context, importPath, version string) (*latestResp, error) { fmt.Printf("moduleInfo\n importpath=%s\n version=%s\n", importPath, version) suffix := version + ".info" if version == "latest" { suffix = "@latest" } req, err := proxyRequest(importPath, suffix) if err != nil { fmt.Println("moduleInfo proxyRequestErr", err) return nil, err } req.Header.Set("Accept", "application/json") resp, err := http.DefaultClient.Do(req.WithContext(ctx)) if err != nil { fmt.Println("moduleInfo DefaultClient.Do err", err) return nil, err } fmt.Println("moduleInfo success: ", resp) defer func() { io.ReadAll(resp.Body) resp.Body.Close() }() if resp.StatusCode == http.StatusNotFound { return nil, nil } if got, want := resp.StatusCode, http.StatusOK; got != want { return nil, fmt.Errorf("unexpected HTTP status: got %v, want %v", resp.Status, want) } var latest latestResp b, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("reading HTTP response: %v", err) } if err := json.Unmarshal(b, &latest); err != nil { return nil, fmt.Errorf("decoding /@latest response: %v", err) } return &latest, nil}
func resolveGoMod(ctx context.Context, importPath string, latest *latestResp) (*resolvedModule, error) { fmt.Println("importpath", importPath) req, err := proxyRequest(importPath, latest.Version+".mod") if err != nil { return nil, err } resp, err := http.DefaultClient.Do(req.WithContext(ctx)) if err != nil { return nil, err } defer func() { io.ReadAll(resp.Body) resp.Body.Close() }() if got, want := resp.StatusCode, http.StatusOK; got != want { return nil, fmt.Errorf("unexpected HTTP status: got %v, want %v", resp.Status, want) } b, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("reading HTTP response: %v", err) } return &resolvedModule{ Module: importPath, Version: latest.Version, GoMod: b, }, nil}
func Resolve(ctx context.Context, importPath, version string) (*resolvedModule, error) { eg, latestctx := errgroup.WithContext(ctx)
parts := strings.Split(path.Clean(importPath), "/") fmt.Println("Resolve importpath", importPath) fmt.Println("parts", parts) resps := make([]*latestResp, len(parts)) for idx := len(parts); idx > 0; idx-- { idx := idx // copy importPath := strings.Join(parts[:idx], "/") fmt.Println("Resolve loop importPath", importPath) eg.Go(func() error { if importPath == "github.com" { // Short-circuit: github.com is not a Go module :) return nil } if strings.HasPrefix(importPath, "github.com/") && !strings.ContainsRune(strings.TrimPrefix(importPath, "github.com/"), '/') { // Short-circuit: github.com/<something> references an // organisation or user, not a repository. return nil } resp, err := moduleInfo(latestctx, importPath, version) if err != nil { return err } resps[idx-1] = resp return nil }) }
if err := eg.Wait(); err != nil { return nil, err }
for idx := len(parts); idx > 0; idx-- { importPath := strings.Join(parts[:idx], "/") fmt.Println("Resolve importpath2", importPath) resp := resps[idx-1] fmt.Println("Resolve resp", importPath) if resp == nil { fmt.Println("response nil") continue } r, err := resolveGoMod(ctx, importPath, resp) fmt.Printf("Resolution module=%s version=%s", r.Module, r.Version) fmt.Printf("Resolution Error %+v", err) return r, err }
return nil, fmt.Errorf("could not resolve import path %q to any Go module", importPath)}