license.nix
160 lines
| 4.9 KiB
| text/x-nix
|
NixLexer
r1 | # Utility to generate the license information | |||
# | ||||
# Usage: | ||||
# | ||||
# nix-build -I ~/dev license.nix -A result | ||||
# | ||||
# Afterwards ./result will contain the license information as JSON files. | ||||
# | ||||
# | ||||
# Overview | ||||
# | ||||
# Uses two steps to get the relevant license information: | ||||
# | ||||
# 1. Walk down the derivations based on "buildInputs" and | ||||
# "propagatedBuildInputs". This results in all dependencies based on the nix | ||||
# declartions. | ||||
# | ||||
# 2. Build Enterprise and query nix-store to get a list of runtime | ||||
# dependencies. The results from step 1 are then limited to the ones which | ||||
# are in this list. | ||||
# | ||||
# The result is then available in ./result/license.json. | ||||
# | ||||
let | ||||
nixpkgs = import <nixpkgs> {}; | ||||
stdenv = nixpkgs.stdenv; | ||||
# Enterprise as simple as possible, goal here is just to identify the runtime | ||||
# dependencies. Ideally we could avoid building Enterprise at all and somehow | ||||
# figure it out without calling into nix-store. | ||||
enterprise = import ./default.nix { | ||||
doCheck = false; | ||||
}; | ||||
# For a given derivation, return the list of all dependencies | ||||
drvToDependencies = drv: nixpkgs.lib.flatten [ | ||||
drv.nativeBuildInputs or [] | ||||
drv.propagatedNativeBuildInputs or [] | ||||
]; | ||||
# Transform the given derivation into the meta information which we need in | ||||
# the resulting JSON files. | ||||
drvToMeta = drv: { | ||||
name = drv.name or "UNNAMED"; | ||||
license = if drv ? meta.license then drv.meta.license else "UNKNOWN"; | ||||
}; | ||||
# Walk the tree of buildInputs and propagatedBuildInputs and return it as a | ||||
# flat list. Duplicates are avoided. | ||||
listDrvDependencies = drv: let | ||||
addElement = element: seen: | ||||
if (builtins.elem element seen) | ||||
then seen | ||||
else let | ||||
newSeen = seen ++ [ element ]; | ||||
newDeps = drvToDependencies element; | ||||
in nixpkgs.lib.fold addElement newSeen newDeps; | ||||
initialElements = drvToDependencies drv; | ||||
in nixpkgs.lib.fold addElement [] initialElements; | ||||
# Reads in a file with store paths and returns a list of derivation names. | ||||
# | ||||
# Reads the file, splits the lines, then removes the prefix, so that we | ||||
# end up with a list of derivation names in the end. | ||||
storePathsToDrvNames = srcPath: let | ||||
rawStorePaths = nixpkgs.lib.removeSuffix "\n" ( | ||||
builtins.readFile srcPath); | ||||
storePaths = nixpkgs.lib.splitString "\n" rawStorePaths; | ||||
# TODO: johbo: Would be nice to use some sort of utility here to convert | ||||
# the path to a derivation name. | ||||
storePathPrefix = ( | ||||
builtins.stringLength "/nix/store/zwy7aavnif9ayw30rya1k6xiacafzzl6-"); | ||||
storePathToName = path: | ||||
builtins.substring storePathPrefix (builtins.stringLength path) path; | ||||
in (map storePathToName storePaths); | ||||
in rec { | ||||
# Build Enterprise and call nix-store to retrieve the runtime | ||||
# dependencies. The result is available in the nix store. | ||||
runtimeDependencies = stdenv.mkDerivation { | ||||
name = "runtime-dependencies"; | ||||
buildInputs = [ | ||||
# Needed to query the store | ||||
nixpkgs.nix | ||||
]; | ||||
unpackPhase = '' | ||||
echo "Nothing to unpack" | ||||
''; | ||||
buildPhase = '' | ||||
# Get a list of runtime dependencies | ||||
nix-store -q --references ${enterprise} > nix-store-references | ||||
''; | ||||
installPhase = '' | ||||
mkdir -p $out | ||||
cp -v nix-store-references $out/ | ||||
''; | ||||
}; | ||||
# Produce the license overview files. | ||||
result = let | ||||
# Dependencies according to the nix-store | ||||
runtimeDependencyNames = ( | ||||
storePathsToDrvNames "${runtimeDependencies}/nix-store-references"); | ||||
# Dependencies based on buildInputs and propagatedBuildInputs | ||||
enterpriseAllDependencies = listDrvDependencies enterprise; | ||||
enterpriseRuntimeDependencies = let | ||||
elemName = element: element.name or "UNNAMED"; | ||||
isRuntime = element: builtins.elem (elemName element) runtimeDependencyNames; | ||||
in builtins.filter isRuntime enterpriseAllDependencies; | ||||
# Extract relevant meta information | ||||
enterpriseAllLicenses = map drvToMeta enterpriseAllDependencies; | ||||
enterpriseRuntimeLicenses = map drvToMeta enterpriseRuntimeDependencies; | ||||
in stdenv.mkDerivation { | ||||
name = "licenses"; | ||||
buildInputs = []; | ||||
unpackPhase = '' | ||||
echo "Nothing to unpack" | ||||
''; | ||||
buildPhase = '' | ||||
mkdir build | ||||
# Copy list of runtime dependencies for the Python processor | ||||
cp "${runtimeDependencies}/nix-store-references" ./build/nix-store-references | ||||
# All licenses which we found by walking buildInputs and | ||||
# propagatedBuildInputs | ||||
cat > build/all-licenses.json <<EOF | ||||
${builtins.toJSON enterpriseAllLicenses} | ||||
EOF | ||||
# License information for our runtime dependencies only. Basically all | ||||
# licenses limited to the items which where also reported by nix-store as | ||||
# a dependency. | ||||
cat > build/licenses.json <<EOF | ||||
${builtins.toJSON enterpriseRuntimeLicenses} | ||||
EOF | ||||
''; | ||||
installPhase = '' | ||||
mkdir -p $out | ||||
# Store it all, that helps when things go wrong | ||||
cp -rv ./build/* $out | ||||
''; | ||||
}; | ||||
} | ||||