push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
{
stdenv,
lib,
php,
autoreconfHook,
fetchurl,
re2c,
nix-update-script,
}:
{
pname,
version,
internalDeps ? [ ],
peclDeps ? [ ],
buildInputs ? [ ],
nativeBuildInputs ? [ ],
postPhpize ? "",
makeFlags ? [ ],
src ? fetchurl (
{
url = "https://pecl.php.net/get/${pname}-${version}.tgz";
}
// lib.filterAttrs (
attrName: _:
lib.elem attrName [
"sha256"
"hash"
]
) args
),
passthru ? { },
...
}@args:
stdenv.mkDerivation (
args
// {
name = "php-${pname}-${version}";
extensionName = pname;
inherit src;
strictDeps = true;
nativeBuildInputs = [
php
autoreconfHook
re2c
]
++ nativeBuildInputs;
buildInputs = [ php ] ++ peclDeps ++ buildInputs;
makeFlags = [ "EXTENSION_DIR=$(out)/lib/php/extensions" ] ++ makeFlags;
autoreconfPhase = ''
phpize
${postPhpize}
${lib.concatMapStringsSep "\n" (
dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}"
) internalDeps}
'';
checkPhase = "NO_INTERACTON=yes make test";
passthru = passthru // {
# Thes flags were introduced for `nix-update` so that it can update
# PHP extensions correctly.
# See the corresponding PR: https://github.com/Mic92/nix-update/pull/123
isPhpExtension = true;
updateScript = passthru.updateScript or (nix-update-script { });
};
}
)

View File

@@ -0,0 +1,15 @@
{ callPackage, callPackages, ... }:
{
v1 = {
buildComposerProject = callPackage ./v1/build-composer-project.nix { };
buildComposerWithPlugin = callPackage ./v1/build-composer-with-plugin.nix { };
mkComposerRepository = callPackage ./v1/build-composer-repository.nix { };
composerHooks = callPackages ./v1/hooks { };
};
v2 = {
buildComposerProject = callPackage ./v2/build-composer-project.nix { };
mkComposerVendor = callPackage ./v2/build-composer-vendor.nix { };
composerHooks = callPackages ./v2/hooks { };
};
}

View File

@@ -0,0 +1,102 @@
{
nix-update-script,
stdenvNoCC,
lib,
php,
}:
let
buildComposerProjectOverride =
finalAttrs: previousAttrs:
let
phpDrv = finalAttrs.php or php;
composer = finalAttrs.composer or phpDrv.packages.composer-local-repo-plugin;
in
{
composerLock = previousAttrs.composerLock or null;
composerNoDev = previousAttrs.composerNoDev or true;
composerNoPlugins = previousAttrs.composerNoPlugins or true;
composerNoScripts = previousAttrs.composerNoScripts or true;
composerStrictValidation = previousAttrs.composerStrictValidation or true;
nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
composer
phpDrv
phpDrv.composerHooks.composerInstallHook
];
buildInputs = (previousAttrs.buildInputs or [ ]) ++ [ phpDrv ];
patches = previousAttrs.patches or [ ];
strictDeps = previousAttrs.strictDeps or true;
# Should we keep these empty phases?
configurePhase =
previousAttrs.configurePhase or ''
runHook preConfigure
runHook postConfigure
'';
buildPhase =
previousAttrs.buildPhase or ''
runHook preBuild
runHook postBuild
'';
doCheck = previousAttrs.doCheck or true;
checkPhase =
previousAttrs.checkPhase or ''
runHook preCheck
runHook postCheck
'';
installPhase =
previousAttrs.installPhase or ''
runHook preInstall
runHook postInstall
'';
doInstallCheck = previousAttrs.doInstallCheck or false;
installCheckPhase =
previousAttrs.installCheckPhase or ''
runHook preInstallCheck
runHook postInstallCheck
'';
composerRepository =
previousAttrs.composerRepository or (phpDrv.mkComposerRepository {
inherit composer;
inherit (finalAttrs)
patches
pname
src
vendorHash
version
;
composerLock = previousAttrs.composerLock or null;
composerNoDev = previousAttrs.composerNoDev or true;
composerNoPlugins = previousAttrs.composerNoPlugins or true;
composerNoScripts = previousAttrs.composerNoScripts or true;
composerStrictValidation = previousAttrs.composerStrictValidation or true;
});
# Projects providing a lockfile from upstream can be automatically updated.
passthru = previousAttrs.passthru or { } // {
updateScript =
previousAttrs.passthru.updateScript
or (if finalAttrs.composerRepository.composerLock == null then nix-update-script { } else null);
};
meta = previousAttrs.meta or { } // {
platforms = lib.platforms.all;
};
};
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerProjectOverride

View File

@@ -0,0 +1,111 @@
{
stdenvNoCC,
lib,
php,
}:
let
mkComposerRepositoryOverride =
/*
We cannot destruct finalAttrs since the attrset below is used to construct it
and Nix currently does not support lazy attribute names.
{
php ? null,
composer ? null,
composerLock ? "composer.lock",
src,
vendorHash,
...
}@finalAttrs:
*/
finalAttrs: previousAttrs:
let
phpDrv = finalAttrs.php or php;
composer = finalAttrs.composer or phpDrv.packages.composer-local-repo-plugin;
in
assert (lib.assertMsg (previousAttrs ? src) "mkComposerRepository expects src argument.");
assert (
lib.assertMsg (previousAttrs ? vendorHash) "mkComposerRepository expects vendorHash argument."
);
assert (lib.assertMsg (previousAttrs ? version) "mkComposerRepository expects version argument.");
assert (lib.assertMsg (previousAttrs ? pname) "mkComposerRepository expects pname argument.");
assert (
lib.assertMsg (previousAttrs ? composerNoDev) "mkComposerRepository expects composerNoDev argument."
);
assert (
lib.assertMsg (
previousAttrs ? composerNoPlugins
) "mkComposerRepository expects composerNoPlugins argument."
);
assert (
lib.assertMsg (
previousAttrs ? composerNoScripts
) "mkComposerRepository expects composerNoScripts argument."
);
{
composerNoDev = previousAttrs.composerNoDev or true;
composerNoPlugins = previousAttrs.composerNoPlugins or true;
composerNoScripts = previousAttrs.composerNoScripts or true;
composerStrictValidation = previousAttrs.composerStrictValidation or true;
name = "${previousAttrs.pname}-composer-repository-${previousAttrs.version}";
# See https://github.com/NixOS/nix/issues/6660
dontPatchShebangs = previousAttrs.dontPatchShebangs or true;
nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
composer
phpDrv
phpDrv.composerHooks.composerRepositoryHook
];
buildInputs = previousAttrs.buildInputs or [ ];
strictDeps = previousAttrs.strictDeps or true;
# Should we keep these empty phases?
configurePhase =
previousAttrs.configurePhase or ''
runHook preConfigure
runHook postConfigure
'';
buildPhase =
previousAttrs.buildPhase or ''
runHook preBuild
runHook postBuild
'';
doCheck = previousAttrs.doCheck or true;
checkPhase =
previousAttrs.checkPhase or ''
runHook preCheck
runHook postCheck
'';
installPhase =
previousAttrs.installPhase or ''
runHook preInstall
runHook postInstall
'';
doInstallCheck = previousAttrs.doInstallCheck or false;
installCheckPhase =
previousAttrs.installCheckPhase or ''
runHook preInstallCheck
runHook postInstallCheck
'';
outputHashMode = "recursive";
outputHashAlgo =
if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256";
outputHash = finalAttrs.vendorHash or "";
};
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs mkComposerRepositoryOverride

View File

@@ -0,0 +1,155 @@
{
stdenvNoCC,
writeText,
lib,
makeBinaryWrapper,
php,
cacert,
nix-update-script,
}:
let
composerJsonBuilder =
pluginName: pluginVersion:
writeText "composer.json" (
builtins.toJSON {
name = "nix/plugin";
description = "Nix Composer plugin";
license = "MIT";
require = {
"${pluginName}" = "${pluginVersion}";
};
config = {
"allow-plugins" = {
"${pluginName}" = true;
};
};
repositories = [
{
type = "path";
url = "./src";
options = {
versions = {
"${pluginName}" = "${pluginVersion}";
};
};
}
];
}
);
buildComposerWithPluginOverride =
finalAttrs: previousAttrs:
let
phpDrv = finalAttrs.php or php;
composer = finalAttrs.composer or phpDrv.packages.composer;
in
{
composerLock = previousAttrs.composerLock or null;
composerNoDev = previousAttrs.composerNoDev or true;
composerNoPlugins = previousAttrs.composerNoPlugins or true;
composerNoScripts = previousAttrs.composerNoScripts or true;
composerStrictValidation = previousAttrs.composerStrictValidation or true;
composerGlobal = true;
nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
composer
phpDrv
makeBinaryWrapper
];
buildInputs = (previousAttrs.buildInputs or [ ]) ++ [ phpDrv ];
patches = previousAttrs.patches or [ ];
strictDeps = previousAttrs.strictDeps or true;
# Should we keep these empty phases?
configurePhase =
previousAttrs.configurePhase or ''
runHook preConfigure
runHook postConfigure
'';
buildPhase =
previousAttrs.buildPhase or ''
runHook preBuild
runHook postBuild
'';
doCheck = previousAttrs.doCheck or true;
checkPhase =
previousAttrs.checkPhase or ''
runHook preCheck
runHook postCheck
'';
installPhase =
previousAttrs.installPhase or ''
runHook preInstall
makeWrapper ${lib.getExe composer} $out/bin/composer \
--prefix COMPOSER_HOME : ${finalAttrs.vendor}
runHook postInstall
'';
doInstallCheck = previousAttrs.doInstallCheck or false;
installCheckPhase =
previousAttrs.installCheckPhase or ''
runHook preInstallCheck
composer global show ${finalAttrs.pname}
runHook postInstallCheck
'';
vendor = previousAttrs.vendor or stdenvNoCC.mkDerivation {
pname = "${finalAttrs.pname}-vendor";
pluginName = finalAttrs.pname;
inherit (finalAttrs) version src;
composerLock = previousAttrs.composerLock or null;
composerNoDev = previousAttrs.composerNoDev or true;
composerNoPlugins = previousAttrs.composerNoPlugins or true;
composerNoScripts = previousAttrs.composerNoScripts or true;
composerStrictValidation = previousAttrs.composerStrictValidation or true;
composerGlobal = true;
composerJson = composerJsonBuilder finalAttrs.pname finalAttrs.version;
nativeBuildInputs = [
cacert
composer
phpDrv.composerHooks.composerWithPluginVendorHook
];
dontPatchShebangs = true;
doCheck = true;
doInstallCheck = true;
env = {
COMPOSER_CACHE_DIR = "/dev/null";
COMPOSER_HTACCESS_PROTECT = "0";
};
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = finalAttrs.vendorHash;
};
# Projects providing a lockfile from upstream can be automatically updated.
passthru = previousAttrs.passthru or { } // {
updateScript =
previousAttrs.passthru.updateScript
or (if finalAttrs.vendor.composerLock == null then nix-update-script { } else null);
};
meta = previousAttrs.meta or composer.meta;
};
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerWithPluginOverride

View File

@@ -0,0 +1,127 @@
declare composerRepository
declare version
declare composerNoDev
declare composerNoPlugins
declare composerNoScripts
preConfigureHooks+=(composerInstallConfigureHook)
preBuildHooks+=(composerInstallBuildHook)
preCheckHooks+=(composerInstallCheckHook)
preInstallHooks+=(composerInstallInstallHook)
source @phpScriptUtils@
composerInstallConfigureHook() {
echo "Executing composerInstallConfigureHook"
if [[ ! -e "${composerRepository}" ]]; then
echo "No local composer repository found."
exit 1
fi
if [[ -e "$composerLock" ]]; then
cp "$composerLock" composer.lock
fi
if [[ ! -f "composer.lock" ]]; then
setComposerRootVersion
composer \
--no-install \
--no-interaction \
--no-progress \
${composerNoDev:+--no-dev} \
${composerNoPlugins:+--no-plugins} \
${composerNoScripts:+--no-scripts} \
update
mkdir -p $out
cp composer.lock $out/
echo
echo -e "\e[31mERROR: No composer.lock found\e[0m"
echo
echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m'
echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m"
echo
echo -e '\e[31mTo fix the issue:\e[0m'
echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m"
echo -e "\e[31m cp $out/composer.lock <path>\e[0m"
echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m'
echo -e '\e[31m composerLock = ./composer.lock;\e[0m'
echo
exit 1
fi
echo "Validating consistency between composer.lock and ${composerRepository}/composer.lock"
if ! @cmp@ -s "composer.lock" "${composerRepository}/composer.lock"; then
echo
echo -e "\e[31mERROR: vendorHash is out of date\e[0m"
echo
echo -e "\e[31mcomposer.lock is not the same in $composerRepository\e[0m"
echo
echo -e "\e[31mTo fix the issue:\e[0m"
echo -e '\e[31m1. Set vendorHash to an empty string: `vendorHash = "";`\e[0m'
echo -e '\e[31m2. Build the derivation and wait for it to fail with a hash mismatch\e[0m'
echo -e '\e[31m3. Copy the "got: sha256-..." value back into the vendorHash field\e[0m'
echo -e '\e[31m You should have: vendorHash = "sha256-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=";\e[0m'
echo
exit 1
fi
chmod +w composer.json composer.lock
echo "Finished composerInstallConfigureHook"
}
composerInstallBuildHook() {
echo "Executing composerInstallBuildHook"
setComposerRootVersion
# Since this file cannot be generated in the composer-repository-hook.sh
# because the file contains hardcoded nix store paths, we generate it here.
composer build-local-repo-lock -m "${composerRepository}" .
echo "Finished composerInstallBuildHook"
}
composerInstallCheckHook() {
echo "Executing composerInstallCheckHook"
checkComposerValidate
echo "Finished composerInstallCheckHook"
}
composerInstallInstallHook() {
echo "Executing composerInstallInstallHook"
setComposerRootVersion
setComposerEnvVariables
# Finally, run `composer install` to install the dependencies and generate
# the autoloader.
composer \
--no-interaction \
--no-progress \
${composerNoDev:+--no-dev} \
${composerNoPlugins:+--no-plugins} \
${composerNoScripts:+--no-scripts} \
install
# Copy the relevant files only in the store.
mkdir -p "$out"/share/php/"${pname}"
cp -r . "$out"/share/php/"${pname}"/
# Create symlinks for the binaries.
jq -r -c 'try (.bin[] | select(test(".bat$")? | not) )' composer.json | while read -r bin; do
echo -e "\e[32mCreating symlink ${bin}...\e[0m"
mkdir -p "$out"/bin
ln -s "$out"/share/php/"${pname}"/"$bin" "$out"/bin/"$(basename "$bin")"
done
echo "Finished composerInstallInstallHook"
}

View File

@@ -0,0 +1,91 @@
declare composerLock
declare version
declare composerNoDev
declare composerNoPlugins
declare composerNoScripts
declare composerStrictValidation
preConfigureHooks+=(composerRepositoryConfigureHook)
preBuildHooks+=(composerRepositoryBuildHook)
preCheckHooks+=(composerRepositoryCheckHook)
preInstallHooks+=(composerRepositoryInstallHook)
source @phpScriptUtils@
composerRepositoryConfigureHook() {
echo "Executing composerRepositoryConfigureHook"
if [[ -e "$composerLock" ]]; then
cp $composerLock composer.lock
fi
if [[ ! -f "composer.lock" ]]; then
setComposerRootVersion
composer \
--no-install \
--no-interaction \
--no-progress \
${composerNoDev:+--no-dev} \
${composerNoPlugins:+--no-plugins} \
${composerNoScripts:+--no-scripts} \
update
mkdir -p $out
cp composer.lock $out/
echo
echo -e "\e[31mERROR: No composer.lock found\e[0m"
echo
echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m'
echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m"
echo
echo -e '\e[31mTo fix the issue:\e[0m'
echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m"
echo -e "\e[31m cp $out/composer.lock <path>\e[0m"
echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m'
echo -e '\e[31m composerLock = ./composer.lock;\e[0m'
echo
exit 1
fi
echo "Finished composerRepositoryConfigureHook"
}
composerRepositoryBuildHook() {
echo "Executing composerRepositoryBuildHook"
mkdir -p repository
setComposerRootVersion
# Build the local composer repository
# The command 'build-local-repo' is provided by the Composer plugin
# nix-community/composer-local-repo-plugin.
composer build-local-repo-lock ${composerNoDev:+--no-dev} -r repository
echo "Finished composerRepositoryBuildHook"
}
composerRepositoryCheckHook() {
echo "Executing composerRepositoryCheckHook"
checkComposerValidate
echo "Finished composerRepositoryCheckHook"
}
composerRepositoryInstallHook() {
echo "Executing composerRepositoryInstallHook"
mkdir -p $out
cp -ar repository/. $out/
# Copy the composer.lock files to the output directory, to be able to validate consistency with
# the src composer.lock file where this fixed-output derivation is used
cp composer.lock $out/
echo "Finished composerRepositoryInstallHook"
}

View File

@@ -0,0 +1,93 @@
declare composerLock
declare version
declare composerNoDev
declare composerNoPlugins
declare composerNoScripts
declare composerStrictValidation
preConfigureHooks+=(composerWithPluginConfigureHook)
preBuildHooks+=(composerWithPluginBuildHook)
preCheckHooks+=(composerWithPluginCheckHook)
preInstallHooks+=(composerWithPluginInstallHook)
preInstallCheckHooks+=(composerWithPluginInstallCheckHook)
source @phpScriptUtils@
composerWithPluginConfigureHook() {
echo "Executing composerWithPluginConfigureHook"
mkdir -p $out
export COMPOSER_HOME=$out
if [[ -e "$composerLock" ]]; then
cp $composerLock $out/composer.lock
fi
cp $composerJson $out/composer.json
cp -ar $src $out/src
if [[ ! -f "$out/composer.lock" ]]; then
setComposerRootVersion
composer \
global \
--no-install \
--no-interaction \
--no-progress \
${composerNoDev:+--no-dev} \
${composerNoPlugins:+--no-plugins} \
${composerNoScripts:+--no-scripts} \
update
echo
echo -e "\e[31mERROR: No composer.lock found\e[0m"
echo
echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m'
echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m"
echo
echo -e '\e[31mTo fix the issue:\e[0m'
echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m"
echo -e "\e[31m cp $out/composer.lock <path>\e[0m"
echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m'
echo -e '\e[31m composerLock = ./composer.lock;\e[0m'
echo
exit 1
fi
echo "Finished composerWithPluginConfigureHook"
}
composerWithPluginBuildHook() {
echo "Executing composerWithPluginBuildHook"
echo "Finished composerWithPluginBuildHook"
}
composerWithPluginCheckHook() {
echo "Executing composerWithPluginCheckHook"
checkComposerValidate
echo "Finished composerWithPluginCheckHook"
}
composerWithPluginInstallHook() {
echo "Executing composerWithPluginInstallHook"
composer \
global \
--no-interaction \
--no-progress \
${composerNoDev:+--no-dev} \
${composerNoPlugins:+--no-plugins} \
${composerNoScripts:+--no-scripts} \
install
echo "Finished composerWithPluginInstallHook"
}
composerWithPluginInstallCheckHook() {
composer global show $pluginName
}

View File

@@ -0,0 +1,62 @@
{
lib,
makeSetupHook,
jq,
writeShellApplication,
cacert,
buildPackages,
}:
let
php-script-utils = writeShellApplication {
name = "php-script-utils";
runtimeInputs = [ jq ];
text = builtins.readFile ./php-script-utils.bash;
};
in
{
composerRepositoryHook = makeSetupHook {
name = "composer-repository-hook.sh";
propagatedNativeBuildInputs = [
jq
];
propagatedBuildInputs = [
cacert
];
substitutions = {
phpScriptUtils = lib.getExe php-script-utils;
};
} ./composer-repository-hook.sh;
composerInstallHook = makeSetupHook {
name = "composer-install-hook.sh";
propagatedNativeBuildInputs = [
jq
];
propagatedBuildInputs = [
cacert
];
substitutions = {
# Specify the stdenv's `diff` by abspath to ensure that the user's build
# inputs do not cause us to find the wrong `diff`.
cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp";
phpScriptUtils = lib.getExe php-script-utils;
};
} ./composer-install-hook.sh;
composerWithPluginVendorHook = makeSetupHook {
name = "composer-with-plugin-vendor-hook.sh";
propagatedNativeBuildInputs = [
jq
];
propagatedBuildInputs = [
cacert
];
substitutions = {
# Specify the stdenv's `diff` by abspath to ensure that the user's build
# inputs do not cause us to find the wrong `diff`.
cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp";
phpScriptUtils = lib.getExe php-script-utils;
};
} ./composer-with-plugin-vendor-hook.sh;
}

View File

@@ -0,0 +1,95 @@
declare version
declare composerStrictValidation
declare composerGlobal
setComposerRootVersion() {
set +e # Disable exit on error
if [[ -v version ]]; then
echo -e "\e[32mSetting COMPOSER_ROOT_VERSION to $version\e[0m"
export COMPOSER_ROOT_VERSION=$version
fi
set -e
}
setComposerEnvVariables() {
echo -e "\e[32mSetting some required environment variables for Composer...\e[0m"
export COMPOSER_MIRROR_PATH_REPOS=1
export COMPOSER_CACHE_DIR=/dev/null
export COMPOSER_HTACCESS_PROTECT=0
}
checkComposerValidate() {
setComposerRootVersion
if [ "1" == "${composerGlobal-}" ]; then
global="global";
else
global="";
fi
command="composer ${global} validate --strict --quiet --no-interaction --no-check-all --no-check-lock"
if ! $command; then
if [ "1" == "${composerStrictValidation-}" ]; then
echo
echo -e "\e[31mERROR: composer files validation failed\e[0m"
echo
echo -e '\e[31mThe validation of the composer.json failed.\e[0m'
echo -e '\e[31mMake sure that the file composer.json is valid.\e[0m'
echo
echo -e '\e[31mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[31m 1. File an issue in the project'\''s issue tracker with detailed information, and apply any available remote patches as a temporary solution '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[31m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
exit 1
else
echo
echo -e "\e[33mWARNING: composer files validation failed\e[0m"
echo
echo -e '\e[33mThe validation of the composer.json failed.\e[0m'
echo -e '\e[33mMake sure that the file composer.json is valid.\e[0m'
echo
echo -e '\e[33mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[33m 1. File an issue in the project'\''s issue tracker with detailed information, and apply any available remote patches as a temporary solution with '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[33m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
echo -e '\e[33mThis check is not blocking, but it is recommended to fix the issue.\e[0m'
echo
fi
fi
command="composer ${global} validate --strict --no-ansi --no-interaction --quiet --no-check-all --check-lock"
if ! $command; then
if [ "1" == "${composerStrictValidation-}" ]; then
echo
echo -e "\e[31mERROR: composer files validation failed\e[0m"
echo
echo -e '\e[31mThe validation of the composer.json and composer.lock failed.\e[0m'
echo -e '\e[31mMake sure that the file composer.lock is consistent with composer.json.\e[0m'
echo
echo -e '\e[31mThis often indicates an issue with the upstream project, which can typically be resolved by reporting the issue to the relevant project maintainers.\e[0m'
echo
echo -e '\e[31mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[31m 1. File an issue in the project'\''s issue tracker with detailed information '\('run '\''composer update --lock --no-install'\'' to fix the issue'\)', and apply any available remote patches as a temporary solution with '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[31m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
exit 1
else
echo
echo -e "\e[33mWARNING: composer files validation failed\e[0m"
echo
echo -e '\e[33mThe validation of the composer.json and composer.lock failed.\e[0m'
echo -e '\e[33mMake sure that the file composer.lock is consistent with composer.json.\e[0m'
echo
echo -e '\e[33mThis often indicates an issue with the upstream project, which can typically be resolved by reporting the issue to the relevant project maintainers.\e[0m'
echo
echo -e '\e[33mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[33m 1. File an issue in the project'\''s issue tracker with detailed information '\('run '\''composer update --lock --no-install'\'' to fix the issue'\)', and apply any available remote patches as a temporary solution with '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[33m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
echo -e '\e[33mThis check is not blocking, but it is recommended to fix the issue.\e[0m'
echo
fi
fi
}

View File

@@ -0,0 +1,119 @@
{
nix-update-script,
stdenvNoCC,
lib,
php,
}@toplevel:
let
buildComposerProjectOverride =
finalAttrs:
{
php ? finalAttrs.php or toplevel.php,
composer ? finalAttrs.php.packages.composer or toplevel.php.packages.composer,
composerLock ? finalAttrs.composerLock or null,
vendorHash ? finalAttrs.vendorHash or "",
composerNoDev ? finalAttrs.composerNoDev or true,
composerNoPlugins ? finalAttrs.composerNoPlugins or true,
composerNoScripts ? finalAttrs.composerNoScripts or true,
composerStrictValidation ? finalAttrs.composerStrictValidation or true,
buildInputs ? [ ],
nativeBuildInputs ? [ ],
strictDeps ? true,
patches ? [ ],
doCheck ? true,
doInstallCheck ? true,
dontCheckForBrokenSymlinks ? true,
passthru ? { },
meta ? { },
...
}@args:
{
inherit
patches
strictDeps
doCheck
doInstallCheck
dontCheckForBrokenSymlinks
;
nativeBuildInputs = nativeBuildInputs ++ [
composer
php
php.composerHooks2.composerInstallHook
];
buildInputs = buildInputs ++ [ php ];
# Should we keep these empty phases?
configurePhase =
args.configurePhase or ''
runHook preConfigure
runHook postConfigure
'';
buildPhase =
args.buildPhase or ''
runHook preBuild
runHook postBuild
'';
checkPhase =
args.checkPhase or ''
runHook preCheck
runHook postCheck
'';
installPhase =
args.installPhase or ''
runHook preInstall
runHook postInstall
'';
installCheckPhase =
args.installCheckPhase or ''
runHook preInstallCheck
runHook postInstallCheck
'';
composerVendor =
args.composerVendor or (php.mkComposerVendor {
inherit (finalAttrs)
pname
src
vendorHash
version
;
inherit
php
composer
composerLock
composerNoDev
composerNoPlugins
composerNoScripts
composerStrictValidation
dontCheckForBrokenSymlinks
;
});
# Projects providing a lockfile from upstream can be automatically updated.
passthru = passthru // {
updateScript =
args.passthru.updateScript
or (if finalAttrs.composerVendor.composerLock == null then nix-update-script { } else null);
};
meta = meta // {
platforms = lib.platforms.all;
};
};
in
lib.extendMkDerivation {
constructDrv = stdenvNoCC.mkDerivation;
extendDrvArgs = buildComposerProjectOverride;
}

View File

@@ -0,0 +1,94 @@
{
stdenvNoCC,
lib,
php,
}@toplevel:
let
mkComposerVendorOverride =
finalAttrs:
{
php ? finalAttrs.php or toplevel.php,
composer ? finalAttrs.php.packages.composer or toplevel.php.packages.composer,
composerLock ? finalAttrs.composerLock or null,
vendorHash ? finalAttrs.vendorHash or "",
composerNoDev ? finalAttrs.composerNoDev or true,
composerNoPlugins ? finalAttrs.composerNoPlugins or true,
composerNoScripts ? finalAttrs.composerNoScripts or true,
composerStrictValidation ? finalAttrs.composerStrictValidation or true,
buildInputs ? [ ],
nativeBuildInputs ? [ ],
dontPatchShebangs ? true,
strictDeps ? true,
doCheck ? true,
doInstallCheck ? false,
dontCheckForBrokenSymlinks ? true,
...
}@args:
assert (lib.assertMsg (args ? pname) "mkComposerVendor expects pname argument.");
assert (lib.assertMsg (args ? version) "mkComposerVendor expects version argument.");
assert (lib.assertMsg (args ? src) "mkComposerVendor expects src argument.");
{
name = "${args.pname}-composer-vendor-${args.version}";
# See https://github.com/NixOS/nix/issues/6660
inherit dontPatchShebangs;
inherit
buildInputs
strictDeps
doCheck
;
nativeBuildInputs = nativeBuildInputs ++ [
composer
php
php.composerHooks2.composerVendorHook
];
# Should we keep these empty phases?
configurePhase =
args.configurePhase or ''
runHook preConfigure
runHook postConfigure
'';
buildPhase =
args.buildPhase or ''
runHook preBuild
runHook postBuild
'';
checkPhase =
args.checkPhase or ''
runHook preCheck
runHook postCheck
'';
installPhase =
args.installPhase or ''
runHook preInstall
runHook postInstall
'';
installCheckPhase =
args.installCheckPhase or ''
runHook preInstallCheck
runHook postInstallCheck
'';
outputHashMode = "recursive";
outputHashAlgo =
if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256";
outputHash = vendorHash;
};
in
lib.extendMkDerivation {
constructDrv = stdenvNoCC.mkDerivation;
extendDrvArgs = mkComposerVendorOverride;
}

View File

@@ -0,0 +1,73 @@
# shellcheck shell=bash
declare -g out
declare -g pname
declare -g composerVendor
declare -g -i composerStrictValidation="${composerStrictValidation:-0}"
preConfigureHooks+=(composerInstallConfigureHook)
preBuildHooks+=(composerInstallBuildHook)
preCheckHooks+=(composerInstallCheckHook)
preInstallHooks+=(composerInstallInstallHook)
# shellcheck source=/dev/null
source @phpScriptUtils@
composerInstallConfigureHook() {
echo "Executing composerInstallConfigureHook"
setComposerRootVersion
if [[ ! -e "${composerVendor}" ]]; then
echo "No local composer vendor found." >&2
exit 1
fi
install -Dm644 "${composerVendor}"/composer.json .
if [[ -f "${composerVendor}/composer.lock" ]]; then
install -Dm644 "${composerVendor}"/composer.lock .
fi
if [[ -f "composer.lock" ]]; then
chmod +w composer.lock
fi
chmod +w composer.json
echo "Finished composerInstallConfigureHook"
}
composerInstallBuildHook() {
echo "Executing composerInstallBuildHook"
echo "Finished composerInstallBuildHook"
}
composerInstallCheckHook() {
echo "Executing composerInstallCheckHook"
checkComposerValidate
echo "Finished composerInstallCheckHook"
}
composerInstallInstallHook() {
echo "Executing composerInstallInstallHook"
cp -ar "${composerVendor}"/* .
# Copy the relevant files only in the store.
mkdir -p "$out"/share/php/"${pname}"
cp -r . "$out"/share/php/"${pname}"/
# Create symlinks for the binaries.
mapfile -t BINS < <(jq -r -c 'try (.bin[] | select(test(".bat$")? | not) )' composer.json)
for bin in "${BINS[@]}"; do
echo -e "\e[32mCreating symlink ${bin}...\e[0m"
mkdir -p "$out/bin"
ln -s "$out/share/php/${pname}/${bin}" "$out/bin/$(basename "$bin")"
done
echo "Finished composerInstallInstallHook"
}

View File

@@ -0,0 +1,126 @@
# shellcheck shell=bash
# shellcheck source=/dev/null
source @phpScriptUtils@
declare -g out
declare -g composerLock
declare -g composerNoDev
declare -g composerNoPlugins
declare -g composerNoScripts
declare -ga composerFlags=()
[[ -n "$composerNoDev" ]] && composerFlags+=(--no-dev)
[[ -n "$composerNoPlugins" ]] && composerFlags+=(--no-plugins)
[[ -n "$composerNoScripts" ]] && composerFlags+=(--no-scripts)
preConfigureHooks+=(composerVendorConfigureHook)
preBuildHooks+=(composerVendorBuildHook)
preCheckHooks+=(composerVendorCheckHook)
preInstallHooks+=(composerVendorInstallHook)
composerVendorConfigureHook() {
echo "Executing composerVendorConfigureHook"
setComposerRootVersion
if [[ -f "composer.lock" ]]; then
echo -e "\e[32mUsing \`composer.lock\` file from the source package\e[0m"
fi
if [[ -e "$composerLock" ]]; then
echo -e "\e[32mUsing user provided \`composer.lock\` file from \`$composerLock\`\e[0m"
install -Dm644 "$composerLock" ./composer.lock
fi
if [[ ! -f "composer.lock" ]]; then
composer \
--no-cache \
--no-install \
--no-interaction \
--no-progress \
--optimize-autoloader \
"${composerFlags[@]}" \
update
if [[ -f "composer.lock" ]]; then
install -Dm644 composer.lock -t "$out"/
echo
echo -e "\e[31mERROR: No composer.lock found\e[0m"
echo
echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m'
echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m"
echo
echo -e '\e[31mTo fix the issue:\e[0m'
echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m"
echo -e "\e[31m cp $out/composer.lock <path>\e[0m"
echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m'
echo -e '\e[31m composerLock = ./composer.lock;\e[0m'
echo
exit 1
fi
fi
if [[ -f "composer.lock" ]]; then
chmod +w composer.lock
fi
chmod +w composer.json
echo "Finished composerVendorConfigureHook"
}
composerVendorBuildHook() {
echo "Executing composerVendorBuildHook"
setComposerEnvVariables
composer \
--no-cache \
--no-interaction \
--no-progress \
--optimize-autoloader \
"${composerFlags[@]}" \
install
echo "Finished composerVendorBuildHook"
}
composerVendorCheckHook() {
echo "Executing composerVendorCheckHook"
checkComposerValidate
echo "Finished composerVendorCheckHook"
}
composerVendorInstallHook() {
echo "Executing composerVendorInstallHook"
mkdir -p "$out"
cp -ar composer.json "$(composer config vendor-dir)" "$out"/
mapfile -t installer_paths < <(jq -r -c 'try((.extra."installer-paths") | keys[])' composer.json)
for installer_path in "${installer_paths[@]}"; do
# Remove everything after {$name} placeholder
installer_path="${installer_path/\{\$name\}*/}"
out_installer_path="$out/${installer_path/\{\$name\}*/}"
# Copy the installer path if it exists
if [[ -d "$installer_path" ]]; then
mkdir -p "$(dirname "$out_installer_path")"
echo -e "\e[32mCopying installer path $installer_path to $out_installer_path\e[0m"
cp -ar "$installer_path" "$out_installer_path"
# Strip out the git repositories
find "$out_installer_path" -name .git -type d -prune -print -exec rm -rf {} ";"
fi
done
if [[ -f "composer.lock" ]]; then
cp -ar composer.lock "$out"/
fi
echo "Finished composerVendorInstallHook"
}

View File

@@ -0,0 +1,46 @@
{
lib,
makeSetupHook,
jq,
writeShellApplication,
cacert,
buildPackages,
}:
let
php-script-utils = writeShellApplication {
name = "php-script-utils";
runtimeInputs = [ jq ];
text = builtins.readFile ./php-script-utils.bash;
};
in
{
composerVendorHook = makeSetupHook {
name = "composer-vendor-hook.sh";
propagatedNativeBuildInputs = [
jq
];
propagatedBuildInputs = [
cacert
];
substitutions = {
phpScriptUtils = lib.getExe php-script-utils;
};
} ./composer-vendor-hook.sh;
composerInstallHook = makeSetupHook {
name = "composer-install-hook.sh";
propagatedNativeBuildInputs = [
jq
];
propagatedBuildInputs = [
cacert
];
substitutions = {
# Specify the stdenv's `diff` by abspath to ensure that the user's build
# inputs do not cause us to find the wrong `diff`.
cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp";
phpScriptUtils = lib.getExe php-script-utils;
};
} ./composer-install-hook.sh;
}

View File

@@ -0,0 +1,72 @@
# shellcheck shell=bash
declare -g version
declare -g -i composerStrictValidation="${composerStrictValidation:-0}"
setComposerRootVersion() {
if [[ -n $version ]]; then
echo -e "\e[32mSetting COMPOSER_ROOT_VERSION to $version\e[0m"
export COMPOSER_ROOT_VERSION="$version"
fi
}
setComposerEnvVariables() {
echo -e "\e[32mSetting some required environment variables for Composer...\e[0m"
export COMPOSER_MIRROR_PATH_REPOS=1
export COMPOSER_HTACCESS_PROTECT=0
export COMPOSER_FUND=0
}
checkComposerValidate() {
command="composer validate --strict --quiet --no-interaction --no-check-all --no-check-lock"
if ! $command; then
echo
echo -e "\e[31mERROR: composer files validation failed\e[0m"
echo
echo -e '\e[31mThe validation of the composer.json failed.\e[0m'
echo -e '\e[31mMake sure that the file composer.json is valid.\e[0m'
echo
echo -e '\e[31mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[31m 1. File an issue in the project'\''s issue tracker with detailed information, and apply any available remote patches as a temporary solution '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[31m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
if [[ "${composerStrictValidation}" == "1" ]]; then
echo
echo -e '\e[33mThis check is blocking, set the attribute composerStrictValidation to false to make it not blocking.\e[0m'
echo
exit 1
else
echo
echo -e '\e[33mThis check is not blocking, but it is recommended to fix the issue.\e[0m'
echo
fi
fi
command="composer validate --strict --no-ansi --no-interaction --quiet --no-check-all --check-lock"
if ! $command; then
echo
echo -e "\e[31mERROR: composer files validation failed\e[0m"
echo
echo -e '\e[31mThe validation of the composer.json and composer.lock failed.\e[0m'
echo -e '\e[31mMake sure that the file composer.lock is consistent with composer.json.\e[0m'
echo
echo -e '\e[31mThis often indicates an issue with the upstream project, which can typically be resolved by reporting the issue to the relevant project maintainers.\e[0m'
echo
echo -e '\e[31mTo address the issue efficiently, follow one of these steps:\e[0m'
echo -e '\e[31m 1. File an issue in the project'\''s issue tracker with detailed information '\('run '\''composer update --lock --no-install'\'' to fix the issue'\)', and apply any available remote patches as a temporary solution with '\('with fetchpatch'\)'.\e[0m'
echo -e '\e[31m 2. If an immediate fix is needed or if reporting upstream isn'\''t suitable, develop a temporary local patch.\e[0m'
echo
if [[ "${composerStrictValidation}" == "1" ]]; then
echo
echo -e '\e[33mThis check is blocking, set the attribute composerStrictValidation to false to make it not blocking.\e[0m'
echo
exit 1
else
echo
echo -e '\e[33mThis check is not blocking, but it is recommended to fix the issue.\e[0m'
echo
fi
fi
}

View File

@@ -0,0 +1,69 @@
{
_7zz,
curl,
fetchurl,
git,
lib,
makeBinaryWrapper,
php,
stdenvNoCC,
unzip,
xz,
version,
pharHash,
installShellFiles,
stdenv,
}:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "composer-phar";
inherit version;
src = fetchurl {
url = "https://github.com/composer/composer/releases/download/${finalAttrs.version}/composer.phar";
hash = pharHash;
};
dontUnpack = true;
nativeBuildInputs = [
makeBinaryWrapper
installShellFiles
];
installPhase = ''
runHook preInstall
mkdir -p $out/bin
install -D $src $out/libexec/composer/composer.phar
makeWrapper ${lib.getExe php} $out/bin/composer \
--add-flags "$out/libexec/composer/composer.phar" \
--prefix PATH : ${
lib.makeBinPath [
_7zz
curl
git
unzip
xz
]
}
runHook postInstall
'';
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
installShellCompletion --cmd composer \
--bash <($out/bin/composer completion bash)
'';
meta = {
changelog = "https://github.com/composer/composer/releases/tag/${finalAttrs.version}";
description = "Dependency Manager for PHP, shipped from the PHAR file";
homepage = "https://getcomposer.org/";
license = lib.licenses.mit;
mainProgram = "composer";
maintainers = [ lib.maintainers.patka ];
teams = [ lib.teams.php ];
platforms = lib.platforms.all;
};
})