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 d0ba103fa9f..cb07135e685 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 65a37eb05a3..c6aed62a939 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 4c04128052b..98b4b92be52 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 1f42078c8cf..437850e408b 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 7ad3f949a02..6f23e267bab 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 00000000000..ae7036e4626 --- /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 24fe20e8105..8ac2019f9d6 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 93400bf0ee6..59e3d5133bb 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