status-react/nix/scripts/node_modules.sh

83 lines
3.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# Check if we need to copy node_modules.
# (e.g. in case it has been modified after last copy)
#
# The reasoning for a (mostly) read-only node_modules folder:
# ideally wed symlink the folder directly to the Nix store
# so that were guaranteed to have a reproducible source.
# Unfortunately react-native wants to build some stuff after the fact
# and this is incompatible with the concept of a pure Nix package.
# Therefore we copy the whole source to the repo directory,
# allow writing only on the folders where it is absolutely required,
# and therefore we still keep some peace of mind that the rest
# of node_modules is unchanged the rest of the time.
#
set -Eeuo pipefail
function replaceNodeModules() {
local deps="$1"
local targetNodeModules="$2"
local needCopyModules=1
local sentinelFilePath="$targetNodeModules/.copied~"
# Check if node_modules exists and is valid
if [ -d "$targetNodeModules" ]; then
if [ -f "$sentinelFilePath" ]; then
existingPath="$(cat $sentinelFilePath)"
if [ "${existingPath}" != "${deps}" ]; then
echo "Yarn modules changed, copying new version over"
else
echo "Checking for modifications in node_modules..."
modifiedFiles=(
$(find $targetNodeModules -writable -type f -newer $sentinelFilePath \
-not \( -path "$targetNodeModules/react-native/ReactAndroid/build/*" -prune \
-o -path "$targetNodeModules/*/android/build/*" -prune \) -print) )
if [ ${#modifiedFiles[@]} -eq 0 ]; then
needCopyModules=0
echo "No modifications detected."
else
echo "Modifications detected in ${#modifiedFiles[@]} files:"
for f in ${modifiedFiles[@]}; do
echo "- $(realpath --relative-to=$STATUS_REACT_HOME $f)"
done
fi
fi
fi
if [ $needCopyModules -eq 1 ] && [ -d $targetNodeModules ]; then
chmod u+w -R $targetNodeModules
rm -rf $targetNodeModules
fi
fi
# Replace node_modules if necessary
if [ ! -d "$targetNodeModules" ]; then
local tmpNodeModules=$(mktemp -d)
echo "Copying node_modules from Nix store:"
echo " - ${deps}"
export TIMEFORMAT="Done in: %Es"
trap "[ -d \"${tmpNodeModules}\" ] && chmod -R u+w \"${tmpNodeModules}\" && rm -rf \"${tmpNodeModules}\"" ERR INT HUP
# WARNING: The -L here is crucial to let Metro find modules.
time cp -LRf ${deps}/node_modules/. "${tmpNodeModules}"
chmod -R u+w "${tmpNodeModules}"
# WARNING: We can't de-reference .bin symlinks
cp -Rf ${deps}/node_modules/.bin/. "${tmpNodeModules}/.bin/"
mv -f "${tmpNodeModules}" "${targetNodeModules}"
echo -n "${deps}" > "${sentinelFilePath}"
trap - ERR INT HUP
fi
}
deps="$1"
[ -d $deps ] || exit 1
nodeModulesDir="$STATUS_REACT_HOME/node_modules"
export -f replaceNodeModules
mkdir -p "$nodeModulesDir/"
# Leverage flock (file lock) utility to create an exclusive lock on node_modules/ while running replaceNodeModules
flock "$nodeModulesDir/" sh -c "replaceNodeModules $deps $nodeModulesDir"