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->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->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain());
$metadata->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());

View file

@ -38,6 +38,7 @@
use ncc\Enums\Options\ComponentDecodeOptions;
use ncc\Enums\Options\InitializeProjectOptions;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Options\ProjectOptions;
use ncc\Enums\RegexPatterns;
use ncc\Enums\Scopes;
use ncc\Enums\Types\ProjectType;
@ -54,6 +55,7 @@
use ncc\Objects\RemotePackageInput;
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\IO;
use ncc\Utilities\PathFinder;
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);
}
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();
if(!isset($options[InstallPackageOptions::SKIP_DEPENDENCIES]))

View file

@ -45,7 +45,7 @@
private $compiler_version;
/**
* @var array|null
* @var array
*/
private $options;
@ -120,9 +120,9 @@
/**
* 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;
}
@ -130,13 +130,29 @@
/**
* 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;
}
/**
* 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
*

View file

@ -61,6 +61,11 @@
*/
private $update_source;
/**
* @var bool
*/
private $symlink_registered;
/**
* Public Constructor
*/
@ -68,6 +73,7 @@
{
$this->name = $name;
$this->versions = $versions;
$this->symlink_registered = false;
}
/**
@ -90,6 +96,22 @@
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
*
@ -456,6 +478,7 @@
($bytecode ? Functions::cbc('name') : 'name') => $this->name,
($bytecode ? Functions::cbc('versions') : 'versions') => $versions,
($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->symlink_registered = Functions::array_bc($data, 'symlink_registered') ?? false;
return $object;
}

View file

@ -26,6 +26,7 @@
use FilesystemIterator;
use JsonException;
use ncc\Enums\Scopes;
use ncc\Enums\Versions;
use ncc\Exceptions\IOException;
use ncc\Exceptions\OperationException;
use ncc\Exceptions\PathNotFoundException;
@ -627,4 +628,19 @@
$input = str_replace('.', '_', $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;
use RuntimeException;
class PathFinder
{
/**
@ -103,4 +105,33 @@
{
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");