status-mobile/nix/scripts/node_modules.sh

83 lines
3.1 KiB
Bash
Raw Normal View History

#!/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"