Compare commits

...

213 commits

Author SHA1 Message Date
netkas
b975508d07 Indentation Correction 2025-01-08 15:46:13 -05:00
netkas
1ef96c3c4c Updated CHANGELOG.md 2024-10-29 12:28:41 -04:00
netkas
2dad5133bd Updated .gitignore 2024-10-25 19:59:33 -04:00
netkas
544d4ebdf6 Validate package instance before checking execution policy 2024-10-25 19:59:22 -04:00
netkas
41947069be Bumped version to 2.1.6 2024-10-25 19:56:25 -04:00
netkas
11aaa39eaa Update build script and bump version to 2.1.5 2024-10-14 15:29:32 -04:00
bdcf510089 Finalized CHANGELOG.md 2024-10-13 14:50:32 -04:00
278b3d0e2e Add executable and compressed templates with CI updates 2024-10-13 14:50:16 -04:00
771748636d Executable Compiler will now correctly create a directory if it does not exist when compiling a package using gcc 2024-10-13 12:31:51 -04:00
netkas
3b5a3882f6 Refactor CI templates to support dynamic build targets 2024-10-12 14:54:48 -04:00
netkas
77c668f7b6 Refactor phpmake template to support dynamic build targets 2024-10-11 14:21:10 -04:00
netkas
c40c7ce8fe 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 2024-10-10 15:31:59 -04:00
netkas
f5433c6bf9 Added new constant '%DEFAULT_BUILD_CONFIGURATION%' which points to the project's default build configuration 2024-10-10 15:17:21 -04:00
netkas
bc86e5a65d Updated CHANGELOG.md 2024-10-10 14:16:25 -04:00
netkas
f8ede74764 Updated Runtime 2024-10-10 14:13:47 -04:00
netkas
c87ebf14dd Bumped version to 2.1.4 2024-09-30 03:13:46 -04:00
netkas
e48e6a55e4 Null-pointer fix 2024-09-27 14:00:15 -04:00
netkas
08c770c9e1 Bumped version 2024-09-27 13:57:56 -04:00
netkas
e2a8dbfe27 Implement pre-install and post-install unit execution 2024-09-27 13:23:46 -04:00
netkas
91fe129bf4 Add getter methods for installation lifecycle steps 2024-09-27 00:42:33 -04:00
netkas
44dc1498f7 Updated CHANGELOG.md 2024-09-27 00:39:47 -04:00
netkas
c659baa9ce Updated DocStrings in PackageManager 2024-09-27 00:39:21 -04:00
netkas
1b33b83926 Fixed incorrect enum usage in RepositoryMenu 2024-09-27 00:35:01 -04:00
netkas
9303158674 Bumped version to version 2.1.2 2024-09-27 00:33:17 -04:00
netkas
d249e99448 Merge remote-tracking branch 'origin/dev' into dev 2024-09-24 12:53:33 -04:00
netkas
3f2f325bcc Updated CHANGELOG.md 2024-09-24 12:52:51 -04:00
netkas
2a20786755 Updated github_ci.yml.tpl 2024-09-24 12:52:51 -04:00
netkas
8ceb6756a4 Updated github_ci.yml.tpl 2024-09-24 12:48:16 -04:00
netkas
51bdb22540 Updated github_ci.yml.tpl 2024-09-24 12:45:09 -04:00
netkas
36d8e6f8c6 Updated github_ci.yml.tpl 2024-09-24 12:42:04 -04:00
netkas
9136396700 Updated github_ci.yml.tpl 2024-09-24 12:39:36 -04:00
netkas
e225add40b Updated github_ci.yml.tpl 2024-09-24 12:37:19 -04:00
netkas
33865d7e48 Updated github_ci.yml.tpl 2024-09-24 12:35:25 -04:00
netkas
cba6942cca Updated github_ci.yml.tpl 2024-09-24 12:32:27 -04:00
netkas
29e0a6e4ae Updated github_ci.yml.tpl 2024-09-24 00:36:31 -04:00
netkas
cba5f7041a Updated github_ci.yml.tpl 2024-09-24 00:34:15 -04:00
netkas
1ddb042175 Updated github_ci.yml.tpl 2024-09-24 00:30:09 -04:00
netkas
093e3341e1 Create class directory if it does not exist 2024-09-24 00:26:31 -04:00
netkas
80a019452f Add GitHub CI template support 2024-09-23 18:56:28 -04:00
netkas
b30ddbdc28 Seperated Makefile template into it's own template, added phpcli_full & phplib_full to combine all Templates together for building a PHP project 2024-09-23 15:17:15 -04:00
netkas
e829a839d1 Updated CHANGELOG.md 2024-09-23 15:05:51 -04:00
netkas
d813ef7b94 Added new template for PHP called "phpunit" to generate PHPUnit bootstrap test 2024-09-23 15:01:56 -04:00
netkas
09fb388ee7 Bumped version to 2.1.1 2024-09-20 20:12:38 -04:00
netkas
87290232f5 Merge branch 'master' into dev
# Conflicts:
#	CHANGELOG.md
#	src/ncc/CLI/Commands/BuildCommand.php
#	src/ncc/Classes/GithubExtension/GithubRepository.php
#	src/ncc/Managers/PackageManager.php
#	src/ncc/VERSION
#	src/ncc/version.json
2024-09-20 20:10:15 -04:00
netkas
adbd1d1751 Updated CHANGELOG.md 2024-09-20 20:07:18 -04:00
netkas
273df6ebb4 Updated ci.yml 2024-09-20 20:01:55 -04:00
netkas
d2baa2d580 Updated ci.yml 2024-09-20 19:57:18 -04:00
netkas
b2ef33d48f Updated ci.yml 2024-09-20 19:49:39 -04:00
netkas
7e79bba762 Updated ci.yml 2024-09-20 19:47:30 -04:00
netkas
45c58c0568 Updated ci.yml 2024-09-20 19:37:53 -04:00
netkas
3b0f1a805c Updated ci.yml 2024-09-20 19:35:47 -04:00
netkas
3640befdcc Updated ci.yml 2024-09-20 19:29:48 -04:00
netkas
798fe9e797 Updated ci.yml 2024-09-20 19:26:18 -04:00
netkas
140b0f2aff Updated ci.yml 2024-09-20 19:21:55 -04:00
netkas
64fdc3b5bd Updated ci.yml 2024-09-20 19:19:33 -04:00
netkas
23bd2c6636 Updated ci.yml 2024-09-20 19:16:45 -04:00
netkas
b29c83f276 Updated ci.yml 2024-09-20 19:14:04 -04:00
netkas
5eeb0d270d Updated ci.yml 2024-09-20 19:13:55 -04:00
netkas
2c5733c5c0 Updated ci.yml 2024-09-20 19:13:44 -04:00
netkas
e041ca2c20 Updated ci.yml 2024-09-20 19:11:23 -04:00
netkas
c9e4a6741a Updated ci.yml 2024-09-20 19:05:39 -04:00
netkas
634f50e317 Updated ci.yml 2024-09-20 19:02:49 -04:00
netkas
6d2d827de2 Updated ci.yml 2024-09-20 19:00:38 -04:00
netkas
1bb6189e57 Updated ci.yml 2024-09-20 18:59:02 -04:00
netkas
4db07af9bb Updated ci.yml 2024-09-20 18:58:40 -04:00
netkas
b93e07bc3d Fix argument passing in ExecCommand runner 2024-09-20 18:43:59 -04:00
netkas
9418125722 Add CLI support for passing and splitting execution arguments 2024-09-20 18:39:46 -04:00
netkas
7494ead7b3 Refactor ProjectManager and Runtime handling 2024-09-20 17:47:30 -04:00
netkas
170cb4bf6d Ensure required files exist before evaluation 2024-09-20 17:13:44 -04:00
netkas
dda710119c Add option to force package build from source 2024-09-20 17:04:30 -04:00
netkas
be70823a79 Bug fixes with Php-Parser 2024-09-20 16:00:53 -04:00
netkas
923117999b Updated nikic/PhpParser to version 5.2.0 2024-09-19 15:44:14 -04:00
netkas
a1404490bb Updated Symfony/polyfill-uuid to version 1.31.0 2024-09-19 15:24:32 -04:00
netkas
e556282f61 Updated Symfony/polyfill-mbstring to version 1.31.0 2024-09-19 15:23:08 -04:00
netkas
cdd3516766 Corrected ctype 2024-09-19 15:21:32 -04:00
netkas
9831b9dca1 Updated Symfony/polyfill-ctype to version 1.31.0 2024-09-19 15:19:41 -04:00
netkas
dd48100f06 Updated Symfony/Process to version 7.1.3 2024-09-19 15:14:53 -04:00
netkas
910477df8e Updated Symfony/Uid to version 7.1.4 2024-09-19 15:10:40 -04:00
netkas
d59f5fb6e0 Updated Symfony/Yaml to version 7.1.4 2024-09-19 15:06:13 -04:00
netkas
4e174821fc Updated CHANGELOG.md 2024-09-19 14:23:00 -04:00
netkas
c7b007c704 Refactor project constants handling in NccCompiler 2024-09-19 14:17:16 -04:00
netkas
272fc8524e Fixed version filtering and sorting in PackagistRepository 2024-09-19 13:52:20 -04:00
netkas
5e173b7cc0 Fix case sensitivity for "Semver" in paths and package name 2024-09-19 13:45:33 -04:00
netkas
91a25390fa Rename 'semver' directory to 'Semver' in composer package 2024-09-19 13:43:08 -04:00
netkas
bcb26d1eec Updated Composer/Semver to 3.4.3 2024-09-19 13:29:02 -04:00
netkas
1389b61fa2 Add support for runtime constants 2024-09-19 13:16:58 -04:00
netkas
16ad69b9f2 Remove RuntimeInterface.php 2024-09-19 01:02:08 -04:00
netkas
3aedd2d94d Remove ComponentFileExtensions enum 2024-09-19 00:57:52 -04:00
netkas
b2d2a1ea15 Simplify optional type value retrieval 2024-09-19 00:50:00 -04:00
netkas
604e1fd3e7 Update PHP language level to 8.3 2024-09-19 00:41:39 -04:00
netkas
3950655024 Remove PACKAGE_LOCK_VERSION constant from Versions enum 2024-09-19 00:41:31 -04:00
netkas
da8a6fac01 Update repository type handling in verbose output 2024-09-19 00:31:57 -04:00
netkas
943048785d Refactor Console color formatting 2024-09-19 00:19:06 -04:00
netkas
bdcf5160de Update Console color formatting method 2024-09-19 00:17:49 -04:00
netkas
46fd39c51c Improve error messages in Repository configuration 2024-09-18 15:30:44 -04:00
netkas
8e6acbbc70 Handle missing 'file' in stack trace 2024-09-18 15:28:53 -04:00
netkas
3adc1b81fb Improve error handling for compiler extensions 2024-09-18 15:20:04 -04:00
netkas
3160ddfa27 Refactor type handling for CompilerExtensions and RepositoryType 2024-09-18 15:18:07 -04:00
netkas
ae8021bb3a Fix misplacement of accessor in PackageReader declarations 2024-09-18 15:17:53 -04:00
netkas
b6cdb2a78c Add ResolverTest for parseArguments method 2024-09-18 14:07:08 -04:00
netkas
3e8af9c43c Remove max_arguments from parseArguments 2024-09-18 14:05:26 -04:00
netkas
e5ceb9bbf7 Add unit tests for Security class filename sanitization 2024-09-18 14:01:57 -04:00
netkas
bcefb6c56a Add unit tests for Validate utility methods 2024-09-18 13:54:36 -04:00
netkas
3c1286d9c2 Refactor regex pattern for CONSTANT_NAME 2024-09-18 13:54:26 -04:00
netkas
d8247b0760 Remove unused import and redundant scope validation method 2024-09-18 13:54:17 -04:00
netkas
68cfed8a05 Refactor authentication type handling 2024-09-18 13:36:08 -04:00
netkas
04a85900fd Removed unused methods from Validate.php 2024-09-18 13:10:24 -04:00
netkas
836d0f33eb Validate and enforce repository type enum usage 2024-09-18 00:54:12 -04:00
netkas
ffc6588ff9 Refactor component data type handling in setData method. 2024-09-18 00:50:27 -04:00
netkas
0afc45f300 Added ComponentTest.php 2024-09-17 22:17:43 -04:00
netkas
61158ff802 Added PhpUnit configuration 2024-09-17 22:17:41 -04:00
netkas
ad9e406657 Updated .gitignore 2024-09-17 22:17:04 -04:00
netkas
27c79b1170 Refactor Component class to use ComponentDataType enum 2024-09-17 22:16:48 -04:00
netkas
7e224d91b2 Removed todos (for now) 2024-09-17 22:08:55 -04:00
netkas
d0e484631f Refactor ProjectType handling 2024-09-17 22:08:23 -04:00
netkas
1bcfe90bea Updated Symfony/Filesystem from version 6.3.1 to 7.1.2 2024-09-17 19:26:23 -04:00
netkas
e624663f62 Refactor log level checking to enum method 2024-09-17 19:20:18 -04:00
netkas
8b64a48a5f Refactor log level parsing with enum method 2024-09-17 19:14:49 -04:00
netkas
24e67061f1 Added TODO 2024-09-17 15:38:16 -04:00
netkas
6398b2958b Refactor logging level checks to use LogLevel enum directly 2024-09-17 15:35:20 -04:00
netkas
5ea0235515 Update PHP include paths in project configuration 2024-09-17 15:29:54 -04:00
netkas
b291604145 Fix incorrect color formatting in installer output 2024-09-17 15:29:44 -04:00
netkas
714228ad2e Refactor code to improve readability in Resolver.php 2024-09-17 15:29:30 -04:00
netkas
aa65dd73cf Refactor checkLogLevel to correctly utilize LogLevel cases 2024-09-17 15:29:03 -04:00
netkas
dfa6b50299 Bumped version 2024-09-17 15:28:15 -04:00
netkas
8f87541a64 Refactor flag handling to use PackageFlags enum directly
Updated the NccCompiler and PackageWriter classes to utilize the PackageFlags enum directly rather than its values. This improves type safety and code readability, reducing the chances of runtime errors associated with invalid flag values.
2024-09-17 15:10:19 -04:00
6482d06ba2 Fixed Division by zero in PackageManager 2024-09-14 09:08:21 -04:00
9fe2dc48fe Updated CHANGELOG.md 2024-09-14 09:03:15 -04:00
039147c8a8 Convert ComponentFlags constants to enum cases 2024-09-14 08:58:26 -04:00
863dffafe7 Convert NccBuildFlags constants to enum cases 2024-09-14 08:57:21 -04:00
0c4ef17bbf Convert PackageFlags constants to enum cases 2024-09-14 08:56:40 -04:00
ac81f2f26d Convert CompressionOptions constants to enum cases 2024-09-14 08:54:14 -04:00
66e6e1528d Convert BuildConfigurationOptions constants to enum cases 2024-09-14 08:53:30 -04:00
c24fce2ee5 Convert BuildConfigurationValues constants to enum cases 2024-09-14 08:49:53 -04:00
ae21d98290 Minor corrections for illegal array key type 2024-09-14 08:45:42 -04:00
d379956437 Convert ComponentDecodeOptions constants to enum cases 2024-09-14 08:44:06 -04:00
2bd2d757fd Convert InitializeProjectOptions constants to enum cases 2024-09-14 08:43:07 -04:00
87844ab00a Convert InstallPackageOptions constants to enum cases 2024-09-14 08:41:25 -04:00
ec6b368a82 Convert ProjectOptions constants to enum cases 2024-09-14 08:39:05 -04:00
2efa6654e6 Removed RuntimeImportOptions 2024-09-14 08:38:10 -04:00
21c2405a27 Convert AssemblyConstants constants to enum cases 2024-09-14 08:37:53 -04:00
87a8ca24a1 Convert BuildConstants constants to enum cases 2024-09-14 08:35:16 -04:00
492548d81f Convert DateTimeConstants constants to enum cases 2024-09-14 08:34:34 -04:00
9c06378258 Convert InstallConstants constants to enum cases 2024-09-14 08:33:13 -04:00
0d9f3d37a3 Convert RuntimeConstants constants to enum cases 2024-09-14 08:32:13 -04:00
e02f1f56dc Convert AuthenticationType constants to enum cases 2024-09-14 08:30:41 -04:00
12f0ff2ffa Convert BuildOutputType constants to enum cases 2024-09-14 08:28:04 -04:00
e11f95a22a Removed BuiltinRemoteSourceType 2024-09-14 08:26:30 -04:00
fd928ffc99 Convert ComponentDataType constants to enum cases 2024-09-14 08:26:16 -04:00
3db33006b7 Convert ComposerPackageTypes constants to enum cases 2024-09-14 08:24:19 -04:00
b5d35ed20e Convert ComposerStabilityTypes constants to enum cases 2024-09-14 08:23:29 -04:00
a2149cdb66 Removed DependencySourceType 2024-09-14 08:22:40 -04:00
28ff80dd41 Convert HttpRequestType constants to enum cases 2024-09-14 08:22:25 -04:00
86cf7467af Convert ProjectType constants to enum cases 2024-09-14 08:19:50 -04:00
3d44562241 Removed RemoteSourceType 2024-09-14 08:18:34 -04:00
5b24fe267d Convert RepositoryResultType constants to enum cases 2024-09-14 08:17:45 -04:00
14ec2e06b2 Added TODO 2024-09-14 00:41:27 -04:00
71ffed1a3f Convert RepositoryType constants to enum cases 2024-09-14 00:40:59 -04:00
d884d0fbda Convert CompilerExtensions constants to enum cases 2024-09-14 00:39:18 -04:00
baf11f5cb9 Convert ConsoleColors constants to enum cases 2024-09-14 00:37:03 -04:00
e1013f6c15 Convert ExceptionCodes constants to enum cases 2024-09-14 00:34:12 -04:00
718c6ff8d8 Convert FileDescriptor constants to enum cases 2024-09-14 00:31:43 -04:00
5dd98083d6 Convert LogLevel constants to enum cases 2024-09-14 00:30:05 -04:00
d612c67cb0 Convert PackageDirectory constants to enum cases 2024-09-14 00:24:49 -04:00
42473390e8 Removed CompilerExtensionDefaultVersions.php 2024-09-14 00:20:59 -04:00
cfc93aa066 Removed HttpStatusCodes.php 2024-09-14 00:20:46 -04:00
91103c1470 Removed ConstantReferences.php 2024-09-14 00:20:28 -04:00
9885d98b55 Removed PackageStandardVersions.php 2024-09-14 00:20:10 -04:00
321fef4228 Convert PackageStructure constants to enum cases 2024-09-14 00:19:53 -04:00
c687d0394d Convert PackageStructureVersions constants to enum cases 2024-09-14 00:13:43 -04:00
2a16b2de6b Convert ProjectTemplates constants to enum cases 2024-09-14 00:12:55 -04:00
e98b949b7d Convert RegexPatterns constants to enum cases 2024-09-13 13:38:48 -04:00
7e5cdf4d64 Removed EncoderType enum file, unused. 2024-09-13 13:34:40 -04:00
90535a3a35 Updated CHANGELOG.md 2024-09-13 13:31:37 -04:00
69de79ccf4 Convert Runners class to enum with string cases 2024-09-13 13:29:40 -04:00
7c9f63955a Update Scopes to enum and adjust scope checks 2024-09-13 13:26:54 -04:00
1ba50cc7ee Convert Versions constants to enum cases 2024-09-13 13:20:12 -04:00
f9047dd0d0 Bumped version to 2.1.0 2024-09-13 13:12:14 -04:00
a65b76b6bf
Updated CHANGELOG.md 2023-10-25 22:02:26 -04:00
957d9a9510
Added the ability to use 'all' as a build configuration when running ncc build, to build all build configurations
in the project.

The build command in ncc has been updated to accept 'all' as a build configuration which prompts the build of all configurations in the project. Previously, builds had to be triggered for each individual configurations. This change simplifies the build process especially for projects with multiple configurations, making the process more efficient and less prone to human error.
2023-10-25 22:00:37 -04:00
d2635b19fd
Fixed issue when creating a shadow copy of a package, if the universe aligns together and the cosmos unit together to
produce a package length exactly to where the end-of-package byte sequence is cut in half, the shadow copy will fail
   to be created due to the end-of-package byte sequence being cut in half, this issue was fixed by reading the package
   in chunks to determine the end-of-package byte sequence.

The PackageReader class has been updated to use a more efficient buffer management when reading data from a file. Previously, buffer size was growing uncontrollably and can eventually lead to out-of-memory errors for large files.

Now, the data is read in chunks and the buffer is cleared when it exceeds approximately 1MB size, maintaining only the last 512KB. This change ensures a more memory-efficient package reading and effectively prevents erroneous deadlocks for large package files.

Additionally, detection for end-of-data byte sequence has been modified to rectify an issue where package length could cut off the end-of-package byte sequence. This results in an improved reliability for package validation.
2023-10-25 21:40:42 -04:00
76f12bb0a3
Fixed issue where all development dependencies were not correctly being added to debug builds in composer projects,
instead these dependencies were added globally to the build configuration. This issue was fixed by adding all the
   development dependencies to the debug build configurations only.

This commit revises the handling of composer dependencies in 'ProjectManager.php'. A problem was encountered where software development dependencies were added globally to the build configuration, rather than exclusively to debug builds. By reassigning these dependencies to the debug configuration, this issue has been remedied.

Additionally, a bug-fix in 'PackageReader.php' has been implemented to validate the package file by checking the data length. If the file is discovered to be invalid (data length is null or zero), an IOException is triggered.

These changes enhance the accuracy of dependency management and improve the robustness of package validation.
2023-10-25 17:57:51 -04:00
7befd995e7
Added host resolving in network calls to improve the handling of invalid or unreachable URLs
The 'Resolver' utility was utilized to resolve the host and cache the result, enhancing the robustness and efficiency of the network calling mechanism across different modules including PackageManager, GiteaRepository, GithubRepository, and others.
2023-10-25 15:08:58 -04:00
b2234d5040
Updated the Download function to attempt to retry the download upon an error for at least 3 times.
Updated the downloadFile function in PackageManager.php to retry the download upon an error for at least 3 times. This improvement on error handling will enhance the resilience of the download process, reducing the likelihood of a single network hiccup resulting in a failed download. This change has also been reflected in the CHANGELOG.md file.
2023-10-25 14:33:42 -04:00
27d1609b23
Added Project.xml 2023-10-25 14:00:46 -04:00
de1e199dff
Fixed issue where a newline is sometimes added to the end of a download output due to how short the download process was, mitigated the issue by enforcing a "done" update at the end of the download process
A fix has been implemented for an issue where a newline was unintentionally added to the end of download output, mostly when the download process was too short. This has been mitigated by ensuring a "done" update whenever a download finishes.

At the same time, improvements have been made to the download progress output. Specifically, the downloaded size now won't exceed the total download size, and a definitive "100%" progress indication is enforced when the download ends.
2023-10-25 14:00:24 -04:00
aa6800e96a
Correction 2023-10-24 16:41:41 -04:00
a2cd98ba98
Updated exception handling in PackageReader
Optimized exception handling in PackageReader class by replacing NotSupportedException with IntegrityException. The update aligns with the objective of more accurate error handling and reporting during ZiProto decoding. The new IntegrityException provides a detailed error message, facilitating easier debugging.
2023-10-24 16:28:10 -04:00
27baeca112
Set default process timeouts to null
This commit sets the default timeout and idleTimeout for the execution process in ExecutionUnitRunner to null when there are no specific timeouts provided by the execution policy. This change was made to avoid unexpected timeouts when no specific values are set in the execution policy.
2023-10-24 16:07:48 -04:00
4f7aa7a859
Update progress bar text to display basename only
Modified the progress bar text display in PackageManager.php and NccCompiler.php classes. Changed 'setMiscText' function to now display only the basename of the component name, execution policy name, and resource name. This change improves readability and clarity of the progress bar by reducing clutter from long file paths.
2023-10-24 16:05:40 -04:00
3ebdeb0cba
Fixed issue where progress bar is displayed in VERBOSE mode
Added checks in the update method of the ConsoleProgressBar class to prevent it from displaying when log level is set to VERBOSE. This is to prevent cluttering the command-line interface with unnecessary information when running in VERBOSE mode. The changes also are reflected in the changelog.
2023-10-22 22:16:33 -04:00
bcc6f45eb4
Fix division by zero in ConsoleProgressBar
The rendering of the progress bar was causing a division by zero error when the maximum value was set to 0. This change adds a condition to check if the maximum value is not 0 before calculating the number of hashes and the percentage done in the progress bar. This avoids the division by zero error and makes the progress bar rendering more robust. The CHANGELOG.md file has also been updated to reflect this bug fix.
2023-10-22 19:26:16 -04:00
698d2e7a1f
Updated file tracking in Runtime class
Implemented changes in Runtime.php to better handle file tracking and to prevent unnecessary inclusion of duplicate files during Runtime. Instead of directly checking if a file is already included, we now create a unique identifier for each file using a crc32 hash function. This identifier (instead of the file path) is checked and stored in the inclusion list, allowing for better handling of dynamic or virtual files.
2023-10-18 16:03:40 -04:00
89d3af8680
Improve build efficiency by preventing duplicate merges
Introduced a private property to the `NccCompiler` class, `$merged_dependencies`, to keep track of the dependencies that have already been merged. This prevents unnecessary re-merging during the build operation, potentially enhancing the efficiency of the process. The implementation involves a check for a preexisting merge before a new merge is performed. If a merge already exists, the process is skipped, thereby avoiding redundancies.
2023-10-18 15:56:24 -04:00
12d7744e1e
Bumped version to 2.0.4 2023-10-18 15:49:16 -04:00
a76a8a4ae6
Updated CHANGELOG.md 2023-10-17 21:44:22 -04:00
7293519ba3
Add error handling for unspecified package in PackageManagerMenu 2023-10-17 21:27:40 -04:00
2605b8d218
- Added new ConsoleProgressBar class for UI improvement, imrpoved the CLI Progress Bar inspired by
[pacman](https://wiki.archlinux.org/title/pacman)
2023-10-17 21:23:05 -04:00
173032df72
- Fixed issue when registering ncc's extension, when using the INSTALLER, the installation path used in the process
appears to be incorrect, added a optional parameter to the `registerExtension` method to allow the installer to pass
   the correct installation path.
 - Implemented support in the AST traversal for the PHP statements `include`, `include_once`, `require`, and
   `require_once`. These statements are transformed into function calls. With this change, ncc can correctly handle and
   import files from system packages or direct binary package files.
2023-10-17 17:01:40 -04:00
c736a896fb
When finding package versions in the package lock, ncc will try to find a satisfying version rather than the exact version, this is to prevent errors when the package lock contains a version that is not available in the repository. 2023-10-13 09:41:39 -04:00
930c206fa9
Bumped version to 2.0.3 2023-10-13 02:33:12 -04:00
4c6f2ddcfe
Updated CHANGELOG.md 2023-10-13 01:32:34 -04:00
d434345c59
Minor corrections 2023-10-13 01:32:21 -04:00
e3ac3cf7a3
Updated CHANGELOG.md 2023-10-12 16:34:21 -04:00
81ea985b68
Updated CHANGELOG.md 2023-10-12 16:27:07 -04:00
71214e769e
Refactor ncc extension registration logic, this also allows for debian packages to install the ncc extension automatically.
The logic related to the registration of the ncc extension has been refactored. Previously, the code that registered the ncc extension was contained in the installer. However, this change moves the code that registers the ncc extension from the installer to the Utilities/Functions class. This change was made because the extension registration is not only applicable to the installer, but is also required for several other components. This fact justified the need for the logic to be located in a more generic and accessible class. The Makefile, installer, generate_build_files.php files have been updated to reflect this change. Components using these should now work properly with the changes.
2023-10-12 16:24:36 -04:00
89b0c931b9
Fixed incorrect mime type in ncc-package.xml
This update addresses a mistake in the `ncc-package.xml` file, where the wrong mime type was specified. The mime type has been corrected from `application/ncc-package` to `application/ncc` and the glob pattern from `*.ncc_pkg` to `*.ncc`. This change will ensure proper recognition and handling of the file type.
2023-10-12 15:59:58 -04:00
4ef923b83c
- Fixed issue where some build artifacts are being bundled with package builds such as output_path and static
where they should not be included in the package.
 - Added the ability to pull static versions of packages from repositories where package names ending with `-static.ncc`
   or `_static.ncc` can be pulled if you use the `--prefer-static` or `--static` option when using the `package install`
   command. Otherwise, the normal package will be installed, avoiding static versions.
 - Added support for importing static packages from the system, allowing you to install static packages onto your
   system and import them without importing additional dependencies that isn't already included in the package.
2023-10-12 15:55:10 -04:00
e4a3dc2f99
Updated CHANGELOG.md 2023-10-11 20:23:45 -04:00
d9b30a755d
Update dependencies import in \ncc\Classes > Runtime > importFromPackage()
Moved the recursive import of dependencies inside an else statement to provide a condition for fake importing dependencies. This change offers an effective way to handle static dependencies. It enhances the robustness of the package reading and dependency import process.
2023-10-11 20:22:07 -04:00
ff5a6c7f7a
Updated CHANGELOG.md 2023-10-11 19:06:46 -04:00
21753364dc
Updated fetchPackage method to include authentication 2023-10-11 19:04:36 -04:00
345a215a56
Bumped version to 2.0.2 2023-10-11 18:59:09 -04:00
518 changed files with 18043 additions and 12918 deletions

136
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,136 @@
name: CI Pipeline
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
release:
types:
- created
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, ctype, common, zip
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y git libpq-dev libzip-dev zip make wget gnupg
- 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
sudo mv phive.phar /usr/local/bin/phive
- name: Install PHPAB
run: sudo phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Build project
run: make redist
- name: Find NCC build directory
id: find-ncc-dir
run: echo "NCC_DIR=$(find build/ -type d -name 'ncc_*' | head -n 1)" >> $GITHUB_ENV
- name: Upload NCC build directory
uses: actions/upload-artifact@v3
with:
name: ncc-build
path: ${{ env.NCC_DIR }}
- name: Create redist.zip
run: zip -r redist.zip ${{ env.NCC_DIR }}
- name: Upload redist.zip
uses: actions/upload-artifact@v3
with:
name: redist-zip
path: redist.zip
- name: Build Debian package
run: make deb
- name: Find Debian package
id: find-deb
run: echo "DEB_FILE=$(find build/ -type f -name '*.deb' | head -n 1)" >> $GITHUB_ENV
- name: Upload Debian package
uses: actions/upload-artifact@v3
with:
name: ncc-deb
path: ${{ env.DEB_FILE }}
test-install:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download NCC build directory
uses: actions/download-artifact@v3
with:
name: ncc-build
path: build
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, ctype, common, zip
- name: Test NCC installation
run: |
ls -l build
sudo php build/INSTALL --auto
upload-release:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'release' && github.event.action == 'created'
permissions: write-all
steps:
- name: Download redist.zip
uses: actions/download-artifact@v3
with:
name: redist-zip
path: .
- name: Download Debian package
uses: actions/download-artifact@v3
with:
name: ncc-deb
path: .
- name: Set DEB_FILE environment variable
run: echo "DEB_FILE=$(find . -type f -name '*.deb' | head -n 1)" >> $GITHUB_ENV
- name: Upload redist.zip to release
uses: softprops/action-gh-release@v1
with:
files: redist.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload ncc.deb to release
uses: softprops/action-gh-release@v1
with:
files: ${{ env.DEB_FILE }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

7
.gitignore vendored
View file

@ -8,7 +8,7 @@
build
# Autoload files
src/ncc/ThirdParty/composer/semver/autoload_spl.php
src/ncc/ThirdParty/composer/Semver/autoload_spl.php
src/ncc/ThirdParty/defuse/php-encryption/autoload_spl.php
src/ncc/ThirdParty/jelix/version/autoload_spl.php
src/ncc/ThirdParty/nikic/PhpParser/autoload_spl.php
@ -28,4 +28,7 @@ src/ncc/autoload.php
# Test files
tests/example_project/project.json
tests/example_project/ncc
tests/example_project/build
tests/example_project/build
/.phpunit.result.cache
/.idea/php-test-framework.xml
/.idea/gbrowser_project.xml

7
.idea/codeStyles/Project.xml generated Normal file
View file

@ -0,0 +1,7 @@
<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>

8
.idea/php.xml generated
View file

@ -12,10 +12,9 @@
<component name="PhpIncludePathManager">
<include_path>
<path value="/usr/share/php" />
<path value="$PROJECT_DIR$/../loglib" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.2">
<component name="PhpProjectSharedConfiguration" php_language_level="8.3">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpRuntimeConfiguration">
@ -26,6 +25,11 @@
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings load_method="PHPUNIT_PHAR" custom_loader_path="" phpunit_phar_path="$USER_HOME$/phpunit.phar" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>

View file

@ -5,6 +5,219 @@ 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/),
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
This update introduces a refactored code-base, code quality improvements, and better exception handling.
### Added
- Added Test unit tests/ncc/Objects/Package/ComponentTest.php
- Added Test unit tests/ncc/Utilities/ResolverTest.php
- Added Test unit tests/ncc/Utilities/SecurityTest.php
- Added Test unit tests/ncc/Utilities/ValidateTest.php
- Add support for runtime constants
### Changed
- Convert Versions constants to enum cases
- Update Scopes to enum and adjust scope checks
- Convert Runners class to enum with string cases
- Convert RegexPatterns constants to enum cases
- Convert ProjectTemplates constants to enum cases
- Convert PackageStructureVersions constants to enum cases
- Convert PackageStructure constants to enum cases
- Convert PackageDirectory constants to enum cases
- Convert LogLevel constants to enum cases
- Convert FileDescriptor constants to enum cases
- Convert ExceptionCodes constants to enum cases
- Convert ConsoleColors constants to enum cases
- Convert CompilerExtensions constants to enum cases
- Convert RepositoryType constants to enum cases
- Convert RepositoryResultType constants to enum cases
- Convert ProjectType constants to enum cases
- Convert HttpRequestType constants to enum cases
- Convert ComposerStabilityTypes constants to enum cases
- Convert ComposerPackageTypes constants to enum cases
- Convert ComponentDataType constants to enum cases
- Convert BuildOutputType constants to enum cases
- Convert AuthenticationType constants to enum cases
- Convert RuntimeConstants constants to enum cases
- Convert InstallConstants constants to enum cases
- Convert DateTimeConstants constants to enum cases
- Convert BuildConstants constants to enum cases
- Convert AssemblyConstants constants to enum cases
- Convert ProjectOptions constants to enum cases
- Convert InstallPackageOptions constants to enum cases
- Convert InitializeProjectOptions constants to enum cases
- Convert ComponentDecodeOptions constants to enum cases
- Convert BuildConfigurationValues constants to enum cases
- Convert BuildConfigurationOptions constants to enum cases
- Convert CompressionOptions constants to enum cases
- Convert PackageFlags constants to enum cases
- Convert NccBuildFlags constants to enum cases
- Convert ComponentFlags constants to enum cases
- Refactor flag handling to use PackageFlags enum directly
- Refactor checkLogLevel to correctly utilize LogLevel cases
- Refactor code to improve readability in Resolver.php
- Update PHP include paths in project configuration
- Refactor logging level checks to use LogLevel enum directly
- Refactor log level parsing with enum method
- Refactor log level checking to enum method
- Updated Symfony/Filesystem from version 6.3.1 to 7.1.2
- Refactor ProjectType handling
- Validate and enforce repository type enum usage
- Updated Composer/Semver to 3.4.3
- Rename 'semver' directory to 'Semver' in composer package
- Refactor project constants handling in NccCompiler
- Updated Symfony/Yaml to version 7.1.4
- Updated Symfony/Uid to version 7.1.4
- Updated Symfony/Process to version 7.1.3
- Updated Symfony/polyfill-ctype to version 1.31.0
- Updated Symfony/polyfill-mbstring to version 1.31.0
- Updated Symfony/polyfill-uuid to version 1.31.0
- Updated nikic/PhpParser to version 5.2.0
### Fixed
- Fixed Division by zero in PackageManager
- Fixed runner argument passing for ExecCommand
### Removed
- Removed EncoderType enum file, unused.
- Removed PackageStandardVersions.php
- Removed ConstantReferences.php
- Removed HttpStatusCodes.php
- Removed CompilerExtensionDefaultVersions.php
- Removed RemoteSourceType
- Removed DependencySourceType
- Removed BuiltinRemoteSourceType
- Removed RuntimeImportOptions
- Remove ComponentFileExtensions enum
- Remove unused import and redundant scope validation method
## [2.0.3] - 2023-10-17
This update includes enhanced support for PHP statements in AST traversal, a friendly CLI Progress Bar, and fixes
related to package version searching, ncc's extension registration, and error handling in PackageManagerMenu.
The changes improve the system's efficiency, error resilience, and user experience.
### Added
- Implemented support in the AST traversal for the PHP statements `include`, `include_once`, `require`, and
`require_once`. These statements are transformed into function calls. With this change, ncc can correctly handle and
import files from system packages or direct binary package files.
- Added new `ConsoleProgressBar` class for UI improvement, imrpoved the CLI Progress Bar inspired by
[pacman](https://wiki.archlinux.org/title/pacman)
### Fixed
- When finding package versions in the package lock, ncc will try to find a satisfying version rather than the exact
version, this is to prevent[CHANGELOG.md](CHANGELOG.md) errors when the package lock contains a version that is not available in the repository.
- Fixed issue when registering ncc's extension, when using the INSTALLER, the installation path used in the process
appears to be incorrect, added a optional parameter to the `registerExtension` method to allow the installer to pass
the correct installation path.
- Add error handling for unspecified package in PackageManagerMenu
## [2.0.2] - 2023-10-13
In this new update, the software introduces a feature for importing static packages without extra dependencies and
supports pulling static versions of packages from repositories. Changes include enhanced security through an updated
fetchPackage method along with improvements in dependency imports and extension registration logic for Debian packages.
Finally, bugs related to unnecessary bundling of some build artifacts and mime type errors in ncc-package.xml have
been fixed.
### Added
- Added support for importing static packages from the system, allowing you to install static packages onto your
system and import them without importing additional dependencies that isn't already included in the package.
- Added the ability to pull static versions of packages from repositories where package names ending with `-static.ncc`
or `_static.ncc` can be pulled if you use the `--prefer-static` or `--static` option when using the `package install`
command. Otherwise, the normal package will be installed, avoiding static versions.
### Changed
- Updated fetchPackage method to include authentication
- Update dependencies import in \ncc\Classes > Runtime > importFromPackage()
- Refactor ncc extension registration logic, this also allows for debian packages to install the ncc extension
automatically.
### Fixed
- Fixed issue where some build artifacts are being bundled with package builds such as `output_path` and `static`
where they should not be included in the package.
- Corrected mistakes in `ncc-package.xml` mime type
## [2.0.1] - 2023-10-11
Added a new feature in `ProjectManager.php` that allows automatic installation of a project's dependencies. The

View file

@ -65,7 +65,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions && sync && \
install-php-extensions zip xsl
# Install ncc
RUN php INSTALL --auto; cd ../; rm -rf ncc
RUN php INSTALL --auto
# Finalize image
RUN mkdir /app

View file

@ -65,7 +65,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions && sync && \
install-php-extensions zip xsl
# Install ncc
RUN php INSTALL --auto; cd ../; rm -rf ncc
RUN php INSTALL --auto
# Finalize image
RUN mkdir /app

View file

@ -18,23 +18,23 @@ DEBIAN_PACKAGE_BUILD_PATH := $(BUILD_PATH)/ncc_$(BUILD_VERSION)_all.deb
# List of paths for autoloading
AUTOLOAD_PATHS := $(addprefix $(SRC_PATH)/ncc/ThirdParty/, \
composer/semver \
defuse/php-encryption \
jelix/version \
nikic/PhpParser \
Symfony/polyfill_ctype \
Symfony/polyfill_mbstring \
Symfony/polyfill_uuid \
Symfony/Process \
Symfony/Uid \
Symfony/Filesystem \
Symfony/Yaml \
theseer/DirectoryScanner \
composer/Semver \
defuse/php-encryption \
jelix/version \
nikic/PhpParser \
Symfony/polyfill_ctype \
Symfony/polyfill_mbstring \
Symfony/polyfill_uuid \
Symfony/Process \
Symfony/Uid \
Symfony/Filesystem \
Symfony/Yaml \
theseer/DirectoryScanner \
)
# Check for necessary binaries
ifndef PHPCC
$(error "PHP binary not found. Please install PHP or check your PATH")
$(error "PHP binary not found. Please install PHP or check your PATH")
endif
# Check if phpab is installed
@ -76,7 +76,6 @@ redist: autoload
cp -f $(CONFIG_PATH)/ncc.yaml $(GENERIC_BUILD_PATH)/CLI/template_config.yaml
cp -f $(CONFIG_PATH)/default_repositories.json $(GENERIC_BUILD_PATH)/default_repositories.json
cp -f $(INSTALLER_SRC_PATH)/ncc-package.xml $(GENERIC_BUILD_PATH)/ncc-package.xml
cp -f $(INSTALLER_SRC_PATH)/extension $(GENERIC_BUILD_PATH)/extension
chmod +x $(GENERIC_BUILD_PATH)/INSTALL
cp -f LICENSE $(GENERIC_BUILD_PATH)/LICENSE
cp -f README.md $(GENERIC_BUILD_PATH)/README.md
@ -154,13 +153,13 @@ clean:
.PHONY: help
help:
@echo "Available commands:"
@echo " make autoload - Generate autoload files"
@echo " make redist - Prepare the project for redistribution"
@echo " make install - Installs ncc on the system (requires root privileges & php)"
@echo " make tar - Package the project into a tarball (Generic installer, requires php)"
@echo " make deb - Package the project into a Debian package"
@echo " make docker-debian - Build a Debian Docker image"
@echo " make autoload - Generate autoload files"
@echo " make redist - Prepare the project for redistribution"
@echo " make install - Installs ncc on the system (requires root privileges & php)"
@echo " make tar - Package the project into a tarball (Generic installer, requires php)"
@echo " make deb - Package the project into a Debian package"
@echo " make docker-debian - Build a Debian Docker image"
@echo " make docker-debian-run - Run the Debian Docker image"
@echo " make docker-alpine - Build an Alpine Docker image"
@echo " make docker-alpine - Build an Alpine Docker image"
@echo " make docker-alpine-run - Run the Alpine Docker image"
@echo " make clean - Clean the build artifacts"
@echo " make clean - Clean the build artifacts"

9
bootstrap.php Normal file
View file

@ -0,0 +1,9 @@
<?php
$autoload_path = __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'ncc' . DIRECTORY_SEPARATOR . 'autoload.php';
if(!file_exists($autoload_path))
{
throw new Exception("Autoload file not found");
}
require $autoload_path;

11
phpunit.xml Normal file
View file

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

View file

@ -13,7 +13,7 @@
$third_party_path = __DIR__ . DIRECTORY_SEPARATOR . 'ThirdParty' . DIRECTORY_SEPARATOR;
$target_files = [
__DIR__ . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'composer' . DIRECTORY_SEPARATOR . 'semver' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'composer' . DIRECTORY_SEPARATOR . 'Semver' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'defuse' . DIRECTORY_SEPARATOR . 'php-encryption' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'jelix' . DIRECTORY_SEPARATOR . 'version' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'nikic' . DIRECTORY_SEPARATOR . 'PhpParser' . DIRECTORY_SEPARATOR . 'autoload_spl.php',

View file

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

View file

@ -41,8 +41,7 @@
'installer',
'checksum.bin',
'build_files',
'ncc.sh',
'extension'
'ncc.sh'
];
ncc\Utilities\Console::out('Creating build_files ...');

View file

@ -242,23 +242,6 @@
$NCC_FILESYSTEM->mkdir($NCC_INSTALL_PATH, 0755);
try
{
if(is_file(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json'))
{
Functions::initializeFiles(Functions::loadJsonFile(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json', Functions::FORCE_ARRAY));
}
else
{
Functions::initializeFiles();
}
}
catch(Exception $e)
{
Console::outException('Cannot initialize NCC files, ' . $e->getMessage(), $e, 1);
return;
}
// Copy files to the installation path
try
{
@ -272,10 +255,12 @@
}
$total_items = count($build_files);
$processed_items = 1;
//$processed_items = 1;
$progress_bar = new \ncc\Utilities\ConsoleProgressBar('Installing ncc', $total_items);
foreach ($build_files as $item)
{
$progress_bar->setMiscText($item, true);
$source = __DIR__ . DIRECTORY_SEPARATOR . $item;
$destination = $NCC_INSTALL_PATH . DIRECTORY_SEPARATOR . $item;
@ -298,8 +283,30 @@
}
}
++$processed_items;
Console::inlineProgressBar($processed_items, $total_items);
//++$processed_items;
//Console::inlineProgressBar($processed_items, $total_items);
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
// Initialize ncc's files
try
{
if(is_file(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json'))
{
Functions::initializeFiles($NCC_INSTALL_PATH, Functions::loadJsonFile(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json', Functions::FORCE_ARRAY));
}
else
{
Functions::initializeFiles($NCC_INSTALL_PATH);
}
}
catch(Exception $e)
{
Console::outException('Cannot initialize NCC files, ' . $e->getMessage(), $e, 1);
return;
}
@ -345,83 +352,6 @@
}
}
// Register the ncc extension
try
{
Console::out('Registering extension');
$extension_shortcut = str_ireplace('%ncc_install', $NCC_INSTALL_PATH, IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'extension'));
}
catch(Exception $e)
{
Console::outException(sprintf('Failed to read file \'%s\', %s', __DIR__ . DIRECTORY_SEPARATOR . 'extension', $e->getMessage()), $e, 1);
return;
}
// Remove all the old extensions first.
/**
* @param string $path
* @param Filesystem $filesystem
* @param string $extension_shortcut
* @return bool
*/
function install_extension(string $path, Filesystem $filesystem, string $extension_shortcut): bool
{
if ($filesystem->exists($path . DIRECTORY_SEPARATOR . 'ncc'))
{
$filesystem->remove($path . DIRECTORY_SEPARATOR . 'ncc');
}
try
{
IO::fwrite($path . DIRECTORY_SEPARATOR . 'ncc', $extension_shortcut);
}
catch (\ncc\Exceptions\IOException $e)
{
Console::outException($e->getMessage(), $e, 1);
return false;
}
return $filesystem->exists($path . DIRECTORY_SEPARATOR . 'ncc');
}
if(function_exists('get_include_path'))
{
$default_share = DIRECTORY_SEPARATOR . 'usr' . DIRECTORY_SEPARATOR . 'share' . DIRECTORY_SEPARATOR . 'php';
$include_paths = explode(':', get_include_path());
$extension_registered = false;
if(!in_array($default_share, $include_paths))
{
foreach($include_paths as $path)
{
if($extension_registered)
{
break;
}
switch($path)
{
// Ignore local files
case '.':
case '..':
break;
// First real include path is /usr/share/php
default:
// Install the extension
$extension_registered = install_extension($path, $NCC_FILESYSTEM, $extension_shortcut);
break;
}
}
}
else
{
// Remove the old extension
install_extension($default_share, $NCC_FILESYSTEM, $extension_shortcut);
}
}
// Backup the configuration file
$config_backup = null;

View file

@ -21,11 +21,11 @@
-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/ncc-package">
<mime-type type="application/ncc">
<comment>ncc package binary</comment>
<magic priority="50">
<match type="string" value="ncc_pkg" offset="0"/>
</magic>
<glob pattern="*.ncc_pkg"/>
<glob pattern="*.ncc"/>
</mime-type>
</mime-info>

View file

@ -75,7 +75,7 @@
if($output_path !== null)
{
$options[BuildConfigurationOptions::OUTPUT_FILE] = $output_path;
$options[BuildConfigurationOptions::OUTPUT_FILE->value] = $output_path;
}
// Load the project
@ -92,7 +92,7 @@
// Build the project
try
{
$build_configuration = $args['config'] ?? $args['c'] ?? BuildConfigurationValues::DEFAULT;
$build_configuration = $args['config'] ?? $args['c'] ?? BuildConfigurationValues::DEFAULT->value;
$output = $project_manager->build($build_configuration, $options);
}
catch (Exception $e)

View file

@ -24,9 +24,11 @@
use Exception;
use ncc\Classes\Runtime;
use ncc\CLI\Main;
use ncc\Objects\CliHelpSection;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\Resolver;
class ExecCommand
{
@ -40,6 +42,12 @@
{
$package = $args['package'] ?? null;
$version = $args['exec-version'] ?? 'latest';
$program_arguments = [];
if(isset($args['exec-args']))
{
$program_arguments = Resolver::splitArguments(Main::getRawArgs(), '--exec-args');
}
if($package === null)
{
@ -58,7 +66,7 @@
try
{
return Runtime::execute($package_name);
return Runtime::execute($package_name, $program_arguments);
}
catch(Exception $e)
{

View file

@ -58,7 +58,7 @@
try
{
Functions::initializeFiles($default_repositories);
Functions::initializeFiles(null, $default_repositories);
}
catch(Exception $e)
{

View file

@ -50,7 +50,12 @@
private static $args;
/**
* @var string|null
* @var array
*/
private static $raw_args;
/**
* @var LogLevel|null
*/
private static $log_level;
@ -63,6 +68,7 @@
public static function start(array $argv): int
{
self::$args = Resolver::parseArguments(implode(' ', $argv));
self::$raw_args = $argv;
if(!isset(self::$args['ncc-cli']))
{
@ -91,30 +97,14 @@
if(isset(self::$args['l']) || isset(self::$args['log-level']))
{
switch(strtolower(self::$args['l'] ?? self::$args['log-level']))
{
case LogLevel::SILENT:
case LogLevel::FATAL:
case LogLevel::ERROR:
case LogLevel::WARNING:
case LogLevel::INFO:
case LogLevel::DEBUG:
case LogLevel::VERBOSE:
self::$log_level = strtolower(self::$args['l'] ?? self::$args['log-level']);
break;
default:
Console::outWarning('Unknown log level: ' . (self::$args['l'] ?? self::$args['log-level']) . ', using \'info\'');
self::$log_level = LogLevel::INFO;
break;
}
self::$log_level = LogLevel::fromOrDefault(strtolower(self::$args['l'] ?? self::$args['log-level']));
}
else
{
self::$log_level = LogLevel::INFO;
}
if(Resolver::checkLogLevel(self::$log_level, LogLevel::DEBUG))
if(self::$log_level->checkLogLevel(LogLevel::DEBUG))
{
Console::outDebug('Debug logging enabled');
@ -125,12 +115,12 @@
Console::outDebug(sprintf('args: %s', json_encode(self::$args, JSON_UNESCAPED_SLASHES)));
}
if(in_array(NccBuildFlags::UNSTABLE, NCC_VERSION_FLAGS, true))
if(in_array(NccBuildFlags::UNSTABLE->value, NCC_VERSION_FLAGS, true))
{
Console::outWarning('This is an unstable build of ncc, expect some features to not work as expected');
}
if(in_array(NccBuildFlags::BETA, NCC_VERSION_FLAGS, true))
if(in_array(NccBuildFlags::BETA->value, NCC_VERSION_FLAGS, true))
{
Console::outWarning('This is a beta build of ncc, expect some features to not work as expected');
}
@ -230,9 +220,19 @@
}
/**
* @return string
* Returns the raw arguments passed to ncc
*
* @return array
*/
public static function getLogLevel(): string
public static function getRawArgs(): array
{
return self::$raw_args;
}
/**
* @return LogLevel
*/
public static function getLogLevel(): LogLevel
{
if(self::$log_level === null)
{

View file

@ -101,7 +101,7 @@
if(isset($args['v']))
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('Insufficient permissions, cannot modify configuration values', true, 1);
return 1;

View file

@ -187,7 +187,7 @@
{
$ResolvedScope = Resolver::resolveScope();
if($ResolvedScope !== Scopes::SYSTEM)
if($ResolvedScope !== Scopes::SYSTEM->value)
{
Console::outError('Insufficient permissions to add entries');
}
@ -313,7 +313,7 @@
{
$ResolvedScope = Resolver::resolveScope();
if($ResolvedScope !== Scopes::SYSTEM)
if($ResolvedScope !== Scopes::SYSTEM->value)
{
Console::outError('Insufficient permissions to remove entries');
}

View file

@ -132,7 +132,7 @@
*/
private static function installPackage(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You cannot install packages in a user scope, please run this command as root', true, 1);
return 1;
@ -145,16 +145,32 @@
$repository_manager = new RepositoryManager();
$package_manager = new PackageManager();
if($package === null)
{
Console::outError('No package specified', true, 1);
return 1;
}
$options = [];
if(isset($args['reinstall']))
{
$options[InstallPackageOptions::REINSTALL] = true;
$options[InstallPackageOptions::REINSTALL->value] = true;
}
if(isset($args['prefer-static']) || isset($args['static']))
{
$options[InstallPackageOptions::PREFER_STATIC->value] = true;
}
if(isset($args['skip-dependencies']))
{
$options[InstallPackageOptions::SKIP_DEPENDENCIES] = true;
$options[InstallPackageOptions::SKIP_DEPENDENCIES->value] = true;
}
if(isset($args['build-source']))
{
$options[InstallPackageOptions::BUILD_SOURCE->value] = true;
}
if($authentication !== null)
@ -188,7 +204,7 @@
$authentication_entry = $entry->getPassword();
}
if(preg_match(RegexPatterns::REMOTE_PACKAGE, $package) === 1)
if(preg_match(RegexPatterns::REMOTE_PACKAGE->value, $package) === 1)
{
$package_input = RemotePackageInput::fromString($package);
@ -377,7 +393,7 @@
*/
private static function uninstallPackage($args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You cannot uninstall packages in a user scope, please run this command as root', true, 1);
return 1;
@ -408,7 +424,7 @@
*/
private static function uninstallAllPackages(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You cannot uninstall all packages in a user scope, please run this command as root', true, 1);
return 1;
@ -444,7 +460,7 @@
*/
private static function fixBrokenPackages(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You cannot fix broken packages in a user scope, please run this command as root', true, 1);
return 1;
@ -548,6 +564,8 @@
new CliHelpSection(['install', '--package', '-p', '--version', '-v'], 'Installs a specified ncc package version'),
new CliHelpSection(['install', '-p', '--skip-dependencies'], 'Installs a specified ncc package but skips the installation of dependencies'),
new CliHelpSection(['install', '-p', '--reinstall'], 'Installs a specified ncc package, reinstall if already installed'),
new CliHelpSection(['install', '--prefer-static', '--static'], 'Installs a static version of the package from the remote repository if available'),
new CliHelpSection(['install', '--build-source'], 'Forces ncc to build the packages from source rather than trying to use a pre-built binary'),
new CliHelpSection(['uninstall', '--package', '-p'], 'Uninstalls a specified ncc package'),
new CliHelpSection(['uninstall', '--package', '-p', '--version', '-v'], 'Uninstalls a specified ncc package version'),
new CliHelpSection(['uninstall-all'], 'Uninstalls all packages'),

View file

@ -23,6 +23,7 @@
namespace ncc\CLI\Management;
use Exception;
use ncc\Enums\CompilerExtensions;
use ncc\Enums\ProjectTemplates;
use ncc\Enums\Scopes;
use ncc\Managers\CredentialManager;
@ -102,7 +103,12 @@
if(isset($args['ext']))
{
$compiler_extension = $args['ext'];
$compiler_extension = CompilerExtensions::tryFrom($args['ext']);
if($compiler_extension === null)
{
Console::outError('Invalid compiler extension, please specify a valid compiler extension', true, 1);
return 1;
}
}
else
{
@ -134,7 +140,7 @@
*/
private static function installProject(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You cannot install packages in a user scope, please run this command as root', true, 1);
return 1;
@ -292,9 +298,9 @@
}
Console::out(PHP_EOL . 'Available Templates:');
foreach(ProjectTemplates::ALL as $template)
foreach(ProjectTemplates::cases() as $template)
{
Console::out(' ' . $template);
Console::out(' ' . $template->value);
}
return 0;

View file

@ -25,6 +25,7 @@
use Exception;
use ncc\Enums\ConsoleColors;
use ncc\Enums\Scopes;
use ncc\Enums\Types\RepositoryType;
use ncc\Managers\RepositoryManager;
use ncc\Objects\CliHelpSection;
use ncc\Objects\RepositoryConfiguration;
@ -118,7 +119,7 @@
$output = sprintf('%s (%s) [%s]',
$source->getName(),
Console::formatColor($source->getHost(), ConsoleColors::GREEN),
Console::formatColor($source->getType(), ConsoleColors::YELLOW)
Console::formatColor($source->getType()->value, ConsoleColors::YELLOW)
);
if(!$source->isSsl())
@ -141,7 +142,7 @@
*/
private static function addEntry(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You must be running as root to add a new repository', true, 1);
return 1;
@ -164,6 +165,13 @@
return 1;
}
$parsed_type = RepositoryType::tryFrom($type);
if($parsed_type === null)
{
Console::outError(sprintf('Unknown repository type \'%s\'.', $type), true, 1);
return 1;
}
if($host === null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'host'), true, 1);
@ -172,7 +180,7 @@
try
{
(new RepositoryManager())->addRepository(new RepositoryConfiguration($name, $host, $type, $ssl));
(new RepositoryManager())->addRepository(new RepositoryConfiguration($name, $host, $parsed_type, $ssl));
}
catch(Exception $e)
{
@ -230,7 +238,7 @@
*/
private static function removeEntry(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM)
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
{
Console::outError('You must be running as root to remove a repository', true, 1);
return 1;

View file

@ -31,6 +31,7 @@
use ncc\Classes\PhpExtension\PhpRunner;
use ncc\Enums\Runners;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException;
@ -54,11 +55,11 @@
{
$bin = match($unit->getExecutionPolicy()->getRunner())
{
Runners::PHP => (new ExecutableFinder())->find('php'),
Runners::BASH => (new ExecutableFinder())->find('bash'),
Runners::PYTHON => (new ExecutableFinder())->find('python'),
Runners::LUA => (new ExecutableFinder())->find('lua'),
Runners::PERL => (new ExecutableFinder())->find('perl'),
Runners::PHP->value => (new ExecutableFinder())->find('php'),
Runners::BASH->value => (new ExecutableFinder())->find('bash'),
Runners::PYTHON->value => (new ExecutableFinder())->find('python'),
Runners::LUA->value => (new ExecutableFinder())->find('lua'),
Runners::PERL->value => (new ExecutableFinder())->find('perl'),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $unit->getExecutionPolicy()->getName(), $unit->getExecutionPolicy()->getRunner()))
};
@ -76,11 +77,19 @@
{
$process->setTimeout($unit->getExecutionPolicy()->getExecute()->getTimeout());
}
else
{
$process->setTimeout(null);
}
if($unit->getExecutionPolicy()->getExecute()->getIdleTimeout() !== null)
{
$process->setIdleTimeout($unit->getExecutionPolicy()->getExecute()->getIdleTimeout());
}
else
{
$process->setIdleTimeout(null);
}
return $process;
}
@ -109,8 +118,8 @@
$execution_unit = ExecutionUnit::fromArray(ZiProto::decode(IO::fread($unit_path)));
return match ($execution_unit->getExecutionPolicy()->getRunner())
{
Runners::PHP => PhpRunner::executeUnit($execution_unit, $args),
Runners::BASH => BashRunner::executeUnit($execution_unit, $args),
Runners::PHP->value => PhpRunner::executeUnit($execution_unit, $args),
Runners::BASH->value => BashRunner::executeUnit($execution_unit, $args),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $execution_unit->getExecutionPolicy()->getName(), $execution_unit->getExecutionPolicy()->getRunner())),
};
}
@ -129,6 +138,7 @@
* @return int
* @throws ConfigurationException
* @throws OperationException
* @throws IntegrityException
*/
public static function executeFromPackage(PackageReader $package_reader, string $policy_name, array $args=[]): int
{
@ -138,8 +148,8 @@
{
return match ($execution_unit->getExecutionPolicy()->getRunner())
{
Runners::PHP => PhpRunner::executeUnit($execution_unit, $args, false),
Runners::BASH => BashRunner::executeUnit($execution_unit, $args),
Runners::PHP->value => PhpRunner::executeUnit($execution_unit, $args, false),
Runners::BASH->value => BashRunner::executeUnit($execution_unit, $args),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $execution_unit->getExecutionPolicy()->getName(), $execution_unit->getExecutionPolicy()->getRunner())),
};
}

View file

@ -25,6 +25,7 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -38,6 +39,7 @@
use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -46,7 +48,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -63,9 +65,9 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
/**
@ -96,15 +98,21 @@
'User-Agent: ncc'
];
if($authentication !== null)
{
$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, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -161,7 +169,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication=null): RepositoryResult
{
if($tag === Versions::LATEST)
if($tag === Versions::LATEST->value)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -185,10 +193,17 @@
$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, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -197,11 +212,11 @@
if(isset($response['zipball_url']))
{
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $tag);
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $tag);
}
elseif(isset($response['tarball_url']))
{
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $tag);
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $tag);
}
else
{
@ -245,10 +260,17 @@
$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, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -298,19 +320,26 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the package
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$endpoint = sprintf('%s://%s/api/v1/repos/%s/%s/releases/tags/%s', ($repository->isSsl() ? 'https' : 'http'), $repository->getHost(), rawurlencode($group), rawurlencode($project), rawurlencode($release));
$endpoint = sprintf('%s://%s/api/v1/repos/%s/%s/releases/tags/%s',
$repository->isSsl() ? 'https' : 'http',
$repository->getHost(),
rawurlencode($group),
rawurlencode($project),
rawurlencode($release)
);
if(RuntimeCache::exists($endpoint))
{
@ -329,30 +358,62 @@
$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, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s', $group, $project, $release, $endpoint));
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s',
$group, $project, $release, $endpoint));
$response = self::processHttpResponse($curl, $group, $project);
if(!isset($response['assets']))
{
throw new NetworkException(sprintf('Failed to get release %s package url for %s/%s', $release, $group, $project));
throw new NetworkException(sprintf('Failed to get release %s package url for %s/%s',
$release, $group, $project));
}
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets'] as $asset)
{
if(isset($asset['name'], $asset['browser_download_url']) && preg_match('/\.ncc$/', $asset['name']))
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']))
{
$result = new RepositoryResult($asset['browser_download_url'], RepositoryResultType::PACKAGE, $release);
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']))
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if($target_asset)
{
$asset_url = $target_asset['browser_download_url'] ?? null;
if($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
throw new NetworkException(sprintf('No ncc package found for %s/%s/%s', $group, $project, $release));
@ -368,6 +429,7 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the archive
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
@ -375,7 +437,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if ($release === Versions::LATEST)
if ($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -399,10 +461,17 @@
$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, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -411,11 +480,11 @@
if(isset($response['zipball_url']))
{
$results = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $release);
$results = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $release);
}
elseif(isset($response['tarball_url']))
{
$results = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $release);
$results = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $release);
}
else
{
@ -446,7 +515,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
case AuthenticationType::USERNAME_PASSWORD:
if($authentication instanceof UsernamePassword)
@ -455,7 +524,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
}
return $headers;
@ -483,14 +552,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
}
switch(curl_getinfo($curl, CURLINFO_HTTP_CODE))

View file

@ -25,6 +25,7 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -46,7 +47,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -63,9 +64,9 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
/**
@ -103,7 +104,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -160,7 +161,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication = null): RepositoryResult
{
if($tag === Versions::LATEST)
if($tag === Versions::LATEST->value)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -185,7 +186,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true
]);
@ -206,7 +207,7 @@
throw new NetworkException(sprintf('Server responded with HTTP code %s when getting tag archive for %s/%s/%s', $http_code, $group, $project, $tag));
}
$result = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE, $tag);
$result = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE->value, $tag);
curl_close($curl);
RuntimeCache::set($endpoint, $result);
@ -248,7 +249,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -298,19 +299,20 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the package
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$endpoint = sprintf('%s://%s/repos/%s/%s/releases/tags/%s', ($repository->isSsl() ? 'https' : 'http'), $repository->getHost(), $group, $project, $release);
$endpoint = sprintf('%s://%s/repos/%s/%s/releases/tags/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, $project, $release);
if(RuntimeCache::exists($endpoint))
{
@ -329,11 +331,7 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
curl_setopt_array($curl, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_HTTPHEADER => $headers]);
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s', $group, $project, $release, $endpoint));
$response = self::processHttpResponse($curl, $group, $project);
@ -343,15 +341,32 @@
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
}
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets'] as $asset)
{
if(preg_match('/\.ncc$/', $asset['name']) === 1)
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']))
{
$result = new RepositoryResult($asset['browser_download_url'], RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']))
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if($target_asset)
{
$asset_url = $target_asset['browser_download_url'];
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
@ -374,7 +389,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication = null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -400,7 +415,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -410,11 +425,11 @@
if(isset($response['zipball_url']))
{
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $release);
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $release);
}
elseif(isset($response['tarball_url']))
{
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $release);
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $release);
}
else
{
@ -444,7 +459,7 @@
$headers[] = 'Authorization: Bearer ' . $authentication->getAccessToken();
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
case AuthenticationType::USERNAME_PASSWORD:
if($authentication instanceof UsernamePassword)
@ -453,7 +468,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
}
return $headers;
@ -481,14 +496,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
}
switch (curl_getinfo($curl, CURLINFO_HTTP_CODE))

View file

@ -25,6 +25,7 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -38,6 +39,7 @@
use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -46,7 +48,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -63,9 +65,9 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
/**
@ -102,10 +104,17 @@
$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, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -163,7 +172,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication=null): RepositoryResult
{
if($tag === Versions::LATEST)
if($tag === Versions::LATEST->value)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -186,10 +195,17 @@
$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, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true
]);
@ -209,7 +225,7 @@
throw new NetworkException(sprintf('Server responded with HTTP code %s when getting tag archive for %s/%s/%s', $http_code, $group, $project, $tag));
}
$results = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE, $tag);
$results = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE->value, $tag);
RuntimeCache::set($endpoint, $results);
return $results;
@ -249,9 +265,16 @@
$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, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -300,19 +323,19 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. The options to use for the request
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig")
$project = str_replace('.', '/', $project);
$endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($release));
if(RuntimeCache::exists($endpoint))
@ -332,34 +355,51 @@
$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, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
$response = self::processHttpResponse($curl, $group, $project);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets']['links'] as $asset)
{
if(preg_match('/\.ncc$/', $asset['name']) === 1)
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']) === 1)
{
if(isset($asset['direct_asset_url']))
{
$result = new RepositoryResult($asset['direct_asset_url'], RepositoryResultType::PACKAGE, $release);
}
elseif(isset($asset['url']))
{
$result = new RepositoryResult($asset['url'], RepositoryResultType::PACKAGE, $release);
}
else
{
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']) === 1)
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if ($target_asset)
{
$asset_url = $target_asset['direct_asset_url'] ?? $target_asset['url'] ?? null;
if ($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
throw new NetworkException(sprintf('No ncc package found for %s/%s/%s', $group, $project, $release));
@ -382,7 +422,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -407,9 +447,16 @@
$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, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -429,11 +476,11 @@
if($asset['format'] === 'zip')
{
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE, $release);
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE->value, $release);
}
elseif($asset['format'] === 'tar')
{
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE, $release);
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE->value, $release);
}
else
{
@ -460,23 +507,23 @@
{
switch($authentication->getAuthenticationType())
{
case AuthenticationType::ACCESS_TOKEN:
case AuthenticationType::ACCESS_TOKEN->value:
if($authentication instanceof AccessToken)
{
$headers[] = 'Private-Token: ' . $authentication->getAccessToken();
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
case AuthenticationType::USERNAME_PASSWORD:
case AuthenticationType::USERNAME_PASSWORD->value:
if($authentication instanceof UsernamePassword)
{
curl_setopt($curl, CURLOPT_USERPWD, $authentication->getUsername() . ':' . $authentication->getPassword());
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
}
return $headers;
@ -504,14 +551,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
}
switch (curl_getinfo($curl, CURLINFO_HTTP_CODE))

View file

@ -22,8 +22,10 @@
namespace ncc\Classes\NccExtension;
use InvalidArgumentException;
use ncc\Enums\SpecialConstants\BuildConstants;
use ncc\Enums\SpecialConstants\DateTimeConstants;
use ncc\Enums\SpecialConstants\GeneralConstants;
use ncc\Enums\SpecialConstants\InstallConstants;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\SpecialConstants\RuntimeConstants;
@ -47,6 +49,67 @@
$input = self::compileBuildConstants($input);
$input = self::compileDateTimeConstants($input, time());
$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;
}
@ -67,10 +130,10 @@
$input = str_replace(
[
AssemblyConstants::ASSEMBLY_NAME,
AssemblyConstants::ASSEMBLY_PACKAGE,
AssemblyConstants::ASSEMBLY_VERSION,
AssemblyConstants::ASSEMBLY_UID
AssemblyConstants::ASSEMBLY_NAME->value,
AssemblyConstants::ASSEMBLY_PACKAGE->value,
AssemblyConstants::ASSEMBLY_VERSION->value,
AssemblyConstants::ASSEMBLY_UID->value,
],
[
$assembly->getName(),
@ -81,27 +144,27 @@
if($assembly->getDescription() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_DESCRIPTION, $assembly->getDescription(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_DESCRIPTION->value, $assembly->getDescription(), $input);
}
if($assembly->getCompany() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_COMPANY, $assembly->getCompany(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_COMPANY->value, $assembly->getCompany(), $input);
}
if($assembly->getProduct() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_PRODUCT, $assembly->getProduct(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_PRODUCT->value, $assembly->getProduct(), $input);
}
if($assembly->getCopyright() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_COPYRIGHT, $assembly->getCopyright(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_COPYRIGHT->value, $assembly->getCopyright(), $input);
}
if($assembly->getTrademark() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_TRADEMARK, $assembly->getTrademark(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_TRADEMARK->value, $assembly->getTrademark(), $input);
}
return $input;
}
@ -121,10 +184,10 @@
return str_replace(
[
BuildConstants::COMPILE_TIMESTAMP,
BuildConstants::NCC_BUILD_VERSION,
BuildConstants::NCC_BUILD_FLAGS,
BuildConstants::NCC_BUILD_BRANCH
BuildConstants::COMPILE_TIMESTAMP->value,
BuildConstants::NCC_BUILD_VERSION->value,
BuildConstants::NCC_BUILD_FLAGS->value,
BuildConstants::NCC_BUILD_BRANCH->value
],
[
time(),
@ -150,10 +213,10 @@
return str_replace(
[
InstallConstants::INSTALL_PATH,
InstallConstants::INSTALL_PATH_BIN,
InstallConstants::INSTALL_PATH_SRC,
InstallConstants::INSTALL_PATH_DATA
InstallConstants::INSTALL_PATH->value,
InstallConstants::INSTALL_PATH_BIN->value,
InstallConstants::INSTALL_PATH_SRC->value,
InstallConstants::INSTALL_PATH_DATA->value
],
[
$installation_paths->getInstallationpath(),
@ -178,36 +241,36 @@
}
return str_replace([
DateTimeConstants::d,
DateTimeConstants::D,
DateTimeConstants::j,
DateTimeConstants::l,
DateTimeConstants::N,
DateTimeConstants::S,
DateTimeConstants::w,
DateTimeConstants::z,
DateTimeConstants::W,
DateTimeConstants::F,
DateTimeConstants::m,
DateTimeConstants::M,
DateTimeConstants::n,
DateTimeConstants::t,
DateTimeConstants::L,
DateTimeConstants::o,
DateTimeConstants::Y,
DateTimeConstants::y,
DateTimeConstants::a,
DateTimeConstants::A,
DateTimeConstants::B,
DateTimeConstants::g,
DateTimeConstants::G,
DateTimeConstants::h,
DateTimeConstants::H,
DateTimeConstants::i,
DateTimeConstants::s,
DateTimeConstants::c,
DateTimeConstants::r,
DateTimeConstants::u
DateTimeConstants::d->value,
DateTimeConstants::D->value,
DateTimeConstants::j->value,
DateTimeConstants::l->value,
DateTimeConstants::N->value,
DateTimeConstants::S->value,
DateTimeConstants::w->value,
DateTimeConstants::z->value,
DateTimeConstants::W->value,
DateTimeConstants::F->value,
DateTimeConstants::m->value,
DateTimeConstants::M->value,
DateTimeConstants::n->value,
DateTimeConstants::t->value,
DateTimeConstants::L->value,
DateTimeConstants::o->value,
DateTimeConstants::Y->value,
DateTimeConstants::y->value,
DateTimeConstants::a->value,
DateTimeConstants::A->value,
DateTimeConstants::B->value,
DateTimeConstants::g->value,
DateTimeConstants::G->value,
DateTimeConstants::h->value,
DateTimeConstants::H->value,
DateTimeConstants::i->value,
DateTimeConstants::s->value,
DateTimeConstants::c->value,
DateTimeConstants::r->value,
DateTimeConstants::u->value
],
[
date('d', $timestamp),
@ -257,7 +320,7 @@
if(function_exists('getcwd'))
{
$input = str_replace(RuntimeConstants::CWD, getcwd(), $input);
$input = str_replace(RuntimeConstants::CWD->value, getcwd(), $input);
}
else
{
@ -266,7 +329,7 @@
if(function_exists('getmypid'))
{
$input = str_replace(RuntimeConstants::PID, getmypid(), $input);
$input = str_replace(RuntimeConstants::PID->value, getmypid(), $input);
}
else
{
@ -275,7 +338,7 @@
if(function_exists('getmyuid'))
{
$input = str_replace(RuntimeConstants::UID, getmyuid(), $input);
$input = str_replace(RuntimeConstants::UID->value, getmyuid(), $input);
}
else
{
@ -284,7 +347,7 @@
if(function_exists('getmygid'))
{
$input = str_replace(RuntimeConstants::GID, getmygid(), $input);
$input = str_replace(RuntimeConstants::GID->value, getmygid(), $input);
}
else
{
@ -293,7 +356,7 @@
if(function_exists('get_current_user'))
{
$input = str_replace(RuntimeConstants::USER, get_current_user(), $input);
$input = str_replace(RuntimeConstants::USER->value, get_current_user(), $input);
}
else
{

View file

@ -47,6 +47,7 @@
use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Utilities\Base64;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
use ncc\Utilities\Functions;
use ncc\Utilities\IO;
use ncc\Utilities\Resolver;
@ -58,11 +59,17 @@
*/
private $project_manager;
/**
* @var array
*/
private $merged_dependencies;
/**
* @param ProjectManager $project_manager
*/
public function __construct(ProjectManager $project_manager)
{
$this->merged_dependencies = [];
$this->project_manager = $project_manager;
}
@ -86,16 +93,17 @@
* @throws PathNotFoundException
* @noinspection UnusedFunctionResultInspection
*/
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT, 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->setOptions(array_merge($configuration->getOptions(), $options));
$static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES]);
$static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]);
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
{
$package_path = ConstantCompiler::compileConstants(
$this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
$this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]
);
}
else
@ -103,15 +111,15 @@
$package_path = ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $configuration->getOutput());
}
$progress = 0;
//$progress = 0;
$steps =
count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()) +
count($this->project_manager->getComponents($build_configuration)) +
count($this->project_manager->getResources($build_configuration));
$progress_bar = new ConsoleProgressBar(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()), $steps);
$package_writer = $this->createPackageWriter($package_path, $configuration);
Console::out(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
Console::outVerbose(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
if($static_dependencies)
{
@ -121,7 +129,7 @@
}
// Debugging information
if(Resolver::checkLogLevel(LogLevel::DEBUG, Main::getLogLevel()))
if(LogLevel::DEBUG->checkLogLevel(Main::getLogLevel()))
{
foreach($this->project_manager->getProjectConfiguration()->getAssembly()->toArray() as $prop => $value)
{
@ -155,39 +163,51 @@
if(count($execution_units) === 0)
{
$progress = count($this->project_manager->getProjectConfiguration()->getExecutionPolicies());
Console::inlineProgressBar($progress, $steps);
//$progress = count($this->project_manager->getProjectConfiguration()->getExecutionPolicies());
//Console::inlineProgressBar($progress, $steps);
$progress_bar->increaseValue(count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()), true);
Console::outWarning('The project contains execution policies but none of them are used');
}
foreach($execution_units as $unit)
{
$progress++;
Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($unit->getExecutionPolicy()->getName()));
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$package_writer->addExecutionUnit($unit);
$progress_bar->increaseValue(1, true);
}
}
// Compile package components
foreach($this->project_manager->getComponents($build_configuration) as $component)
{
$progress++;
Console::inlineProgressBar($progress, $steps);
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($component));
Console::outVerbose(sprintf('Compiling \'%s\'', $component));
$this->processComponent($package_writer, $component);
$progress_bar->increaseValue(1, true);
}
// Compile package resources
foreach($this->project_manager->getResources($build_configuration) as $resource)
{
$progress++;
Console::inlineProgressBar($progress, $steps);
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($resource));
Console::outVerbose(sprintf('Processing \'%s\'', $resource));
$this->processResource($package_writer, $resource);
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
Console::out(sprintf('Processing dependencies...'));
// Add the project dependencies
foreach($this->project_manager->getProjectConfiguration()->getBuild()->getDependencies() as $dependency)
{
@ -211,6 +231,7 @@
* @param Dependency $dependency
* @param bool $static
* @return void
* @throws ConfigurationException
* @throws IOException
*/
private function processDependency(PackageWriter $package_writer, Dependency $dependency, bool $static=false): void
@ -220,13 +241,14 @@
/** @noinspection UnusedFunctionResultInspection */
$package_writer->addDependencyConfiguration($dependency);
if(!$static)
if(!$static || in_array($dependency->getName(), $this->merged_dependencies, true))
{
return;
}
$entry = (new PackageManager())->getPackageLock()->getVersionEntry($dependency->getName(), $dependency->getVersion());
$package_writer->merge((new PackageReader($entry->getShadowPackagePath($dependency->getName()))));
$this->merged_dependencies[] = $dependency->getName();
foreach($entry->getDependencies() as $sub_dependency)
{
@ -247,25 +269,25 @@
{
$package_writer = new PackageWriter($path);
if(isset($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]))
if(isset($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
{
$package_writer->addFlag(PackageFlags::COMPRESSION);
switch(strtolower($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]))
switch(strtolower($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
{
case BuildConfigurationOptions\CompressionOptions::HIGH:
case BuildConfigurationOptions\CompressionOptions::HIGH->value:
$package_writer->addFlag(PackageFlags::HIGH_COMPRESSION);
break;
case BuildConfigurationOptions\CompressionOptions::MEDIUM:
case BuildConfigurationOptions\CompressionOptions::MEDIUM->value:
$package_writer->addFlag(PackageFlags::MEDIUM_COMPRESSION);
break;
case BuildConfigurationOptions\CompressionOptions::LOW:
case BuildConfigurationOptions\CompressionOptions::LOW->value:
$package_writer->addFlag(PackageFlags::LOW_COMPRESSION);
break;
default:
throw new NotSupportedException(sprintf('The compression level \'%s\' is not supported', $build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]));
throw new NotSupportedException(sprintf('The compression level \'%s\' is not supported', $build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]));
}
}
@ -313,16 +335,38 @@
* @param string $build_configuration
* @return void
*/
public function processMetadata(PackageWriter $package_writer, string $build_configuration=BuildConfigurationValues::DEFAULT): void
public function processMetadata(PackageWriter $package_writer, string $build_configuration=BuildConfigurationValues::DEFAULT->value): void
{
$metadata = new Metadata($this->project_manager->getProjectConfiguration()->getProject()->getCompiler());
$metadata->addOptions($this->project_manager->getProjectConfiguration()->getBuild()->getOptions($build_configuration));
$metadata->addOptions($this->project_manager->getProjectConfiguration()->getProject()->getOptions());
$metadata->addConstants($this->project_manager->getConstants($build_configuration));
$metadata->setUpdateSource($this->project_manager->getProjectConfiguration()->getProject()->getUpdateSource());
$metadata->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain());
$metadata->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());
// Strip out 'output_file' build artifact.
if(isset($metadata->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
{
$metadata->removeOption(BuildConfigurationOptions::OUTPUT_FILE->value);
}
// Strip out 'static' build artifact, PackageFlags::STATIC_DEPENDENCIES is used instead
// Making this option redundant.
if(isset($metadata->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]))
{
$metadata->removeOption(BuildConfigurationOptions::STATIC_DEPENDENCIES->value);
}
$compiled_constants = [];
foreach($this->project_manager->getConstants() as $constant => $value)
{
$compiled_constants[$constant] = ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $value);
}
$metadata->addConstants($compiled_constants);
/** @noinspection UnusedFunctionResultInspection */
$package_writer->setMetadata($metadata);
}

View file

@ -29,6 +29,7 @@
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit;
@ -83,6 +84,11 @@
*/
private $package_file;
/**
* @var string
*/
private $package_path;
/**
* @var array
*/
@ -101,7 +107,9 @@
throw new IOException(sprintf('File \'%s\' does not exist', $file_path));
}
$this->package_path = $file_path;
$this->package_file = fopen($file_path, 'rb');
if($this->package_file === false)
{
throw new IOException(sprintf('Failed to open file \'%s\'', $file_path));
@ -167,27 +175,38 @@
throw new IOException(sprintf('File \'%s\' is not a valid package file (corrupted header)', $file_path), $e);
}
if(!isset($this->headers[PackageStructure::FILE_VERSION]))
if(!isset($this->headers[PackageStructure::FILE_VERSION->value]))
{
throw new IOException(sprintf('File \'%s\' is not a valid package file (invalid header)', $file_path));
}
// Seek the data until the end of the package (FF AA 55 F0)
fseek($this->package_file, $this->data_offset);
$buffer = '';
while(!feof($this->package_file))
{
$buffer = fread($this->package_file, 1024);
$this->data_length += strlen($buffer);
$current_chunk = fread($this->package_file, 1024);
$this->data_length += strlen($current_chunk);
$buffer .= $current_chunk;
// If we detect the end-of-data byte sequence
if (($position = strpos($buffer, "\xFF\xAA\x55\xF0")) !== false)
{
$this->data_length -= strlen($buffer) - $position;
$this->package_length += $this->data_length + 4;
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));
}
@ -212,7 +231,7 @@
*/
public function getFileVersion(): string
{
return $this->headers[PackageStructure::FILE_VERSION];
return $this->headers[PackageStructure::FILE_VERSION->value];
}
/**
@ -222,7 +241,7 @@
*/
public function getFlags(): array
{
return $this->headers[PackageStructure::FLAGS];
return $this->headers[PackageStructure::FLAGS->value];
}
/**
@ -233,7 +252,7 @@
*/
public function getFlag(string $name): bool
{
return in_array($name, $this->headers[PackageStructure::FLAGS], true);
return in_array($name, $this->headers[PackageStructure::FLAGS->value], true);
}
/**
@ -243,7 +262,7 @@
*/
public function getDirectory(): array
{
return $this->headers[PackageStructure::DIRECTORY];
return $this->headers[PackageStructure::DIRECTORY->value];
}
/**
@ -254,15 +273,15 @@
*/
public function get(string $name): string
{
if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{
throw new RuntimeException(sprintf('File \'%s\' not found in package', $name));
throw new RuntimeException(sprintf('File \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
$location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
fseek($this->package_file, ($this->data_offset + (int)$location[0]));
if(in_array(PackageFlags::COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
if(in_array(PackageFlags::COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
{
return gzuncompress(fread($this->package_file, (int)$location[1]));
}
@ -278,12 +297,12 @@
*/
public function getPointer(string $name): array
{
if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{
throw new RuntimeException(sprintf('Resource \'%s\' not found in package', $name));
throw new RuntimeException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
$location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
return [(int)$location[0], (int)$location[1]];
}
@ -295,7 +314,7 @@
*/
public function exists(string $name): bool
{
return isset($this->headers[PackageStructure::DIRECTORY][$name]);
return isset($this->headers[PackageStructure::DIRECTORY->value][$name]);
}
/**
@ -316,22 +335,31 @@
*
* @return Assembly
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getAssembly(): Assembly
{
$directory = sprintf('@%s', PackageDirectory::ASSEMBLY);
$directory = sprintf('@%s', PackageDirectory::ASSEMBLY->value);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
{
throw new ConfigurationException('Package does not contain an assembly');
throw new ConfigurationException(sprintf('Assembly object not found in package \'%s\'', $this->package_path));
}
try
{
$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);
}
$assembly = Assembly::fromArray(ZiProto::decode($this->get($directory)));
$this->cache[$directory] = $assembly;
return $assembly;
}
@ -341,22 +369,36 @@
*
* @return Metadata
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getMetadata(): Metadata
{
$directory = sprintf('@%s', PackageDirectory::METADATA);
$directory = sprintf('@%s', PackageDirectory::METADATA->value);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
{
throw new ConfigurationException('Package does not contain metadata');
throw new ConfigurationException(sprintf('Metadata object not found in package \'%s\'', $this->package_path));
}
try
{
$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)
{
$metadata->setOption($flag, true);
}
$metadata = Metadata::fromArray(ZiProto::decode($this->get($directory)));
$this->cache[$directory] = $metadata;
return $metadata;
}
@ -365,22 +407,31 @@
* Optional. Returns the package's installer
*
* @return Installer|null
* @throws IntegrityException
*/
public function getInstaller(): ?Installer
{
$directory = sprintf('@%s', PackageDirectory::INSTALLER);
$directory = sprintf('@%s', PackageDirectory::INSTALLER->value);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
{
return null;
}
$installer = Installer::fromArray(ZiProto::decode($this->get($directory)));
try
{
$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;
return $installer;
}
@ -393,9 +444,9 @@
public function getDependencies(): array
{
$dependencies = [];
$directory = sprintf('@%s:', PackageDirectory::DEPENDENCIES);
$directory = sprintf('@%s:', PackageDirectory::DEPENDENCIES->value);
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -412,16 +463,24 @@
* @param string $name
* @return Dependency
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getDependency(string $name): Dependency
{
$dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$dependency_name]))
$dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$dependency_name]))
{
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package', $name));
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
return Dependency::fromArray(ZiProto::decode($this->get($dependency_name)));
try
{
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);
}
}
/**
@ -430,11 +489,18 @@
* @param int $pointer
* @param int $length
* @return Dependency
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getDependencyByPointer(int $pointer, int $length): Dependency
{
return Dependency::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
try
{
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);
}
}
/**
@ -445,9 +511,9 @@
public function getExecutionUnits(): array
{
$execution_units = [];
$directory = sprintf('@%s:', PackageDirectory::EXECUTION_UNITS);
$directory = sprintf('@%s:', PackageDirectory::EXECUTION_UNITS->value);
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -464,16 +530,35 @@
* @param string $name
* @return ExecutionUnit
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getExecutionUnit(string $name): ExecutionUnit
{
$execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$execution_unit_name]))
$execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$execution_unit_name]))
{
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package', $name));
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name)));
try
{
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)]);
}
/**
@ -482,11 +567,18 @@
* @param int $pointer
* @param int $length
* @return ExecutionUnit
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getExecutionUnitByPointer(int $pointer, int $length): ExecutionUnit
{
return ExecutionUnit::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
try
{
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);
}
}
/**
@ -497,9 +589,9 @@
public function getComponents(): array
{
$components = [];
$directory = sprintf('@%s:', PackageDirectory::COMPONENTS);
$directory = sprintf('@%s:', PackageDirectory::COMPONENTS->value);
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -518,9 +610,9 @@
public function getClassMap(): array
{
$class_map = [];
$directory = sprintf('@%s:', PackageDirectory::CLASS_POINTER);
$directory = sprintf('@%s:', PackageDirectory::CLASS_POINTER->value);
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -537,16 +629,24 @@
* @param string $name
* @return Component
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getComponent(string $name): Component
{
$component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$component_name]))
$component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$component_name]))
{
throw new ConfigurationException(sprintf('Component \'%s\' not found in package', $name));
throw new ConfigurationException(sprintf('Component \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
return Component::fromArray(ZiProto::decode($this->get($component_name)));
try
{
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);
}
}
/**
@ -555,11 +655,18 @@
* @param int $pointer
* @param int $length
* @return Component
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getComponentByPointer(int $pointer, int $length): Component
{
return Component::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
try
{
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);
}
}
/**
@ -568,16 +675,24 @@
* @param string $class
* @return Component
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getComponentByClass(string $class): Component
{
$class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER, $class);
if(!isset($this->headers[PackageStructure::DIRECTORY][$class_name]))
$class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$class_name]))
{
throw new ConfigurationException(sprintf('Class map \'%s\' not found in package', $class));
throw new ConfigurationException(sprintf('Class map \'%s\' not found in package \'%s\'', $class, $this->package_path));
}
return Component::fromArray(ZiProto::decode($this->get($class_name)));
try
{
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);
}
}
/**
@ -588,9 +703,9 @@
public function getResources(): array
{
$resources = [];
$directory = sprintf('@%s:', PackageDirectory::RESOURCES);
$directory = sprintf('@%s:', PackageDirectory::RESOURCES->value);
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -607,16 +722,24 @@
* @param string $name
* @return Resource
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getResource(string $name): Resource
{
$resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$resource_name]))
$resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$resource_name]))
{
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package', $name));
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path));
}
return Resource::fromArray(ZiProto::decode($this->get($resource_name)));
try
{
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);
}
}
/**
@ -625,11 +748,37 @@
* @param int $pointer
* @param int $length
* @return Resource
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getResourceByPointer(int $pointer, int $length): Resource
{
return Resource::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
try
{
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
*
* @param string $filename
* @return string|false
*/
public function find(string $filename): string|false
{
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_ends_with($name, $filename))
{
return $name;
}
}
return false;
}
/**
@ -729,7 +878,7 @@
fseek($this->package_file, $this->package_offset);
$remaining_bytes = $this->package_length;
while ($remaining_bytes > 0)
while($remaining_bytes > 0)
{
$bytes_to_read = min($remaining_bytes, 4096);
$data = fread($this->package_file, $bytes_to_read);

View file

@ -25,10 +25,12 @@
namespace ncc\Classes;
use InvalidArgumentException;
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory;
use ncc\Enums\PackageStructure;
use ncc\Enums\PackageStructureVersions;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IOException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit;
@ -39,6 +41,7 @@
use ncc\Objects\ProjectConfiguration\Installer;
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
class PackageWriter
{
@ -106,9 +109,9 @@
$this->temp_file = @fopen($this->temporary_path, 'wb'); // Create a temporary data file
$this->package_file = @fopen($file_path, 'wb');
$this->headers = [
PackageStructure::FILE_VERSION => PackageStructureVersions::_2_0,
PackageStructure::FLAGS => [],
PackageStructure::DIRECTORY => []
PackageStructure::FILE_VERSION->value => PackageStructureVersions::_2_0->value,
PackageStructure::FLAGS->value => [],
PackageStructure::DIRECTORY->value => []
];
if($this->temp_file === false || $this->package_file === false)
@ -124,7 +127,7 @@
*/
public function getFileVersion(): string
{
return (string)$this->headers[PackageStructure::FILE_VERSION];
return (string)$this->headers[PackageStructure::FILE_VERSION->value];
}
/**
@ -135,7 +138,7 @@
*/
public function setFileVersion(string $version): void
{
$this->headers[PackageStructure::FILE_VERSION] = $version;
$this->headers[PackageStructure::FILE_VERSION->value] = $version;
}
/**
@ -145,13 +148,13 @@
*/
public function getFlags(): array
{
return (array)$this->headers[PackageStructure::FLAGS];
return (array)$this->headers[PackageStructure::FLAGS->value];
}
/**
* Sets the package flags
*
* @param array $flags
* @param string[]|PackageFlags[] $flags
* @return void
* @throws IOException
*/
@ -162,26 +165,47 @@
throw new IOException('Cannot set flags after data has been written to the package');
}
$this->headers[PackageStructure::FLAGS] = $flags;
foreach($flags as $flag)
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
$this->headers[PackageStructure::FLAGS->value] = $flag->value;
}
}
/**
* Adds a flag to the package
*
* @param string $flag
* @param PackageFlags|string $flag
* @return void
* @throws IOException
*/
public function addFlag(string $flag): void
public function addFlag(PackageFlags|string $flag): void
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
if($this->data_written)
{
throw new IOException('Cannot add a flag after data has been written to the package');
}
if(!in_array($flag, $this->headers[PackageStructure::FLAGS], true))
if(!in_array($flag, $this->headers[PackageStructure::FLAGS->value], true))
{
$this->headers[PackageStructure::FLAGS][] = $flag;
$this->headers[PackageStructure::FLAGS->value][] = $flag->value;
}
}
@ -192,14 +216,23 @@
* @return void
* @throws IOException
*/
public function removeFlag(string $flag): void
public function removeFlag(PackageFlags|string $flag): void
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
if($this->data_written)
{
throw new IOException('Cannot remove a flag after data has been written to the package');
}
$this->headers[PackageStructure::FLAGS] = array_diff($this->headers[PackageStructure::FLAGS], [$flag]);
$this->headers[PackageStructure::FLAGS->value] = array_diff($this->headers[PackageStructure::FLAGS->value], [$flag->value]);
}
/**
@ -211,22 +244,22 @@
*/
public function add(string $name, string $data): array
{
if(isset($this->headers[PackageStructure::DIRECTORY][$name]))
if(isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{
return explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
return explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
}
if(in_array(PackageFlags::COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
if(in_array(PackageFlags::COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
{
if(in_array(PackageFlags::LOW_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
if(in_array(PackageFlags::LOW_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
{
$data = gzcompress($data, 1);
}
else if(in_array(PackageFlags::MEDIUM_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
else if(in_array(PackageFlags::MEDIUM_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
{
$data = gzcompress($data, 6);
}
else if(in_array(PackageFlags::HIGH_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
else if(in_array(PackageFlags::HIGH_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
{
$data = gzcompress($data, 9);
}
@ -237,7 +270,7 @@
}
$pointer = sprintf("%d:%d", ftell($this->temp_file), strlen($data));
$this->headers[PackageStructure::DIRECTORY][$name] = $pointer;
$this->headers[PackageStructure::DIRECTORY->value][$name] = $pointer;
$this->data_written = true;
fwrite($this->temp_file, $data);
@ -254,12 +287,12 @@
*/
public function addPointer(string $name, int $offset, int $length): void
{
if(isset($this->headers[PackageStructure::DIRECTORY][$name]))
if(isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
{
return;
}
$this->headers[PackageStructure::DIRECTORY][$name] = sprintf("%d:%d", $offset, $length);
$this->headers[PackageStructure::DIRECTORY->value][$name] = sprintf("%d:%d", $offset, $length);
}
/**
@ -270,7 +303,7 @@
*/
public function setAssembly(Assembly $assembly): array
{
return $this->add(sprintf('@%s', PackageDirectory::ASSEMBLY), ZiProto::encode($assembly->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::ASSEMBLY->value), ZiProto::encode($assembly->toArray(true)));
}
/**
@ -281,7 +314,7 @@
*/
public function setMetadata(Metadata $metadata): array
{
return $this->add(sprintf('@%s', PackageDirectory::METADATA), ZiProto::encode($metadata->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::METADATA->value), ZiProto::encode($metadata->toArray(true)));
}
/**
@ -292,7 +325,7 @@
*/
public function setInstaller(Installer $installer): array
{
return $this->add(sprintf('@%s', PackageDirectory::INSTALLER), ZiProto::encode($installer->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::INSTALLER->value), ZiProto::encode($installer->toArray(true)));
}
/**
@ -303,7 +336,7 @@
*/
public function addDependencyConfiguration(Dependency $dependency): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::DEPENDENCIES, $dependency->getName()), ZiProto::encode($dependency->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $dependency->getName()), ZiProto::encode($dependency->toArray(true)));
}
/**
@ -314,7 +347,7 @@
*/
public function addExecutionUnit(ExecutionUnit $unit): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS, $unit->getExecutionPolicy()->getName()), ZiProto::encode($unit->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $unit->getExecutionPolicy()->getName()), ZiProto::encode($unit->toArray(true)));
}
/**
@ -325,7 +358,7 @@
*/
public function addComponent(Component $component): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::COMPONENTS, $component->getName()), ZiProto::encode($component->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $component->getName()), ZiProto::encode($component->toArray(true)));
}
/**
@ -336,7 +369,7 @@
*/
public function addResource(Resource $resource): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::RESOURCES, $resource->getName()), ZiProto::encode($resource->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $resource->getName()), ZiProto::encode($resource->toArray(true)));
}
/**
@ -349,7 +382,7 @@
*/
public function mapClass(string $class, int $offset, int $length): void
{
$this->addPointer(sprintf('@%s:%s', PackageDirectory::CLASS_POINTER, $class), $offset, $length);
$this->addPointer(sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class), $offset, $length);
}
/**
@ -357,19 +390,23 @@
*
* @param PackageReader $reader
* @return void
* @throws ConfigurationException
*/
public function merge(PackageReader $reader): void
{
$progress_bar = new ConsoleProgressBar(sprintf('Merging %s', $reader->getAssembly()->getPackage()), count($reader->getDirectory()));
$processed_resources = [];
foreach($reader->getDirectory() as $name => $pointer)
{
$progress_bar->setMiscText($name, true);
switch((int)substr(explode(':', $name, 2)[0], 1))
{
case PackageDirectory::METADATA:
case PackageDirectory::ASSEMBLY:
case PackageDirectory::INSTALLER:
case PackageDirectory::EXECUTION_UNITS:
case PackageDirectory::METADATA->value:
case PackageDirectory::ASSEMBLY->value:
case PackageDirectory::INSTALLER->value:
case PackageDirectory::EXECUTION_UNITS->value:
Console::outDebug(sprintf('Skipping %s', $name));
break;
@ -383,9 +420,13 @@
Console::outDebug(sprintf('Merging %s', $name));
$processed_resources[$pointer] = $this->add($name, $reader->get($name));
}
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
}
/**

View file

@ -35,9 +35,10 @@
use ncc\Interfaces\RepositoryInterface;
use ncc\Objects\RepositoryConfiguration;
use ncc\Objects\RepositoryResult;
use ncc\ThirdParty\composer\Semver\Comparator;
use ncc\ThirdParty\composer\Semver\Semver;
use ncc\ThirdParty\composer\semver\Comparator;
use ncc\ThirdParty\composer\semver\Semver;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -46,9 +47,9 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
if($version === Versions::LATEST)
if($version === Versions::LATEST->value)
{
$version = self::getLatestVersion($repository, $vendor, $project);
}
@ -70,9 +71,16 @@
'User-Agent: ncc'
];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -91,14 +99,14 @@
throw new NetworkException(sprintf('Invalid response from %s/%s, version %s does not have a dist URL', $vendor, $project, $version));
}
return new RepositoryResult($response['package']['versions'][$version]['dist']['url'], RepositoryResultType::SOURCE, $version);
return new RepositoryResult($response['package']['versions'][$version]['dist']['url'], RepositoryResultType::SOURCE->value, $version);
}
/**
* @inheritDoc
* @throws NotSupportedException
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
throw new NotSupportedException('Fetching ncc packages from Packagist is not supported');
}
@ -130,9 +138,16 @@
'User-Agent: ncc'
];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_HTTPHEADER => $headers
]);
@ -163,23 +178,21 @@
{
$versions = self::getVersions($repository, $vendor, $project);
/** @noinspection KeysFragmentationWithArrayFunctionsInspection */
// Filter out pre-release versions such as alpha, beta, rc, dev
$versions = array_filter($versions, static function($version)
{
return !preg_match('/-alpha|-beta|-rc|dev/i', $version);
});
usort($versions, static function($a, $b)
{
return Comparator::lessThanOrEqualTo($a, $b) ? 1 : -1;
});
// Sort versions in descending order using Semver::rsort
$versions = Semver::rsort($versions);
if($versions[0] === null)
if (!isset($versions[0]))
{
throw new NetworkException(sprintf('Failed to resolve latest version for %s/%s', $vendor, $project));
}
return $versions[0];
return $versions[0]; // The first version in the sorted array is the latest
}
/**

View file

@ -24,33 +24,13 @@
use ncc\ThirdParty\nikic\PhpParser\Comment;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeTraverser;
use ReflectionClass;
use ReflectionException;
use RuntimeException;
class AstWalker
{
/**
* Returns an array representation of the node recursively
*
* @param array|Node $node
* @return array
*/
public static function serialize(array|Node $node): array
{
if(is_array($node))
{
$serialized = [];
foreach($node as $sub_node)
{
$serialized[] = $sub_node->jsonSerialize();
}
return $serialized;
}
return $node->jsonSerialize();
}
/**
* Returns an array of classes associated with the node recursively
*
@ -60,9 +40,10 @@
*/
public static function extractClasses(Node|array $node, string $prefix=''): array
{
$classes = [];
if(is_array($node))
{
$classes = [];
foreach($node as $sub_node)
{
/** @noinspection SlowArrayOperationsInLoopInspection */
@ -71,8 +52,6 @@
return $classes;
}
$classes = [];
if ($node instanceof Node\Stmt\ClassLike)
{
$classes[] = $prefix . $node->name;
@ -80,9 +59,9 @@
if ($node instanceof Node\Stmt\Namespace_)
{
if ($node->name && $node->name->parts)
if ($node->name && $node->name->getParts())
{
$prefix .= implode('\\', $node->name->parts) . '\\';
$prefix .= implode('\\', $node->name->getParts()) . '\\';
}
else
{
@ -112,146 +91,4 @@
return $classes;
}
/**
* Reconstructs nodes from an array representation recursively
*
* @param $value
* @return array|Comment|Node
* @noinspection PhpMissingReturnTypeInspection
* @throws ReflectionException
*/
public static function decodeRecursive($value)
{
if (is_array($value))
{
if (isset($value['nodeType']))
{
if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc')
{
return self::decodeComment($value);
}
return self::decodeNode($value);
}
return self::decodeArray($value);
}
return $value;
}
/**
* Decodes an array by recursively decoding each value
*
* @param array $array
* @return array
* @throws ReflectionException
*/
private static function decodeArray(array $array) : array
{
$decoded_array = [];
foreach ($array as $key => $value)
{
$decoded_array[$key] = self::decodeRecursive($value);
}
return $decoded_array;
}
/**
* Returns the node from the node type
*
* @param array $value
* @return Node
* @throws ReflectionException
*/
private static function decodeNode(array $value) : Node
{
$node_type = $value['nodeType'];
if (!is_string($node_type))
{
throw new RuntimeException('Node type must be a string');
}
/** @var Node $node */
$node = self::reflectionClassFromNodeType($node_type)->newInstanceWithoutConstructor();
if (isset($value['attributes'])) {
if (!is_array($value['attributes']))
{
throw new RuntimeException('Attributes must be an array');
}
$node->setAttributes(self::decodeArray($value['attributes']));
}
foreach ($value as $name => $sub_node) {
if ($name === 'nodeType' || $name === 'attributes')
{
continue;
}
$node->$name = self::decodeRecursive($sub_node);
}
return $node;
}
/**
* Returns the comment from the node type
*
* @param array $value
* @return Comment
*/
private static function decodeComment(array $value): Comment
{
$class_name = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
if (!isset($value['text']))
{
throw new RuntimeException('Comment must have text');
}
return new $class_name(
$value['text'],
$value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
$value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
);
}
/**
* Returns the reflection class from the node type
*
* @param string $node_type
* @return ReflectionClass
* @throws ReflectionException
*/
private static function reflectionClassFromNodeType(string $node_type): ReflectionClass
{
return new ReflectionClass(self::classNameFromNodeType($node_type));
}
/**
* Returns the class name from the node type
*
* @param string $nodeType
* @return string
*/
private static function classNameFromNodeType(string $nodeType): string
{
$class_name = 'ncc\\ThirdParty\\nikic\\PhpParser\\Node\\' . str_replace('_', '\\', $nodeType);
if (class_exists($class_name))
{
return $class_name;
}
$class_name .= '_';
if (class_exists($class_name))
{
return $class_name;
}
throw new RuntimeException("Unknown node type \"$nodeType\"");
}
}

View file

@ -31,6 +31,7 @@
use ncc\ThirdParty\Symfony\Process\ExecutableFinder;
use ncc\ThirdParty\Symfony\Process\Process;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
use ncc\Utilities\Functions;
use ncc\Utilities\PathFinder;
@ -40,7 +41,7 @@
* @inheritDoc
* @throws BuildException
*/
public function build(string $build_configuration = BuildConfigurationValues::DEFAULT, array $options=[]): string
public function build(string $build_configuration = BuildConfigurationValues::DEFAULT->value, array $options=[]): string
{
$configuration = $this->getProjectManager()->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
@ -49,14 +50,14 @@
$configuration->setOptions(array_merge($configuration->getOptions(), $options));
}
if(!isset($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION]))
if(!isset($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION->value]))
{
throw new BuildException(sprintf("Unable to compile the binary, the build configuration '%s' does not have a ncc_configuration.", $build_configuration));
}
// Build the ncc package first
Console::outVerbose('Building ncc package.');
$ncc_package = parent::build($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION]);
$ncc_package = parent::build($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION->value]);
// Prepare the ncc package for compilation
$hex_dump_file = PathFinder::getCachePath() . DIRECTORY_SEPARATOR . $this->getProjectManager()->getProjectConfiguration()->getAssembly()->getName() . '.c';
@ -71,11 +72,11 @@
// Prepare the gcc command
$gcc_path = (new ExecutableFinder())->find('gcc');
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
{
$binary_path = ConstantCompiler::compileConstants(
$this->getProjectManager()->getProjectConfiguration(),
$configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
$configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]
);
}
else
@ -83,6 +84,12 @@
$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)
{
throw new BuildException("Unable to find gcc executable, please make sure it is installed and in your PATH environment variable.");
@ -168,32 +175,35 @@
*/
private function hexDump(string $input_path, string $output_path, string $variable_name): void
{
Console::out(sprintf('Processing %s to hex dump', $input_path));
Console::outVerbose(sprintf('Processing %s to hex dump', $input_path));
$input = fopen($input_path, 'rb');
$output = fopen($output_path, 'wb');
$byte_count = 0;
$total_bytes = filesize($input_path);
fwrite($output, sprintf("unsigned char %s[] = {\n", Functions::toSnakeCase($variable_name)));
$progress_bar = new ConsoleProgressBar(sprintf('HexDump %s', $input_path), filesize($input_path));
// Convert the binary data to hex and write it to the output file
fwrite($output, sprintf("unsigned char %s[] = {\n", Functions::toSnakeCase($variable_name)));
// Convert the binary data to hex and write it to the output file using chunks
while (!feof($input))
{
Console::inlineProgressBar(ftell($input), $total_bytes);
$bytes = fread($input, 5026);
$len = strlen($bytes);
$byte = fread($input, 1);
if (strlen($byte) === 1)
for ($i = 0; $i < $len; $i++)
{
fwrite($output, sprintf(" 0x%02x,", ord($byte)));
fwrite($output, sprintf(" 0x%02x,", ord($bytes[$i])));
$byte_count++;
// Write 12 bytes per line or when reaching the end of the file
if ($byte_count === 12 || ($i == $len - 1 && feof($input)))
{
fwrite($output, "\n");
$byte_count = 0;
}
}
// Write 12 bytes per line or when reaching the end of the file
if ($byte_count === 12 || feof($input))
{
fwrite($output, "\n");
$byte_count = 0;
}
$progress_bar->increaseValue($len, true);
$progress_bar->setMiscText(sprintf('Processed (%d/%d)', $progress_bar->getValue(), $progress_bar->getMaxValue()));
}
// Close the output file
@ -204,5 +214,9 @@
// Finally, close the input and output files
fclose($input);
fclose($output);
// Close the progress bar
$progress_bar->setMiscText('done', true);
unset($progress_bar);
}
}

View file

@ -0,0 +1,74 @@
<?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;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeVisitorAbstract;
use ncc\Utilities\Console;
class ExpressionTraverser extends NodeVisitorAbstract
{
/**
* @var string|null
*/
private ?string $package;
/**
* ExpressionTraverser constructor.
*
* @param string|null $package
*/
public function __construct(?string $package)
{
$this->package = $package;
}
/**
* @param Node $node
* @return array|int|Node|null
*/
public function leaveNode(Node $node): array|int|Node|null
{
if($node instanceof Node\Expr\Include_)
{
Console::outDebug(sprintf('Processing ExpressionTraverser on: %s', $node->getType()));
$args = [$node->expr];
if(!is_null($this->package))
{
$args[] = new Node\Arg(new Node\Scalar\String_($this->package));
}
$types = [
Node\Expr\Include_::TYPE_INCLUDE => '\ncc\Classes\Runtime::runtimeInclude',
Node\Expr\Include_::TYPE_INCLUDE_ONCE => '\ncc\Classes\Runtime::runtimeIncludeOnce',
Node\Expr\Include_::TYPE_REQUIRE => '\ncc\Classes\Runtime::runtimeRequire',
Node\Expr\Include_::TYPE_REQUIRE_ONCE => '\ncc\Classes\Runtime::runtimeRequireOnce',
];
return new Node\Expr\FuncCall(new Node\Name($types[$node->type]), $args);
}
return null;
}
}

View file

@ -30,7 +30,9 @@
use ncc\Exceptions\PathNotFoundException;
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Objects\Package\Component;
use ncc\ThirdParty\nikic\PhpParser\NodeDumper;
use ncc\ThirdParty\nikic\PhpParser\ParserFactory;
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
use ncc\Utilities\Base64;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
@ -52,10 +54,9 @@
try
{
$stmts = (new ParserFactory())->create(ParserFactory::PREFER_PHP7)->parse(IO::fread($file_path));
$component = new Component($component_name, ZiProto::encode($stmts), ComponentDataType::AST);
$component->addFlag(ComponentFlags::PHP_AST);
$stmts = ((new ParserFactory())->createForNewestSupportedVersion())->parse(IO::fread($file_path));
$component = new Component($component_name, ZiProto::encode(Serializer::nodesToArray($stmts)), ComponentDataType::AST);
$component->addFlag(ComponentFlags::PHP_AST->value);
$pointer = $package_writer->addComponent($component);
foreach(AstWalker::extractClasses($stmts) as $class)
@ -71,7 +72,7 @@
}
$component = new Component($component_name, Base64::encode(IO::fread($file_path)), ComponentDataType::BASE64_ENCODED);
$component->addFlag(ComponentFlags::PHP_B64);
$component->addFlag(ComponentFlags::PHP_B64->value);
$package_writer->addComponent($component);
}
}

View file

@ -44,7 +44,7 @@
*/
public static function executeUnit(ExecutionUnit $unit, array $args=[], bool $local=true): int
{
if($unit->getExecutionPolicy()->getRunner() !== Runners::PHP)
if($unit->getExecutionPolicy()->getRunner() !== Runners::PHP->value)
{
throw new InvalidArgumentException(sprintf('The execution unit %s is not a php execution unit', $unit->getExecutionPolicy()->getName()));
}

View file

@ -0,0 +1,151 @@
<?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;
use ncc\ThirdParty\nikic\PhpParser\Comment;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
use ReflectionClass;
use RuntimeException;
use function is_array;
use function is_string;
class Serializer
{
/** @var ReflectionClass<Node>[] Node type to reflection class map */
private static array $reflectionClassCache;
/**
* @param NodeAbstract[] $nodeAbstracts
* @return array
*/
public static function nodesToArray(array $nodeAbstracts): array
{
$serialized = [];
foreach ($nodeAbstracts as $nodeAbstract)
{
$serialized[] = $nodeAbstract->jsonSerialize();
}
return $serialized;
}
/**
* @param array $nodeAbstracts
* @return NodeAbstract[]
*/
public static function arrayToNodes(array $nodeAbstracts): array
{
return self::decodeRecursive($nodeAbstracts);
}
/**
* @param mixed $value
* @return mixed
*/
private static function decodeRecursive($value) {
if (is_array($value)) {
if (isset($value['nodeType'])) {
if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
return self::decodeComment($value);
}
return self::decodeNode($value);
}
return self::decodeArray($value);
}
return $value;
}
private static function decodeArray(array $array): array {
$decodedArray = [];
foreach ($array as $key => $value) {
$decodedArray[$key] = self::decodeRecursive($value);
}
return $decodedArray;
}
private static function decodeNode(array $value): Node {
$nodeType = $value['nodeType'];
if (!is_string($nodeType)) {
throw new RuntimeException('Node type must be a string');
}
$reflectionClass = self::reflectionClassFromNodeType($nodeType);
$node = $reflectionClass->newInstanceWithoutConstructor();
if (isset($value['attributes'])) {
if (!is_array($value['attributes'])) {
throw new RuntimeException('Attributes must be an array');
}
$node->setAttributes(self::decodeArray($value['attributes']));
}
foreach ($value as $name => $subNode) {
if ($name === 'nodeType' || $name === 'attributes') {
continue;
}
$node->$name = self::decodeRecursive($subNode);
}
return $node;
}
private static function decodeComment(array $value): Comment {
$className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
if (!isset($value['text'])) {
throw new RuntimeException('Comment must have text');
}
return new $className(
$value['text'],
$value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
$value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
);
}
private static function reflectionClassFromNodeType(string $nodeType): ReflectionClass {
if (!isset(self::$reflectionClassCache[$nodeType])) {
$className = self::classNameFromNodeType($nodeType);
self::$reflectionClassCache[$nodeType] = new ReflectionClass($className);
}
return self::$reflectionClassCache[$nodeType];
}
/** @return class-string<Node> */
private static function classNameFromNodeType(string $nodeType): string {
$className = '\\ncc\\ThirdParty\\nikic\\PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
if (class_exists($className)) {
return $className;
}
$className .= '_';
if (class_exists($className)) {
return $className;
}
throw new RuntimeException("Unknown node type \"$nodeType\"");
}
}

View file

@ -49,32 +49,31 @@
public static function applyTemplate(ProjectManager $project_manager): void
{
$project_manager->getProjectConfiguration()->addExecutionPolicy(
new ExecutionPolicy('main_policy', Runners::PHP, new ExecutionPolicy\Execute('main'))
new ExecutionPolicy('main_policy', Runners::PHP->value, new ExecutionPolicy\Execute('main'))
);
$project_manager->getProjectConfiguration()->getBuild()->setMain('main_policy');
$project_manager->getProjectConfiguration()->getProject()->addOption(ProjectOptions::CREATE_SYMLINK, true);
$project_manager->getProjectConfiguration()->getProject()->addOption(ProjectOptions::CREATE_SYMLINK->value, true);
// Create the release build configuration
$release_executable = new BuildConfiguration('release_executable',
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME->value
);
$release_executable->setBuildType(BuildOutputType::EXECUTABLE);
$release_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION, 'release');
$release_executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$release_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, 'release');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($release_executable);
// Create the debug build configuration
$debug_executable = new BuildConfiguration('debug_executable',
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME->value
);
$debug_executable->setDefinedConstant('DEBUG', '1');
$debug_executable->setBuildType(BuildOutputType::EXECUTABLE);
$debug_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION, 'debug');
$debug_executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$debug_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, 'debug');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($debug_executable);
self::writeProgramTemplate($project_manager);
self::writeMainEntryTemplate($project_manager);
self::writeMakefileTemplate($project_manager);
$project_manager->save();
}
@ -114,22 +113,4 @@
)
);
}
/**
* 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

@ -0,0 +1,61 @@
<?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

@ -0,0 +1,77 @@
<?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

@ -0,0 +1,117 @@
<?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,8 +48,14 @@
*/
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(
$project_manager->getProjectSourcePath() . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php',
$class_directory . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'class.php.tpl')
)

View file

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

View file

@ -0,0 +1,78 @@
<?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

@ -0,0 +1,93 @@
<?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

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

View file

@ -0,0 +1,187 @@
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

@ -0,0 +1,49 @@
%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

@ -0,0 +1,12 @@
- 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

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

View file

@ -0,0 +1,11 @@
<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

@ -29,9 +29,12 @@
use ncc\Enums\FileDescriptor;
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\Options\ComponentDecodeOptions;
use ncc\Enums\PackageDirectory;
use ncc\Enums\Versions;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\ImportException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException;
@ -39,8 +42,14 @@
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Managers\PackageManager;
use ncc\Objects\Package\Metadata;
use ncc\Utilities\Console;
use ncc\Utilities\IO;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use ncc\Utilities\Validate;
use RuntimeException;
use Throwable;
use function trigger_error;
class Runtime
{
@ -59,19 +68,26 @@
*/
private static $package_manager;
/**
* @var array
*/
private static $included_files = [];
/**
* Executes the main execution point of an imported package and returns the evaluated result
* This method may exit the program without returning a value
*
* @param string $package
* @param array $arguments
* @return mixed
* @throws ConfigurationException
* @throws IOException
* @throws IntegrityException
* @throws NotSupportedException
* @throws PathNotFoundException
* @throws OperationException
* @throws PathNotFoundException
*/
public static function execute(string $package): int
public static function execute(string $package, array $arguments=[]): int
{
if(!self::isImported($package))
{
@ -80,6 +96,12 @@
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(
self::$imported_packages[$package],
self::$imported_packages[$package]->getMetadata()->getMainExecutionPolicy()
@ -88,7 +110,7 @@
if(is_string(self::$imported_packages[$package]))
{
$metadata_path = self::$imported_packages[$package] . DIRECTORY_SEPARATOR . FileDescriptor::METADATA;
$metadata_path = self::$imported_packages[$package] . DIRECTORY_SEPARATOR . FileDescriptor::METADATA->value;
if(!is_file($metadata_path))
{
@ -97,7 +119,8 @@
return ExecutionUnitRunner::executeFromSystem(
self::$imported_packages[$package],
Metadata::fromArray(ZiProto::decode(IO::fread($metadata_path)))->getMainExecutionPolicy()
Metadata::fromArray(ZiProto::decode(IO::fread($metadata_path)))->getMainExecutionPolicy(),
$arguments
);
}
@ -110,7 +133,7 @@
* @return string
* @throws ImportException
*/
public static function import(string $package, string $version=Versions::LATEST): string
public static function import(string $package, string $version=Versions::LATEST->value): string
{
if(self::isImported($package))
{
@ -149,7 +172,7 @@
}
}
throw new RuntimeException('Importing from a package name is not supported yet');
throw new RuntimeException(sprintf('Failed to import package "%s" because it does not exist', $package));
}
/**
@ -162,7 +185,7 @@
* @throws NotSupportedException
* @throws PathNotFoundException
*/
private static function importFromSystem(string $package, string $version=Versions::LATEST): string
private static function importFromSystem(string $package, string $version=Versions::LATEST->value): string
{
if(!self::getPackageManager()->getPackageLock()->entryExists($package))
{
@ -170,6 +193,7 @@
}
$entry = self::getPackageManager()->getPackageLock()->getEntry($package);
self::$imported_packages[$package] = $entry->getPath($version);
foreach($entry->getClassMap($version) as $class => $component_name)
{
@ -177,32 +201,95 @@
self::$class_map[strtolower($class)] = $component_path;
}
self::$imported_packages[$package] = $entry->getPath($version);
// Import dependencies recursively
foreach($entry->getVersion($version)->getDependencies() as $dependency)
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) !== null)
{
/** @noinspection UnusedFunctionResultInspection */
self::import($dependency->getName(), $dependency->getVersion());
}
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) !== null)
{
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) as $item)
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) as $item)
{
$required_file = $entry->getPath($version) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $item;
try
{
// Get the file contents and prepare it
$required_file = IO::fread($entry->getPath($version) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $item);
$required_file = preg_replace('/^<\?php|<\?PHP/', '', $required_file, 1);
if(!file_exists($required_file))
{
throw new PathNotFoundException($required_file);
}
eval($required_file);
unset($required_file);
// Get the file contents and prepare it
$evaluated_code = IO::fread($required_file);
// Remove the PHP tags
$evaluated_code = preg_replace('/^<\?php|<\?PHP/', '', $evaluated_code, 1);
// Replace __DIR__ with the actual directory that the file is in
$evaluated_code = str_replace('__DIR__', sprintf('"%s"', dirname($required_file)), $evaluated_code);
set_error_handler(function ($error_number, $message, $file, $line) use ($item, $package)
{
throw new ImportException(sprintf('Fatal Evaluation Error: Failed to import "%s" from %s on %s:%s: %s', $item, $package, $file, $line, $message));
});
// Evaluate the code
eval($evaluated_code);
restore_error_handler();
unset($evaluated_code);
}
catch(ConfigurationException $e)
catch (ConfigurationException $e)
{
throw new ImportException(sprintf('Failed to import "%s" from %s: %s', $item, $package, $e->getMessage()), $e);
throw new ImportException(sprintf('%s: Failed to import "%s" from %s: %s', $required_file, $item, $package, $e->getMessage()), $e);
}
catch(ImportException $e)
{
throw $e;
}
catch (Throwable $e)
{
throw new ImportException(sprintf('%s: Failed to import "%s" from %s: %s', $required_file, $item, $package, $e->getMessage()), $e);
}
}
}
$safe_package_name = strtoupper($entry->getAssembly($version)->getName());
foreach($entry->getMetadata($version)->getConstants() as $constant => $value)
{
$constant_full_name = sprintf("%s_%s", $safe_package_name, $constant);
// Skip if already defined.
if(defined($constant_full_name))
{
if(RuntimeCache::get(sprintf("defined_%s", $constant_full_name)))
{
continue;
}
trigger_error(sprintf('Cannot define constant %s from package %s because the constant is already defined', $constant_full_name, $package), E_USER_WARNING);
continue;
}
if(!Validate::constantName($constant_full_name))
{
// trigger warning only
trigger_error(sprintf('Cannot define constant %s from package %s because the constant name is invalid', $constant_full_name, $package), E_USER_WARNING);
continue;
}
RuntimeCache::set(sprintf("defined_%s", $constant_full_name), true);
define($constant_full_name, $value);
}
if(isset($entry->getMetadata($version)->getOptions()[PackageFlags::STATIC_DEPENDENCIES->value]))
{
// Fake import the dependencies
foreach($entry->getVersion($version)->getDependencies() as $dependency)
{
self::$imported_packages[$dependency->getName()] = $entry->getPath($version);
}
}
else
{
// Import dependencies recursively
foreach($entry->getVersion($version)->getDependencies() as $dependency)
{
/** @noinspection UnusedFunctionResultInspection */
self::import($dependency->getName(), $dependency->getVersion());
}
}
@ -215,10 +302,9 @@
* @param string $package_path
* @return string
* @throws ConfigurationException
* @throws IOException
* @throws ImportException
* @throws IntegrityException
* @throws OperationException
* @throws PathNotFoundException
*/
private static function importFromPackage(string $package_path): string
{
@ -253,9 +339,9 @@
}
// Import the required files
if($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES) !== null)
if($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) !== null)
{
foreach($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES) as $item)
foreach($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) as $item)
{
try
{
@ -268,9 +354,18 @@
}
}
// Import dependencies recursively
if(!$package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES))
if($package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES->value))
{
// Fake import the dependencies
foreach($package_reader->getDependencies() as $dependency_name)
{
$dependency = $package_reader->getDependency($dependency_name);
self::$imported_packages[$dependency->getName()] = $package_reader;
}
}
else
{
// Import dependencies recursively
foreach($package_reader->getDependencies() as $dependency)
{
$dependency = $package_reader->getDependency($dependency);
@ -326,7 +421,6 @@
if(is_string(self::$class_map[$class]) && is_file(self::$class_map[$class]))
{
require_once self::$class_map[$class];
return;
}
}
@ -342,4 +436,289 @@
return self::$package_manager;
}
/**
* Returns an array of included files both from the php runtime and ncc runtime
*
* @return array
*/
public static function runtimeGetIncludedFiles(): array
{
return array_merge(get_included_files(), self::$included_files);
}
/**
* Evaluates and executes PHP code with error handling, this function
* gracefully handles <?php ?> tags and exceptions the same way as the
* require/require_once/include/include_once expressions
*
* @param string $code The PHP code to be executed
*/
public static function extendedEvaluate(string $code): void
{
if(ob_get_level() > 0)
{
ob_clean();
}
$exceptions = [];
$code = preg_replace_callback('/<\?php(.*?)\?>/s', static function ($matches) use (&$exceptions)
{
ob_start();
try
{
eval($matches[1]);
}
catch (Throwable $e)
{
$exceptions[] = $e;
}
return ob_get_clean();
}, $code);
ob_start();
try
{
eval('?>' . $code);
}
catch (Throwable $e)
{
$exceptions[] = $e;
}
if (!empty($exceptions))
{
print(ob_get_clean());
$exception_stack = null;
foreach ($exceptions as $e)
{
if($exception_stack === null)
{
$exception_stack = $e;
}
else
{
$exception_stack = new Exception($exception_stack->getMessage(), $exception_stack->getCode(), $e);
}
}
throw new RuntimeException('An exception occurred while evaluating the code', 0, $exception_stack);
}
print(ob_get_clean());
}
/**
* Returns the content of the aquired file
*
* @param string $path
* @param string|null $package
* @return string
* @throws ConfigurationException
* @throws IOException
* @throws OperationException
* @throws PathNotFoundException
* @throws IntegrityException
*/
private static function acquireFile(string $path, ?string $package=null): string
{
$cwd_checked = false; // sanity check to prevent checking the cwd twice
// Check if the file is absolute
if(is_file($path))
{
Console::outDebug(sprintf('Acquired file "%s" from absolute path', $path));
return IO::fread($path);
}
// Since $package is not null, let's try to acquire the file from the package
if($package !== null && isset(self::$imported_packages[$package]))
{
$base_path = basename($path);
if(self::$imported_packages[$package] instanceof PackageReader)
{
$acquired_file = self::$imported_packages[$package]->find($base_path);
Console::outDebug(sprintf('Acquired file "%s" from package "%s"', $path, $package));
return match (Resolver::componentType($acquired_file))
{
PackageDirectory::RESOURCES->value => self::$imported_packages[$package]->getResource(Resolver::componentName($acquired_file))->getData(),
PackageDirectory::COMPONENTS->value => self::$imported_packages[$package]->getComponent(Resolver::componentName($acquired_file))->getData([ComponentDecodeOptions::AS_FILE->value]),
default => throw new IOException(sprintf('Unable to acquire file "%s" from package "%s" because it is not a resource or component', $path, $package)),
};
}
if(is_dir(self::$imported_packages[$package]))
{
$base_path = basename($path);
foreach(IO::scan(self::$imported_packages[$package]) as $file)
{
if(str_ends_with($file, $base_path))
{
Console::outDebug(sprintf('Acquired file "%s" from package "%s"', $path, $package));
return IO::fread($file);
}
}
}
}
// If not, let's try the include_path
foreach(explode(PATH_SEPARATOR, get_include_path()) as $file_path)
{
if($file_path === '.' && !$cwd_checked)
{
$cwd_checked = true;
$file_path = getcwd();
}
if(is_file($file_path . DIRECTORY_SEPARATOR . $path))
{
Console::outDebug(sprintf('Acquired file "%s" from include_path', $path));
return IO::fread($file_path . DIRECTORY_SEPARATOR . $path);
}
if(is_file($file_path . DIRECTORY_SEPARATOR . basename($path)))
{
Console::outDebug(sprintf('Acquired file "%s" from include_path (using basename)', $path));
return IO::fread($file_path . DIRECTORY_SEPARATOR . basename($path));
}
}
// Check the current working directory
if(!$cwd_checked)
{
if(is_file(getcwd() . DIRECTORY_SEPARATOR . $path))
{
Console::outDebug(sprintf('Acquired file "%s" from current working directory', $path));
return IO::fread(getcwd() . DIRECTORY_SEPARATOR . $path);
}
if(is_file(getcwd() . DIRECTORY_SEPARATOR . basename($path)))
{
Console::outDebug(sprintf('Acquired file "%s" from current working directory (using basename)', $path));
return IO::fread(getcwd() . DIRECTORY_SEPARATOR . basename($path));
}
}
// Check the calling script's directory
$called_script_directory = dirname(debug_backtrace()[0]['file']);
$file_path = $called_script_directory . DIRECTORY_SEPARATOR . $path;
if(is_file($file_path))
{
Console::outDebug(sprintf('Acquired file "%s" from calling script\'s directory', $path));
return IO::fread($file_path);
}
throw new IOException(sprintf('Unable to acquire file "%s" because it does not exist', $path));
}
/**
* Includes a file at runtime
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeInclude(string $path, ?string $package=null): void
{
try
{
$acquired_file = self::acquireFile($path, $package);
}
catch(Exception $e)
{
$package ?
Console::outWarning(sprintf('Failed to acquire file "%s" from package "%s" at runtime: %s', $path, $package, $e->getMessage())) :
Console::outWarning(sprintf('Failed to acquire file "%s" at runtime: %s', $path, $e->getMessage()));
return;
}
$acquired_name = $path;
if(!is_file($path))
{
$acquired_name = hash('crc32', $acquired_file);
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
}
self::extendedEvaluate($acquired_file);
}
/**
* Includes a file at runtime if it's not already included
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeIncludeOnce(string $path, ?string $package=null): void
{
if(in_array($path, self::runtimeGetIncludedFiles(), true))
{
return;
}
self::runtimeInclude($path, $package);
}
/**
* Requires a file at runtime, throws an exception if the file failed to require
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeRequire(string $path, ?string $package=null): void
{
try
{
$acquired_file = self::acquireFile($path, $package);
}
catch(Exception $e)
{
$package ?
throw new RuntimeException(sprintf('Failed to acquire file "%s" from package "%s" at runtime: %s', $path, $package, $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(!is_file($path))
{
$acquired_name = hash('crc32', $acquired_file);
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
}
self::extendedEvaluate($acquired_file);
}
/**
* Requires a file at runtime if it's not already required
*
* @param string $path
* @return void
*/
public static function runtimeRequireOnce(string $path): void
{
if(in_array($path, self::runtimeGetIncludedFiles(), true))
{
return;
}
self::runtimeRequire($path);
}
}

View file

@ -1,33 +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\Enums;
final class CompilerExtensionDefaultVersions
{
// ----------------------------------------------------------------
// [0] = MinimumVersion
// [1] = MaximumVersion
// ----------------------------------------------------------------
public const PHP = ['8.0', '8.2'];
}

View file

@ -24,5 +24,6 @@
final class CompilerExtensionSupportedVersions
{
// TODO: Cannot convert this to enum, try another way
public const PHP = ['8.0', '8.1', '8.2'];
}

View file

@ -22,11 +22,7 @@
namespace ncc\Enums;
final class CompilerExtensions
enum CompilerExtensions : string
{
public const PHP = 'php';
public const ALL = [
CompilerExtensions::PHP
];
case PHP = 'php';
}

View file

@ -1,33 +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\Enums;
final class ComponentFileExtensions
{
/**
* The file extensions that the PHP compiler extension will accept as components.
*
* @var array
*/
public const PHP = ['*.php', '*.php3', '*.php4', '*.php5', '*.phtml'];
}

View file

@ -22,39 +22,39 @@
namespace ncc\Enums;
final class ConsoleColors
enum ConsoleColors : string
{
public const DEFAULT = "\e[39m";
case DEFAULT = "\e[39m";
public const BLACK = "\e[30m";
case BLACK = "\e[30m";
public const RED = "\e[31m";
case RED = "\e[31m";
public const GREEN = "\e[32m";
case GREEN = "\e[32m";
public const YELLOW = "\e[33m";
case YELLOW = "\e[33m";
public const BLUE = "\e[34m";
case BLUE = "\e[34m";
public const MAGENTA = "\e[35m";
case MAGENTA = "\e[35m";
public const CYAN = "\e[36m";
case CYAN = "\e[36m";
public const LIGHT_GREY = "\e[37m";
case LIGHT_GREY = "\e[37m";
public const DARK_GREY = "\e[90m";
case DARK_GREY = "\e[90m";
public const LIGHT_RED = "\e[91m";
case LIGHT_RED = "\e[91m";
public const LIGHT_GREEN = "\e[92m";
case LIGHT_GREEN = "\e[92m";
public const LIGHT_YELLOW = "\e[93m";
case LIGHT_YELLOW = "\e[93m";
public const LIGHT_BLUE = "\e[94m";
case LIGHT_BLUE = "\e[94m";
public const LIGHT_MAGENTA = "\e[95m";
case LIGHT_MAGENTA = "\e[95m";
public const LIGHT_CYAN = "\e[96m";
case LIGHT_CYAN = "\e[96m";
public const WHITE = "\e[97m";
case WHITE = "\e[97m";
}

View file

@ -1,36 +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\Enums;
final class ConstantReferences
{
public const ASSEMBLY = 'assembly';
public const BUILD = 'build';
public const DATE_TIME = 'date_time';
public const INSTALL = 'install';
public const RUNTIME = 'runtime';
}

View file

@ -26,95 +26,80 @@
* @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved.
*/
final class ExceptionCodes
enum ExceptionCodes : int
{
/**
* @see RuntimeException
*/
public const RUNTIME = -1706;
case RUNTIME = -1706;
/**
* @see BuildException
*/
public const BUILD_EXCEPTION = -1727;
case BUILD_EXCEPTION = -1727;
/**
* @see IOException
*/
public const IO_EXCEPTION = -1735;
case IO_EXCEPTION = -1735;
/**
* @see ComposerException
*/
public const COMPOSER_EXCEPTION = -1749;
case COMPOSER_EXCEPTION = -1749;
/**
* @see AuthenticationException
*/
public const AUTHENTICATION_EXCEPTION = -1760;
case AUTHENTICATION_EXCEPTION = -1760;
/**
* @see NotSupportedException
*/
public const NOT_SUPPORTED_EXCEPTION = -1761;
case NOT_SUPPORTED_EXCEPTION = -1761;
/**
* @see ArchiveException
*/
public const ARCHIVE_EXCEPTION = -1764;
case ARCHIVE_EXCEPTION = -1764;
/**
* @see PathNotFoundException
*/
public const PATH_NOT_FOUND = -1769;
case PATH_NOT_FOUND = -1769;
/**
* @see GitException
*/
public const GIT_EXCEPTION = -1770;
case GIT_EXCEPTION = -1770;
/**
* @see ConfigurationException
*/
public const CONFIGURATION_EXCEPTION = -1772;
case CONFIGURATION_EXCEPTION = -1772;
/**
* @see PackageException
*/
public const PACKAGE_EXCEPTION = -1773;
case PACKAGE_EXCEPTION = -1773;
/**
* @see NetworkException
*/
public const NETWORK_EXCEPTION = -1774;
case NETWORK_EXCEPTION = -1774;
/**
* @see IntegrityException
*/
public const INTEGRITY_EXCEPTION = -1775;
case INTEGRITY_EXCEPTION = -1775;
/**
* @see OperationException
*/
public const OPERATION_EXCEPTION = -1776;
case OPERATION_EXCEPTION = -1776;
/**
* All the exception codes from NCC
* @see ImportException
*/
public const All = [
self::RUNTIME,
self::BUILD_EXCEPTION,
self::IO_EXCEPTION,
self::COMPOSER_EXCEPTION,
self::AUTHENTICATION_EXCEPTION,
self::NOT_SUPPORTED_EXCEPTION,
self::ARCHIVE_EXCEPTION,
self::PATH_NOT_FOUND,
self::GIT_EXCEPTION,
self::CONFIGURATION_EXCEPTION,
self::PACKAGE_EXCEPTION,
self::NETWORK_EXCEPTION,
self::INTEGRITY_EXCEPTION,
self::OPERATION_EXCEPTION
];
case IMPORT_EXCEPTION = -1777;
}

View file

@ -22,17 +22,17 @@
namespace ncc\Enums;
final class FileDescriptor
enum FileDescriptor : string
{
public const ASSEMBLY = 'ASSEMBLY';
case ASSEMBLY = 'ASSEMBLY';
public const METADATA = 'METADATA';
case METADATA = 'METADATA';
public const INSTALLER = 'INSTALLER';
case INSTALLER = 'INSTALLER';
public const CLASS_MAP = 'CLASS_MAP';
case CLASS_MAP = 'CLASS_MAP';
public const UPDATE = 'UPDATE';
case UPDATE = 'UPDATE';
public const SHADOW_PACKAGE = 'SHADOW_PKG';
case SHADOW_PACKAGE = 'SHADOW_PKG';
}

View file

@ -22,23 +22,15 @@
namespace ncc\Enums\Flags;
final class ComponentFlags
enum ComponentFlags : string
{
/**
* Indicates that the component is the AST of a PHP file encoded with msgpack.
*/
public const PHP_AST = 'php_ast';
case PHP_AST = 'php_ast';
/**
* Indicates that the component is a PHP file encoded with base64.
*/
public const PHP_B64 = 'php_b64';
/**
* All the possible flags of a component
*/
public const ALL = [
self::PHP_AST,
self::PHP_B64
];
case PHP_B64 = 'php_b64';
}

View file

@ -22,16 +22,16 @@
namespace ncc\Enums\Flags;
final class NccBuildFlags
enum NccBuildFlags : string
{
/**
* Indicates if the build is currently unstable and some features may not work correctly
* and can cause errors
*/
public const UNSTABLE = 'unstable';
case UNSTABLE = 'unstable';
/**
* Indicates if the build is currently in beta testing phase
*/
public const BETA = 'beta';
case BETA = 'beta';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Flags;
final class PackageFlags
enum PackageFlags : string
{
public const COMPRESSION = 'gzip';
case COMPRESSION = 'gzip';
public const LOW_COMPRESSION = 'low_gz`';
case LOW_COMPRESSION = 'low_gz`';
public const MEDIUM_COMPRESSION = 'medium_gz';
case MEDIUM_COMPRESSION = 'medium_gz';
public const HIGH_COMPRESSION = 'high_gz';
case HIGH_COMPRESSION = 'high_gz';
public const STATIC_DEPENDENCIES = 'static_dependencies';
case STATIC_DEPENDENCIES = 'static_dependencies';
}

View file

@ -1,124 +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\Enums;
final class HttpStatusCodes
{
public const OK = 200;
public const CREATED = 201;
public const ACCEPTED = 202;
public const NO_CONTENT = 204;
public const MOVED_PERMANENTLY = 301;
public const FOUND = 302;
public const SEE_OTHER = 303;
public const NOT_MODIFIED = 304;
public const TEMPORARY_REDIRECT = 307;
public const PERMANENT_REDIRECT = 308;
public const BAD_REQUEST = 400;
public const UNAUTHORIZED = 401;
public const FORBIDDEN = 403;
public const NOT_FOUND = 404;
public const METHOD_NOT_ALLOWED = 405;
public const NOT_ACCEPTABLE = 406;
public const REQUEST_TIMEOUT = 408;
public const CONFLICT = 409;
public const GONE = 410;
public const LENGTH_REQUIRED = 411;
public const PRECONDITION_FAILED = 412;
public const PAYLOAD_TOO_LARGE = 413;
public const URI_TOO_LONG = 414;
public const UNSUPPORTED_MEDIA_TYPE = 415;
public const RANGE_NOT_SATISFIABLE = 416;
public const EXPECTATION_FAILED = 417;
public const IM_A_TEAPOT = 418;
public const MISDIRECTED_REQUEST = 421;
public const UNPROCESSABLE_ENTITY = 422;
public const LOCKED = 423;
public const FAILED_DEPENDENCY = 424;
public const UPGRADE_REQUIRED = 426;
public const PRECONDITION_REQUIRED = 428;
public const TOO_MANY_REQUESTS = 429;
public const REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
public const UNAVAILABLE_FOR_LEGAL_REASONS = 451;
public const INTERNAL_SERVER_ERROR = 500;
public const NOT_IMPLEMENTED = 501;
public const BAD_GATEWAY = 502;
public const SERVICE_UNAVAILABLE = 503;
public const GATEWAY_TIMEOUT = 504;
public const HTTP_VERSION_NOT_SUPPORTED = 505;
public const VARIANT_ALSO_NEGOTIATES = 506;
public const INSUFFICIENT_STORAGE = 507;
public const LOOP_DETECTED = 508;
public const NOT_EXTENDED = 510;
public const NETWORK_AUTHENTICATION_REQUIRED = 511;
public const ALL = [
self::OK,
self::CREATED,
self::ACCEPTED,
self::NO_CONTENT,
self::MOVED_PERMANENTLY,
self::FOUND,
self::SEE_OTHER,
self::NOT_MODIFIED,
self::TEMPORARY_REDIRECT,
self::PERMANENT_REDIRECT,
self::BAD_REQUEST,
self::UNAUTHORIZED,
self::FORBIDDEN,
self::NOT_FOUND,
self::METHOD_NOT_ALLOWED,
self::NOT_ACCEPTABLE,
self::REQUEST_TIMEOUT,
self::CONFLICT,
self::GONE,
self::LENGTH_REQUIRED,
self::PRECONDITION_FAILED,
self::PAYLOAD_TOO_LARGE,
self::URI_TOO_LONG,
self::UNSUPPORTED_MEDIA_TYPE,
self::RANGE_NOT_SATISFIABLE,
self::EXPECTATION_FAILED,
self::IM_A_TEAPOT,
self::MISDIRECTED_REQUEST,
self::UNPROCESSABLE_ENTITY,
self::LOCKED,
self::FAILED_DEPENDENCY,
self::UPGRADE_REQUIRED,
self::PRECONDITION_REQUIRED,
self::TOO_MANY_REQUESTS,
self::REQUEST_HEADER_FIELDS_TOO_LARGE,
self::UNAVAILABLE_FOR_LEGAL_REASONS,
self::INTERNAL_SERVER_ERROR,
self::NOT_IMPLEMENTED,
self::BAD_GATEWAY,
self::SERVICE_UNAVAILABLE,
self::GATEWAY_TIMEOUT,
self::HTTP_VERSION_NOT_SUPPORTED,
self::VARIANT_ALSO_NEGOTIATES,
self::INSUFFICIENT_STORAGE,
self::LOOP_DETECTED,
self::NOT_EXTENDED,
self::NETWORK_AUTHENTICATION_REQUIRED
];
}

View file

@ -22,29 +22,65 @@
namespace ncc\Enums;
final class LogLevel
use ncc\Utilities\Validate;
enum LogLevel : string
{
public const SILENT = 'silent';
case SILENT = 'silent';
public const VERBOSE = 'verbose';
case VERBOSE = 'verbose';
public const DEBUG = 'debug';
case DEBUG = 'debug';
public const INFO = 'info';
case INFO = 'info';
public const WARNING = 'warn';
case WARNING = 'warn';
public const ERROR = 'error';
case ERROR = 'error';
public const FATAL = 'fatal';
case FATAL = 'fatal';
public const ALL = [
self::SILENT,
self::VERBOSE,
self::DEBUG,
self::INFO,
self::WARNING,
self::ERROR,
self::FATAL,
];
/**
* Checks if the current log level permits logging at the specified level.
*
* @param LogLevel|null $current_level The log level to be checked. If null, the method returns false.
* @return bool Returns true if logging is permitted at the specified level, otherwise false.
*/
public function checkLogLevel(?LogLevel $current_level): bool
{
if ($current_level === null)
{
return false;
}
return match ($current_level)
{
LogLevel::DEBUG => in_array($this, [LogLevel::DEBUG, LogLevel::VERBOSE, LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::VERBOSE => in_array($this, [LogLevel::VERBOSE, LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::INFO => in_array($this, [LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::WARNING => in_array($this, [LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::ERROR => in_array($this, [LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::FATAL => $this === LogLevel::FATAL,
default => false,
};
}
/**
* Converts the given string input to a LogLevel.
* If the input is invalid or not found, it defaults to LogLevel::INFO.
*
* @param string $input The input string to be converted to a LogLevel.
* @return LogLevel Returns the corresponding LogLevel for the input string or LogLevel::INFO if not found.
*/
public static function fromOrDefault(string $input): LogLevel
{
$value = self::tryFrom($input);
if($value === null)
{
return self::INFO;
}
return $value;
}
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Options;
final class BuildConfigurationOptions
enum BuildConfigurationOptions : string
{
public const COMPRESSION = 'compression';
case COMPRESSION = 'compression';
public const REQUIRE_FILES = 'require_files';
case REQUIRE_FILES = 'require_files';
public const NCC_CONFIGURATION = 'ncc_configuration';
case NCC_CONFIGURATION = 'ncc_configuration';
public const OUTPUT_FILE = 'output_file';
case OUTPUT_FILE = 'output_file';
public const STATIC_DEPENDENCIES = 'static';
case STATIC_DEPENDENCIES = 'static';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums\Options\BuildConfigurationOptions;
final class CompressionOptions
enum CompressionOptions : string
{
public const HIGH = 'high';
case HIGH = 'high';
public const MEDIUM = 'medium';
case MEDIUM = 'medium';
public const LOW = 'low';
case LOW = 'low';
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums\Options;
final class BuildConfigurationValues
enum BuildConfigurationValues : string
{
public const DEFAULT = 'default';
case DEFAULT = 'default';
public const ALL = 'all';
case ALL = 'all';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
final class ComponentDecodeOptions
enum ComponentDecodeOptions : string
{
public const AS_FILE = 'as_file';
case AS_FILE = 'as_file';
}

View file

@ -22,25 +22,25 @@
namespace ncc\Enums\Options;
final class InitializeProjectOptions
enum InitializeProjectOptions : string
{
/**
* A custom path to the project's source directory
*/
public const PROJECT_SRC_PATH = 'PROJECT_SRC_PATH';
case PROJECT_SRC_PATH = 'PROJECT_SRC_PATH';
/**
* A boolean option that indicates whether to overwrite the project file if it already exists
*/
public const OVERWRITE_PROJECT_FILE = 'OVERWRITE_PROJECT_FILE';
case OVERWRITE_PROJECT_FILE = 'OVERWRITE_PROJECT_FILE';
/**
* Composer Only, used to define the package's real version
*/
public const COMPOSER_PACKAGE_VERSION = 'COMPOSER_PACKAGE_VERSION';
case COMPOSER_PACKAGE_VERSION = 'COMPOSER_PACKAGE_VERSION';
/**
* Composer Only, used to define the package's update source
*/
public const COMPOSER_REMOTE_SOURCE = 'COMPOSER_REMOTE_SOURCE';
case COMPOSER_REMOTE_SOURCE = 'COMPOSER_REMOTE_SOURCE';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
final class InstallPackageOptions
enum InstallPackageOptions : string
{
/**
* Skips the installation of dependencies of the package
@ -30,11 +30,23 @@
* @warning This will cause the package to fail to import of
* the dependencies are not met
*/
public const SKIP_DEPENDENCIES = 'skip_dependencies';
case SKIP_DEPENDENCIES = 'skip-dependencies';
/**
* Reinstall all packages if they are already installed,
* Including dependencies if they are being processed.
*/
public const REINSTALL = 'reinstall';
case REINSTALL = 'reinstall';
/**
* Installs a static version of the package if it's available
* otherwise it will install non-static version
*/
case PREFER_STATIC = 'prefer-static';
/**
* Forces ncc to build packages from source rather than trying to obtain
* a pre-built version of the package
*/
case BUILD_SOURCE = 'build-source';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
final class ProjectOptions
enum ProjectOptions : string
{
public const CREATE_SYMLINK = 'create_symlink';
case CREATE_SYMLINK = 'create_symlink';
}

View file

@ -1,38 +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\Enums\Options;
final class RuntimeImportOptions
{
/**
* Indicates if the import should require PHP's autoload.php file
* for the package (Only applies to PHP packages)
*/
public const IMPORT_AUTOLOADER = 'import_autoloader';
/**
* Indicates if the import should require all static files
* for the package (Only applies to PHP packages)
*/
public const IMPORT_STATIC_FILES = 'import_static_files';
}

View file

@ -22,21 +22,21 @@
namespace ncc\Enums;
final class PackageDirectory
enum PackageDirectory : int
{
public const ASSEMBLY = 0x61737365;
case ASSEMBLY = 0x61737365;
public const METADATA = 0x6D657461;
case METADATA = 0x6D657461;
public const INSTALLER = 0x696E7374;
case INSTALLER = 0x696E7374;
public const DEPENDENCIES = 0x64657065;
case DEPENDENCIES = 0x64657065;
public const EXECUTION_UNITS = 0x65786563;
case EXECUTION_UNITS = 0x65786563;
public const COMPONENTS = 0x636F6D70;
case COMPONENTS = 0x636F6D70;
public const RESOURCES = 0x7265736F;
case RESOURCES = 0x7265736F;
public const CLASS_POINTER = 0x636C6173;
case CLASS_POINTER = 0x636C6173;
}

View file

@ -1,28 +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\Enums;
final class PackageStandardVersions
{
public const VERSION_1 = '1.0';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums;
final class PackageStructure
enum PackageStructure : int
{
public const FILE_VERSION = 0x73746669;
case FILE_VERSION = 0x73746669;
public const FLAGS = 0x73736166;
case FLAGS = 0x73736166;
public const DIRECTORY = 0x6f746365;
case DIRECTORY = 0x6f746365;
}

View file

@ -1,44 +1,36 @@
<?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.
*
*/
/*
* 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\Enums;
namespace ncc\Enums;
final class PackageStructureVersions
enum PackageStructureVersions : string
{
/**
* ncc 1.0.0 to 1.0.3
*/
public const _1_0 = '1.0';
case _1_0 = '1.0';
/**
* ncc 1.0.4 and above
*/
public const _2_0 = '2.0';
/**
* All supported versions
*/
public const ALL = [
self::_1_0,
self::_2_0
];
case _2_0 = '2.0';
}

View file

@ -22,23 +22,81 @@
namespace ncc\Enums;
final class ProjectTemplates
enum ProjectTemplates : string
{
/**
* A template that is used to create a PHP library project
*/
public const PHP_LIBRARY = 'phplib';
case PHP_LIBRARY = 'phplib';
/**
* A template that is used to create a PHP CLI application project
*/
public const PHP_CLI = 'phpcli';
case PHP_CLI = 'phpcli';
/**
* An array of all the available project templates
* A template for generating a Makefile for the PHP project
*/
public const ALL = [
self::PHP_LIBRARY,
self::PHP_CLI
];
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

@ -26,27 +26,27 @@
* @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved.
*/
final class RegexPatterns
enum RegexPatterns : string
{
public const UUID = '{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di';
case UUID = '{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di';
public const PACKAGE_NAME_FORMAT = '/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$/';
case PACKAGE_NAME_FORMAT = '/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$/';
public const COMPOSER_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
case COMPOSER_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
public const PYTHON_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
case PYTHON_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
public const SEMANTIC_VERSIONING_2 = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/m';
case SEMANTIC_VERSIONING_2 = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/m';
public const UNIX_PATH = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m';
case UNIX_PATH = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m';
public const CONSTANT_NAME = '/^([^\x00-\x7F]|[\w_\ \.\+\-]){2,64}$/';
case CONSTANT_NAME = '/^([^\x00-\x7F]|[\w_.+]){2,64}$/';
public const EXECUTION_POLICY_NAME = '/^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/m';
case EXECUTION_POLICY_NAME = '/^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/m';
/**
* @author <purplex>
*/
public const REMOTE_PACKAGE = '/^(?<vendor>[^\/\n]+)\/(?<package>[^:=\n@]+)(?:=(?<version>[^:@\n]+))?(?::(?<branch>[^@\n]+))?@(?<source>.*)$/m';
case REMOTE_PACKAGE = '/^(?<vendor>[^\/\n]+)\/(?<package>[^:=\n@]+)(?:=(?<version>[^:@\n]+))?(?::(?<branch>[^@\n]+))?@(?<source>.*)$/m';
}

View file

@ -22,25 +22,15 @@
namespace ncc\Enums;
final class Runners
enum Runners : string
{
public const PHP = 'php';
case PHP = 'php';
public const BASH = 'bash';
case BASH = 'bash';
public const PYTHON = 'python';
case PYTHON = 'python';
public const PERL = 'perl';
case PERL = 'perl';
public const LUA = 'lua';
public const ALL = [
self::PHP,
self::BASH,
self::PYTHON,
self::PYTHON_3,
self::PYTHON_2,
self::PERL,
self::LUA
];
case LUA = 'lua';
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums;
final class Scopes
enum Scopes : string
{
public const USER = 'USER';
case USER = 'USER';
public const SYSTEM = 'SYSTEM';
case SYSTEM = 'SYSTEM';
}

View file

@ -22,50 +22,50 @@
namespace ncc\Enums\SpecialConstants;
final class AssemblyConstants
enum AssemblyConstants : string
{
/**
* Assembly's Name Property
*/
public const ASSEMBLY_NAME = '%ASSEMBLY.NAME%';
case ASSEMBLY_NAME = '%ASSEMBLY.NAME%';
/**
* Assembly's Package Property
*/
public const ASSEMBLY_PACKAGE = '%ASSEMBLY.PACKAGE%';
case ASSEMBLY_PACKAGE = '%ASSEMBLY.PACKAGE%';
/**
* Assembly's Description Property
*/
public const ASSEMBLY_DESCRIPTION = '%ASSEMBLY.DESCRIPTION%';
case ASSEMBLY_DESCRIPTION = '%ASSEMBLY.DESCRIPTION%';
/**
* Assembly's Company Property
*/
public const ASSEMBLY_COMPANY = '%ASSEMBLY.COMPANY%';
case ASSEMBLY_COMPANY = '%ASSEMBLY.COMPANY%';
/**
* Assembly's Product Property
*/
public const ASSEMBLY_PRODUCT = '%ASSEMBLY.PRODUCT%';
case ASSEMBLY_PRODUCT = '%ASSEMBLY.PRODUCT%';
/**
* Assembly's Copyright Property
*/
public const ASSEMBLY_COPYRIGHT = '%ASSEMBLY.COPYRIGHT%';
case ASSEMBLY_COPYRIGHT = '%ASSEMBLY.COPYRIGHT%';
/**
* Assembly's Trademark Property
*/
public const ASSEMBLY_TRADEMARK = '%ASSEMBLY.TRADEMARK%';
case ASSEMBLY_TRADEMARK = '%ASSEMBLY.TRADEMARK%';
/**
* Assembly's Version Property
*/
public const ASSEMBLY_VERSION = '%ASSEMBLY.VERSION%';
case ASSEMBLY_VERSION = '%ASSEMBLY.VERSION%';
/**
* Assembly's UUID property
*/
public const ASSEMBLY_UID = '%ASSEMBLY.UID%';
case ASSEMBLY_UID = '%ASSEMBLY.UID%';
}

View file

@ -22,25 +22,25 @@
namespace ncc\Enums\SpecialConstants;
final class BuildConstants
enum BuildConstants : string
{
/**
* The Unix Timestamp for when the package was compiled
*/
public const COMPILE_TIMESTAMP = '%COMPILE_TIMESTAMP%';
case COMPILE_TIMESTAMP = '%COMPILE_TIMESTAMP%';
/**
* The version of NCC that was used to compile the package
*/
public const NCC_BUILD_VERSION = '%NCC_BUILD_VERSION%';
case NCC_BUILD_VERSION = '%NCC_BUILD_VERSION%';
/**
* NCC Build Flags exploded into spaces
*/
public const NCC_BUILD_FLAGS = '%NCC_BUILD_FLAGS%';
case NCC_BUILD_FLAGS = '%NCC_BUILD_FLAGS%';
/**
* NCC Build Branch
*/
public const NCC_BUILD_BRANCH = '%NCC_BUILD_BRANCH%';
case NCC_BUILD_BRANCH = '%NCC_BUILD_BRANCH%';
}

View file

@ -22,49 +22,49 @@
namespace ncc\Enums\SpecialConstants;
final class DateTimeConstants
enum DateTimeConstants : string
{
// Day Format
/**
* Day of the month, 2 digits with leading zeros
*/
public const d = '%d%'; // 01 through 31
case d = '%d%'; // 01 through 31
/**
* A textual representation of a day, three letters
*/
public const D = '%D%'; // Mon through Sun
case D = '%D%'; // Mon through Sun
/**
* Day of the month without leading zeros
*/
public const j = '%j%'; // 1 through 31
case j = '%j%'; // 1 through 31
/**
* A full textual representation of the day of the week
*/
public const l = '%l%'; // Sunday through Saturday
case l = '%l%'; // Sunday through Saturday
/**
* ISO 8601 numeric representation of the day of the week
*/
public const N = '%N%'; // 1 (Monday) to 7 (Sunday)
case N = '%N%'; // 1 (Monday) to 7 (Sunday)
/**
* English ordinal suffix for the day of the month, 2 characters
*/
public const S = '%S%'; // st, nd, rd, th
case S = '%S%'; // st, nd, rd, th
/**
* Numeric representation of the day of the week
*/
public const w = '%w%'; // 0 (sunday) through 6 (Saturday)
case w = '%w%'; // 0 (sunday) through 6 (Saturday)
/**
* The day of the year (starting from 0)
*/
public const z = '%z%'; // 0 through 365
case z = '%z%'; // 0 through 365
@ -73,7 +73,7 @@
/**
* ISO 8601 week number of year, weeks starting on Monday
*/
public const W = '%W%'; // 42 (42nd week in year)
case W = '%W%'; // 42 (42nd week in year)
@ -82,27 +82,27 @@
/**
* A full textual representation of a month, such as January or March
*/
public const F = '%F%'; // January through December
case F = '%F%'; // January through December
/**
* Numeric representation of a month, with leading zeros
*/
public const m = '%m%'; // 01 through 12
case m = '%m%'; // 01 through 12
/**
* A short textual representation of a month, three letters
*/
public const M = '%M%'; // Jan through Dec
case M = '%M%'; // Jan through Dec
/**
* Numeric representation of a month, without leading zeros
*/
public const n = '%n%'; // 1 through 12
case n = '%n%'; // 1 through 12
/**
* Number of days in the given month
*/
public const t = '%t%'; // 28 through 31
case t = '%t%'; // 28 through 31
@ -110,73 +110,73 @@
/**
* Whether it's a leap year
*/
public const L = '%L%'; // 1 (leap year), 0 otherwise
case L = '%L%'; // 1 (leap year), 0 otherwise
/**
* ISO 8601 week-numbering year. This has the same value as Y,
* except that if the ISO week number (W) belongs to the previous
* or next year, that year is used instead.
*/
public const o = '%o%'; // Same as Y, except that it use week number to decide which year it falls onto
case o = '%o%'; // Same as Y, except that it use week number to decide which year it falls onto
/**
* A full numeric representation of a year, at least 4 digits, with - for years BCE.
*/
public const Y = '%Y%'; // 1991, 2012, 2014, ...
case Y = '%Y%'; // 1991, 2012, 2014, ...
/**
* A two digit representation of a year
*/
public const y = '%y%'; // 91, 12, 14, ...
case y = '%y%'; // 91, 12, 14, ...
// Time Format
/**
* Lowercase Ante meridiem and Post meridiem
*/
public const a = '%a%'; // am or pm
case a = '%a%'; // am or pm
/**
* Uppercase Ante meridiem and Post meridiem
*/
public const A = '%A%'; // AM or PM
case A = '%A%'; // AM or PM
/**
* Swatch Internet time
*/
public const B = '%B%'; // 000 through 999
case B = '%B%'; // 000 through 999
/**
* 12-hour format of an hour without leading zeros
*/
public const g = '%g%'; // 1 through 12
case g = '%g%'; // 1 through 12
/**
* 24-hour format of an hour without leading zeros
*/
public const G = '%G%'; // 0 through 23
case G = '%G%'; // 0 through 23
/**
* 12-hour format of an hour with leading zeros
*/
public const h = '%h%'; // 01 through 12
case h = '%h%'; // 01 through 12
/**
* 24-hour format of an hour with leading zeros
*/
public const H = '%H%'; // 01 through 23
case H = '%H%'; // 01 through 23
/**
* Minutes with leading zeros
*/
public const i = '%i%'; // 01 through 59
case i = '%i%'; // 01 through 59
/**
* Seconds with leading zeros
*/
public const s = '%s%'; // 00 through 59
case s = '%s%'; // 00 through 59
// DateTime format
public const c = '%c%'; // 2004-02-12T15:19:21
public const r = '%r%'; // Thu, 21 Dec 2000 16:01:07
public const u = '%u%'; // Unix Timestamp (seconds since Jan 1 1970 00:00:00)
case c = '%c%'; // 2004-02-12T15:19:21
case r = '%r%'; // Thu, 21 Dec 2000 16:01:07
case u = '%u%'; // Unix Timestamp (seconds since Jan 1 1970 00:00:00)
}

View file

@ -1,6 +1,6 @@
<?php
/*
* Copyright (c) Nosial 2022-2023, all rights reserved.
* 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
@ -20,18 +20,18 @@
*
*/
namespace ncc\Enums\Types;
namespace ncc\Enums\SpecialConstants;
final class BuiltinRemoteSourceType
enum GeneralConstants : string
{
/**
* The remote source indicates the package is to be
* fetched using the composer utility.
* The project's default build configuration
*/
public const COMPOSER = 'composer';
case DEFAULT_BUILD_CONFIGURATION = '%DEFAULT_BUILD_CONFIGURATION%';
public const ALL = [
self::COMPOSER
];
}
/**
* Configurable build output path
*/
case BUILD_OUTPUT_PATH = '%BUILD_OUTPUT_PATH%';
}

View file

@ -22,13 +22,13 @@
namespace ncc\Enums\SpecialConstants;
final class InstallConstants
enum InstallConstants : string
{
public const INSTALL_PATH = '%INSTALL_PATH%';
case INSTALL_PATH = '%INSTALL_PATH%';
public const INSTALL_PATH_BIN = '%INSTALL_PATH.BIN%';
case INSTALL_PATH_BIN = '%INSTALL_PATH.BIN%';
public const INSTALL_PATH_SRC = '%INSTALL_PATH.SRC%';
case INSTALL_PATH_SRC = '%INSTALL_PATH.SRC%';
public const INSTALL_PATH_DATA = '%INSTALL_PATH.DATA%';
case INSTALL_PATH_DATA = '%INSTALL_PATH.DATA%';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums\SpecialConstants;
final class RuntimeConstants
enum RuntimeConstants : string
{
public const CWD = '%CWD%';
public const PID = '%PID%';
public const UID = '%UID%';
public const GID = '%GID%';
public const USER = '%USER%';
case CWD = '%CWD%';
case PID = '%PID%';
case UID = '%UID%';
case GID = '%GID%';
case USER = '%USER%';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Types;
final class AuthenticationType
enum AuthenticationType : int
{
/**
* A combination of a username and password is used for authentication
*/
public const USERNAME_PASSWORD = 1;
case USERNAME_PASSWORD = 1;
/**
* A single private access token is used for authentication
*/
public const ACCESS_TOKEN = 2;
case ACCESS_TOKEN = 2;
}

View file

@ -22,8 +22,8 @@
namespace ncc\Enums\Types;
final class BuildOutputType
enum BuildOutputType : string
{
public const NCC_PACKAGE = 'ncc';
public const EXECUTABLE = 'executable';
case NCC_PACKAGE = 'ncc';
case EXECUTABLE = 'executable';
}

View file

@ -22,35 +22,25 @@
namespace ncc\Enums\Types;
final class ComponentDataType
enum ComponentDataType : string
{
/**
* Indicates whether the component is represented as an AST representation
*/
public const AST = 'ast';
case AST = 'ast';
/**
* Indicates whether the component is represented as plaintext
*/
public const PLAIN = 'plain';
case PLAIN = 'plain';
/**
* Indicates whether the component is represented as binary or executable
*/
public const BINARY = 'binary';
case BINARY = 'binary';
/**
* Indicates whether the component is represented as as a base64 encoded string (Raw bytes' representation)
*/
public const BASE64_ENCODED = 'b64enc';
/**
* All the possible data types of a component
*/
public const ALL = [
self::AST,
self::PLAIN,
self::BINARY,
self::BASE64_ENCODED
];
case BASE64_ENCODED = 'b64enc';
}

View file

@ -22,12 +22,12 @@
namespace ncc\Enums\Types;
final class ComposerPackageTypes
enum ComposerPackageTypes : string
{
/**
* This is the default. It will copy the files to `vendor`
*/
public const LIBRARY = 'library';
case LIBRARY = 'library';
/**
* This denotes a project rather than a library. For example
@ -37,7 +37,7 @@
* to provide listings of projects to initialize when creating
* a new workspace.
*/
public const PROJECT = 'project';
case PROJECT = 'project';
/**
* An empty package that contains requirements and will trigger
@ -45,11 +45,11 @@
* anything to the filesystem. As such, it does not require a
* a dist or source key to be installable
*/
public const METAPACKAGE = 'metapackage';
case METAPACKAGE = 'metapackage';
/**
* A package of type `composer-plugin` may provide an installer
* for other packages that have a custom type.
*/
public const COMPOSER_PLUGIN = 'composer-plugin';
case COMPOSER_PLUGIN = 'composer-plugin';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Types;
final class ComposerStabilityTypes
enum ComposerStabilityTypes : string
{
public const DEV = 'dev';
case DEV = 'dev';
public const ALPHA = 'alpha';
case ALPHA = 'alpha';
public const BETA = 'beta';
case BETA = 'beta';
public const RC = 'rc';
case RC = 'rc';
public const STABLE ='stable';
case STABLE ='stable';
}

View file

@ -1,49 +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\Enums\Types;
final class DependencySourceType
{
/**
* The dependency pointer does not point to a package
*/
public const NONE = 'none';
/**
* Indicates if the dependency is statically linked and the
* reference points to the compiled package of the dependency
*/
public const STATIC = 'static';
/**
* Indicates if the pointer reference points to a remote source
* to fetch the dependency from
*/
public const REMOTE = 'remote';
/**
* Indicates if the pointer reference points to a relative file with the
* filename format "{package_name}=={version}.ncc" to fetch the dependency from
*/
public const LOCAL = 'local';
}

View file

@ -1,28 +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\Enums\Types;
final class EncoderType
{
public const ZI_PROTO = '3';
}

View file

@ -22,10 +22,10 @@
namespace ncc\Enums\Types;
final class HttpRequestType
enum HttpRequestType : string
{
public const GET = 'GET';
public const POST = 'POST';
public const PUT = 'PUT';
public const DELETE = 'DELETE';
case GET = 'GET';
case POST = 'POST';
case PUT = 'PUT';
case DELETE = 'DELETE';
}

View file

@ -22,14 +22,9 @@
namespace ncc\Enums\Types;
final class ProjectType
enum ProjectType : string
{
public const COMPOSER = 'composer';
case COMPOSER = 'composer';
public const NCC = 'ncc';
public const ALL = [
self::COMPOSER,
self::NCC,
];
case NCC = 'ncc';
}

View file

@ -1,56 +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\Enums\Types;
final class RemoteSourceType
{
/**
* A builtin source type is not defined by the user but handled by
* an extension built into NCC
*/
public const BUILTIN = 'builtin';
/**
* A defined source type is defined by the user in the remote sources file
* and handled by an extension designed by passing on the information of
* the source to the extension
*/
public const DEFINED = 'defined';
/**
* Unsupported or invalid source type
*/
public const UNKNOWN = 'unknown';
/**
* No remote source type
*/
public const NONE = 'none';
public const All = [
self::BUILTIN,
self::DEFINED,
self::UNKNOWN,
self::NONE
];
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums\Types;
final class RepositoryResultType
enum RepositoryResultType : string
{
public const SOURCE = 'source';
case SOURCE = 'source';
public const PACKAGE = 'package';
case PACKAGE = 'package';
}

Some files were not shown because too many files have changed in this diff Show more