Unverified Commit dbc4f15b authored by Pol Dellaiera's avatar Pol Dellaiera Committed by GitHub
Browse files

Merge pull request #308059 from drupol/build-support/php/remove-composer-local-repo-plugin

build-support/php: init `buildComposerProject2` and `mkComposerRepository2`
parents aecf9050 d90ff2a8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6,4 +6,10 @@
    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 { };
  };
}
+108 −0
Original line number Diff line number Diff line
{
  nix-update-script,
  stdenvNoCC,
  lib,
  php,
}:

let
  buildComposerProjectOverride =
    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;

      nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
        composer
        phpDrv
        phpDrv.composerHooks2.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
        '';

      composerVendor =
        previousAttrs.composerVendor or (phpDrv.mkComposerVendor {
          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.composerVendor.composerLock == null then nix-update-script { } else null);
      };

      env = {
        COMPOSER_CACHE_DIR = "/dev/null";
        COMPOSER_DISABLE_NETWORK = "1";
        COMPOSER_MIRROR_PATH_REPOS = "1";
      };

      meta = previousAttrs.meta or { } // {
        platforms = lib.platforms.all;
      };
    };
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerProjectOverride
+103 −0
Original line number Diff line number Diff line
{
  stdenvNoCC,
  lib,
  php,
}:

let
  mkComposerVendorOverride =
    /*
      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;
    in
    assert (lib.assertMsg (previousAttrs ? src) "mkComposerVendor expects src argument.");
    assert (lib.assertMsg (previousAttrs ? vendorHash) "mkComposerVendor expects vendorHash argument.");
    assert (lib.assertMsg (previousAttrs ? version) "mkComposerVendor expects version argument.");
    assert (lib.assertMsg (previousAttrs ? pname) "mkComposerVendor expects pname argument.");
    {
      composerNoDev = previousAttrs.composerNoDev or true;
      composerNoPlugins = previousAttrs.composerNoPlugins or true;
      composerNoScripts = previousAttrs.composerNoScripts or true;
      composerStrictValidation = previousAttrs.composerStrictValidation or true;

      name = "${previousAttrs.pname}-${previousAttrs.version}-composer-repository";

      # See https://github.com/NixOS/nix/issues/6660
      dontPatchShebangs = previousAttrs.dontPatchShebangs or true;

      nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
        composer
        phpDrv
        phpDrv.composerHooks2.composerVendorHook
      ];

      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
        '';

      env = {
        COMPOSER_CACHE_DIR = "/dev/null";
        COMPOSER_MIRROR_PATH_REPOS = "1";
        COMPOSER_HTACCESS_PROTECT = "0";
        COMPOSER_DISABLE_NETWORK = "0";
      };

      outputHashMode = "recursive";
      outputHashAlgo =
        if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256";
      outputHash = finalAttrs.vendorHash or "";
    };
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs mkComposerVendorOverride
+91 −0
Original line number Diff line number Diff line
declare composerVendor
declare version
declare composerNoDev
declare composerNoPlugins
declare composerNoScripts

preConfigureHooks+=(composerInstallConfigureHook)
preBuildHooks+=(composerInstallBuildHook)
preCheckHooks+=(composerInstallCheckHook)
preInstallHooks+=(composerInstallInstallHook)

source @phpScriptUtils@

composerInstallConfigureHook() {
    echo "Executing composerInstallConfigureHook"

    setComposeRootVersion

    if [[ ! -e "${composerVendor}" ]]; then
        echo "No local composer vendor found."
        exit 1
    fi

    install -Dm644 ${composerVendor}/composer.{json,lock} .

    if [[ ! -f "composer.lock" ]]; then
        composer \
            --no-install \
            --no-interaction \
            --no-progress \
            --optimize-autoloader \
            ${composerNoDev:+--no-dev} \
            ${composerNoPlugins:+--no-plugins} \
            ${composerNoScripts:+--no-scripts} \
            update

        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

    chmod +w composer.{json,lock}

    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.
    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"
}
+91 −0
Original line number Diff line number Diff line
declare composerLock
declare version
declare composerNoDev
declare composerNoPlugins
declare composerNoScripts
declare composerStrictValidation

preConfigureHooks+=(composerVendorConfigureHook)
preBuildHooks+=(composerVendorBuildHook)
preCheckHooks+=(composerVendorCheckHook)
preInstallHooks+=(composerVendorInstallHook)

source @phpScriptUtils@

composerVendorConfigureHook() {
    echo "Executing composerVendorConfigureHook"

    setComposeRootVersion

    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-install \
            --no-interaction \
            --no-progress \
            --optimize-autoloader \
            ${composerNoDev:+--no-dev} \
            ${composerNoPlugins:+--no-plugins} \
            ${composerNoScripts:+--no-scripts} \
            update

        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

    chmod +w composer.{json,lock}

    echo "Finished composerVendorConfigureHook"
}

composerVendorBuildHook() {
    echo "Executing composerVendorBuildHook"

    composer \
        --apcu-autoloader \
        --apcu-autoloader-prefix="$(jq -r -c 'try ."content-hash"' < composer.lock)" \
        --no-interaction \
        --no-progress \
        --optimize-autoloader \
        ${composerNoDev:+--no-dev} \
        ${composerNoPlugins:+--no-plugins} \
        ${composerNoScripts:+--no-scripts} \
        install

    echo "Finished composerVendorBuildHook"
}

composerVendorCheckHook() {
    echo "Executing composerVendorCheckHook"

    checkComposerValidate

    echo "Finished composerVendorCheckHook"
}

composerVendorInstallHook() {
    echo "Executing composerVendorInstallHook"

    mkdir -p $out
    cp -ar composer.{json,lock} $(composer config vendor-dir) $out/

    echo "Finished composerVendorInstallHook"
}
Loading