Files
awx/awx/ui/utils/get_licenses.js

240 lines
9.4 KiB
JavaScript
Executable File

#!/usr/bin/env node
/* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */
const { lstatSync, readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync } = require('fs');
const { join } = require('path');
const licenseTexts = require('./license_texts');
// path to shrinkwrap file
const SHRINKWRAP_PATH = `${__dirname}/../npm-shrinkwrap.json`;
// folder that npm install node_modules to
const NODE_MODULES_FOLDER = `${__dirname}/../node_modules`;
// the folder which we will put the ui license files
const UI_LICENSE_FOLDER = `${__dirname}/../../../docs/licenses/ui`;
// these folders in node_modules should be ommited
const OMITTED_NODE_MODULES_FOLDERS = ['@uirouter', '.bin', 'cycle'];
// all the ways in which deps with license files have license files named
const LICENSE_FILE_NAMES = ['LICENSE', 'LICENCE', 'LICENSE.md', 'LICENSE.txt', 'MIT-LICENSE.txt', 'LICENSE-MIT.txt', 'LICENSE-MIT', 'LICENSE.MIT', 'LICENSE.APACHE2', 'LICENSE.BSD'];
// all the ways in which deps with license info included in readme have the license header
const LICENSE_HEADER_NAMES = ['LICENSE', 'License', 'Licence'];
// all the ways in which deps with license info included in readme have readme files named
const README_FILE_NAMES = ['README', 'README.md', 'README.markdown'];
// deps that we need to manually grab the license info (and that info)
const MANUAL_NODE_MODULES_LICENSE_INFO = [];
// commenting out for now as cycle is a dev dependency,
// leaving in to show the format expected for this array
// {
// module_name: 'cycle',
// license_info: 'cycle was released as JSON-js
// under the public domain (original repo here: https://github.com/douglascrockford/JSON-js)
// and published to npm as cycle (repo here: https://github.com/dscape/cycle)'
// }
// ];
// texts of the licenses when the license attr is grabbed from package.json
const LICENSE_TEXTS = licenseTexts;
// below are helper functions the getters and main script execution functions
// call to piece together the license info
const isDirectory = source => lstatSync(source).isDirectory();
const manualNodeModulesSubDirectories = source => [join(source, '@uirouter/angularjs'), join(source, '@uirouter/core')];
const getNonDevDependencyModulesFromShrinkwrap = () => {
const getModDeps = (deps) => {
const depNamesArr = Object.keys(deps);
let arr = [];
depNamesArr.forEach(name => {
if (deps[name].dependecies) {
arr = arr.concat(getModDeps(deps[name].dependecies));
}
if (!deps[name].dev) {
arr.push(name);
}
});
return arr;
};
const shrinkwrap = JSON.parse(readFileSync(SHRINKWRAP_PATH).toString());
return getModDeps(shrinkwrap.dependencies);
};
const getSubdirectories = source => {
const listOfNonDevDependencyModules = getNonDevDependencyModulesFromShrinkwrap();
const fromNodeModsDir = readdirSync(source)
.filter(name => OMITTED_NODE_MODULES_FOLDERS.indexOf(name) === -1)
.filter(name => listOfNonDevDependencyModules.indexOf(name) !== -1)
.map(name => join(source, name))
.filter(isDirectory);
return fromNodeModsDir.concat(manualNodeModulesSubDirectories(source));
};
const getModulename = path => {
let updatedPath;
if (path.includes('@uirouter')) {
updatedPath = path.split('/').slice(-2).join('-');
} else {
updatedPath = path.split('/').slice(-1).join('');
}
return updatedPath;
};
const licenseTextIncludedInReadme = (readmeText, returnLicenseText) => LICENSE_HEADER_NAMES
.reduce((a, b) => {
let licenseVal;
if (!returnLicenseText) {
licenseVal = a || readmeText.includes(b);
} else if (a !== false) {
licenseVal = a;
} else if (readmeText.includes(b)) {
licenseVal = readmeText.split(b).slice(-1);
} else {
licenseVal = false;
}
return licenseVal;
}, false);
const readmeIncludedInLicense = (path, returnLicenseText) => {
const readmeText = readFileSync(path).toString();
return licenseTextIncludedInReadme(readmeText, returnLicenseText);
};
const licenseAttrInPackageJSON = (path, returnLicenseType) => {
const packageJSON = JSON.parse(readFileSync(path).toString());
let isInPackageJSON;
if (!returnLicenseType) {
isInPackageJSON = packageJSON.license !== undefined || packageJSON.licenses !== undefined;
} else if (packageJSON.license && packageJSON.license.type) {
isInPackageJSON = packageJSON.license.type.toString();
} else if (packageJSON.licenses && Array
.isArray(packageJSON.licenses) && packageJSON.licenses[0] && packageJSON.licenses[0].type) {
isInPackageJSON = packageJSON.licenses[0].type.toString();
} else if (packageJSON.licenses) {
isInPackageJSON = packageJSON.licenses.toString();
} else {
isInPackageJSON = packageJSON.license.toString();
}
return isInPackageJSON;
};
// below are getters for the various types of ways licenses are included in the packages
const hasLicenseFile = (path, returnFileName) => LICENSE_FILE_NAMES
.reduce((a, b) => {
let isLicenseFile;
if (!returnFileName) {
isLicenseFile = a || existsSync(join(path, b));
} else if (a !== false) {
isLicenseFile = a;
} else if (existsSync(join(path, b))) {
isLicenseFile = join(path, b);
} else {
isLicenseFile = false;
}
return isLicenseFile;
}, false);
const hasLicenseAttrInNPM = (path, returnLicenseType) => {
const packageJSONPath = join(path, 'package.json');
return existsSync(packageJSONPath) &&
licenseAttrInPackageJSON(packageJSONPath, returnLicenseType);
};
const hasLicenseInReadme = (path, returnLicenseText) => README_FILE_NAMES
.reduce((a, b) => {
const readmePath = join(path, b);
const readmeIncluded = existsSync(readmePath) && readmeIncludedInLicense(readmePath);
let isLicenseInReadme;
if (!returnLicenseText) {
isLicenseInReadme = a || readmeIncluded;
} else if (a !== false) {
isLicenseInReadme = a;
} else if (readmeIncluded) {
isLicenseInReadme = readmeIncludedInLicense(readmePath, returnLicenseText);
} else {
isLicenseInReadme = false;
}
return isLicenseInReadme;
}, false);
const hasManualLicenseInfo = (path) => Object.prototype.hasOwnProperty
.call(MANUAL_NODE_MODULES_LICENSE_INFO, path);
// checks to make sure all deps have some sort of license info associated
const licenseCheck = () => {
console.log('Checking each module for license.');
const noLicensePackage = getSubdirectories(NODE_MODULES_FOLDER)
.filter(path => !hasLicenseFile(path) &&
!hasLicenseAttrInNPM(path) &&
!hasLicenseInReadme(path) &&
!hasManualLicenseInfo(path));
if (noLicensePackage.length === 0) {
console.log('Success! All modules probably have a license associated.');
} else {
console.log(`Warning! The following modules do not have license info associated with them: ${noLicensePackage.join(', ')}.`);
}
};
// copies the license info from the deps into a licenses folder
const licenseWrite = () => {
// create the ui license folder if it doesn't exist
if (!existsSync(UI_LICENSE_FOLDER)) {
mkdirSync(UI_LICENSE_FOLDER);
}
console.log('Copying licenses from modules with license files.');
const modulesWithLicenseFile = getSubdirectories(NODE_MODULES_FOLDER)
.filter(path => hasLicenseFile(path));
console.log(`${modulesWithLicenseFile.length} modules with license files.`);
modulesWithLicenseFile.forEach(path => {
writeFileSync(
join(UI_LICENSE_FOLDER, getModulename(path)),
readFileSync(hasLicenseFile(path, true)).toString()
);
});
const modulesWithPackageJSONLicenseAttr = getSubdirectories(NODE_MODULES_FOLDER)
.filter(path => !hasLicenseFile(path) && hasLicenseAttrInNPM(path));
console.log(`${modulesWithPackageJSONLicenseAttr.length} modules with license attr in package.json.`);
modulesWithPackageJSONLicenseAttr.forEach(path => {
const licenseType = hasLicenseAttrInNPM(path, true);
let licenseText = LICENSE_TEXTS[licenseType];
if (!licenseText) {
console.log(`WARNING! License text for ${licenseType} is not in license_texts.js. Please add it. Just adding the license type to the module's file for now.`);
licenseText = licenseType;
}
writeFileSync(join(UI_LICENSE_FOLDER, getModulename(path)), licenseText);
});
const modulesWithLicenseInfoInReadme = getSubdirectories(NODE_MODULES_FOLDER)
.filter(path => !hasLicenseFile(path) &&
!hasLicenseAttrInNPM(path) &&
hasLicenseInReadme(path));
console.log(`${modulesWithLicenseInfoInReadme.length} modules with license text in readme.`);
modulesWithLicenseInfoInReadme.forEach(path => {
writeFileSync(join(UI_LICENSE_FOLDER, getModulename(path)), hasLicenseInReadme(path, true));
});
console.log(`${MANUAL_NODE_MODULES_LICENSE_INFO.length} modules with license info manually added to this script.`);
MANUAL_NODE_MODULES_LICENSE_INFO.forEach(mod => {
writeFileSync(join(UI_LICENSE_FOLDER, mod.module_name), mod.license_info);
});
};
licenseCheck();
licenseWrite();