in internal/frontend/main.go [108:226]
func fetchMainDetails(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta,
requestedVersion string, expandReadme bool, bc internal.BuildContext) (_ *MainDetails, err error) {
defer middleware.ElapsedStat(ctx, "fetchMainDetails")()
unit, err := ds.GetUnit(ctx, um, internal.WithMain, bc)
if err != nil {
return nil, err
}
subdirectories := getSubdirectories(um, unit.Subdirectories, requestedVersion)
if err != nil {
return nil, err
}
nestedModules, err := getNestedModules(ctx, ds, um, subdirectories)
if err != nil {
return nil, err
}
readme, err := readmeContent(ctx, unit)
if err != nil {
return nil, err
}
var (
docParts = &dochtml.Parts{}
docLinks, modLinks []link
files []*File
synopsis string
goos, goarch string
buildContexts []internal.BuildContext
)
unit.Documentation = cleanDocumentation(unit.Documentation)
// There should be at most one Documentation.
var doc *internal.Documentation
if len(unit.Documentation) > 0 {
doc = unit.Documentation[0]
}
if doc != nil {
synopsis = doc.Synopsis
goos = doc.GOOS
goarch = doc.GOARCH
buildContexts = unit.BuildContexts
end := middleware.ElapsedStat(ctx, "DecodePackage")
docPkg, err := godoc.DecodePackage(doc.Source)
end()
if err != nil {
if errors.Is(err, godoc.ErrInvalidEncodingType) {
// Instead of returning a 500, return a 404 so the user can
// reprocess the documentation.
log.Errorf(ctx, "fetchMainDetails(%q, %q, %q): %v", um.Path, um.ModulePath, um.Version, err)
return nil, errUnitNotFoundWithoutFetch
}
return nil, err
}
docParts, err = getHTML(ctx, unit, docPkg, unit.SymbolHistory, bc)
// If err is ErrTooLarge, then docBody will have an appropriate message.
if err != nil && !errors.Is(err, dochtml.ErrTooLarge) {
return nil, err
}
for _, l := range docParts.Links {
docLinks = append(docLinks, link{Href: l.Href, Body: l.Text})
}
end = middleware.ElapsedStat(ctx, "sourceFiles")
files = sourceFiles(unit, docPkg)
end()
}
// If the unit is not a module, fetch the module readme to extract its
// links.
// In the unlikely event that the module is redistributable but the unit is
// not, we will not show the module links on the unit page.
if unit.Path != unit.ModulePath && unit.IsRedistributable {
modReadme, err := ds.GetModuleReadme(ctx, unit.ModulePath, unit.Version)
if err != nil && !errors.Is(err, derrors.NotFound) {
return nil, err
}
if err == nil {
rm, err := processReadme(ctx, modReadme, um.SourceInfo)
if err != nil {
return nil, err
}
modLinks = rm.Links
}
}
versionType, err := version.ParseType(um.Version)
if err != nil {
return nil, err
}
isTaggedVersion := versionType != version.TypePseudo
isStableVersion := semver.Major(um.Version) != "v0" && versionType == version.TypeRelease
pr := message.NewPrinter(middleware.LanguageTag(ctx))
return &MainDetails{
ExpandReadme: expandReadme,
Directories: unitDirectories(append(subdirectories, nestedModules...)),
Licenses: transformLicenseMetadata(um.Licenses),
CommitTime: absoluteTime(um.CommitTime),
Readme: readme.HTML,
ReadmeOutline: readme.Outline,
ReadmeLinks: readme.Links,
DocLinks: docLinks,
ModuleReadmeLinks: modLinks,
DocOutline: docParts.Outline,
DocBody: docParts.Body,
DocSynopsis: synopsis,
GOOS: goos,
GOARCH: goarch,
BuildContexts: buildContexts,
SourceFiles: files,
RepositoryURL: um.SourceInfo.RepoURL(),
SourceURL: um.SourceInfo.DirectoryURL(internal.Suffix(um.Path, um.ModulePath)),
MobileOutline: docParts.MobileOutline,
NumImports: pr.Sprint(unit.NumImports),
ImportedByCount: pr.Sprint(unit.NumImportedBy),
IsPackage: unit.IsPackage(),
ModFileURL: um.SourceInfo.ModuleURL() + "/go.mod",
IsTaggedVersion: isTaggedVersion,
IsStableVersion: isStableVersion,
}, nil
}