func printDir(path string) { if *local != "" { gosrc.SetLocalDevMode(*local) } dir, err := gosrc.Get(http.DefaultClient, path, *etag) if e, ok := err.(gosrc.NotFoundError); ok && e.Redirect != "" { log.Fatalf("redirect to %s", e.Redirect) } else if err != nil { log.Fatalf("%+v", err) } fmt.Println("ImportPath ", dir.ImportPath) fmt.Println("ResovledPath ", dir.ResolvedPath) fmt.Println("ProjectRoot ", dir.ProjectRoot) fmt.Println("ProjectName ", dir.ProjectName) fmt.Println("ProjectURL ", dir.ProjectURL) fmt.Println("VCS ", dir.VCS) fmt.Println("Etag ", dir.Etag) fmt.Println("BrowseURL ", dir.BrowseURL) fmt.Println("Subdirectories", strings.Join(dir.Subdirectories, ", ")) fmt.Println("LineFmt ", dir.LineFmt) fmt.Println("Files:") for _, file := range dir.Files { fmt.Printf("%30s %5d %s\n", file.Name, len(file.Data), file.BrowseURL) } }
func runLint(r *http.Request, importPath string) (*lintPackage, error) { dir, err := gosrc.Get(httpClient(r), importPath, "") if err != nil { return nil, err } pkg := lintPackage{ Path: importPath, Updated: time.Now(), LineFmt: dir.LineFmt, URL: dir.BrowseURL, } linter := lint.Linter{} for _, f := range dir.Files { if !strings.HasSuffix(f.Name, ".go") { continue } problems, err := linter.Lint(f.Name, f.Data) if err == nil && len(problems) == 0 { continue } file := lintFile{Name: f.Name, URL: f.BrowseURL} if err != nil { file.Problems = []*lintProblem{{Text: err.Error()}} } else { for _, p := range problems { file.Problems = append(file.Problems, &lintProblem{ Line: p.Position.Line, Text: p.Text, LineText: p.LineText, Confidence: p.Confidence, Link: p.Link, }) } } if len(file.Problems) > 0 { pkg.Files = append(pkg.Files, &file) } } if err := putPackage(appengine.NewContext(r), importPath, &pkg); err != nil { return nil, err } return &pkg, nil }
func Get(client *http.Client, importPath string, etag string) (*Package, error) { const versionPrefix = PackageVersion + "-" if strings.HasPrefix(etag, versionPrefix) { etag = etag[len(versionPrefix):] } else { etag = "" } dir, err := gosrc.Get(client, importPath, etag) if err != nil { return nil, err } pdoc, err := newPackage(dir) if err != nil { return pdoc, err } if pdoc.Synopsis == "" && pdoc.Doc == "" && !pdoc.IsCmd && pdoc.Name != "" && dir.ImportPath == dir.ProjectRoot && len(pdoc.Errors) == 0 { project, err := gosrc.GetProject(client, dir.ResolvedPath) switch { case err == nil: pdoc.Synopsis = doc.Synopsis(project.Description) case gosrc.IsNotFound(err): // ok default: return nil, err } } return pdoc, nil }
func ResolveDep(importPath string) (*dep.ResolvedTarget, error) { // Look up in cache. if target := resolveCache.Get(importPath); target != nil { return target, nil } if strings.HasSuffix(importPath, "_test") { // TODO(sqs): handle xtest packages - these should not be appearing here // as import paths, but they are, so suppress errors return nil, fmt.Errorf("xtest package (%s) is not yet supported", importPath) } // Check if this import path is in this tree. if pkg, err := buildContext.Import(importPath, "", build.FindOnly); err == nil && (pathHasPrefix(pkg.Dir, cwd) || isInEffectiveConfigGOPATH(pkg.Dir)) { // TODO(sqs): do we want to link refs to vendored deps to // their vendored code inside this repo? that's what it's // doing now. The alternative is to link to the external repo // that the code was vendored from. return &dep.ResolvedTarget{ // empty ToRepoCloneURL to indicate it's from this repository ToRepoCloneURL: "", ToUnit: importPath, ToUnitType: "GoPackage", }, nil } // Handle some special (and edge) cases faster for performance and corner-cases. target := &dep.ResolvedTarget{ToUnit: importPath, ToUnitType: "GoPackage"} switch { // CGO package "C" case importPath == "C": return nil, nil // Go standard library packages case gosrc.IsGoRepoPath(importPath) || strings.HasPrefix(importPath, "debug/") || strings.HasPrefix(importPath, "cmd/"): target.ToRepoCloneURL = "https://github.com/golang/go" target.ToVersionString = runtime.Version() target.ToRevSpec = "" // TODO(sqs): fill in when graphing stdlib repo // Special-case github.com/... import paths for performance. case strings.HasPrefix(importPath, "github.com/") || strings.HasPrefix(importPath, "sourcegraph.com/"): parts := strings.SplitN(importPath, "/", 4) if len(parts) < 3 { return nil, fmt.Errorf("import path starts with '(github|sourcegraph).com/' but is not valid: %q", importPath) } target.ToRepoCloneURL = "https://" + strings.Join(parts[:3], "/") + ".git" // Special-case google.golang.org/... (e.g., /appengine) import // paths for performance and to avoid hitting GitHub rate limit. case strings.HasPrefix(importPath, "google.golang.org/"): target.ToRepoCloneURL = "https://" + strings.Replace(importPath, "google.golang.org/", "github.com/golang/", 1) + ".git" // Special-case code.google.com/p/... import paths for performance. case strings.HasPrefix(importPath, "code.google.com/p/"): parts := strings.SplitN(importPath, "/", 4) if len(parts) < 3 { return nil, fmt.Errorf("import path starts with 'code.google.com/p/' but is not valid: %q", importPath) } target.ToRepoCloneURL = "https://" + strings.Join(parts[:3], "/") // Special-case golang.org/x/... import paths for performance. case strings.HasPrefix(importPath, "golang.org/x/"): parts := strings.SplitN(importPath, "/", 4) if len(parts) < 3 { return nil, fmt.Errorf("import path starts with 'golang.org/x/' but is not valid: %q", importPath) } target.ToRepoCloneURL = "https://" + strings.Replace(strings.Join(parts[:3], "/"), "golang.org/x/", "github.com/golang/", 1) // Try to resolve everything else default: log.Printf("Resolving Go dep: %s", importPath) dir, err := gosrc.Get(http.DefaultClient, string(importPath), "") if err == nil { target.ToRepoCloneURL = strings.TrimSuffix(dir.ProjectURL, "/") } else { log.Printf("warning: unable to fetch information about Go package %q: %s", importPath, err) target.ToRepoCloneURL = importPath } } // Save in cache. resolveCache.Put(importPath, target) return target, nil }