async function populateVersionAndModuleFromDep()

in generate-attribution/generate-attribution-file.js [300:401]


async function populateVersionAndModuleFromDep(dependencies) {
    const goListDepFilePath = path.join(projectAttributionDirectory, 'go-deps.json');
    const goListDepFileContent = await fsPromises.readFile(goListDepFilePath, 'utf8');
    const goListDeps = JSON.parse(goListDepFileContent);

    const isModuleMatch = (dep, goListDep, allowPrefixMatch = false) => {
        if (!goListDep.Module) return false;
        return dep.module === goListDep.Module.Path ||
            dep.module === goListDep.ImportPath ||
            (allowPrefixMatch && dep.module.startsWith(`${goListDep.Module.Path}/pkg`)) ||
            (allowPrefixMatch && dep.module.startsWith(goListDep.Module.Path))
    }

    const getDepVersion = (goListDep) => {
        return goListDep.Module.Replace?.Version ?? goListDep.Module.Version;
    }

    const isVersionMismatch = (depVersion, goDepVersion) => {
        if (!depVersion || !goDepVersion) {
            return false;
        }
        return depVersion !== goDepVersion;
    }

    const isPathMismatch = (dep, goListDep) => {
        return dep.modulePath !== goListDep.Module.Path &&
            dep.modulePath !== goListDep.Module.Replace?.Path;
    }

    const isRelativePath = (path) => {
        if (!path) return false;
        return path.startsWith('./') || path.startsWith('../');
    }

    const useReplacePath = (goListDep) => {
        // some replace paths end up being local to the repo
        // and start with ./ in that case leave the module alone
        // otherwise the replace module path is more accurate
        return goListDep.Module.Replace?.Path &&
            !isRelativePath(goListDep.Module.Replace?.Path) &&
            goListDep.Module.Replace.Path !== goListDep.Module.Path;
    }

    const handleFound = (dep, goListDep, found) => {
        const goDepVersion = getDepVersion(goListDep);
        const bothVersionsUndef = dep.Version ?? goDepVersion;
        if (found &&
            (
                isVersionMismatch(dep.version, goDepVersion) ||
                isPathMismatch(dep, goListDep)
            )
        ) {
            console.log("NOTICE: Dep matched go list more than once.  Check it out", dep, goListDep)
        }
        dep.version ??= goDepVersion
        dep.modulePath = useReplacePath(goListDep) ? goListDep.Module.Replace.Path : goListDep.Module.Path;
        dep.moduleOverride = useReplacePath(goListDep) ? goListDep.Module.Replace.Path : goListDep.module;
    }

    const finalDeps = [];
    dependencies.forEach((dep) => {
        let found = false;
        if (dep.version) {
            // the package itself which was added using the GIT_TAG
            finalDeps.push(dep);
            return;
        }

        goListDeps.forEach((goListDep) => {
            if (isModuleMatch(dep, goListDep)) {
                handleFound(dep, goListDep, found);
                found = true;
            }
        });

        if (!found) {
            let match;
            goListDeps.forEach((goListDep) => {
                // these matches were found by the prefix match above
                // find the longest prefix and use that as our module
                if (isModuleMatch(dep, goListDep, true)) {
                    if (!match || goListDep.Module.Path.length > match.Module.Path.length) {
                        match = goListDep;
                    }
                }
            });
            if (match) {
                handleFound(dep, match, found);
                found = true;
            }
        }

        if (!found) {
            console.log("ERROR: Dep from go-license.csv was not found. Check it out", dep);
            process.exit(1);
        }
        else {
            finalDeps.push(dep);
        }
    });
    return finalDeps;
}