Compare commits

..

No commits in common. "master" and "2.1.0" have entirely different histories.

40 changed files with 110 additions and 1522 deletions

1
.gitignore vendored
View file

@ -31,4 +31,3 @@ tests/example_project/ncc
tests/example_project/build tests/example_project/build
/.phpunit.result.cache /.phpunit.result.cache
/.idea/php-test-framework.xml /.idea/php-test-framework.xml
/.idea/gbrowser_project.xml

View file

@ -1,7 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<ScalaCodeStyleSettings>
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
</ScalaCodeStyleSettings>
</code_scheme>
</component>

View file

@ -5,83 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.1.6] - 2024-10-29
This update introduces critical bug fixes
### Fixed
- Validate package instance before checking execution policy
## [2.1.5] - 2024-10-14
This update introduces a critical bug fix
## [2.1.4] - 2024-10-13
This update introduces minor bug fixes & improvements
### Added
- Added new constant `%DEFAULT_BUILD_CONFIGURATION%` which points to the project's default build configuration
- Added new dynamic constant `%BUILD_OUTPUT_PATH%` which can be used as `%BUILD_OUTPUT_PATH%:release` to show the
output path of a specific build configuration
- Refactor CI templates to support dynamic build targets
- Added template `phpexe` & `phpgz` for generating executable binaries and compressed executables for the project
### Changed
- Refactor phpmake template to support dynamic build targets
### Fixed
- ncc will now correctly handle package execution where the main unit is not defined in the package instead of
throwing an exception.
- Executable Compiler will now correctly create a directory if it does not exist when compiling a package using gcc
## [2.1.3] - 2024-09-27
This update introduces bug fixes
### Fixed
- Null-pointer fix
## [2.1.2] - 2024-09-27
This update introduces bug fixes
### Added
- Add getter methods for installation lifecycle steps
- Added pre-install & post-install execution unit handling
### Changed
- Updated DocStrings in PackageManager
### Fixed
- Fixed incorrect enum usage in RepositoryMenu
## [2.1.1] - 2024-09-24
This update introduces a couple of new features and quality of life improvements
### Added
- Added new PHP template `phpunit` for generating PhpUnit tests for the project
- Added new PHP template `phpmake` for generating a Makefile for the project
- Added new PHP template `phplib_full` That combines `phplib`, `phpmake` and `phpunit` templates
- Added new PHP template `phpcli_full` That combines `phpcli`, `phplib`, `phpmake` and `phpunit` templates
- Added new PHP template `phpci_github` that generates a Github CI workflow for the project
### Changed
- The template `phpcli` no longer includes a Makefile, instead use `phpmake` to generate a Makefile for the project
### Fixed
- Fixed incorrect enum usage with a logging method call.
## [2.1.0] - 2024-09-20 ## [2.1.0] - 2024-09-20
This update introduces a refactored code-base, code quality improvements, and better exception handling. This update introduces a refactored code-base, code quality improvements, and better exception handling.

View file

@ -2,7 +2,7 @@ Package: ncc
Source: ncc Source: ncc
Section: devel Section: devel
Priority: optional Priority: optional
Version: 2.0.4 Version: 2.0.3
Maintainer: netkas <netkas@nosial.net> Maintainer: netkas <netkas@nosial.net>
Build-Depends: debhelper-compat (= 13) Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.5.1 Standards-Version: 4.5.1

View file

@ -119,7 +119,7 @@
$output = sprintf('%s (%s) [%s]', $output = sprintf('%s (%s) [%s]',
$source->getName(), $source->getName(),
Console::formatColor($source->getHost(), ConsoleColors::GREEN), Console::formatColor($source->getHost(), ConsoleColors::GREEN),
Console::formatColor($source->getType()->value, ConsoleColors::YELLOW) Console::formatColor($source->getType(), ConsoleColors::YELLOW)
); );
if(!$source->isSsl()) if(!$source->isSsl())

View file

@ -31,7 +31,6 @@
use ncc\Classes\PhpExtension\PhpRunner; use ncc\Classes\PhpExtension\PhpRunner;
use ncc\Enums\Runners; use ncc\Enums\Runners;
use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException; use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException; use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException; use ncc\Exceptions\OperationException;
@ -77,19 +76,11 @@
{ {
$process->setTimeout($unit->getExecutionPolicy()->getExecute()->getTimeout()); $process->setTimeout($unit->getExecutionPolicy()->getExecute()->getTimeout());
} }
else
{
$process->setTimeout(null);
}
if($unit->getExecutionPolicy()->getExecute()->getIdleTimeout() !== null) if($unit->getExecutionPolicy()->getExecute()->getIdleTimeout() !== null)
{ {
$process->setIdleTimeout($unit->getExecutionPolicy()->getExecute()->getIdleTimeout()); $process->setIdleTimeout($unit->getExecutionPolicy()->getExecute()->getIdleTimeout());
} }
else
{
$process->setIdleTimeout(null);
}
return $process; return $process;
} }
@ -138,7 +129,6 @@
* @return int * @return int
* @throws ConfigurationException * @throws ConfigurationException
* @throws OperationException * @throws OperationException
* @throws IntegrityException
*/ */
public static function executeFromPackage(PackageReader $package_reader, string $policy_name, array $args=[]): int public static function executeFromPackage(PackageReader $package_reader, string $policy_name, array $args=[]): int
{ {

View file

@ -39,7 +39,6 @@
use ncc\Objects\Vault\Password\AccessToken; use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword; use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache; use ncc\Utilities\RuntimeCache;
use RuntimeException; use RuntimeException;
@ -98,18 +97,12 @@
'User-Agent: ncc' 'User-Agent: ncc'
]; ];
if($authentication !== null) if($authentication !== null)
{ {
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
@ -193,13 +186,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_URL => $endpoint, CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@ -260,13 +246,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_URL => $endpoint, CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@ -358,13 +337,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_URL => $endpoint, CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@ -461,13 +433,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_URL => $endpoint, CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,

View file

@ -39,7 +39,6 @@
use ncc\Objects\Vault\Password\AccessToken; use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword; use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache; use ncc\Utilities\RuntimeCache;
use RuntimeException; use RuntimeException;
@ -104,13 +103,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_URL => $endpoint, CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@ -195,13 +187,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true, CURLOPT_NOBODY => true,
@ -265,13 +250,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
@ -355,13 +333,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
@ -447,13 +418,6 @@
$headers = self::injectAuthentication($authentication, $curl, $headers); $headers = self::injectAuthentication($authentication, $curl, $headers);
} }
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,

View file

@ -22,10 +22,8 @@
namespace ncc\Classes\NccExtension; namespace ncc\Classes\NccExtension;
use InvalidArgumentException;
use ncc\Enums\SpecialConstants\BuildConstants; use ncc\Enums\SpecialConstants\BuildConstants;
use ncc\Enums\SpecialConstants\DateTimeConstants; use ncc\Enums\SpecialConstants\DateTimeConstants;
use ncc\Enums\SpecialConstants\GeneralConstants;
use ncc\Enums\SpecialConstants\InstallConstants; use ncc\Enums\SpecialConstants\InstallConstants;
use ncc\Enums\SpecialConstants\AssemblyConstants; use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\SpecialConstants\RuntimeConstants; use ncc\Enums\SpecialConstants\RuntimeConstants;
@ -49,67 +47,6 @@
$input = self::compileBuildConstants($input); $input = self::compileBuildConstants($input);
$input = self::compileDateTimeConstants($input, time()); $input = self::compileDateTimeConstants($input, time());
$input = self::compileRuntimeConstants($input); $input = self::compileRuntimeConstants($input);
$input = self::compileGeneralConstants($input, $project_configuration);
return $input;
}
/**
* Compiles general constants from the given input string based on the provided project configuration.
*
* @param string|null $input The input string containing constants to be compiled.
* @param ProjectConfiguration $project_configuration The project configuration used to resolve constants.
* @return string|null The input string with constants replaced, or null if the input was null.
*/
public static function compileGeneralConstants(?string $input, ProjectConfiguration $project_configuration): ?string
{
if ($input === null)
{
return null;
}
// Replace %DEFAULT_BUILD_CONFIGURATION%
$input = str_replace(
[
GeneralConstants::DEFAULT_BUILD_CONFIGURATION->value
],
[
$project_configuration->getBuild()->getDefaultConfiguration()
],
$input
);
if (str_starts_with($input, GeneralConstants::BUILD_OUTPUT_PATH->value))
{
$build_name = null;
if (preg_match('/' . preg_quote(GeneralConstants::BUILD_OUTPUT_PATH->value, '/') . ':(\S+)/', $input, $matches))
{
$build_name = $matches[1];
}
if ($build_name === null)
{
Console::outWarning(sprintf("Cannot compile constant %s because it's not valid, usage: %%CONSTANT%%:<name>", $input));
}
else
{
try
{
$output_path = $project_configuration->getBuild()->getBuildConfiguration($build_name)->getOutput();
$input = preg_replace(
'/' . preg_quote(GeneralConstants::BUILD_OUTPUT_PATH->value, '/') . ':\S+/',
$output_path,
$input,
1
);
}
catch (InvalidArgumentException $e)
{
Console::outError(sprintf("Cannot compile constant %s because it does not point to an existing build configuration name", $input));
}
}
}
return $input; return $input;
} }
@ -133,7 +70,7 @@
AssemblyConstants::ASSEMBLY_NAME->value, AssemblyConstants::ASSEMBLY_NAME->value,
AssemblyConstants::ASSEMBLY_PACKAGE->value, AssemblyConstants::ASSEMBLY_PACKAGE->value,
AssemblyConstants::ASSEMBLY_VERSION->value, AssemblyConstants::ASSEMBLY_VERSION->value,
AssemblyConstants::ASSEMBLY_UID->value, AssemblyConstants::ASSEMBLY_UID->value
], ],
[ [
$assembly->getName(), $assembly->getName(),

View file

@ -59,17 +59,11 @@
*/ */
private $project_manager; private $project_manager;
/**
* @var array
*/
private $merged_dependencies;
/** /**
* @param ProjectManager $project_manager * @param ProjectManager $project_manager
*/ */
public function __construct(ProjectManager $project_manager) public function __construct(ProjectManager $project_manager)
{ {
$this->merged_dependencies = [];
$this->project_manager = $project_manager; $this->project_manager = $project_manager;
} }
@ -95,7 +89,6 @@
*/ */
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT->value, array $options=[]): string public function build(string $build_configuration=BuildConfigurationValues::DEFAULT->value, array $options=[]): string
{ {
$this->merged_dependencies = [];
$configuration = $this->project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration); $configuration = $this->project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
$configuration->setOptions(array_merge($configuration->getOptions(), $options)); $configuration->setOptions(array_merge($configuration->getOptions(), $options));
$static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]); $static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]);
@ -171,7 +164,7 @@
foreach($execution_units as $unit) foreach($execution_units as $unit)
{ {
$progress_bar->setMiscText(basename($unit->getExecutionPolicy()->getName())); $progress_bar->setMiscText($unit->getExecutionPolicy()->getName());
//$progress++; //$progress++;
//Console::inlineProgressBar($progress, $steps); //Console::inlineProgressBar($progress, $steps);
$package_writer->addExecutionUnit($unit); $package_writer->addExecutionUnit($unit);
@ -184,7 +177,7 @@
{ {
//$progress++; //$progress++;
//Console::inlineProgressBar($progress, $steps); //Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($component)); $progress_bar->setMiscText($component);
Console::outVerbose(sprintf('Compiling \'%s\'', $component)); Console::outVerbose(sprintf('Compiling \'%s\'', $component));
$this->processComponent($package_writer, $component); $this->processComponent($package_writer, $component);
@ -196,7 +189,7 @@
{ {
//$progress++; //$progress++;
//Console::inlineProgressBar($progress, $steps); //Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($resource)); $progress_bar->setMiscText($resource);
Console::outVerbose(sprintf('Processing \'%s\'', $resource)); Console::outVerbose(sprintf('Processing \'%s\'', $resource));
$this->processResource($package_writer, $resource); $this->processResource($package_writer, $resource);
@ -241,14 +234,13 @@
/** @noinspection UnusedFunctionResultInspection */ /** @noinspection UnusedFunctionResultInspection */
$package_writer->addDependencyConfiguration($dependency); $package_writer->addDependencyConfiguration($dependency);
if(!$static || in_array($dependency->getName(), $this->merged_dependencies, true)) if(!$static)
{ {
return; return;
} }
$entry = (new PackageManager())->getPackageLock()->getVersionEntry($dependency->getName(), $dependency->getVersion()); $entry = (new PackageManager())->getPackageLock()->getVersionEntry($dependency->getName(), $dependency->getVersion());
$package_writer->merge((new PackageReader($entry->getShadowPackagePath($dependency->getName())))); $package_writer->merge((new PackageReader($entry->getShadowPackagePath($dependency->getName()))));
$this->merged_dependencies[] = $dependency->getName();
foreach($entry->getDependencies() as $sub_dependency) foreach($entry->getDependencies() as $sub_dependency)
{ {

View file

@ -29,8 +29,8 @@
use ncc\Enums\Flags\PackageFlags; use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory; use ncc\Enums\PackageDirectory;
use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException; use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Objects\Package\Component; use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit; use ncc\Objects\Package\ExecutionUnit;
use ncc\Objects\Package\Metadata; use ncc\Objects\Package\Metadata;
@ -84,11 +84,6 @@
*/ */
private $package_file; private $package_file;
/**
* @var string
*/
private $package_path;
/** /**
* @var array * @var array
*/ */
@ -107,9 +102,7 @@
throw new IOException(sprintf('File \'%s\' does not exist', $file_path)); throw new IOException(sprintf('File \'%s\' does not exist', $file_path));
} }
$this->package_path = $file_path;
$this->package_file = fopen($file_path, 'rb'); $this->package_file = fopen($file_path, 'rb');
if($this->package_file === false) if($this->package_file === false)
{ {
throw new IOException(sprintf('Failed to open file \'%s\'', $file_path)); throw new IOException(sprintf('Failed to open file \'%s\'', $file_path));
@ -182,31 +175,20 @@
// Seek the data until the end of the package (FF AA 55 F0) // Seek the data until the end of the package (FF AA 55 F0)
fseek($this->package_file, $this->data_offset); fseek($this->package_file, $this->data_offset);
$buffer = '';
while(!feof($this->package_file)) while(!feof($this->package_file))
{ {
$current_chunk = fread($this->package_file, 1024); $buffer = fread($this->package_file, 1024);
$this->data_length += strlen($current_chunk); $this->data_length += strlen($buffer);
$buffer .= $current_chunk;
// If we detect the end-of-data byte sequence
if (($position = strpos($buffer, "\xFF\xAA\x55\xF0")) !== false) if (($position = strpos($buffer, "\xFF\xAA\x55\xF0")) !== false)
{ {
$this->data_length -= strlen($buffer) - $position; $this->data_length -= strlen($buffer) - $position;
$this->package_length += $this->data_length + 4; $this->package_length += $this->data_length + 4;
break; break;
} }
// Check if the buffer is 1MB or larger
if(strlen($buffer) > 1048576)
{
// Remove the first 512kb of the buffer
$buffer = substr($buffer, 512000);
} }
} if($this->data_length === null)
if($this->data_length === null || $this->data_length === 0)
{ {
throw new IOException(sprintf('File \'%s\' is not a valid package file (missing end of package)', $file_path)); throw new IOException(sprintf('File \'%s\' is not a valid package file (missing end of package)', $file_path));
} }
@ -275,7 +257,7 @@
{ {
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{ {
throw new RuntimeException(sprintf('File \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new RuntimeException(sprintf('File \'%s\' not found in package', $name));
} }
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]); $location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
@ -299,7 +281,7 @@
{ {
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{ {
throw new RuntimeException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new RuntimeException(sprintf('Resource \'%s\' not found in package', $name));
} }
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]); $location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
@ -335,7 +317,6 @@
* *
* @return Assembly * @return Assembly
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getAssembly(): Assembly public function getAssembly(): Assembly
{ {
@ -348,18 +329,10 @@
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
{ {
throw new ConfigurationException(sprintf('Assembly object not found in package \'%s\'', $this->package_path)); throw new ConfigurationException('Package does not contain an assembly');
} }
try
{
$assembly = Assembly::fromArray(ZiProto::decode($this->get($directory))); $assembly = Assembly::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode assembly from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
}
$this->cache[$directory] = $assembly; $this->cache[$directory] = $assembly;
return $assembly; return $assembly;
} }
@ -369,7 +342,7 @@
* *
* @return Metadata * @return Metadata
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException * @throws NotSupportedException
*/ */
public function getMetadata(): Metadata public function getMetadata(): Metadata
{ {
@ -382,18 +355,10 @@
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
{ {
throw new ConfigurationException(sprintf('Metadata object not found in package \'%s\'', $this->package_path)); throw new ConfigurationException('Package does not contain metadata');
} }
try
{
$metadata = Metadata::fromArray(ZiProto::decode($this->get($directory))); $metadata = Metadata::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode metadata from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
}
foreach($this->getFlags() as $flag) foreach($this->getFlags() as $flag)
{ {
$metadata->setOption($flag, true); $metadata->setOption($flag, true);
@ -407,7 +372,6 @@
* Optional. Returns the package's installer * Optional. Returns the package's installer
* *
* @return Installer|null * @return Installer|null
* @throws IntegrityException
*/ */
public function getInstaller(): ?Installer public function getInstaller(): ?Installer
{ {
@ -423,15 +387,7 @@
return null; return null;
} }
try
{
$installer = Installer::fromArray(ZiProto::decode($this->get($directory))); $installer = Installer::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode installer from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
}
$this->cache[$directory] = $installer; $this->cache[$directory] = $installer;
return $installer; return $installer;
} }
@ -463,25 +419,17 @@
* @param string $name * @param string $name
* @return Dependency * @return Dependency
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getDependency(string $name): Dependency public function getDependency(string $name): Dependency
{ {
$dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $name); $dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$dependency_name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$dependency_name]))
{ {
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package', $name));
} }
try
{
return Dependency::fromArray(ZiProto::decode($this->get($dependency_name))); return Dependency::fromArray(ZiProto::decode($this->get($dependency_name)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode dependency \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns a dependency from the package by pointer * Returns a dependency from the package by pointer
@ -489,19 +437,12 @@
* @param int $pointer * @param int $pointer
* @param int $length * @param int $length
* @return Dependency * @return Dependency
* @throws IntegrityException * @throws ConfigurationException
*/ */
public function getDependencyByPointer(int $pointer, int $length): Dependency public function getDependencyByPointer(int $pointer, int $length): Dependency
{
try
{ {
return Dependency::fromArray(ZiProto::decode($this->getByPointer($pointer, $length))); return Dependency::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode dependency from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns an array of execution units from the package * Returns an array of execution units from the package
@ -530,36 +471,17 @@
* @param string $name * @param string $name
* @return ExecutionUnit * @return ExecutionUnit
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getExecutionUnit(string $name): ExecutionUnit public function getExecutionUnit(string $name): ExecutionUnit
{ {
$execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name); $execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$execution_unit_name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$execution_unit_name]))
{ {
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package', $name));
} }
try
{
return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name))); return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode execution unit \'%s\' from package file \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
}
/**
* Checks if an execution unit with the specified name exists in the package.
*
* @param string $name The name of the execution unit to check.
* @return bool True if the execution unit exists, false otherwise.
*/
public function executionUnitExists(string $name): bool
{
return isset($this->headers[PackageStructure::DIRECTORY->value][sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name)]);
}
/** /**
* Returns an execution unit from the package by pointer * Returns an execution unit from the package by pointer
@ -567,19 +489,12 @@
* @param int $pointer * @param int $pointer
* @param int $length * @param int $length
* @return ExecutionUnit * @return ExecutionUnit
* @throws IntegrityException * @throws ConfigurationException
*/ */
public function getExecutionUnitByPointer(int $pointer, int $length): ExecutionUnit public function getExecutionUnitByPointer(int $pointer, int $length): ExecutionUnit
{
try
{ {
return ExecutionUnit::fromArray(ZiProto::decode($this->getByPointer($pointer, $length))); return ExecutionUnit::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode execution unit from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns the package's component pointers * Returns the package's component pointers
@ -629,25 +544,17 @@
* @param string $name * @param string $name
* @return Component * @return Component
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getComponent(string $name): Component public function getComponent(string $name): Component
{ {
$component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $name); $component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$component_name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$component_name]))
{ {
throw new ConfigurationException(sprintf('Component \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new ConfigurationException(sprintf('Component \'%s\' not found in package', $name));
} }
try
{
return Component::fromArray(ZiProto::decode($this->get($component_name))); return Component::fromArray(ZiProto::decode($this->get($component_name)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns a component from the package by pointer * Returns a component from the package by pointer
@ -655,19 +562,12 @@
* @param int $pointer * @param int $pointer
* @param int $length * @param int $length
* @return Component * @return Component
* @throws IntegrityException * @throws ConfigurationException
*/ */
public function getComponentByPointer(int $pointer, int $length): Component public function getComponentByPointer(int $pointer, int $length): Component
{
try
{ {
return Component::fromArray(ZiProto::decode($this->getByPointer($pointer, $length))); return Component::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns a component from the package by a class pointer * Returns a component from the package by a class pointer
@ -675,25 +575,17 @@
* @param string $class * @param string $class
* @return Component * @return Component
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getComponentByClass(string $class): Component public function getComponentByClass(string $class): Component
{ {
$class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class); $class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$class_name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$class_name]))
{ {
throw new ConfigurationException(sprintf('Class map \'%s\' not found in package \'%s\'', $class, $this->package_path)); throw new ConfigurationException(sprintf('Class map \'%s\' not found in package', $class));
} }
try
{
return Component::fromArray(ZiProto::decode($this->get($class_name))); return Component::fromArray(ZiProto::decode($this->get($class_name)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component from class pointer \'%s\' from package \'%s\' using ZiProto: %s', $class, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns an array of resource pointers from the package * Returns an array of resource pointers from the package
@ -722,25 +614,17 @@
* @param string $name * @param string $name
* @return Resource * @return Resource
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function getResource(string $name): Resource public function getResource(string $name): Resource
{ {
$resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $name); $resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$resource_name])) if(!isset($this->headers[PackageStructure::DIRECTORY->value][$resource_name]))
{ {
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path)); throw new ConfigurationException(sprintf('Resource \'%s\' not found in package', $name));
} }
try
{
return Resource::fromArray(ZiProto::decode($this->get($resource_name))); return Resource::fromArray(ZiProto::decode($this->get($resource_name)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode resource \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Returns a resource from the package by pointer * Returns a resource from the package by pointer
@ -748,19 +632,12 @@
* @param int $pointer * @param int $pointer
* @param int $length * @param int $length
* @return Resource * @return Resource
* @throws IntegrityException * @throws ConfigurationException
*/ */
public function getResourceByPointer(int $pointer, int $length): Resource public function getResourceByPointer(int $pointer, int $length): Resource
{
try
{ {
return Resource::fromArray(ZiProto::decode($this->getByPointer($pointer, $length))); return Resource::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
} }
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode resource from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
}
/** /**
* Searches the package's directory for a file that matches the given filename * Searches the package's directory for a file that matches the given filename

View file

@ -38,7 +38,6 @@
use ncc\ThirdParty\composer\semver\Comparator; use ncc\ThirdParty\composer\semver\Comparator;
use ncc\ThirdParty\composer\semver\Semver; use ncc\ThirdParty\composer\semver\Semver;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache; use ncc\Utilities\RuntimeCache;
use RuntimeException; use RuntimeException;
@ -71,13 +70,6 @@
'User-Agent: ncc' 'User-Agent: ncc'
]; ];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
@ -138,13 +130,6 @@
'User-Agent: ncc' 'User-Agent: ncc'
]; ];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [ curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,

View file

@ -84,12 +84,6 @@
$binary_path = ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutput()); $binary_path = ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutput());
} }
// Create the directory recursively if it does not exist
if(!is_dir(dirname($binary_path)))
{
mkdir(dirname($binary_path), 0777, true);
}
if($gcc_path === null) if($gcc_path === null)
{ {
throw new BuildException("Unable to find gcc executable, please make sure it is installed and in your PATH environment variable."); throw new BuildException("Unable to find gcc executable, please make sure it is installed and in your PATH environment variable.");

View file

@ -74,6 +74,7 @@
self::writeProgramTemplate($project_manager); self::writeProgramTemplate($project_manager);
self::writeMainEntryTemplate($project_manager); self::writeMainEntryTemplate($project_manager);
self::writeMakefileTemplate($project_manager);
$project_manager->save(); $project_manager->save();
} }
@ -113,4 +114,22 @@
) )
); );
} }
/**
* Writes the Makefile to the project directory
*
* @param ProjectManager $project_manager
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function writeMakefileTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'Makefile',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'Makefile.tpl')
)
);
}
} }

View file

@ -1,61 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Classes\PhpExtension\Templates;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\IOException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
class CompressedTemplate implements TemplateInterface
{
/**
* @inheritDoc
* @throws IOException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
// Create the release build configuration
$release_compressed = new BuildConfiguration('release-compressed',
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_PACKAGE->value . '.gz.ncc'
);
$release_compressed->setBuildType(BuildOutputType::NCC_PACKAGE->value);
$release_compressed->setOption(BuildConfigurationOptions::COMPRESSION->value, BuildConfigurationOptions\CompressionOptions::HIGH->value);
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($release_compressed);
// Create the debug build configuration
$debug_compressed = new BuildConfiguration('debug-compressed',
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_PACKAGE->value . '.gz.ncc'
);
$debug_compressed->setBuildType(BuildOutputType::NCC_PACKAGE->value);
$debug_compressed->setOption(BuildConfigurationOptions::COMPRESSION->value, BuildConfigurationOptions\CompressionOptions::HIGH->value);
$debug_compressed->setDefinedConstant('DEBUG', '1');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($debug_compressed);
$project_manager->save();
}
}

View file

@ -1,77 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Classes\PhpExtension\Templates;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\IOException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
class ExecutableTemplate implements TemplateInterface
{
/**
* @inheritDoc
* @throws IOException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_configuration)
{
$executable_name = sprintf('%s-executable', $build_configuration);
$configuration = $project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
// Skip if the executable version of the build configuration already exists
if($project_manager->getProjectConfiguration()->getBuild()->buildConfigurationExists($executable_name))
{
continue;
}
// Skip if the build configuration is not an ncc package that the executable can be based on
if($configuration->getBuildType() !== BuildOutputType::NCC_PACKAGE->value)
{
continue;
}
if(isset($configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
{
$output = dirname($configuration->getOutput()) . DIRECTORY_SEPARATOR . str_replace('-', '_', $executable_name);
}
else
{
$output = dirname($configuration->getOutput()) . DIRECTORY_SEPARATOR . str_replace('-', '_', $executable_name) . '_gz';
}
// Create the executable build configuration
$executable = new BuildConfiguration($executable_name, $output);
$executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, $configuration->getName());
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($executable);
}
$project_manager->save();
}
}

View file

@ -1,117 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Classes\PhpExtension\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Managers\ProjectManager;
use ncc\Utilities\IO;
class GitHubWorkflowTemplate
{
/**
* @inheritDoc
* @param ProjectManager $project_manager
* @throws IOException
* @throws PathNotFoundException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::writeCiTemplate($project_manager);
}
/**
* Writes the Makefile to the project directory
*
* @param ProjectManager $project_manager
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function writeCiTemplate(ProjectManager $project_manager): void
{
$ci_dir = $project_manager->getProjectPath() . DIRECTORY_SEPARATOR . '.github' . DIRECTORY_SEPARATOR . 'workflows';
if(!file_exists($ci_dir))
{
mkdir($ci_dir, 0777, true);
}
$template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci.yml.tpl');
$default_configuration = $project_manager->getProjectConfiguration()->getBuild()->getDefaultConfiguration();
$builds = [];
$releases = [];
$downloads = [];
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_name)
{
$build_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci_build.yml.tpl');
$build_template = str_replace('%TPL_BUILD_NAME%', $build_name, $build_template);
$build_template = str_replace('%TPL_BUILD_OUTPUT%',
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_name)->getOutput(),
$build_template
);
$builds[$build_name] = $build_template;
$download_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci_download.yml.tpl');
$download_template = str_replace('%TPL_BUILD_NAME%', $build_name, $download_template);
$downloads[$build_name] = $download_template;
$release_template = str_repeat(' ', 12) . $build_name . DIRECTORY_SEPARATOR . basename(
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_name)->getOutput()
);
$releases[$build_name] = $release_template;
}
$build_jobs = '';
foreach($builds as $name => $build_template)
{
$build_jobs .= $build_template . PHP_EOL;
}
$download_jobs = '';
foreach($downloads as $name => $download_template)
{
$download_jobs .= $download_template . PHP_EOL;
}
$release_jobs = '';
foreach($releases as $name => $release_template)
{
$release_jobs .= $release_template . PHP_EOL;
}
$template = str_replace('%TPL_BUILDS%', $build_jobs, $template);
$template = str_replace('%TPL_DOWNLOAD_ARTIFACTS%', $download_jobs, $template);
$template = str_replace('%TPL_ARTIFACT_FILES%', $release_jobs, $template);
$template = str_replace('%TPL_BUILD_NAMES%', implode(', ', array_keys($builds)), $template);
$template = str_replace('%TPL_DEFAULT_BUILD_CONFIGURATION%', $default_configuration, $template);
$template = str_replace('%TPL_DEFAULT_ARTIFACT_BUILD_OUTPUT%', $default_configuration . DIRECTORY_SEPARATOR . basename(
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($default_configuration)->getOutput()
), $template);
IO::fwrite($ci_dir . DIRECTORY_SEPARATOR . 'ncc_workflow.yml',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(), $template)
);
}
}

View file

@ -48,14 +48,8 @@
*/ */
private static function createClassTemplate(ProjectManager $project_manager): void private static function createClassTemplate(ProjectManager $project_manager): void
{ {
$class_directory = $project_manager->getProjectSourcePath() . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName();
if(!file_exists($class_directory))
{
mkdir($class_directory, 0777, true);
}
IO::fwrite( IO::fwrite(
$class_directory . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php', $project_manager->getProjectSourcePath() . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(), ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'class.php.tpl') IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'class.php.tpl')
) )

View file

@ -1,21 +1,20 @@
# Variables # Variables
DEFAULT_CONFIGURATION ?= %TPL_DEFAULT_BUILD_CONFIGURATION% CONFIG ?= release
LOG_LEVEL = debug LOG_LEVEL = debug
OUTDIR = build/$(CONFIG)
PACKAGE = $(OUTDIR)/%ASSEMBLY.PACKAGE%.ncc
# Default Target # Default Target
all: %TPL_BUILD_NAMES% all: build
# Build Steps # Build Steps
%TPL_BUILDS% build:
ncc build --config=$(CONFIG) --log-level $(LOG_LEVEL)
install: %TPL_DEFAULT_BUILD_CONFIGURATION% install:
ncc package install --package=%TPL_DEFAULT_BUILD_PATH% --skip-dependencies --build-source --reinstall -y --log-level $(LOG_LEVEL) ncc package install --package=$(PACKAGE) --skip-dependencies --reinstall -y --log-level $(LOG_LEVEL)
test: %TPL_DEFAULT_BUILD_CONFIGURATION%
[ -f phpunit.xml ] || { echo "phpunit.xml not found"; exit 1; }
phpunit
clean: clean:
rm -rf build rm -rf build
.PHONY: all install test clean %TPL_BUILD_NAMES% .PHONY: all build install clean

View file

@ -1,78 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Classes\PhpExtension\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Managers\ProjectManager;
use ncc\Utilities\IO;
class MakefileTemplate
{
/**
* @inheritDoc
* @param ProjectManager $project_manager
* @throws IOException
* @throws PathNotFoundException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::writeMakefileTemplate($project_manager);
}
/**
* Writes the Makefile template for the given project.
*
* @param ProjectManager $project_manager The project manager containing project configurations.
* @throws IOException If there is an error reading or writing files.
* @throws PathNotFoundException If a required file path is not found.
*/
private static function writeMakefileTemplate(ProjectManager $project_manager): void
{
$makefile_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'Makefile.tpl');
$builds = [];
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_name)
{
$builds[$build_name] = str_replace('%TPL_BUILD_NAME%', $build_name, IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'make_build.tpl'));
}
$default_build = $project_manager->getProjectConfiguration()->getBuild()->getDefaultConfiguration();
$makefile_template = str_replace('%TPL_DEFAULT_BUILD_CONFIGURATION%', $default_build, $makefile_template);
$makefile_template = str_replace('%TPL_DEFAULT_BUILD_PATH%', $project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($default_build)->getOutput(), $makefile_template);
$makefile_template = str_replace('%TPL_BUILD_NAMES%', implode(' ', array_keys($builds)), $makefile_template);
$build_template = '';
foreach($builds as $name => $template)
{
$build_template .= $template . PHP_EOL;
}
$makefile_template = str_replace('%TPL_BUILDS%', $build_template, $makefile_template);
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'Makefile',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(), $makefile_template)
);
}
}

View file

@ -1,93 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2023, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Classes\PhpExtension\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\Options\ProjectOptions;
use ncc\Enums\Runners;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
use ncc\Utilities\IO;
class PhpUnitTemplate implements TemplateInterface
{
/**
* Applies the necessary templates for the given project.
*
* @param ProjectManager $project_manager Manager responsible for handling project-related tasks.
*
* @return void
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::createPhpUnitBootstrapTemplate($project_manager);
self::createPhpUnitTemplate($project_manager);
}
/**
* Creates a PHPUnit template in the specified project directory.
*
* @param ProjectManager $project_manager The project manager instance containing project configuration and path details.
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function createPhpUnitTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'phpunit.xml',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml.tpl')
)
);
if(!file_exists($project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'tests'))
{
mkdir($project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'tests');
}
}
/**
* Creates the PHPUnit bootstrap template file for the given project.
*
* @param ProjectManager $project_manager The project manager instance handling project configuration and paths.
* @return void
*/
private static function createPhpUnitBootstrapTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'bootstrap.php',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php.tpl')
)
);
}
}

View file

@ -1,3 +0,0 @@
<?php
require 'ncc';
import('%ASSEMBLY.PACKAGE%');

View file

@ -1,187 +0,0 @@
name: CI
on:
push:
branches:
- '**'
release:
types: [created]
workflow_dispatch:
jobs:
%TPL_BUILDS%
# Checking for phpunit.xml
check-phpunit:
runs-on: ubuntu-latest
outputs:
phpunit-exists: ${{ steps.check.outputs.phpunit-exists }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for phpunit.xml
id: check
run: |
if [ -f phpunit.xml ]; then
echo "phpunit-exists=true" >> $GITHUB_OUTPUT
else
echo "phpunit-exists=false" >> $GITHUB_OUTPUT
fi
# Checking for phpdoc.dist.xml
check-phpdoc:
runs-on: ubuntu-latest
outputs:
phpdoc-exists: ${{ steps.check.outputs.phpdoc-exists }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for phpdoc.dist.xml
id: check
run: |
if [ -f phpdoc.dist.xml ]; then
echo "phpdoc-exists=true" >> $GITHUB_OUTPUT
else
echo "phpdoc-exists=false" >> $GITHUB_OUTPUT
fi
generate-phpdoc:
needs: [%TPL_DEFAULT_BUILD_CONFIGURATION%, check-phpdoc]
runs-on: ubuntu-latest
container:
image: php:8.3
if: needs.check-phpdoc.outputs.phpdoc-exists == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
- name: Download PHPDocumentor
run: |
wget https://phpdoc.org/phpDocumentor.phar
chmod +x phpDocumentor.phar
- name: Generate PHPDoc
run: |
php phpDocumentor.phar -d src -t docs
- name: Archive PHPDoc
run: |
zip -r docs.zip docs
- name: Upload PHPDoc
uses: actions/upload-artifact@v4
with:
name: documentation
path: docs.zip
test:
needs: [%TPL_BUILD_NAMES%, check-phpunit]
runs-on: ubuntu-latest
container:
image: php:8.3
if: needs.check-phpunit.outputs.phpunit-exists == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: %TPL_DEFAULT_BUILD_CONFIGURATION%
path: %TPL_DEFAULT_BUILD_CONFIGURATION%
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
curl -sSLf -o /usr/local/bin/install-php-extensions https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions
chmod +x /usr/local/bin/install-php-extensions
install-php-extensions zip
- name: Install phive
run: |
wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
mv phive.phar /usr/local/bin/phive
- name: Install phab
run: |
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Install latest version of NCC
run: |
git clone https://git.n64.cc/nosial/ncc.git
cd ncc
make redist
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
if [ -z "$NCC_DIR" ]; then
echo "NCC build directory not found"
exit 1
fi
php "$NCC_DIR/INSTALL" --auto
cd .. && rm -rf ncc
- name: Install NCC packages
run: |
ncc package install --package="%TPL_DEFAULT_ARTIFACT_BUILD_OUTPUT%" --build-source --reinstall -y --log-level debug
- name: Run PHPUnit tests
run: |
wget https://phar.phpunit.de/phpunit-11.3.phar
php phpunit-11.3.phar --configuration phpunit.xml --log-junit reports/junit.xml --log-teamcity reports/teamcity --testdox-html reports/testdox.html --testdox-text reports/testdox.txt
- name: Upload test reports
uses: actions/upload-artifact@v4
with:
name: reports
path: reports
release-documentation:
needs: generate-phpdoc
permissions: write-all
runs-on: ubuntu-latest
container:
image: php:8.3
if: github.event_name == 'release'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download documentation artifact
uses: actions/download-artifact@v4
with:
name: documentation
path: documentation
- name: Upload documentation artifact
uses: softprops/action-gh-release@v1
with:
files: |
documentation/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
release-artifacts:
needs: [%TPL_BUILD_NAMES%]
permissions: write-all
runs-on: ubuntu-latest
container:
image: php:8.3
if: github.event_name == 'release'
steps:
- name: Checkout repository
uses: actions/checkout@v4
%TPL_DOWNLOAD_ARTIFACTS%

View file

@ -1,49 +0,0 @@
%TPL_BUILD_NAME%:
runs-on: ubuntu-latest
container:
image: php:8.3
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
- name: Install phive
run: |
wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
mv phive.phar /usr/local/bin/phive
- name: Install phab
run: |
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Install latest version of NCC
run: |
git clone https://git.n64.cc/nosial/ncc.git
cd ncc
make redist
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
if [ -z "$NCC_DIR" ]; then
echo "NCC build directory not found"
exit 1
fi
php "$NCC_DIR/INSTALL" --auto
cd .. && rm -rf ncc
- name: Build project
run: |
ncc build --config %TPL_BUILD_NAME% --build-source --log-level debug
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: %TPL_BUILD_NAME%
path: %TPL_BUILD_OUTPUT%

View file

@ -1,12 +0,0 @@
- name: Download %TPL_BUILD_NAME% artifact
uses: actions/download-artifact@v4
with:
name: %TPL_BUILD_NAME%
path: %TPL_BUILD_NAME%
- name: Upload %TPL_BUILD_NAME% artifact to release
uses: softprops/action-gh-release@v1
with:
files: |
%TPL_BUILD_NAME%/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,2 +0,0 @@
%TPL_BUILD_NAME%:
ncc build --config=%TPL_BUILD_NAME% --log-level $(LOG_LEVEL)

View file

@ -1,11 +0,0 @@
<phpunit bootstrap="bootstrap.php">
<testsuites>
<testsuite name="%ASSEMBLY.NAME% Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_DIR" value="app/"/>
</php>
</phpunit>

View file

@ -34,7 +34,6 @@
use ncc\Enums\Versions; use ncc\Enums\Versions;
use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\ImportException; use ncc\Exceptions\ImportException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException; use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException; use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException; use ncc\Exceptions\OperationException;
@ -78,14 +77,12 @@
* This method may exit the program without returning a value * This method may exit the program without returning a value
* *
* @param string $package * @param string $package
* @param array $arguments
* @return mixed * @return mixed
* @throws ConfigurationException * @throws ConfigurationException
* @throws IOException * @throws IOException
* @throws IntegrityException
* @throws NotSupportedException * @throws NotSupportedException
* @throws OperationException
* @throws PathNotFoundException * @throws PathNotFoundException
* @throws OperationException
*/ */
public static function execute(string $package, array $arguments=[]): int public static function execute(string $package, array $arguments=[]): int
{ {
@ -96,12 +93,6 @@
if(self::$imported_packages[$package] instanceof PackageReader) if(self::$imported_packages[$package] instanceof PackageReader)
{ {
if(self::$imported_packages[$package]?->getMetadata()?->getMainExecutionPolicy() === null)
{
Console::out('The package does not have a main execution policy, skipping execution');
return 0;
}
return ExecutionUnitRunner::executeFromPackage( return ExecutionUnitRunner::executeFromPackage(
self::$imported_packages[$package], self::$imported_packages[$package],
self::$imported_packages[$package]->getMetadata()->getMainExecutionPolicy() self::$imported_packages[$package]->getMetadata()->getMainExecutionPolicy()
@ -303,7 +294,7 @@
* @return string * @return string
* @throws ConfigurationException * @throws ConfigurationException
* @throws ImportException * @throws ImportException
* @throws IntegrityException * @throws NotSupportedException
* @throws OperationException * @throws OperationException
*/ */
private static function importFromPackage(string $package_path): string private static function importFromPackage(string $package_path): string
@ -522,7 +513,6 @@
* @throws IOException * @throws IOException
* @throws OperationException * @throws OperationException
* @throws PathNotFoundException * @throws PathNotFoundException
* @throws IntegrityException
*/ */
private static function acquireFile(string $path, ?string $package=null): string private static function acquireFile(string $path, ?string $package=null): string
{ {
@ -639,16 +629,9 @@
return; return;
} }
$acquired_name = $path; if(!in_array($path, self::$included_files, true))
if(!is_file($path))
{ {
$acquired_name = hash('crc32', $acquired_file); self::$included_files[] = $path;
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
} }
self::extendedEvaluate($acquired_file); self::extendedEvaluate($acquired_file);
@ -691,16 +674,9 @@
throw new RuntimeException(sprintf('Failed to acquire file "%s" at runtime: %s', $path, $e->getMessage()), $e->getCode(), $e); throw new RuntimeException(sprintf('Failed to acquire file "%s" at runtime: %s', $path, $e->getMessage()), $e->getCode(), $e);
} }
$acquired_name = $path; if(!in_array($path, self::$included_files, true))
if(!is_file($path))
{ {
$acquired_name = hash('crc32', $acquired_file); self::$included_files[] = $path;
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
} }
self::extendedEvaluate($acquired_file); self::extendedEvaluate($acquired_file);

View file

@ -33,70 +33,4 @@
* A template that is used to create a PHP CLI application project * A template that is used to create a PHP CLI application project
*/ */
case PHP_CLI = 'phpcli'; case PHP_CLI = 'phpcli';
/**
* A template for generating a Makefile for the PHP project
*/
case PHP_MAKE = 'phpmake';
/**
* A template used for creating PHP Unit testing bootstrap
*/
case PHP_UNIT = 'phpunit';
/**
* A template that is used to create a PHP executable project
*/
case PHP_COMPRESSED = 'phpgz';
/**
* A template that is used to create a PHP executable project
*/
case PHP_EXECUTABLE = 'phpexe';
/**
* Template that combines PHP_LIBRARY, PHP_MAKE and PHP_UNIT in one
*/
case PHP_LIBRARY_FULL = 'phplib_full';
/**
* Template that combines PHP_LIBRARY, PHP_MAKE, PHP_UNIT and PHP_CLI in one
*/
case PHP_CLI_FULL = 'phpcli_full';
/**
* Template that applies a GitHub workflow CI that builds the project, tests the project and creates
* automatic builds for releases
*/
case PHP_GITHUB_CI = 'phpci_github';
/**
* Suggests the closest matching `ProjectTemplates` instance based on the given input string.
*
* @param string $input The input string to compare against.
* @return ProjectTemplates|null The closest matching `ProjectTemplates` instance, or null if no close match is found.
*/
public static function suggest(string $input): ?ProjectTemplates
{
$closest = null;
$shortest_distance = -1;
foreach (self::cases() as $case)
{
$distance = levenshtein($input, $case->value);
if ($distance === 0)
{
return $case;
}
if ($shortest_distance === -1 || $distance < $shortest_distance)
{
$closest = $case;
$shortest_distance = $distance;
}
}
return $closest ?: null;
}
} }

View file

@ -1,37 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, all rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace ncc\Enums\SpecialConstants;
enum GeneralConstants : string
{
/**
* The project's default build configuration
*/
case DEFAULT_BUILD_CONFIGURATION = '%DEFAULT_BUILD_CONFIGURATION%';
/**
* Configurable build output path
*/
case BUILD_OUTPUT_PATH = '%BUILD_OUTPUT_PATH%';
}

View file

@ -28,7 +28,6 @@
use Exception; use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use ncc\Classes\ArchiveExtractor; use ncc\Classes\ArchiveExtractor;
use ncc\Classes\ExecutionUnitRunner;
use ncc\Classes\PackageReader; use ncc\Classes\PackageReader;
use ncc\Classes\ShutdownHandler; use ncc\Classes\ShutdownHandler;
use ncc\CLI\Main; use ncc\CLI\Main;
@ -45,7 +44,6 @@
use ncc\Enums\Types\ProjectType; use ncc\Enums\Types\ProjectType;
use ncc\Enums\Versions; use ncc\Enums\Versions;
use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException; use ncc\Exceptions\IOException;
use ncc\Exceptions\NetworkException; use ncc\Exceptions\NetworkException;
use ncc\Exceptions\NotSupportedException; use ncc\Exceptions\NotSupportedException;
@ -114,7 +112,6 @@
* @param PackageReader $package_reader * @param PackageReader $package_reader
* @return Dependency[] * @return Dependency[]
* @throws ConfigurationException * @throws ConfigurationException
* @throws IntegrityException
*/ */
public function checkRequiredDependencies(PackageReader $package_reader): array public function checkRequiredDependencies(PackageReader $package_reader): array
{ {
@ -398,7 +395,6 @@
* @return array * @return array
* @throws ConfigurationException * @throws ConfigurationException
* @throws IOException * @throws IOException
* @throws IntegrityException
* @throws OperationException * @throws OperationException
* @throws PathNotFoundException * @throws PathNotFoundException
*/ */
@ -427,20 +423,6 @@
$this->uninstall($package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion()); $this->uninstall($package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion());
} }
if($package_reader->getInstaller() !== null && count($package_reader->getInstaller()->getPreInstall()) > 0)
{
foreach ($package_reader->getInstaller()->getPreInstall() as $unit)
{
Console::outVerbose(sprintf('Running pre-install unit: %s', $unit));
if(!$package_reader->executionUnitExists($unit))
{
throw new OperationException(sprintf("Unable to run pre-install unit '%s' because it is not defined in the package", $unit));
}
ExecutionUnitRunner::executeFromPackage($package_reader, $unit);
}
}
$filesystem = new Filesystem(); $filesystem = new Filesystem();
$package_path = PathFinder::getPackagesPath() . DIRECTORY_SEPARATOR . sprintf( $package_path = PathFinder::getPackagesPath() . DIRECTORY_SEPARATOR . sprintf(
'%s=%s', $package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion() '%s=%s', $package_reader->getAssembly()->getPackage(), $package_reader->getAssembly()->getVersion()
@ -543,20 +525,6 @@
} }
} }
if($package_reader->getInstaller() !== null && count($package_reader->getInstaller()->getPostInstall()) > 0)
{
foreach ($package_reader->getInstaller()->getPostInstall() as $unit)
{
Console::outVerbose(sprintf('Running post-install unit: %s', $unit));
if(!$package_reader->executionUnitExists($unit))
{
throw new OperationException(sprintf("Unable to run post-install unit '%s' because it is not defined in the package", $unit));
}
ExecutionUnitRunner::executeFromPackage($package_reader, $unit);
}
}
return $installed_packages; return $installed_packages;
} }
@ -686,8 +654,8 @@
* @return void * @return void
* @throws ConfigurationException * @throws ConfigurationException
* @throws IOException * @throws IOException
* @throws NotSupportedException
* @throws OperationException * @throws OperationException
* @throws IntegrityException
*/ */
private function extractPackageContents(PackageReader $package_reader, string $package_path): void private function extractPackageContents(PackageReader $package_reader, string $package_path): void
{ {

View file

@ -29,13 +29,9 @@
use ncc\Classes\PhpExtension\ExecutableCompiler; use ncc\Classes\PhpExtension\ExecutableCompiler;
use ncc\Classes\PhpExtension\NccCompiler; use ncc\Classes\PhpExtension\NccCompiler;
use ncc\Classes\PhpExtension\Templates\CliTemplate; use ncc\Classes\PhpExtension\Templates\CliTemplate;
use ncc\Classes\PhpExtension\Templates\CompressedTemplate;
use ncc\Classes\PhpExtension\Templates\ExecutableTemplate;
use ncc\Classes\PhpExtension\Templates\GitHubWorkflowTemplate;
use ncc\Classes\PhpExtension\Templates\LibraryTemplate; use ncc\Classes\PhpExtension\Templates\LibraryTemplate;
use ncc\Classes\PhpExtension\Templates\MakefileTemplate;
use ncc\Classes\PhpExtension\Templates\PhpUnitTemplate;
use ncc\Enums\CompilerExtensions; use ncc\Enums\CompilerExtensions;
use ncc\Enums\ComponentFileExtensions;
use ncc\Enums\Options\BuildConfigurationOptions; use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\Options\BuildConfigurationValues; use ncc\Enums\Options\BuildConfigurationValues;
use ncc\Enums\Options\InitializeProjectOptions; use ncc\Enums\Options\InitializeProjectOptions;
@ -193,59 +189,17 @@
*/ */
public function applyTemplate(string $template_name): void public function applyTemplate(string $template_name): void
{ {
switch(ProjectTemplates::tryFrom(strtolower($template_name))) switch(strtolower($template_name))
{ {
case ProjectTemplates::PHP_CLI: case ProjectTemplates::PHP_CLI->value:
CliTemplate::applyTemplate($this); CliTemplate::applyTemplate($this);
break; break;
case ProjectTemplates::PHP_LIBRARY: case ProjectTemplates::PHP_LIBRARY->value:
LibraryTemplate::applyTemplate($this); LibraryTemplate::applyTemplate($this);
break; break;
case ProjectTemplates::PHP_MAKE:
MakefileTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_UNIT:
PhpUnitTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_COMPRESSED:
CompressedTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_EXECUTABLE:
ExecutableTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_LIBRARY_FULL:
LibraryTemplate::applyTemplate($this);
MakefileTemplate::applyTemplate($this);
PhpUnitTemplate::applyTemplate($this);
CompressedTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_CLI_FULL:
CliTemplate::applyTemplate($this);
LibraryTemplate::applyTemplate($this);
MakefileTemplate::applyTemplate($this);
PhpUnitTemplate::applyTemplate($this);
CompressedTemplate::applyTemplate($this);
ExecutableTemplate::applyTemplate($this);
break;
case ProjectTemplates::PHP_GITHUB_CI:
GitHubWorkflowTemplate::applyTemplate($this);
break;
default: default:
$suggestion = ProjectTemplates::suggest($template_name);
if($suggestion !== null)
{
throw new NotSupportedException('The given template \'' . $template_name . '\' is not supported, did you mean \'' . $suggestion->value . '\'?');
}
throw new NotSupportedException('The given template \'' . $template_name . '\' is not supported'); throw new NotSupportedException('The given template \'' . $template_name . '\' is not supported');
} }
} }
@ -537,7 +491,6 @@
// Create the build configuration // Create the build configuration
$build = new ProjectConfiguration\Build('auto_src'); $build = new ProjectConfiguration\Build('auto_src');
$build->setDefaultConfiguration('release_ncc'); $build->setDefaultConfiguration('release_ncc');
$require_dev = [];
// Process dependencies // Process dependencies
if($composer_json->getRequire() !== null) if($composer_json->getRequire() !== null)
@ -558,6 +511,7 @@
} }
// Process developer dependencies // Process developer dependencies
$require_dev = [];
if($composer_json->getRequireDev() !== null) if($composer_json->getRequireDev() !== null)
{ {
/** @var ComposerJson\PackageLink $package_link */ /** @var ComposerJson\PackageLink $package_link */
@ -569,9 +523,10 @@
} }
$source = sprintf('%s=%s@packagist', $package_link->getPackageName(), $package_link->getVersion()); $source = sprintf('%s=%s@packagist', $package_link->getPackageName(), $package_link->getVersion());
$require_dev[] = new ProjectConfiguration\Dependency( $build->addDependency(new ProjectConfiguration\Dependency(
Resolver::composerNameToPackage($package_link->getPackageName()), $source, $package_link->getVersion() Resolver::composerNameToPackage($package_link->getPackageName()), $source, $package_link->getVersion()
); ));
$require_dev[] = $package_link->getPackageName();
} }
} }

View file

@ -24,7 +24,6 @@
namespace ncc\Objects\PackageLock; namespace ncc\Objects\PackageLock;
use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use ncc\Classes\PackageReader; use ncc\Classes\PackageReader;
use ncc\Enums\FileDescriptor; use ncc\Enums\FileDescriptor;
@ -42,7 +41,6 @@
use ncc\Objects\ProjectConfiguration\UpdateSource; use ncc\Objects\ProjectConfiguration\UpdateSource;
use ncc\ThirdParty\composer\semver\Semver; use ncc\ThirdParty\composer\semver\Semver;
use ncc\ThirdParty\jelix\Version\VersionComparator; use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\Utilities\Console;
use ncc\Utilities\Functions; use ncc\Utilities\Functions;
use ncc\Utilities\IO; use ncc\Utilities\IO;
@ -191,9 +189,8 @@
{ {
$version = $this->getLatestVersion(); $version = $this->getLatestVersion();
} }
catch(Exception $e) catch(InvalidArgumentException $e)
{ {
Console::outWarning(sprintf('Unable to find latest version for package %s, called on versionExists() in PackageEntry: %s', $this->name, $e->getMessage()));
return false; return false;
} }
} }

View file

@ -500,25 +500,6 @@
throw new InvalidArgumentException(sprintf('The build configuration "%s" does not exist', $name)); throw new InvalidArgumentException(sprintf('The build configuration "%s" does not exist', $name));
} }
/**
* Checks if a build configuration exists
*
* @param string $name The name of the build configuration to check
* @return bool Returns true if the build configuration exists, false otherwise
*/
public function buildConfigurationExists(string $name): bool
{
try
{
$this->getBuildConfiguration($name);
return true;
}
catch(InvalidArgumentException)
{
return false;
}
}
/** /**
* @param array $build_configurations * @param array $build_configurations
* @return void * @return void

View file

@ -84,64 +84,6 @@
$this->post_update = []; $this->post_update = [];
} }
/**
* Retrieves the pre-installation configuration.
*
* @return array The pre-installation configuration settings.
*/
public function getPreInstall(): array
{
return $this->pre_install;
}
/**
*
* @return array Returns the post-installation steps.
*/
public function getPostInstall(): array
{
return $this->post_install;
}
/**
* Retrieves the list of pre-uninstall tasks.
*
* @return array The array containing pre-uninstall tasks.
*/
public function getPreUninstall(): array
{
return $this->pre_uninstall;
}
/**
* Retrieves the post-uninstall steps array.
*
* @return array An array containing the post-uninstall steps.
*/
public function getPostUninstall(): array
{
return $this->post_uninstall;
}
/**
*
* @return array The pre-update data array.
*/
public function getPreUpdate(): array
{
return $this->pre_update;
}
/**
* Retrieves the list of post-update actions.
*
* @return array An array containing post-update actions.
*/
public function getPostUpdate(): array
{
return $this->post_update;
}
/** /**
* @inheritDoc * @inheritDoc
*/ */

View file

@ -25,9 +25,6 @@
namespace ncc\Utilities; namespace ncc\Utilities;
use ncc\CLI\Main;
use ncc\Enums\LogLevel;
class ConsoleProgressBar class ConsoleProgressBar
{ {
/** /**
@ -289,11 +286,6 @@
*/ */
public function update(): void public function update(): void
{ {
if(LogLevel::VERBOSE->checkLogLevel(Main::getLogLevel()))
{
return;
}
if($this->auto_end && $this->value >= $this->max_value) if($this->auto_end && $this->value >= $this->max_value)
{ {
print($this->renderInformation() . $this->renderProgressBar() . "\n"); print($this->renderInformation() . $this->renderProgressBar() . "\n");
@ -375,17 +367,11 @@
* @return string The progress bar string. * @return string The progress bar string.
*/ */
private function renderProgressBar(): string private function renderProgressBar(): string
{
$hashes_count = 0;
$percent_done = 0;
if($this->max_value !== 0)
{ {
$hashes_count = round($this->progress_width * $this->value / $this->max_value); $hashes_count = round($this->progress_width * $this->value / $this->max_value);
$percent_done = round($this->value * 100 / $this->max_value);
}
$dashes_count = $this->progress_width - $hashes_count; $dashes_count = $this->progress_width - $hashes_count;
$percent_done = round($this->value * 100 / $this->max_value);
return ' [' . str_repeat('#', $hashes_count) . str_repeat('-', $dashes_count) . ']' . sprintf('%4s', $percent_done) . '%'; return ' [' . str_repeat('#', $hashes_count) . str_repeat('-', $dashes_count) . ']' . sprintf('%4s', $percent_done) . '%';
} }

View file

@ -41,11 +41,6 @@
*/ */
private static $user_id_cache; private static $user_id_cache;
/**
* @var array
*/
private static $resolved_hosts = [];
/** /**
* Returns the current scope of the application * Returns the current scope of the application
* *
@ -304,54 +299,4 @@
return explode(':', $component_path, 2)[1]; return explode(':', $component_path, 2)[1];
} }
/**
* Resolve host and cache the result
*
* @param string $host The host to resolve
* @return string The resolved host IP address
*/
public static function resolveHost(string $host): string
{
$resolved_host = self::$resolved_hosts[$host] ?? null;
if($resolved_host !== null)
{
Console::outDebug(sprintf('Resolved host "%s" to "%s" from cache', $host, $resolved_host));
return $resolved_host;
}
$resolved_host = gethostbyname($host);
if($resolved_host === $host)
{
Console::outDebug(sprintf('Unable to resolve host "%s"', $host));
return $host;
}
Console::outDebug(sprintf('Resolved host "%s" to "%s"', $host, $resolved_host));
self::$resolved_hosts[$host] = $resolved_host;
return $resolved_host;
}
/**
* Get resolved option for the given URL
*
* @param string $url The input URL
* @return string|null Resolved option in the format "{host}:{port}:{ip_address}", or null if $ip_address is same as $host
*/
public static function getResolveOption(string $url): ?string
{
$parsed_url = parse_url($url);
$host = $parsed_url['host'];
$port = str_starts_with($url, 'https') ? 443 : 80;
$ip_address = self::resolveHost($host);
if($ip_address === $host)
{
return null;
}
return "{$host}:{$port}:{$ip_address}";
}
} }

View file

@ -1 +1 @@
2.1.6 2.1.0

View file

@ -1,5 +1,5 @@
{ {
"version": "2.1.6", "version": "2.1.0",
"branch": "stable", "branch": "stable",
"flags": [], "flags": [],
"components": [ "components": [