1
1
mirror of https://github.com/NixOS/mobile-nixos.git synced 2024-12-17 13:10:29 +03:00
mobile-nixos/lib/image-builder/makeFilesystem.nix

153 lines
3.8 KiB
Nix

{ stdenvNoCC, lib, writeText }:
/* */ let scope = { "fileSystem.makeFilesystem" =
let
inherit (lib) optionals optionalString assertMsg;
in
{
name
# Size (in bytes) the filesystem image will be given.
# When size is not given, it is assumed that `populateCommands` will populate
# the filesystem, and the size will be derived (see computeMinimalSize).
, size ? null
# The populate commands are executed in a subshell. The CWD at the star is the
# public API to know where to add files that will be added to the image.
, populateCommands ? null
# Used with the assumption that files are rounded up to blockSize increments.
, blockSize
# Additional commands to compute a required increase in size to fit files.
, computeMinimalSize ? null
# When automatic sizing is used, additional amount of bytes to pad the image by.
, extraPadding ? 0
, ...
} @ args:
assert lib.asserts.assertMsg
(size !=null || populateCommands != null)
"Either a size or populateCommands needs to be given to build a filesystem.";
let
partName = name;
in
stdenvNoCC.mkDerivation (args // rec {
# Do not inherit `size`; we don't want to accidentally use it. The `size` can
# be dynamic depending on the contents.
inherit partName blockSize;
name = "partition-${partName}";
filename = "${partName}.img";
img = "${placeholder "out"}/${filename}";
nativeBuildInputs = [
] ++ optionals (args ? nativeBuildInputs) args.nativeBuildInputs;
buildCommand = ''
adjust-minimal-size() {
size="$1"
echo "$size"
}
compute-minimal-size() {
local size=0
(
cd files
# Size rounded in blocks. This assumes all files are to be rounded to a
# multiple of blockSize.
# Use of `--apparent-size` is to ensure we don't get the block size of the underlying FS.
# Use of `--block-size` is to get *our* block size.
size=$(find . ! -type d -exec 'du' '--apparent-size' '--block-size' "$blockSize" '{}' ';' | cut -f1 | sum-lines)
echo "Reserving $size sectors for files..." 1>&2
# Adds one blockSize per directory, they do take some place, in the end.
# FIXME: write test to confirm this assumption
local directories=$(find . -type d | wc -l)
echo "Reserving $directories sectors for directories..." 1>&2
size=$(( directories + size ))
size=$((size * blockSize))
${if computeMinimalSize == null then "" else computeMinimalSize}
size=$(( size + ${toString extraPadding} ))
echo "$size"
)
}
sum-lines() {
local acc=0
while read -r number; do
acc=$((acc+number))
done
echo "$acc"
}
# The default stdenv/generic clashes with `runHook`.
# It doesn't override as expected.
unset -f checkPhase
mkdir -p $out
mkdir -p files
${optionalString (populateCommands != null) ''
echo
echo "Populating disk image"
echo
(
cd files
${populateCommands}
)
''}
${optionalString (size == null) ''
size=$(compute-minimal-size)
''}
if (( size < minimumSize )); then
size=$minimumSize
echo "WARNING: the '$partName' partition was too small, size increased to $minimumSize bytes."
fi
echo
echo "Building partition ${partName}"
echo "With ${if size == null
then "automatic size ($size bytes)"
else "$size bytes"
}"
echo
echo " -> Allocating space"
truncate -s $size "$img"
echo " -> Making filesystem"
runHook filesystemPhase
echo " -> Copying files"
(
cd files
runHook copyPhase
)
echo " -> Checking filesystem"
echo "$checkPhase"
runHook checkPhase
'';
})
# mkdir -p $out/nix-support
# cat ${writeText "${name}-metadata" (builtins.toJSON {
# inherit size;
# })} > $out/nix-support/partition-metadata.json
/* */ ;}; in scope."fileSystem.makeFilesystem"