chriswarbo-net: dd4ce41242c3e46b4dded6f8b7c07e4e04b81538
1: { commands, emptyDirectory, fail, lib, metadata, newScope, nix-helpers
2: , nixpkgs-lib, pageTests, relTo, runCommand, warbo-packages, withArgs
3: , writeScript }:
4:
5: with rec {
6: inherit (builtins) attrValues elem getAttr hasAttr hashFile map readFile;
7: inherit (lib)
8: concatMapStringsSep concatStringsSep escapeShellArg hasSuffix mapAttrs
9: optionalAttrs;
10:
11: test = { file, name }:
12: runCommand name { inherit file; } (concatStringsSep "\n" (attrValues
13: (mapAttrs (testName: t:
14: if elem testName [ "override" "overrideDerivation" ] then
15: ""
16: else
17: ''${t} "$file"'') pageTests) ++ [ ''ln -s "$file" "$out"'' ]));
18: };
19: { file, inputs ? [ ], name, SOURCE_PATH, TO_ROOT ? "", unfinished ? false
20: , vars ? { }, }:
21: with rec {
22: md = metadata.of file;
23: extraPkgs = map (n:
24: if hasAttr n commands then
25: getAttr n commands
26: else
27: newScope (nix-helpers // warbo-packages) (withArgs [ n ] (getAttr n)) { })
28: (md.packages or [ ]);
29:
30: dir = if md ? dependencies then
31: nixpkgs-lib.fileset.toSource {
32: root = ../..;
33: fileset =
34: nixpkgs-lib.fileset.unions (map (p: ../.. + "/${p}") md.dependencies);
35: }
36: else
37: emptyDirectory;
38:
39: # If the page specifies a 'sha256' in its metadata, its renderer will be a
40: # fixed-output derivation (hence allowing network access)
41: hash = if md ? sha256 then {
42: outputHashMode = "flat";
43: outputHashAlgo = "sha256";
44: outputHash = md.sha256;
45: } else
46: { };
47:
48: # If we're using a fixed-output derivation, its hash will be looked up in the
49: # cache, even if we've changed the page. We would prefer such pages to be
50: # rebuilt when changed, just in case their hash is out of date. To make this
51: # happen, we append a hash of the page's content to its derivation name, so
52: # when the content changes, so does the name (and hence the store path).
53: prefix = with {
54: # When we hash the file, we need to strip out the `sha256:` line, so that
55: # when we plug in the correct hash, that won't cause the file's hash to
56: # change!
57: # We also add the paths to our processing commands, so any changes to those
58: # will cause rebuilds too.
59: # See https://stackoverflow.com/a/23696995/884682 for the awk command
60: stripHash = runCommand "strip-hash-${name}" { inherit file; } ''
61: {
62: echo ${commands.render_page}
63: awk '!/^sha256:/ || f++' < "$file"
64: } > "$out"
65: '';
66: };
67: if md ? sha256 then "${hashFile "sha256" "${stripHash}"}-" else "";
68:
69: # A "raw" page has been rendered, but not postprocessed or checked. We do that
70: # in separate derivations, to prevent tweaks from triggering the whole site to
71: # re-render (note that, due to Panpipe, each page can take arbitrarily long!)
72: raw = runCommand "raw-${prefix + name}" ({
73: inherit dir file SOURCE_PATH;
74: buildInputs = inputs ++ extraPkgs ++ [ commands.render_page fail ];
75:
76: } // optionalAttrs (hasAttr "parseArgs" md) {
77: parseArgF = writeScript "${name}-parseArgs.sh" ''
78: parseArgs=()
79: ${concatMapStringsSep "\n" (arg: "parseArgs+=(${escapeShellArg arg})")
80: md.parseArgs}
81: '';
82: } // optionalAttrs (hasAttr "renderArgs" md) {
83: renderArgF = writeScript "${name}-renderArgs.sh" ''
84: renderArgs=()
85: ${concatMapStringsSep "\n" (arg: "renderArgs+=(${escapeShellArg arg})")
86: md.renderArgs}
87: '';
88: } // hash // vars) ''
89: export DEST="$PWD/out.html"
90:
91: cd "$dir"
92: SOURCE="$file" render_page
93: grep '^.' < "$DEST" > /dev/null || fail "Error: No output when rendering"
94: mv "$DEST" "$out"
95: '';
96:
97: untested = runCommand "untested-${name}" {
98: inherit raw TO_ROOT;
99: buildInputs = [
100: commands.cleanup
101: commands.relativise
102: ]
103: # If postprocessor is given, it will usually refer to a commands element
104: ++ (if md ? postprocessor && hasAttr md.postprocessor commands then
105: [ (getAttr md.postprocessor commands) ]
106: else
107: [ ]);
108: postprocessor = md.postprocessor or "cat";
109: } ''
110: # Perform some post-processing steps: we always run cleanup and relativise,
111: # and pages are free to set another postprocessor in their YAML (defaults
112: # to 'cat', which passes its stdio along unchanged)
113: < "$raw" cleanup | "$postprocessor" | relativise > "$out"
114: '';
115:
116: rendered = if unfinished then
117: untested
118: else
119: test {
120: inherit name;
121: file = untested;
122: };
123: };
124: if hasSuffix ".html" file then
125: with { data = writeScript name (readFile file); };
126: if TO_ROOT == "" then data else relTo TO_ROOT data
127: else
128: rendered
Generated by git2html.