diff --git a/bin/composer2nix b/bin/composer2nix index a8c8f33..1e07acb 100755 --- a/bin/composer2nix +++ b/bin/composer2nix @@ -28,6 +28,8 @@ Options: --no-dev Do not install the development packages --name Name of the generated package (defaults to the name provided in the composer.json file) + --executable Generate a Nix package for an executable as opposed to + a library or web application. --no-copy-composer-env Do not create a copy of the Nix expression that builds composer packages @@ -54,6 +56,7 @@ $options = getopt("hv", array( "prefer-dist", "no-dev", "name:", + "executable", "no-copy-composer-env", "help", "version" @@ -115,21 +118,20 @@ if(array_key_exists("prefer-source", $options)) if(array_key_exists("prefer-dist", $options)) $preferredInstall = "dist"; -if(array_key_exists("no-dev", $options)) - $noDev = true; -else - $noDev = false; +$noDev = array_key_exists("no-dev", $options); if(array_key_exists("name", $options)) $name = $options["name"]; else $name = null; +$executable = array_key_exists("executable", $options); + /* Execute the generator */ try { - Generator::generateNixExpressions($name, $preferredInstall, $noDev, $configFile, $lockFile, $outputFile, $compositionFile, $composerEnvFile, $noCopyComposerEnv); + Generator::generateNixExpressions($name, $executable, $preferredInstall, $noDev, $configFile, $lockFile, $outputFile, $compositionFile, $composerEnvFile, $noCopyComposerEnv); } catch(Exception $ex) { diff --git a/src/Composer2Nix/Generator.php b/src/Composer2Nix/Generator.php index 6d78f78..9584995 100644 --- a/src/Composer2Nix/Generator.php +++ b/src/Composer2Nix/Generator.php @@ -39,14 +39,14 @@ class Generator } } - private static function generatePackagesExpression($outputFile, $name, $preferredInstall, array $packages) + private static function generatePackagesExpression($outputFile, $name, $preferredInstall, array $packages, $executable) { $handle = fopen($outputFile, "w"); if($handle === false) throw new Exception("Cannot write to: ".$outputFile); - fwrite($handle, "{composerEnv, fetchgit ? null}:\n\n"); + fwrite($handle, "{composerEnv, fetchurl, fetchgit ? null, fetchhg ? null, fetchsvn ? null}:\n\n"); fwrite($handle, "let\n"); fwrite($handle, " dependencies = {\n"); @@ -61,13 +61,29 @@ class Generator break; case "zip": - $hash = shell_exec('nix-prefetch-url "'.$sourceObj['url'].'"'); fwrite($handle, ' "'.$package["name"].'" = composerEnv.buildZipPackage {'."\n"); - fwrite($handle, ' name = "'.strtr($package["name"], "/", "-").'-'.$sourceObj["reference"].'";'."\n"); - fwrite($handle, ' url = "'.$sourceObj["url"].'";'."\n"); - fwrite($handle, ' sha256 = "'.substr($hash, 0, -1).'";'."\n"); + + if($sourceObj["reference"] == "") + $reference = ""; + else + $reference = "-".$sourceObj["reference"]; + + fwrite($handle, ' name = "'.strtr($package["name"], "/", "-").$reference.'";'."\n"); + + if(substr($sourceObj["url"], 0, 7) === "http://" || substr($sourceObj["url"], 0, 8) === "https://") + { + $hash = shell_exec('nix-prefetch-url "'.$sourceObj['url'].'"'); + fwrite($handle, " src = fetchurl {\n"); + fwrite($handle, ' url = "'.$sourceObj["url"].'";'."\n"); + fwrite($handle, ' sha256 = "'.substr($hash, 0, -1).'";'."\n"); + fwrite($handle, " };\n"); + } + else + fwrite($handle, " src = ".Generator::composeNixFilePath($sourceObj['url']).";\n"); + fwrite($handle, " };\n"); break; + case "git": $outputStr = shell_exec('nix-prefetch-git "'.$sourceObj['url'].'" '.$sourceObj["reference"]); @@ -81,18 +97,29 @@ class Generator fwrite($handle, ' sha256 = "'.$hash.'";'."\n"); fwrite($handle, " };\n"); break; - case "hg": - $outputStr = shell_exec('nix-prefetch-hg "'.$sourceObj['url'].'" '.$sourceObj["reference"]); - $output = json_decode($outputStr, true); - $hash = $output["sha256"]; + case "hg": + $hash = shell_exec('nix-prefetch-hg "'.$sourceObj['url'].'" '.$sourceObj["reference"]); fwrite($handle, ' "'.$package["name"].'" = fetchhg {'."\n"); fwrite($handle, ' name = "'.strtr($package["name"], "/", "-").'-'.$sourceObj["reference"].'";'."\n"); fwrite($handle, ' url = "'.$sourceObj["url"].'";'."\n"); fwrite($handle, ' rev = "'.$sourceObj["reference"].'";'."\n"); - fwrite($handle, ' sha256 = "'.$hash.'";'."\n"); + fwrite($handle, ' sha256 = "'.substr($hash, 0, -1).'";'."\n"); fwrite($handle, " };\n"); + break; + + case "svn": + $hash = shell_exec('nix-prefetch-svn "'.$sourceObj['url'].'" '.$sourceObj["reference"]); + + fwrite($handle, ' "'.$package["name"].'" = fetchsvn {'."\n"); + fwrite($handle, ' name = "'.strtr($package["name"], "/", "-").'-'.$sourceObj["reference"].'";'."\n"); + fwrite($handle, ' url = "'.$sourceObj["url"].'";'."\n"); + fwrite($handle, ' rev = "'.$sourceObj["reference"].'";'."\n"); + fwrite($handle, ' sha256 = "'.substr($hash, 0, -1).'";'."\n"); + fwrite($handle, " };\n"); + break; + default: throw new Exception("Cannot convert dependency of type: ".$sourceObj["type"]); } @@ -103,6 +130,7 @@ class Generator fwrite($handle, "composerEnv.buildPackage {\n"); fwrite($handle, ' name = "'.$name.'";'."\n"); fwrite($handle, " src = ./.;\n"); + fwrite($handle, " executable = ".($executable ? "true" : "false").";\n"); fwrite($handle, " inherit dependencies;\n"); fwrite($handle, "}\n"); @@ -127,13 +155,13 @@ class Generator fwrite($handle, "in\n"); fwrite($handle, "import ".Generator::composeNixFilePath($outputFile)." {\n"); fwrite($handle, " inherit composerEnv;\n"); - fwrite($handle, " inherit (pkgs) fetchgit;\n"); + fwrite($handle, " inherit (pkgs) fetchurl fetchgit fetchhg fetchsvn;\n"); fwrite($handle, "}\n"); fclose($handle); } - public static function generateNixExpressions($name, $preferredInstall, $noDev, $configFile, $lockFile, $outputFile, $compositionFile, $composerEnvFile, $noCopyComposerEnv) + public static function generateNixExpressions($name, $executable, $preferredInstall, $noDev, $configFile, $lockFile, $outputFile, $compositionFile, $composerEnvFile, $noCopyComposerEnv) { /* Open the composer.json file and decode it */ $composerJSONStr = file_get_contents($configFile); @@ -183,7 +211,7 @@ class Generator $packages = array(); /* Generate packages expression */ - Generator::generatePackagesExpression($outputFile, $name, $preferredInstall, $packages); + Generator::generatePackagesExpression($outputFile, $name, $preferredInstall, $packages, $executable); /* Generate composition expression */ Generator::generateCompositionExpression($compositionFile, $outputFile, $composerEnvFile); diff --git a/src/Composer2Nix/composer-env.nix b/src/Composer2Nix/composer-env.nix index f223c25..99355da 100644 --- a/src/Composer2Nix/composer-env.nix +++ b/src/Composer2Nix/composer-env.nix @@ -36,12 +36,9 @@ rec { }; }; - buildZipPackage = { name, url, sha256 }: + buildZipPackage = { name, src }: stdenv.mkDerivation { - inherit name; - src = fetchurl { - inherit url sha256; - }; + inherit name src; buildInputs = [ unzip ]; buildCommand = '' unzip $src @@ -52,7 +49,7 @@ rec { ''; }; - buildPackage = { name, src, dependencies ? [], removeComposerArtifacts ? false }: + buildPackage = { name, src, dependencies ? [], executable ? false, removeComposerArtifacts ? false }: let reconstructInstalled = writeTextFile { name = "reconstructinstalled.php"; @@ -76,14 +73,55 @@ rec { ?> ''; }; + + constructBin = writeTextFile { + name = "constructbin.php"; + executable = true; + text = '' + #! ${php}/bin/php + + ''; + }; in stdenv.mkDerivation { inherit name src; buildInputs = [ php composer ]; buildCommand = '' - cp -av $src $out - chmod -R u+w $out - cd $out + ${if executable then '' + mkdir -p $out/share/php + cp -av $src $out/share/php/$name + chmod -R u+w $out/share/php/$name + cd $out/share/php/$name + '' else '' + cp -av $src $out + chmod -R u+w $out + cd $out + ''} # Remove unwanted files rm -f *.nix @@ -115,6 +153,12 @@ rec { # Run the install step as a validation to confirm that everything works out as expected composer install --optimize-autoloader + ${stdenv.lib.optionalString executable '' + ${constructBin} composer.json + ln -s $(pwd)/vendor/bin $out/bin + patchShebangs $out/bin + ''} + ${stdenv.lib.optionalString (removeComposerArtifacts) '' # Remove composer stuff rm composer.json composer.lock