From 5daee73ce41652d21743a7304b4fd3f9da926c35 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Fri, 5 Oct 2018 10:46:58 -0400 Subject: [PATCH] Generate links to function definitions Hydra passes the full revision in to the input, which we pass through. If we don't get this ,we try to get it from other sources, or default to master which should have the definition in a close-ish location. All published docs should have theURL resolve properly, only local hackers will have the link break. --- doc/.gitignore | 1 + doc/Makefile | 8 ++- doc/default.nix | 5 +- doc/functions/library/asserts.xml | 4 ++ doc/functions/library/attrsets.xml | 32 +++++++++++ doc/lib-function-locations.nix | 85 ++++++++++++++++++++++++++++++ doc/shell.nix | 2 +- pkgs/top-level/release.nix | 4 +- 8 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 doc/lib-function-locations.nix diff --git a/doc/.gitignore b/doc/.gitignore index d0ba103fa9f1..cb07135e6858 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -4,3 +4,4 @@ out manual-full.xml highlightjs +functions/library/locations.xml diff --git a/doc/Makefile b/doc/Makefile index 65a37eb05a3a..c6aed62a9396 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -19,7 +19,7 @@ fix-misc-xml: .PHONY: clean clean: - rm -f ${MD_TARGETS} .version manual-full.xml + rm -f ${MD_TARGETS} .version manual-full.xml functions/library/locations.xml rm -rf ./out/ ./highlightjs .PHONY: validate @@ -69,13 +69,17 @@ highlightjs: cp -r "$$HIGHLIGHTJS/loader.js" highlightjs/ -manual-full.xml: ${MD_TARGETS} .version *.xml **/*.xml **/**/*.xml +manual-full.xml: ${MD_TARGETS} .version functions/library/locations.xml *.xml **/*.xml **/**/*.xml xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml .version: nix-instantiate --eval \ -E '(import ../lib).version' > .version +functions/library/locations.xml: + nix-build ./lib-function-locations.nix \ + --out-link ./functions/library/locations.xml + %.section.xml: %.section.md pandoc $^ -w docbook+smart \ -f markdown+smart \ diff --git a/doc/default.nix b/doc/default.nix index 4c04128052bc..98b4b92be524 100644 --- a/doc/default.nix +++ b/doc/default.nix @@ -1,6 +1,7 @@ +{ pkgs ? (import ./.. { }), nixpkgs ? { }}: let - pkgs = import ./.. { }; lib = pkgs.lib; + locationsXml = import ./lib-function-locations.nix { inherit pkgs nixpkgs; }; in pkgs.stdenv.mkDerivation { name = "nixpkgs-manual"; @@ -29,6 +30,8 @@ pkgs.stdenv.mkDerivation { ]; postPatch = '' + rm -rf ./functions/library/locations.xml + ln -s ${locationsXml} ./functions/library/locations.xml echo ${lib.version} > .version ''; diff --git a/doc/functions/library/asserts.xml b/doc/functions/library/asserts.xml index 1f42078c8cf3..437850e408bc 100644 --- a/doc/functions/library/asserts.xml +++ b/doc/functions/library/asserts.xml @@ -10,6 +10,8 @@ assertMsg :: Bool -> String -> Bool + + Print a trace message if pred is false. @@ -59,6 +61,8 @@ stderr> assert failed StringList -> Bool + + Specialized asserts.assertMsg for checking if val is one of the elements of xs. diff --git a/doc/functions/library/attrsets.xml b/doc/functions/library/attrsets.xml index 7ad3f949a024..6f23e267bab2 100644 --- a/doc/functions/library/attrsets.xml +++ b/doc/functions/library/attrsets.xml @@ -10,6 +10,8 @@ attrByPath :: [String] -> Any -> AttrSet + + Return an attribute from within nested attribute sets. @@ -73,6 +75,8 @@ lib.attrsets.attrByPath [ "a" "b" ] 0 {} hasAttrByPath :: [String] -> AttrSet -> Bool + + Determine if an attribute exists within a nested attribute set. @@ -118,6 +122,8 @@ lib.attrsets.hasAttrByPath setAttrByPath :: [String] -> Any -> AttrSet + + Create a new attribute set with value set at the nested attribute location specified in attrPath. @@ -162,6 +168,8 @@ lib.attrsets.setAttrByPath [ "a" "b" ] 3 getAttrFromPath :: [String] -> AttrSet -> Value + + Like except without a default, and it will throw if the value doesn't exist. @@ -214,6 +222,8 @@ lib.attrsets.getAttrFromPath [ "x" "y" ] { } attrVals :: [String] -> AttrSet -> [Any] + + Return the specified attributes from a set. All values must exist. @@ -265,6 +275,8 @@ error: attribute 'd' missing attrValues :: AttrSet -> [Any] + + Get all the attribute values from an attribute set. @@ -302,6 +314,8 @@ lib.attrsets.attrValues { a = 1; b = 2; c = 3; } catAttrs :: String -> AttrSet -> [Any] + + Collect each attribute named `attr' from the list of attribute sets, sets. Sets that don't contain the named attribute are @@ -355,6 +369,8 @@ catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet + + Filter an attribute set by removing all attributes for which the given predicate return false. @@ -428,6 +444,8 @@ filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; } filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet + + Filter an attribute set recursively by removing all attributes for which the given predicate return false. @@ -523,6 +541,8 @@ lib.attrsets.filterAttrsRecursive foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any + + Apply fold function to values grouped by key. @@ -609,6 +629,8 @@ lib.attrsets.foldAttrs collect :: (Any -> Bool) -> AttrSet -> [Any] + + Recursively collect sets that verify a given predicate named pred from the set attrs. The recursion @@ -677,6 +699,8 @@ collect (x: x ? outPath) nameValuePair :: String -> Any -> AttrSet + + Utility function that creates a {name, value} pair as expected by builtins.listToAttrs. @@ -720,6 +744,8 @@ nameValuePair "some" 6 + + Apply a function to each element in an attribute set, creating a new attribute set. @@ -785,6 +811,8 @@ lib.attrsets.mapAttrs mapAttrs' :: (String -> Any -> { name = String; value = Any }) -> AttrSet -> AttrSet + + Like mapAttrs, but allows the name of each attribute to be changed in addition to the value. The applied function should return both @@ -860,6 +888,8 @@ lib.attrsets.mapAttrs' (name: value: lib.attrsets.nameValuePair ("foo_" + name) AttrSet -> Any + + Call fn for each attribute in the given set and return the result in a list. @@ -929,6 +959,8 @@ lib.attrsets.mapAttrsToList (name: value: "${name}=${value}") mapAttrsRecursive :: ([String] > Any -> Any) -> AttrSet -> AttrSet + + Like mapAttrs, except that it recursively applies itself to attribute sets. Also, the first argument of the argument function diff --git a/doc/lib-function-locations.nix b/doc/lib-function-locations.nix new file mode 100644 index 000000000000..ae7036e46264 --- /dev/null +++ b/doc/lib-function-locations.nix @@ -0,0 +1,85 @@ +{ pkgs ? (import ./.. { }), nixpkgs ? { }}: +let + revision = pkgs.lib.trivial.revisionWithDefault (nixpkgs.revision or "master"); + + libDefPos = set: + builtins.map + (name: { + name = name; + location = builtins.unsafeGetAttrPos name set; + }) + (builtins.attrNames set); + + libset = toplib: + builtins.map + (subsetname: { + subsetname = subsetname; + functions = libDefPos toplib."${subsetname}"; + }) + (builtins.filter + (name: builtins.isAttrs toplib."${name}") + (builtins.attrNames toplib)); + + nixpkgsLib = pkgs.lib; + + flattenedLibSubset = { subsetname, functions }: + builtins.map + (fn: { + name = "lib.${subsetname}.${fn.name}"; + value = fn.location; + }) + functions; + + locatedlibsets = libs: builtins.map flattenedLibSubset (libset libs); + removeFilenamePrefix = prefix: filename: + let + prefixLen = (builtins.stringLength prefix) + 1; # +1 to remove the leading / + filenameLen = builtins.stringLength filename; + substr = builtins.substring prefixLen filenameLen filename; + in substr; + + removeNixpkgs = removeFilenamePrefix (builtins.toString pkgs.path); + + liblocations = + builtins.filter + (elem: elem.value != null) + (nixpkgsLib.lists.flatten + (locatedlibsets nixpkgsLib)); + + fnLocationRelative = { name, value }: + { + inherit name; + value = value // { file = removeNixpkgs value.file; }; + }; + + relativeLocs = (builtins.map fnLocationRelative liblocations); + sanitizeId = builtins.replaceStrings + [ "'" ] + [ "-prime" ]; + + urlPrefix = "https://github.com/NixOS/nixpkgs/blob/${revision}"; + xmlstrings = (nixpkgsLib.strings.concatMapStrings + ({ name, value }: + '' +
${name} + + Located at + ${value.file}:${builtins.toString value.line} + in <nixpkgs>. + +
+ '') + relativeLocs); + +in pkgs.writeText + "locations.xml" + '' +
+ All the locations for every lib function + This file is only for inclusion by other files. + ${xmlstrings} +
+ '' diff --git a/doc/shell.nix b/doc/shell.nix index 24fe20e81050..8ac2019f9d66 100644 --- a/doc/shell.nix +++ b/doc/shell.nix @@ -1,5 +1,5 @@ { pkgs ? import ../. {} }: -(import ./default.nix).overrideAttrs (x: { +(import ./default.nix {}).overrideAttrs (x: { buildInputs = x.buildInputs ++ [ pkgs.xmloscopy pkgs.ruby ]; }) diff --git a/pkgs/top-level/release.nix b/pkgs/top-level/release.nix index 93400bf0ee65..59e3d5133bbe 100644 --- a/pkgs/top-level/release.nix +++ b/pkgs/top-level/release.nix @@ -8,7 +8,7 @@ $ nix-build pkgs/top-level/release.nix -A coreutils.x86_64-linux */ -{ nixpkgs ? { outPath = (import ../../lib).cleanSource ../..; revCount = 1234; shortRev = "abcdef"; } +{ nixpkgs ? { outPath = (import ../../lib).cleanSource ../..; revCount = 1234; shortRev = "abcdef"; revision = "0000000000000000000000000000000000000000"; } , officialRelease ? false # The platforms for which we build Nixpkgs. , supportedSystems ? [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ] @@ -32,7 +32,7 @@ let metrics = import ./metrics.nix { inherit pkgs nixpkgs; }; - manual = import ../../doc; + manual = import ../../doc { inherit pkgs nixpkgs; }; lib-tests = import ../../lib/tests/release.nix { inherit pkgs; }; darwin-tested = if supportDarwin then pkgs.releaseTools.aggregate