in tool/preprocess/match.go [425:510]
func parseVendorModules(projDir string) ([]*vendorModule, error) {
vendorFile := filepath.Join(projDir, "vendor", "modules.txt")
if util.PathNotExists(vendorFile) {
return nil, errc.New(errc.ErrNotExist, "vendor/modules.txt not found")
}
file, err := os.Open(vendorFile)
if err != nil {
return nil, errc.New(errc.ErrOpenFile, err.Error())
}
defer func(dryRunLog *os.File) {
err := dryRunLog.Close()
if err != nil {
util.Log("Failed to close dry run log file: %v", err)
}
}(file)
scanner := bufio.NewScanner(file)
// 10MB should be enough to accommodate most long line
buffer := make([]byte, 0, 10*1024*1024)
scanner.Buffer(buffer, cap(buffer))
vms := make([]*vendorModule, 0)
var mod *vendorModule
vendorVersion := make(map[string]string)
// From src/cmd/go/internal/modload/vendor.go
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "# ") {
f := strings.Fields(line)
if len(f) < 3 {
continue
}
if semver.IsValid(f[2]) {
// A module, but we don't yet know whether it is in the build list or
// only included to indicate a replacement.
mod = &vendorModule{path: f[1], version: f[2]}
f = f[3:]
} else if f[2] == "=>" {
// A wildcard replacement found in the main module's go.mod file.
mod = &vendorModule{path: f[1]}
f = f[2:]
} else {
// Not a version or a wildcard replacement.
// We don't know how to interpret this module line, so ignore it.
mod = &vendorModule{}
continue
}
if len(f) >= 2 && f[0] == "=>" {
// Skip replacement lines
}
continue
}
// Not a module line. Must be a package within a module or a metadata
// directive, either of which requires a preceding module line.
if mod.path == "" {
continue
}
if _, ok := cutPrefix(line, "## "); ok {
// Skip annotations lines
continue
}
if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil {
// A package within the current module.
mod.submodules = append(mod.submodules, f[0])
// Since this module provides a package for the build, we know that it
// is in the build list and is the selected version of its path.
// If this information is new, record it.
if v, ok := vendorVersion[mod.path]; !ok || semver.Compare(v, mod.version) < 0 {
vms = append(vms, mod)
vendorVersion[mod.path] = mod.version
}
}
}
err = scanner.Err()
if err != nil {
return nil, errc.New(errc.ErrParseCode,
"cannot parse vendor/modules.txt")
}
return vms, nil
}