Copyright 2020 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package localdatasource implements an in-memory internal.DataSource used to load and display documentation for local modules that are not available via a proxy. Similar to proxydatasource, search and other tabs are not supported in this mode.
package localdatasource

import (
	
	
	
	
	
	
	
	

	
	
	
	
)
DataSource implements an in-memory internal.DataSource used to display documentation locally. DataSource is not backed by a database or a proxy instance.
New creates and returns a new local datasource that bypasses license checks by default.
Load loads a module from the given local path. Loading is required before being able to display the module.
func ( *DataSource) ( context.Context,  string) ( error) {
	defer derrors.Wrap(&, "Load(%q)", )
	return .fetch(, "", )
}
LoadFromGOPATH loads a module from GOPATH using the given import path. The full path of the module should be GOPATH/src/importPath. If several GOPATHs exist, the module is loaded from the first one that contains the import path. Loading is required before being able to display the module.
func ( *DataSource) ( context.Context,  string) ( error) {
	defer derrors.Wrap(&, "LoadFromGOPATH(%q)", )

	 := getFullPath()
	if  == "" {
		return fmt.Errorf("path %s doesn't exist: %w", , derrors.NotFound)
	}

	return .fetch(, , )
}
fetch fetches a module using FetchLocalModule and adds it to the datasource. If the fetching fails, an error is returned.
func ( *DataSource) ( context.Context, ,  string) error {
	 := fetch.FetchLocalModule(, , , .sourceClient)
	if .Error != nil {
		return .Error
	}

	.Module.IsRedistributable = true
	for ,  := range .Module.Units {
		.IsRedistributable = true
	}

	for ,  := range .Module.Units {
		for ,  := range .Documentation {
			.BuildContexts = append(.BuildContexts, internal.BuildContext{
				GOOS:   .GOOS,
				GOARCH: .GOARCH,
			})
		}
	}

	.mu.Lock()
	defer .mu.Unlock()
	.loadedModules[.ModulePath] = .Module
	return nil
}
getFullPath takes an import path, tests it relative to each GOPATH, and returns a full path to the module. If the given import path doesn't exist in any GOPATH, an empty string is returned.
func ( string) string {
	 := filepath.SplitList(os.Getenv("GOPATH"))
	for ,  := range  {
		 := filepath.Join(, "src", )
		,  := os.Stat()
		if  == nil && .IsDir() {
			return 
		}
	}
	return ""
}
GetUnit returns information about a unit. Both the module path and package path must be known.
func ( *DataSource) ( context.Context,  *internal.UnitMeta,  internal.FieldSet,  internal.BuildContext) ( *internal.Unit,  error) {
	defer derrors.Wrap(&, "GetUnit(%q, %q)", .Path, .ModulePath)

	 := .ModulePath
	 := .Path

	.mu.Lock()
	defer .mu.Unlock()
	if .loadedModules[] == nil {
		return nil, fmt.Errorf("%s not loaded: %w", , derrors.NotFound)
	}

	 := .loadedModules[]
	for ,  := range .Units {
		if .Path ==  {
			return , nil
		}
	}

	return nil, fmt.Errorf("%s not found: %w", , derrors.NotFound)
}
GetUnitMeta returns information about a path.
func ( *DataSource) ( context.Context, , ,  string) ( *internal.UnitMeta,  error) {
	defer derrors.Wrap(&, "GetUnitMeta(%q, %q, %q)", , , )

	if  == internal.UnknownModulePath {
		,  = .findModule()
		if  != nil {
			return nil, 
		}
	}

	.mu.Lock()
	 := .loadedModules[]
	.mu.Unlock()
	if  == nil {
		return nil, fmt.Errorf("%s not loaded: %w", , derrors.NotFound)
	}

	 := &internal.UnitMeta{
		Path: ,
		ModuleInfo: internal.ModuleInfo{
			ModulePath:        ,
			Version:           fetch.LocalVersion,
			CommitTime:        fetch.LocalCommitTime,
			IsRedistributable: .IsRedistributable,
		},
	}

	for ,  := range .Units {
		if .Path ==  {
			.Name = .Name
			.IsRedistributable = .IsRedistributable
		}
	}

	return , nil
}
findModule finds the longest module path in loadedModules containing the given package path. It iteratively checks parent directories to find an import path. Returns an error if no module is found.
func ( *DataSource) ( string) ( string,  error) {
	defer derrors.Wrap(&, "findModule(%q)", )

	 = strings.TrimLeft(, "/")

	.mu.Lock()
	defer .mu.Unlock()
	for  := ;  != "" &&  != ".";  = path.Dir() {
		if .loadedModules[] != nil {
			return , nil
		}
	}

	return "", fmt.Errorf("%s not loaded: %w", , derrors.NotFound)
}
GetLatestInfo is not implemented.
func ( *DataSource) ( context.Context, ,  string,  *internal.UnitMeta) (internal.LatestInfo, error) {
	return internal.LatestInfo{}, nil
}
GetNestedModules is not implemented.
func ( *DataSource) ( context.Context,  string) ([]*internal.ModuleInfo, error) {
	return nil, nil
}
GetModuleReadme is not implemented.
func (*DataSource) ( context.Context, ,  string) (*internal.Readme, error) {
	return nil, nil