#!/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 we’d symlink the folder directly to the Nix store # so that we’re 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 (${deps}/node_modules)..." trap "[ -d \"$tmpNodeModules\" ] && chmod -R u+w \"$tmpNodeModules\" && rm -rf \"$tmpNodeModules\"" ERR INT HUP time cp -HRf --preserve=all ${deps}/node_modules/. "$tmpNodeModules" chmod -R u+w "$tmpNodeModules" mv -f "$tmpNodeModules" "$targetNodeModules" echo -n "${deps}" > $sentinelFilePath trap - ERR INT HUP echo "Done" 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"