1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
{ pkgs, lib }:
# Shared by the system service in ncdu.nix (servers) and the user service in
# rolery.nix: index each root with ncdu into its own binary export, browse with
# `ncdu-ui [name]`.
#
# Every run writes a fresh <name>.ncdu.new and renames it over <name>.ncdu, so
# the index never grows (duc rewrote its database in place and never deleted a
# record) and readers always see the last complete export, even if a run is
# killed. ncdu -f reads the export lazily, one directory at a time (~13 MB
# resident even inside /nix/store), so browsing is cheap on 3 GB servers.
#
# -x: stay on the root's filesystem (btrfs: subvolume), so /proc, /sys, /boot,
# snapshot subvolumes and other mounts are not counted twice; index every
# filesystem you want to see as its own root.
# -e: also record mtime, owner and mode (+~6% size).
# Hard links are counted once and shown as shared size, ncdu needs no flag.
# cacheDir and the root paths are spliced into the script inside double
# quotes, so they may use shell variables like $HOME (the user service does).
# They must not contain `"`, `` ` `` or `\`.
{ cacheDir, roots, threads, defaultRoot }:
let
ncdu = "${pkgs.ncdu}/bin/ncdu";
in
{
index = pkgs.writeShellScript "ncdu-index" ''
set -euo pipefail
cache=${cacheDir}
mkdir -p "$cache"
${lib.concatStrings (lib.mapAttrsToList (name: path: ''
rm -f "$cache/${name}.ncdu.new"
${ncdu} -0 -x -e -t${toString threads} -O "$cache/${name}.ncdu.new" "${path}"
mv -f "$cache/${name}.ncdu.new" "$cache/${name}.ncdu"
'') roots)}
'';
ui = pkgs.writeShellScriptBin "ncdu-ui" ''
set -eu
cache=${cacheDir}
name=''${1:-${defaultRoot}}
if [ ! -e "$cache/$name.ncdu" ]; then
echo "ncdu-ui: no index $cache/$name.ncdu; have: $(cd "$cache" 2>/dev/null && ls *.ncdu 2>/dev/null | sed 's/\.ncdu$//' | tr '\n' ' ')" >&2
exit 1
fi
exec ${ncdu} -f "$cache/$name.ncdu"
'';
}
|