2019-06-04 16:50:29 +00:00
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
|
|
#
|
2020-05-07 10:21:39 +00:00
|
|
|
|
# Check if we need to copy node_modules.
|
|
|
|
|
# (e.g. in case it has been modified after last copy)
|
2019-06-04 16:50:29 +00:00
|
|
|
|
#
|
|
|
|
|
# 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
|
|
|
|
|
|
2020-05-15 23:08:10 +00:00
|
|
|
|
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
|
|
|
|
|
source "${GIT_ROOT}/scripts/colors.sh"
|
|
|
|
|
|
|
|
|
|
# More concise output from 'time'
|
|
|
|
|
export TIMEFORMAT="Done in: %Es"
|
|
|
|
|
|
2022-01-05 13:32:02 +00:00
|
|
|
|
removeDir() {
|
2020-05-15 23:08:10 +00:00
|
|
|
|
[[ ! -d "${tmp}" ]] && return
|
|
|
|
|
chmod -R u+w "${tmp}"
|
|
|
|
|
rm -rf "${tmp}"
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-05 13:32:02 +00:00
|
|
|
|
copyNodeModules() {
|
2020-05-15 23:08:10 +00:00
|
|
|
|
local src="${1}"
|
|
|
|
|
local dst="${2}"
|
|
|
|
|
# WARNING: The ../ is there to avoid a Nix builtins.path bug:
|
|
|
|
|
# https://github.com/NixOS/nix/issues/3593
|
|
|
|
|
local tmp=$(mktemp -d -p "$(dirname ${dst})/../")
|
|
|
|
|
|
|
|
|
|
# We use a temporary directory to use mv as "atomic" change
|
|
|
|
|
trap "removeDir ${tmp}" ERR INT HUP
|
|
|
|
|
|
|
|
|
|
# WARNING: The -L here is crucial to let Metro find modules.
|
|
|
|
|
cp -LRf ${src}/node_modules/. "${tmp}"
|
|
|
|
|
chmod -R +w "${tmp}"
|
|
|
|
|
|
|
|
|
|
# WARNING: We can't de-reference .bin symlinks
|
|
|
|
|
cp -Rf ${src}/node_modules/.bin/. "${tmp}/.bin/"
|
|
|
|
|
rm -r "${dst}"
|
|
|
|
|
mv -f "${tmp}" "${dst}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Find files that were modified and should cause a re-copying of node modules.
|
|
|
|
|
# Some files are generated/modified by build processes and should be ignored.
|
2022-01-05 13:32:02 +00:00
|
|
|
|
findFilesNewerThan() {
|
2020-05-15 23:08:10 +00:00
|
|
|
|
local sentinel="${1}"
|
|
|
|
|
local dir="${2}"
|
|
|
|
|
find ${dir} -type f -writable \
|
|
|
|
|
-newer ${sentinel} \
|
|
|
|
|
-not -ipath "*/*android/build/*" -prune \
|
|
|
|
|
-not -ipath "*/xcuserdata/*" -prune \
|
|
|
|
|
-not -ipath "*/unpacked_bin/clj-kondo" \
|
|
|
|
|
-not -ipath "*/scripts/.packager.env" \
|
|
|
|
|
-print
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-05 13:32:02 +00:00
|
|
|
|
nodeModulesUnchanged() {
|
2020-05-15 23:08:10 +00:00
|
|
|
|
local src="$1"
|
|
|
|
|
local dst="$2"
|
|
|
|
|
local sentinelFile="${dst}/.copied~"
|
2019-06-04 16:50:29 +00:00
|
|
|
|
|
2019-09-13 13:45:24 +00:00
|
|
|
|
# Check if node_modules exists and is valid
|
2020-05-15 23:08:10 +00:00
|
|
|
|
if [[ ! -f "${sentinelFile}" ]]; then
|
|
|
|
|
# node_modules have not been created by this script
|
|
|
|
|
echo -e "${YLW}Node modules not created by Nix${RST}" >&2
|
|
|
|
|
return 1
|
2019-06-04 16:50:29 +00:00
|
|
|
|
fi
|
|
|
|
|
|
2020-05-15 23:08:10 +00:00
|
|
|
|
# Sentinel file holds location of the node_modules source in Nix store
|
|
|
|
|
currentNixSrc="$(cat ${sentinelFile})"
|
|
|
|
|
|
|
|
|
|
if [ "${currentNixSrc}" != "${src}" ]; then
|
|
|
|
|
echo -e "${YLW}Yarn modules changed, copying new version over${RST}" >&2
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Some build processes modify files in node_modules
|
|
|
|
|
modifiedFiles=($(findFilesNewerThan "${sentinelFile}" "${dst}"))
|
|
|
|
|
if [ ${#modifiedFiles[@]} -ne 0 ]; then
|
|
|
|
|
echo -e "${YLW}Changes detected in node_modules:${RST} ${#modifiedFiles[@]}" >&2
|
|
|
|
|
# Print files that have changes
|
|
|
|
|
for file in ${modifiedFiles[@]}; do
|
|
|
|
|
echo "- $(realpath --relative-to=${dst} ${file})" >&2
|
|
|
|
|
done
|
|
|
|
|
return 1
|
2019-06-04 16:50:29 +00:00
|
|
|
|
fi
|
2020-05-15 23:08:10 +00:00
|
|
|
|
|
|
|
|
|
echo -e "${GRN}No changes detected.${RST}" >&2
|
|
|
|
|
return 0
|
2019-09-13 13:45:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-05 13:32:02 +00:00
|
|
|
|
replaceNodeModules() {
|
2020-05-15 23:08:10 +00:00
|
|
|
|
local src="$1"
|
|
|
|
|
local dst="$2"
|
|
|
|
|
local sentinelFile="${dst}/.copied~"
|
|
|
|
|
|
|
|
|
|
if nodeModulesUnchanged ${src} ${dst}; then
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Replace node_modules if necessary
|
|
|
|
|
echo "Copying node_modules from Nix store:" >&2
|
|
|
|
|
echo " - ${src}" >&2
|
|
|
|
|
copyNodeModules ${src} ${dst}
|
|
|
|
|
echo -n "${src}" > "${sentinelFile}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Destination folder, Nix sets STATUS_REACT_HOME
|
|
|
|
|
dst="$STATUS_REACT_HOME/node_modules"
|
|
|
|
|
# Source of Node modules from /nix/store
|
|
|
|
|
src="$1"
|
|
|
|
|
|
|
|
|
|
if [[ ! -d ${src} ]]; then
|
|
|
|
|
echo -e "${RED}No such folder:${RST} ${src}" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2019-09-13 13:45:24 +00:00
|
|
|
|
|
2020-05-15 23:08:10 +00:00
|
|
|
|
# Make those available in shell spawned by flock
|
|
|
|
|
export -f replaceNodeModules nodeModulesUnchanged copyNodeModules findFilesNewerThan removeDir
|
2019-09-13 13:45:24 +00:00
|
|
|
|
|
2020-05-15 23:08:10 +00:00
|
|
|
|
mkdir -p "${dst}"
|
|
|
|
|
# Leverage file lock to create an exclusive lock.
|
|
|
|
|
# Otherwise multiple calls to this script would clash.
|
|
|
|
|
flock "${dst}/" sh -c "time replaceNodeModules ${src} ${dst}"
|