Implemented "symlink" registration for system-level packages

This commit is contained in:
Netkas 2023-10-08 12:20:24 -04:00
parent 2d3c1f3ab0
commit 32b455576d
No known key found for this signature in database
GPG key ID: 5DAF58535614062B
7 changed files with 146 additions and 11 deletions

View file

@ -317,7 +317,8 @@
{ {
$metadata = new Metadata($this->project_manager->getProjectConfiguration()->getProject()->getCompiler()); $metadata = new Metadata($this->project_manager->getProjectConfiguration()->getProject()->getCompiler());
$metadata->setOptions($this->project_manager->getProjectConfiguration()->getBuild()->getOptions($build_configuration)); $metadata->addOptions($this->project_manager->getProjectConfiguration()->getBuild()->getOptions($build_configuration));
$metadata->addOptions($this->project_manager->getProjectConfiguration()->getProject()->getOptions());
$metadata->setUpdateSource($this->project_manager->getProjectConfiguration()->getProject()->getUpdateSource()); $metadata->setUpdateSource($this->project_manager->getProjectConfiguration()->getProject()->getUpdateSource());
$metadata->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain()); $metadata->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain());
$metadata->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller()); $metadata->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());

View file

@ -38,6 +38,7 @@
use ncc\Enums\Options\ComponentDecodeOptions; use ncc\Enums\Options\ComponentDecodeOptions;
use ncc\Enums\Options\InitializeProjectOptions; use ncc\Enums\Options\InitializeProjectOptions;
use ncc\Enums\Options\InstallPackageOptions; use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Options\ProjectOptions;
use ncc\Enums\RegexPatterns; use ncc\Enums\RegexPatterns;
use ncc\Enums\Scopes; use ncc\Enums\Scopes;
use ncc\Enums\Types\ProjectType; use ncc\Enums\Types\ProjectType;
@ -54,6 +55,7 @@
use ncc\Objects\RemotePackageInput; use ncc\Objects\RemotePackageInput;
use ncc\ThirdParty\Symfony\Filesystem\Filesystem; use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\IO; use ncc\Utilities\IO;
use ncc\Utilities\PathFinder; use ncc\Utilities\PathFinder;
use ncc\Utilities\Resolver; use ncc\Utilities\Resolver;
@ -374,6 +376,56 @@
throw new IOException(sprintf('Failed to add package to package lock file due to an exception: %s', $e->getMessage()), $e); throw new IOException(sprintf('Failed to add package to package lock file due to an exception: %s', $e->getMessage()), $e);
} }
if($package_reader->getMetadata()->getOption(ProjectOptions::CREATE_SYMLINK) === null)
{
// Remove the symlink if it exists
if($this->package_lock->getEntry($package_reader->getAssembly()->getPackage())->isSymlinkRegistered())
{
if(is_file(PathFinder::findBinPath() . DIRECTORY_SEPARATOR . strtolower($package_reader->getAssembly()->getName())))
{
Console::outVerbose(sprintf(
'Removing symlink for %s=%s at %s',
$package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion(),
PathFinder::findBinPath() . DIRECTORY_SEPARATOR . strtolower($package_reader->getAssembly()->getName())
));
$filesystem->remove(PathFinder::findBinPath() . DIRECTORY_SEPARATOR . strtolower($package_reader->getAssembly()->getName()));
}
}
$this->package_lock->getEntry($package_reader->getAssembly()->getPackage())->setSymlinkRegistered(false);
}
else
{
// Register/Update the symlink
$symlink = PathFinder::findBinPath() . DIRECTORY_SEPARATOR . strtolower($package_reader->getAssembly()->getName());
if(is_file($symlink) && !$this->package_lock->getEntry($package_reader->getAssembly()->getPackage())->isSymlinkRegistered())
{
// Avoid overwriting already existing symlinks that are not handled by ncc
Console::outWarning(sprintf(
'A symlink already exists at %s, skipping symlink creation for %s=%s',
$symlink, $package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion()
));
}
else
{
Console::outVerbose(sprintf(
'Creating symlink for %s=%s at %s',
$package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion(), $symlink
));
if(is_file($symlink))
{
$filesystem->remove($symlink);
}
IO::fwrite($symlink, Functions::createExecutionPointer($package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion()));
chmod($symlink, 0755); // Make it executable
$this->package_lock->getEntry($package_reader->getAssembly()->getPackage())->setSymlinkRegistered(true);
}
}
$this->saveLock(); $this->saveLock();
if(!isset($options[InstallPackageOptions::SKIP_DEPENDENCIES])) if(!isset($options[InstallPackageOptions::SKIP_DEPENDENCIES]))

View file

@ -45,7 +45,7 @@
private $compiler_version; private $compiler_version;
/** /**
* @var array|null * @var array
*/ */
private $options; private $options;
@ -120,9 +120,9 @@
/** /**
* Returns an array of options associated with the package * Returns an array of options associated with the package
* *
* @return array|null * @return array
*/ */
public function getOptions(): ?array public function getOptions(): array
{ {
return $this->options; return $this->options;
} }
@ -130,13 +130,29 @@
/** /**
* Sets an array of options associated with the package * Sets an array of options associated with the package
* *
* @param array|null $options * @param array $options
*/ */
public function setOptions(?array $options): void public function setOptions(array $options): void
{ {
$this->options = $options; $this->options = $options;
} }
/**
* Adds an option associated with the package
*
* @param array $options
* @return void
*/
public function addOptions(array $options): void
{
if($this->options === null)
{
$this->options = [];
}
$this->options = array_merge($this->options, $options);
}
/** /**
* Sets an option associated with the package * Sets an option associated with the package
* *

View file

@ -61,6 +61,11 @@
*/ */
private $update_source; private $update_source;
/**
* @var bool
*/
private $symlink_registered;
/** /**
* Public Constructor * Public Constructor
*/ */
@ -68,6 +73,7 @@
{ {
$this->name = $name; $this->name = $name;
$this->versions = $versions; $this->versions = $versions;
$this->symlink_registered = false;
} }
/** /**
@ -90,6 +96,22 @@
return $this->update_source; return $this->update_source;
} }
/**
* @return bool
*/
public function isSymlinkRegistered(): bool
{
return $this->symlink_registered;
}
/**
* @param bool $symlink_registered
*/
public function setSymlinkRegistered(bool $symlink_registered): void
{
$this->symlink_registered = $symlink_registered;
}
/** /**
* Returns the path to where the package is installed * Returns the path to where the package is installed
* *
@ -456,6 +478,7 @@
($bytecode ? Functions::cbc('name') : 'name') => $this->name, ($bytecode ? Functions::cbc('name') : 'name') => $this->name,
($bytecode ? Functions::cbc('versions') : 'versions') => $versions, ($bytecode ? Functions::cbc('versions') : 'versions') => $versions,
($bytecode ? Functions::cbc('update_source') : 'update_source') => ($this->update_source?->toArray($bytecode)), ($bytecode ? Functions::cbc('update_source') : 'update_source') => ($this->update_source?->toArray($bytecode)),
($bytecode ? Functions::cbc('symlink_registered') : 'symlink_registered') => $this->symlink_registered,
]; ];
} }
@ -490,6 +513,7 @@
$object->update_source = UpdateSource::fromArray($update_source); $object->update_source = UpdateSource::fromArray($update_source);
} }
$object->symlink_registered = Functions::array_bc($data, 'symlink_registered') ?? false;
return $object; return $object;
} }

View file

@ -26,6 +26,7 @@
use FilesystemIterator; use FilesystemIterator;
use JsonException; use JsonException;
use ncc\Enums\Scopes; use ncc\Enums\Scopes;
use ncc\Enums\Versions;
use ncc\Exceptions\IOException; use ncc\Exceptions\IOException;
use ncc\Exceptions\OperationException; use ncc\Exceptions\OperationException;
use ncc\Exceptions\PathNotFoundException; use ncc\Exceptions\PathNotFoundException;
@ -627,4 +628,19 @@
$input = str_replace('.', '_', $input); $input = str_replace('.', '_', $input);
return strtolower(trim(preg_replace('/[^a-zA-Z0-9_]/', '', preg_replace('/([a-z])([A-Z])/', '$1_$2', $input)), '_')); return strtolower(trim(preg_replace('/[^a-zA-Z0-9_]/', '', preg_replace('/([a-z])([A-Z])/', '$1_$2', $input)), '_'));
} }
/**
* Returns a shell script that can be used to execute the given package
*
* @param string $package_name
* @param string $version
* @return string
*/
public static function createExecutionPointer(string $package_name, string $version=Versions::LATEST): string
{
$content = "#!/bin/sh\n";
$content .= sprintf('exec ncc exec --package "%s" --exec-version "%s" --exec-args "$@"', $package_name, $version);
return $content;
}
} }

View file

@ -22,6 +22,8 @@
namespace ncc\Utilities; namespace ncc\Utilities;
use RuntimeException;
class PathFinder class PathFinder
{ {
/** /**
@ -103,4 +105,33 @@
{ {
return self::getDataPath() . DIRECTORY_SEPARATOR . 'ncc.yaml'; return self::getDataPath() . DIRECTORY_SEPARATOR . 'ncc.yaml';
} }
/**
* Returns the path where binaries are stored
*
* @return string
*/
public static function findBinPath(): string
{
$path_directories = explode(PATH_SEPARATOR, getenv('PATH'));
// Check if the bin directory is in the path
if(in_array(DIRECTORY_SEPARATOR . 'usr' . DIRECTORY_SEPARATOR . 'bin', $path_directories))
{
return DIRECTORY_SEPARATOR . 'usr' . DIRECTORY_SEPARATOR . 'bin';
}
Console::outWarning('The /usr/bin directory is not in the PATH environment variable, an alternative will be used');
// If not, find something appropriate
foreach($path_directories as $path_directory)
{
if(is_dir($path_directory) && is_writable($path_directory))
{
return $path_directory;
}
}
throw new RuntimeException('Could not find a suitable bin directory in the PATH environment variable');
}
} }

View file

@ -1,5 +0,0 @@
<?php
LogLib\Log::info("test.php", "Hello World! from test.php\n");