Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reuse devmode utility from nixos/nixpkgs manuals #788

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 9 additions & 27 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,16 @@
(import ./overlay.nix)
];
};
devmode =
let
pythonEnvironment = pkgs.python310.withPackages (ps: with ps; [
livereload
]);
script = ''
from livereload import Server, shell

server = Server()

build_docs = shell("nix build")

print("Doing an initial build of the docs...")
build_docs()

server.watch("source/*", build_docs)
server.watch("source/**/*", build_docs)
server.watch("_templates/*.html", build_docs)
server.serve(root="result/")
'';
in
pkgs.writeShellApplication {
name = "devmode";
runtimeInputs = [ pythonEnvironment ];
text = ''
python ${pkgs.writeText "live.py" script}
'';
};
devmode = let
outputPath = "share/doc/nixpkgs";
indexPath = "manual.html";
in
pkgs.devmode-init {
inherit pkgs;
buildArgs = "./.";
open = "/index.html";
};
in
{
packages.default = pkgs.stdenv.mkDerivation {
Expand Down
121 changes: 121 additions & 0 deletions overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,128 @@ final: prev: let
license = licenses.mit;
};
};

devmode-init = {
pkgs,
# arguments to `nix-build`, e.g. `"foo.nix -A bar"`
buildArgs,
# what path to open a browser at
open,
}: let
inherit (pkgs) lib;

error_page = pkgs.writeShellScriptBin "error_page" ''
echo "<!DOCTYPE html>
<html>
<head>
<style>
@media (prefers-color-scheme: dark) {
:root { filter: invert(100%); }
}
</style>
</head>
<body><pre>$1</pre></body>
</html>"
'';

# The following would have been simpler:
# 1. serve from `$serve`
# 2. pass each build a `--out-link $serve/result`
# But that way live-server does not seem to detect changes and therefore no
# auto-reloads occur.
# Instead, we copy the contents of each build to the `$serve` directory.
# Using rsync here, instead of `cp`, to get as close to an atomic
# directory copy operation as possible. `--delay-updates` should
# also go towards that.
build_and_copy = pkgs.writeShellScriptBin "build_and_copy" ''
set -euxo pipefail

set +e
stderr=$(2>&1 nix-build --out-link $out_link ${buildArgs})
exit_status=$?
set -e

if [ $exit_status -eq 0 ];
then
# setting permissions to be able to clean up
${lib.getBin pkgs.rsync}/bin/rsync \
--recursive \
--chmod=u=rwX \
--delete-before \
--delay-updates \
$out_link/ \
$serve/
else
set +x
${lib.getBin error_page}/bin/error_page "$stderr" > $error_page_absolute
set -x

${lib.getBin pkgs.findutils}/bin/find $serve \
-type f \
! -name $error_page_relative \
-delete
fi
'';

# https://watchexec.github.io/
watcher = pkgs.writeShellScriptBin "watcher" ''
set -euxo pipefail

${lib.getBin pkgs.watchexec}/bin/watchexec \
--shell=none \
--restart \
--print-events \
${lib.getBin build_and_copy}/bin/build_and_copy
'';

# A Rust alternative to live-server exists, but it was not in nixpkgs.
# `--no-css-inject`: without this it seems that only CSS is auto-reloaded.
# https://www.npmjs.com/package/live-server
server = pkgs.writeShellScriptBin "server" ''
set -euxo pipefail

${lib.getBin pkgs.nodePackages_latest.live-server}/bin/live-server \
--host=127.0.0.1 \
--verbose \
--no-css-inject \
--entry-file=$error_page_relative \
--open=${open} \
$serve
'';

devmode =
pkgs.writeShellScriptBin "devmode"
''
set -euxo pipefail

function handle_exit {
rm -rf "$tmpdir"
}

tmpdir=$(mktemp -d)
trap handle_exit EXIT

export out_link="$tmpdir/result"
export serve="$tmpdir/serve"
mkdir $serve
export error_page_relative=error.html
export error_page_absolute=$serve/$error_page_relative
${lib.getBin error_page}/bin/error_page "building …" > $error_page_absolute

${lib.getBin pkgs.parallel}/bin/parallel \
--will-cite \
--line-buffer \
--tagstr '{/}' \
::: \
"${lib.getBin watcher}/bin/watcher" \
"${lib.getBin server}/bin/server"
'';
in
devmode
;
in {
inherit devmode-init;

python310 = prev.python310.override {
packageOverrides = python-final: python-prev: {
sphinx-sitemap = python-module-sphinx-sitemap {
Expand Down