Bug Fixes Part 3

Also included refactoring of the current Remote repository system to make the codebase easier to maintain
This commit is contained in:
Netkas 2022-12-17 06:58:35 -05:00
parent 722c99879e
commit 61146d1b1d
13 changed files with 752 additions and 415 deletions

View file

@ -323,6 +323,21 @@
*/
const UnsupportedProjectTypeException = -1762;
/**
* @see UnsupportedArchiveException
*/
const UnsupportedArchiveException = -1763;
/**
* @see ArchiveException
*/
const ArchiveException = -1764;
/**
* @see PackageFetchException
*/
const PackageFetchException = -1765;
/**
* All the exception codes from NCC
*/
@ -386,6 +401,9 @@
self::GitTagsException,
self::AuthenticationException,
self::NotSupportedException,
self::UnsupportedProjectTypeException
self::UnsupportedProjectTypeException,
self::UnsupportedArchiveException,
self::ArchiveException,
self::PackageFetchException
];
}

View file

@ -47,7 +47,6 @@
use ncc\Utilities\PathFinder;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use ncc\Utilities\Validate;
use SplFileInfo;
class ComposerSourceBuiltin implements ServiceSourceInterface
@ -277,15 +276,7 @@
{
if (array_key_exists($package_name, $version_map))
{
$version = $version_map[$package_name];
if(stripos($version, 'v') === 0)
$version = substr($version, 1);
if(!Validate::version($version))
$version = Functions::convertToSemVer($version);
if(!Validate::version($version))
return '1.0.0';
return $version;
return Functions::convertToSemVer($version_map[$package_name]);
}
return '1.0.0';
@ -335,7 +326,7 @@
$dependency = new ProjectConfiguration\Dependency();
$dependency->Name = $package_name;
$dependency->SourceType = DependencySourceType::Local;
$dependency->Version = self::versionMap($item->PackageName, $version_map);;
$dependency->Version = self::versionMap($item->PackageName, $version_map);
$dependency->Source = $package_name . '.ncc';
$project_configuration->Build->addDependency($dependency);
}
@ -359,22 +350,6 @@
return $project_configuration;
}
/**
* Extracts a version if available from the input
*
* @param string $input
* @return string|null
*/
private static function extractVersion(string $input): ?string
{
if (stripos($input, ':'))
{
return explode(':', $input)[1];
}
return null;
}
/**
* Gets the applicable options configured for composer
*

View file

@ -2,12 +2,9 @@
namespace ncc\Classes\GithubExtension;
use Exception;
use ncc\Abstracts\HttpRequestType;
use ncc\Abstracts\Versions;
use ncc\Classes\GitClient;
use ncc\Classes\HttpClient;
use ncc\Classes\NccExtension\PackageCompiler;
use ncc\Exceptions\AuthenticationException;
use ncc\Exceptions\GithubServiceException;
use ncc\Exceptions\GitlabServiceException;
@ -18,134 +15,28 @@
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\HttpRequest;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\RepositoryQueryResults;
use ncc\Objects\Vault\Entry;
use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\Validate;
class GithubService implements RepositorySourceInterface
{
/**
* Attempts to fetch the .ncc package from a remote source, optionally attempts to compile
* the package if it cannot find a pre-compiled version.
*
* Priority of fetching:
* - Pre-compiled version
* - Source code of specified release
* - Git repository (checkout specified release)
* - Git repository master branch (If version is not specified or set to latest)
*
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @throws GithubServiceException
*/
public static function fetch(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry): string
{
// Check if there is a pre-compiled version of the package available
try
{
Console::outVerbose(sprintf('Attempting to fetch pre-compiled package from %s', $definedRemoteSource->Host));
$ncc_package = self::getNccPackage($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$ncc_package = null;
unset($e);
}
if($ncc_package !== null)
{
try
{
return Functions::downloadGitServiceFile($ncc_package, $entry);
}
catch(Exception $e)
{
throw new GithubServiceException(sprintf('Failed to download pre-compiled package from %s', $definedRemoteSource->Host), $e);
}
}
// Check if the specified version is a release
try
{
Console::outVerbose(sprintf('Attempting to fetch source code from %s', $definedRemoteSource->Host));
$release_url = self::getRelease($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$release_url = null;
unset($e);
}
// If the specified version is a release, download the source code
if($release_url !== null)
{
try
{
$release_file = Functions::downloadGitServiceFile($release_url, $entry);
$project_path = Functions::extractArchive($release_file);
return PackageCompiler::tryCompile($project_path);
}
catch(Exception $e)
{
throw new GithubServiceException(sprintf('Failed to download release from %s', $definedRemoteSource->Host), $e);
}
}
try
{
Console::outVerbose(sprintf('Attempting to fetch git repository from %s', $definedRemoteSource->Host));
$git_url = self::fetchGitUri($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$git_url = null;
unset($e);
}
if($git_url !== null)
{
try
{
$project_path = GitClient::cloneRepository($git_url);
foreach(GitClient::getTags($project_path) as $tag)
{
$tag = str_replace('v', '', $tag);
if(VersionComparator::compareVersion($tag, $packageInput->Version) === 0)
{
GitClient::checkout($project_path, $tag);
return PackageCompiler::tryCompile($project_path);
}
}
}
catch(Exception $e)
{
throw new GithubServiceException(sprintf('Failed to clone git repository from %s', $definedRemoteSource->Host), $e);
}
}
throw new GithubServiceException('Unable to fetch package from remote source');
}
/**
* Returns the git repository url of the repository, versions cannot be specified.
*
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws AuthenticationException
* @throws GithubServiceException
* @throws GitlabServiceException
* @throws AuthenticationException
* @throws HttpException
* @throws MalformedJsonException
*/
public static function fetchGitUri(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string
public static function getGitRepository(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults
{
$httpRequest = new HttpRequest();
$protocol = ($definedRemoteSource->SSL ? "https" : "http");
@ -153,23 +44,17 @@
$owner_f = str_ireplace(".", "%2F", $owner_f);
$repository = urlencode($packageInput->Package);
$httpRequest->Url = $protocol . '://' . $definedRemoteSource->Host . "/repos/$owner_f/$repository";
$httpRequest->Type = HttpRequestType::GET;
$httpRequest = Functions::prepareGitServiceRequest($httpRequest, $entry, false);
$httpRequest->Headers[] = 'X-GitHub-Api-Version: 2022-11-28';
$httpRequest->Headers[] = 'Accept: application/vnd.github+json';
$response_decoded = self::getJsonResponse($httpRequest, $entry);
$response = HttpClient::request($httpRequest, true);
$query = new RepositoryQueryResults();
$query->Files->GitSshUrl = ($response_decoded['ssh_url'] ?? null);
$query->Files->GitHttpUrl = ($response_decoded['clone_url'] ?? null);
$query->Version = Functions::convertToSemVer($response_decoded['default_branch'] ?? null);
$query->ReleaseDescription = ($response_decoded['description'] ?? null);
$query->ReleaseName = ($response_decoded['name'] ?? null);
if($response->StatusCode != 200)
throw new GithubServiceException(sprintf('Failed to fetch releases for the given repository. Status code: %s', $response->StatusCode));
$response_decoded = Functions::loadJson($response->Body, Functions::FORCE_ARRAY);
return
$response_decoded['git_url'] ??
$response_decoded['clone_url'] ??
$response_decoded['ssh_url'] ??
throw new GithubServiceException('Failed to fetch the repository URL.');
return $query;
}
/**
@ -178,7 +63,7 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws AuthenticationException
* @throws GithubServiceException
* @throws GitlabServiceException
@ -186,42 +71,16 @@
* @throws MalformedJsonException
* @throws VersionNotFoundException
*/
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults
{
$releases = self::getReleases($packageInput, $definedRemoteSource, $entry);
if(count($releases) === 0)
throw new VersionNotFoundException('No releases found for the given repository.');
if($packageInput->Version == Versions::Latest)
{
$latest_version = null;
foreach($releases as $version => $url)
{
if($latest_version == null)
{
$latest_version = $version;
continue;
}
if(VersionComparator::compareVersion($version, $latest_version) == 1)
$latest_version = $version;
}
return $releases[$latest_version]['url'];
}
if(!isset($releases[$packageInput->Version]))
throw new VersionNotFoundException(sprintf('The given version "%s" does not exist.', $packageInput->Version));
return $releases[$packageInput->Version]['url'];
return self::processReleases($packageInput, $definedRemoteSource, $entry);
}
/**
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws AuthenticationException
* @throws GithubServiceException
* @throws GitlabServiceException
@ -229,43 +88,9 @@
* @throws MalformedJsonException
* @throws VersionNotFoundException
*/
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults
{
$releases = self::getReleases($packageInput, $definedRemoteSource, $entry);
if(count($releases) === 0)
throw new VersionNotFoundException('No releases found for the given repository.');
if($packageInput->Version == Versions::Latest)
{
$latest_version = null;
foreach($releases as $version => $url)
{
if($latest_version == null)
{
$latest_version = $version;
continue;
}
if(VersionComparator::compareVersion($version, $latest_version) == 1)
$latest_version = $version;
}
$return = $releases[$latest_version]['package'] ?? null;
if($return === null)
throw new VersionNotFoundException('No releases found for the given repository.');
return $return;
}
if(!isset($releases[$packageInput->Version]))
throw new VersionNotFoundException(sprintf('The given version "%s" does not exist.', $packageInput->Version));
$return = $releases[$packageInput->Version]['package'] ?? null;
if($return === null)
throw new VersionNotFoundException('No releases found for the given repository.');
return $return;
return self::processReleases($packageInput, $definedRemoteSource, $entry);
}
/**
@ -289,17 +114,7 @@
$owner_f = str_ireplace(".", "%2F", $owner_f);
$repository = urlencode($packageInput->Package);
$httpRequest->Url = $protocol . '://' . $definedRemoteSource->Host . "/repos/$owner_f/$repository/releases";
$httpRequest->Type = HttpRequestType::GET;
$httpRequest = Functions::prepareGitServiceRequest($httpRequest, $entry, false);
$httpRequest->Headers[] = 'X-GitHub-Api-Version: 2022-11-28';
$httpRequest->Headers[] = 'Accept: application/vnd.github+json';
$response = HttpClient::request($httpRequest, true);
if($response->StatusCode != 200)
throw new GithubServiceException(sprintf('Failed to fetch releases for the given repository. Status code: %s', $response->StatusCode));
$response_decoded = Functions::loadJson($response->Body, Functions::FORCE_ARRAY);
$response_decoded = self::getJsonResponse($httpRequest, $entry);
if(count($response_decoded) == 0)
return [];
@ -307,20 +122,24 @@
$return = [];
foreach($response_decoded as $release)
{
// Make the tag_name version friendly
$release_version = str_replace('v', '', $release['tag_name']);
$return[$release_version] = [
'url' => ($release['zipball_url'] ?? $release['tarball_url'] ?? null)
];
$query_results = new RepositoryQueryResults();
$query_results->Version = Functions::convertToSemVer($release['tag_name']);
$query_results->ReleaseName = $release['name'];
$query_results->ReleaseDescription = $release['body'];
$query_results->Files->ZipballUrl = ($release['zipball_url'] ?? null);
$query_results->Files->TarballUrl = ($release['tarball_url'] ?? null);
if(isset($release['assets']))
{
foreach($release['assets'] as $asset)
{
if(self::parseAsset($asset) !== null)
$return[$release_version]['package'] = $asset['browser_download_url'];
$parsed_asset = self::parseAsset($asset);
if($parsed_asset !== null)
$query_results->Files->PackageUrl = $parsed_asset;
}
}
$return[$query_results->Version] = $query_results;
}
return $return;
@ -343,4 +162,98 @@
return null;
}
/**
* @param HttpRequest $httpRequest
* @param Entry|null $entry
* @return array
* @throws AuthenticationException
* @throws GithubServiceException
* @throws GitlabServiceException
* @throws HttpException
* @throws MalformedJsonException
*/
private static function getJsonResponse(HttpRequest $httpRequest, ?Entry $entry): array
{
$httpRequest->Type = HttpRequestType::GET;
$httpRequest = Functions::prepareGitServiceRequest($httpRequest, $entry, false);
$httpRequest->Headers[] = 'X-GitHub-Api-Version: 2022-11-28';
$httpRequest->Headers[] = 'Accept: application/vnd.github+json';
$response = HttpClient::request($httpRequest, true);
if ($response->StatusCode != 200)
throw new GithubServiceException(sprintf('Failed to fetch releases for the given repository. Status code: %s', $response->StatusCode));
$response_decoded = Functions::loadJson($response->Body, Functions::FORCE_ARRAY);
return $response_decoded;
}
/**
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return mixed
* @throws AuthenticationException
* @throws GithubServiceException
* @throws GitlabServiceException
* @throws HttpException
* @throws MalformedJsonException
* @throws VersionNotFoundException
*/
private static function processReleases(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry): mixed
{
$releases = self::getReleases($packageInput, $definedRemoteSource, $entry);
if (count($releases) === 0)
throw new VersionNotFoundException('No releases found for the given repository.');
if ($packageInput->Version == Versions::Latest)
{
$latest_version = null;
foreach ($releases as $release)
{
if ($latest_version == null)
{
$latest_version = $release->Version;
continue;
}
if (VersionComparator::compareVersion($release->Version, $latest_version) == 1)
$latest_version = $release->Version;
}
return $releases[$latest_version];
}
// Query a specific version
if (!isset($releases[$packageInput->Version]))
{
// Find the closest thing to the requested version
$selected_version = null;
foreach ($releases as $version => $url)
{
if ($selected_version == null)
{
$selected_version = $version;
continue;
}
if (VersionComparator::compareVersion($version, $packageInput->Version) == 1)
$selected_version = $version;
}
if ($selected_version == null)
throw new VersionNotFoundException('No releases found for the given repository.');
}
else
{
$selected_version = $packageInput->Version;
}
if (!isset($releases[$selected_version]))
throw new VersionNotFoundException(sprintf('No releases found for the given repository. (Selected version: %s)', $selected_version));
return $releases[$selected_version];
}
}

View file

@ -2,11 +2,8 @@
namespace ncc\Classes\GitlabExtension;
use Exception;
use ncc\Abstracts\Versions;
use ncc\Classes\GitClient;
use ncc\Classes\HttpClient;
use ncc\Classes\NccExtension\PackageCompiler;
use ncc\Exceptions\AuthenticationException;
use ncc\Exceptions\GitlabServiceException;
use ncc\Exceptions\HttpException;
@ -17,88 +14,13 @@
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\HttpRequest;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\RepositoryQueryResults;
use ncc\Objects\Vault\Entry;
use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
class GitlabService implements RepositorySourceInterface
{
/**
* Attempts to fetch the requested package from the Gitlab repository, and returns the pre-compiled package
*
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @throws GitlabServiceException
*/
public static function fetch(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry): string
{
// Check if the specified version is a release
try
{
Console::outVerbose(sprintf('Attempting to fetch source code from %s', $definedRemoteSource->Host));
$release_url = self::getRelease($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$release_url = null;
unset($e);
}
// If the specified version is a release, download the source code
if($release_url !== null)
{
try
{
$release_file = Functions::downloadGitServiceFile($release_url, $entry);
$project_path = Functions::extractArchive($release_file);
return PackageCompiler::tryCompile($project_path);
}
catch(Exception $e)
{
throw new GitlabServiceException(sprintf('Failed to download release from %s', $definedRemoteSource->Host), $e);
}
}
try
{
Console::outVerbose(sprintf('Attempting to fetch git repository from %s', $definedRemoteSource->Host));
$git_url = self::fetchGitUri($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$git_url = null;
unset($e);
}
if($git_url !== null)
{
try
{
$project_path = GitClient::cloneRepository($git_url);
foreach(GitClient::getTags($project_path) as $tag)
{
$tag = str_replace('v', '', $tag);
if(VersionComparator::compareVersion($tag, $packageInput->Version) === 0)
{
GitClient::checkout($project_path, $tag);
return PackageCompiler::tryCompile($project_path);
}
}
}
catch(Exception $e)
{
throw new GitlabServiceException(sprintf('Failed to clone git repository from %s', $definedRemoteSource->Host), $e);
}
}
throw new GitlabServiceException('Unable to fetch package from remote source');
}
/**
* Attempts to return the gitRepositoryUrl of a release, cannot specify a version.
* This needs to be done using git
@ -106,13 +28,13 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws AuthenticationException
* @throws GitlabServiceException
* @throws HttpException
* @throws MalformedJsonException
* @throws AuthenticationException
*/
public static function fetchGitUri(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry=null): string
public static function getGitRepository(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry=null): RepositoryQueryResults
{
$httpRequest = new HttpRequest();
$protocol = ($definedRemoteSource->SSL ? "https" : "http");
@ -130,10 +52,14 @@
$response_decoded = Functions::loadJson($response->Body, Functions::FORCE_ARRAY);
return
$response_decoded['http_url_to_repo'] ??
$response_decoded['ssh_url_to_repo'] ??
throw new GitlabServiceException('Failed to fetch the repository URL.');
$query = new RepositoryQueryResults();
$query->Files->GitSshUrl = ($response_decoded['ssh_url_to_repo'] ?? null);
$query->Files->GitHttpUrl = ($response_decoded['http_url_to_repo'] ?? null);
$query->Version = Functions::convertToSemVer($response_decoded['default_branch']) ?? null;
$query->ReleaseDescription = ($response_decoded['description'] ?? null);
$query->ReleaseName = ($response_decoded['name'] ?? null);
return $query;
}
/**
@ -142,52 +68,78 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws AuthenticationException
* @throws GitlabServiceException
* @throws HttpException
* @throws MalformedJsonException
* @throws VersionNotFoundException
*/
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults
{
$releases = self::getReleases($packageInput->Vendor, $packageInput->Package, $definedRemoteSource, $entry);
if(count($releases) === 0)
throw new VersionNotFoundException('No releases found for the given repository.');
// Query the latest package only
if($packageInput->Version == Versions::Latest)
{
$latest_version = null;
foreach($releases as $version => $url)
foreach($releases as $release)
{
if($latest_version == null)
{
$latest_version = $version;
$latest_version = $release->Version;
continue;
}
if(VersionComparator::compareVersion($version, $latest_version) == 1)
$latest_version = $version;
if(VersionComparator::compareVersion($release->Version, $latest_version) == 1)
$latest_version = $release->Version;
}
return $releases[$latest_version];
}
// Query a specific version
if(!isset($releases[$packageInput->Version]))
throw new VersionNotFoundException(sprintf('The given version "%s" does not exist.', $packageInput->Version));
{
// Find the closest thing to the requested version
$selected_version = null;
foreach($releases as $version => $url)
{
if($selected_version == null)
{
$selected_version = $version;
continue;
}
return $releases[$packageInput->Version];
if(VersionComparator::compareVersion($version, $packageInput->Version) == 1)
$selected_version = $version;
}
if($selected_version == null)
throw new VersionNotFoundException('No releases found for the given repository.');
}
else
{
$selected_version = $packageInput->Version;
}
if(!isset($releases[$selected_version]))
throw new VersionNotFoundException(sprintf('No releases found for the given repository. (Selected version: %s)', $selected_version));
return $releases[$selected_version];
}
/**
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
* @throws NotSupportedException
*/
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults
{
throw new NotSupportedException(sprintf('The given repository source "%s" does not support ncc packages.', $definedRemoteSource->Host));
}
@ -230,25 +182,39 @@
$return = [];
foreach($response_decoded as $release)
{
// Make the tag_name version friendly
$release_version = str_replace('v', '', $release['tag_name']);
$query_results = new RepositoryQueryResults();
$query_results->ReleaseName = ($release['name'] ?? null);
$query_results->ReleaseDescription = ($release['description'] ?? null);
$query_results->Version = Functions::convertToSemVer($release['tag_name']);
if(isset($release['assets']) && isset($release['assets']['sources']))
{
if(count($release['assets']['sources']) > 0)
{
// Use the first source as the download url, if a tar.gz file is available, use that instead.
$return[$release_version] = $release['assets']['sources'][0]['url'];
foreach($release['assets']['sources'] as $source)
{
if($source['format'] == 'zip')
{
$return[$release_version] = $source['url'];
$query_results->Files->ZipballUrl = $source['url'];
break;
}
if($source['format'] == 'tar.gz')
{
$query_results->Files->ZipballUrl = $source['url'];
break;
}
if($source['format'] == 'ncc')
{
$query_results->Files->PackageUrl = $source['url'];
break;
}
}
}
}
$return[$query_results->Version] = $query_results;
}
return $return;

View file

@ -5,10 +5,14 @@
use Exception;
use ncc\Abstracts\CompilerExtensions;
use ncc\Abstracts\ConstantReferences;
use ncc\Abstracts\DefinedRemoteSourceType;
use ncc\Abstracts\LogLevel;
use ncc\Abstracts\Options\BuildConfigurationValues;
use ncc\Abstracts\ProjectType;
use ncc\Classes\ComposerExtension\ComposerSourceBuiltin;
use ncc\Classes\GitClient;
use ncc\Classes\GithubExtension\GithubService;
use ncc\Classes\GitlabExtension\GitlabService;
use ncc\Classes\PhpExtension\PhpCompiler;
use ncc\CLI\Main;
use ncc\Exceptions\AccessDeniedException;
@ -17,17 +21,24 @@
use ncc\Exceptions\FileNotFoundException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\MalformedJsonException;
use ncc\Exceptions\PackageFetchException;
use ncc\Exceptions\PackagePreparationFailedException;
use ncc\Exceptions\ProjectConfigurationNotFoundException;
use ncc\Exceptions\UnsupportedCompilerExtensionException;
use ncc\Exceptions\UnsupportedProjectTypeException;
use ncc\Exceptions\UnsupportedRemoteSourceTypeException;
use ncc\Exceptions\UnsupportedRunnerException;
use ncc\Interfaces\CompilerInterface;
use ncc\Interfaces\RepositorySourceInterface;
use ncc\Managers\ProjectManager;
use ncc\ncc;
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\Package;
use ncc\Objects\ProjectConfiguration;
use ncc\Objects\ProjectConfiguration\Assembly;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\Vault\Entry;
use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
@ -96,10 +107,13 @@
* @throws BuildException
* @throws UnsupportedProjectTypeException
*/
public static function tryCompile(string $path): string
public static function tryCompile(string $path, ?string $version=null): string
{
$project_type = Resolver::detectProjectType($path);
if($version !== null)
$version = Functions::convertToSemVer($version);
try
{
if($project_type->ProjectType == ProjectType::Composer)
@ -108,6 +122,7 @@
if($project_type->ProjectType == ProjectType::Ncc)
{
$project_manager = new ProjectManager($project_type->ProjectPath);
$project_manager->getProjectConfiguration()->Assembly->Version = $version;
return $project_manager->build();
}
}
@ -119,6 +134,7 @@
throw new UnsupportedProjectTypeException('The project type \'' . $project_type->ProjectType . '\' is not supported');
}
/**
* Compiles the execution policies of the package
*

View file

@ -0,0 +1,15 @@
<?php
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class ArchiveException extends Exception
{
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::ArchiveException, $previous);
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace ncc\Exceptions;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class PackageFetchException extends \Exception
{
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::PackageFetchException, $previous);
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class UnsupportedArchiveException extends Exception
{
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::UnsupportedArchiveException, $previous);
$this->message = $message;
}
}

View file

@ -4,6 +4,7 @@
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\RepositoryQueryResults;
use ncc\Objects\Vault\Entry;
interface RepositorySourceInterface
@ -14,9 +15,9 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
*/
public static function fetchGitUri(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry=null): string;
public static function getGitRepository(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry=null): RepositoryQueryResults;
/**
* Returns the release url of the repository, versions can be specified.
@ -24,9 +25,9 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
*/
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string;
public static function getRelease(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults;
/**
* Returns the download URL of the pre-compiled .ncc package if available
@ -34,7 +35,7 @@
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return string
* @return RepositoryQueryResults
*/
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): string;
public static function getNccPackage(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry = null): RepositoryQueryResults;
}

View file

@ -8,15 +8,13 @@
use ncc\Abstracts\BuiltinRemoteSourceType;
use ncc\Abstracts\CompilerExtensions;
use ncc\Abstracts\ConstantReferences;
use ncc\Abstracts\DefinedRemoteSourceType;
use ncc\Abstracts\DependencySourceType;
use ncc\Abstracts\LogLevel;
use ncc\Abstracts\RemoteSourceType;
use ncc\Abstracts\Scopes;
use ncc\Abstracts\Versions;
use ncc\Classes\ComposerExtension\ComposerSourceBuiltin;
use ncc\Classes\GithubExtension\GithubService;
use ncc\Classes\GitlabExtension\GitlabService;
use ncc\Classes\GitClient;
use ncc\Classes\NccExtension\PackageCompiler;
use ncc\Classes\PhpExtension\PhpInstaller;
use ncc\CLI\Main;
@ -28,13 +26,14 @@
use ncc\Exceptions\MissingDependencyException;
use ncc\Exceptions\NotImplementedException;
use ncc\Exceptions\PackageAlreadyInstalledException;
use ncc\Exceptions\PackageFetchException;
use ncc\Exceptions\PackageLockException;
use ncc\Exceptions\PackageNotFoundException;
use ncc\Exceptions\PackageParsingException;
use ncc\Exceptions\UnsupportedCompilerExtensionException;
use ncc\Exceptions\UnsupportedRemoteSourceTypeException;
use ncc\Exceptions\UnsupportedRunnerException;
use ncc\Exceptions\VersionNotFoundException;
use ncc\Interfaces\RepositorySourceInterface;
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\InstallationPaths;
use ncc\Objects\Package;
@ -43,9 +42,11 @@
use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\Vault\Entry;
use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
use ncc\ThirdParty\theseer\DirectoryScanner\DirectoryScanner;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\IO;
use ncc\Utilities\PathFinder;
use ncc\Utilities\Resolver;
@ -80,6 +81,7 @@
* Installs a local package onto the system
*
* @param string $package_path
* @param Entry|null $entry
* @return string
* @throws AccessDeniedException
* @throws FileNotFoundException
@ -340,75 +342,122 @@
/**
* @param string $source
* @param Entry|null $auth_entry
* @param Entry|null $entry
* @return string
* @throws InstallationException
* @throws NotImplementedException
* @throws PackageFetchException
*/
public function fetchFromSource(string $source, ?Entry $auth_entry=null): string
public function fetchFromSource(string $source, ?Entry $entry=null): string
{
$parsed_source = new RemotePackageInput($source);
$input = new RemotePackageInput($source);
if($parsed_source->Source == null)
throw new InstallationException('No source specified');
if($parsed_source->Package == null)
throw new InstallationException('No package specified');
if($parsed_source->Version == null)
$parsed_source->Version = Versions::Latest;
$remote_source_type = Resolver::detectRemoteSourceType($parsed_source->Source);
if($input->Source == null)
throw new PackageFetchException('No source specified');
if($input->Package == null)
throw new PackageFetchException('No package specified');
if($input->Version == null)
$input->Version = Versions::Latest;
$remote_source_type = Resolver::detectRemoteSourceType($input->Source);
if($remote_source_type == RemoteSourceType::Builtin)
{
switch($parsed_source->Source)
switch($input->Source)
{
case BuiltinRemoteSourceType::Composer:
try
{
return ComposerSourceBuiltin::fetch($parsed_source);
return ComposerSourceBuiltin::fetch($input);
}
catch(Exception $e)
{
throw new InstallationException('Cannot fetch package from composer source, ' . $e->getMessage(), $e);
throw new PackageFetchException('Cannot fetch package from composer source, ' . $e->getMessage(), $e);
}
default:
throw new InstallationException('Builtin source type ' . $parsed_source->Source . ' is not implemented');
throw new NotImplementedException('Builtin source type ' . $input->Source . ' is not implemented');
}
}
if($remote_source_type == RemoteSourceType::Defined)
{
$remote_source_manager = new RemoteSourcesManager();
$remote_source = $remote_source_manager->getRemoteSource($parsed_source->Source);
if($remote_source == null)
throw new InstallationException('Remote source ' . $parsed_source->Source . ' is not defined');
$source = $remote_source_manager->getRemoteSource($input->Source);
if($source == null)
throw new InstallationException('Remote source ' . $input->Source . ' is not defined');
/** @var RepositorySourceInterface $remote_service_client */
$remote_service_client = match ($remote_source->Type) {
DefinedRemoteSourceType::Gitlab => GitlabService::class,
DefinedRemoteSourceType::Github => GithubService::class,
default => throw new InstallationException('Remote source type ' . $remote_source->Type . ' is not implemented'),
};
$repositoryQueryResults = Functions::getRepositoryQueryResults($input, $source, $entry);
try
if($repositoryQueryResults->Files->ZipballUrl !== null)
{
return $remote_service_client::fetch($parsed_source, $remote_source, $auth_entry);
try
{
$archive = Functions::downloadGitServiceFile($repositoryQueryResults->Files->ZipballUrl, $entry);
return PackageCompiler::tryCompile(Functions::extractArchive($archive), $repositoryQueryResults->Version);
}
catch(Exception $e)
{
unset($e);
}
}
catch(Exception $e)
if($repositoryQueryResults->Files->TarballUrl !== null)
{
throw new InstallationException('Cannot fetch package from remote source, ' . $e->getMessage(), $e);
try
{
$archive = Functions::downloadGitServiceFile($repositoryQueryResults->Files->TarballUrl, $entry);
return PackageCompiler::tryCompile(Functions::extractArchive($archive), $repositoryQueryResults->Version);
}
catch(Exception $e)
{
unset($e);
}
}
if($repositoryQueryResults->Files->PackageUrl !== null)
{
try
{
return Functions::downloadGitServiceFile($repositoryQueryResults->Files->PackageUrl, $entry);
}
catch(Exception $e)
{
unset($e);
}
}
if($repositoryQueryResults->Files->GitHttpUrl !== null || $repositoryQueryResults->Files->GitSshUrl !== null)
{
try
{
$git_repository = GitClient::cloneRepository($repositoryQueryResults->Files->GitHttpUrl ?? $repositoryQueryResults->Files->GitSshUrl);
foreach(GitClient::getTags($git_repository) as $tag)
{
if(VersionComparator::compareVersion($tag, $repositoryQueryResults->Version) === 0)
{
GitClient::checkout($git_repository, $tag);
return PackageCompiler::tryCompile($git_repository, $repositoryQueryResults->Version);
}
}
}
catch(Exception $e)
{
unset($e);
}
}
throw new PackageFetchException(sprintf('Failed to fetch package \'%s\'', $input->Package));
}
throw new InstallationException(sprintf('Unknown remote source type %s', $remote_source_type));
throw new PackageFetchException(sprintf('Unknown remote source type %s', $remote_source_type));
}
/**
* Installs a package from a source syntax (vendor/package=version@source)
*
* @param string $source
* @param Entry|null $entry
* @return string
* @throws InstallationException
*/
@ -429,6 +478,7 @@
* @param Dependency $dependency
* @param Package $package
* @param string $package_path
* @param Entry|null $entry
* @return void
* @throws AccessDeniedException
* @throws FileNotFoundException

View file

@ -0,0 +1,46 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects;
use ncc\Objects\RepositoryQueryResults\Files;
class RepositoryQueryResults
{
/**
* A collection of files that are available for download
*
* @var Files
*/
public $Files;
/**
* The version of the package returned by the query
*
* @var string|null
*/
public $Version;
/**
* The name of the release returned by the query
*
* @var string|null
*/
public $ReleaseName;
/**
* The description of the release returned by the query
*
* @var string|null
*/
public $ReleaseDescription;
/**
* Public Constructor
*/
public function __construct()
{
$this->Files = new Files();
}
}

View file

@ -0,0 +1,50 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects\RepositoryQueryResults;
class Files
{
/**
* The URL that points to a pre-compiled .ncc package
*
* @var string|null
*/
public $PackageUrl;
/**
* The URL that points to a archived version of the source code
*
* @var string|null
*/
public $SourceUrl;
/**
* The URL that points to a tarball archive of the repository
*
* @var string|null
*/
public $TarballUrl;
/**
* The URL that points to a zip archive of the repository
*
* @var string
*/
public $ZipballUrl;
/**
* The URL that points to the repository's source code
*
* @var string
*/
public $GitHttpUrl;
/**
* The URL that points to the repository's source code
*
* @var string
*/
public $GitSshUrl;
}

View file

@ -4,10 +4,13 @@
use Exception;
use ncc\Abstracts\AuthenticationType;
use ncc\Abstracts\DefinedRemoteSourceType;
use ncc\Abstracts\HttpRequestType;
use ncc\Abstracts\Runners;
use ncc\Abstracts\Scopes;
use ncc\Classes\BashExtension\BashRunner;
use ncc\Classes\GithubExtension\GithubService;
use ncc\Classes\GitlabExtension\GitlabService;
use ncc\Classes\HttpClient;
use ncc\Classes\LuaExtension\LuaRunner;
use ncc\Classes\PerlExtension\PerlRunner;
@ -16,6 +19,7 @@
use ncc\Classes\PythonExtension\Python3Runner;
use ncc\Classes\PythonExtension\PythonRunner;
use ncc\Exceptions\AccessDeniedException;
use ncc\Exceptions\ArchiveException;
use ncc\Exceptions\AuthenticationException;
use ncc\Exceptions\FileNotFoundException;
use ncc\Exceptions\GitlabServiceException;
@ -23,23 +27,29 @@
use ncc\Exceptions\InvalidScopeException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\MalformedJsonException;
use ncc\Exceptions\UnsupportedArchiveException;
use ncc\Exceptions\UnsupportedRunnerException;
use ncc\Managers\ConfigurationManager;
use ncc\Managers\CredentialManager;
use ncc\Managers\PackageLockManager;
use ncc\Objects\CliHelpSection;
use ncc\Objects\ComposerJson;
use ncc\Objects\DefinedRemoteSource;
use ncc\Objects\HttpRequest;
use ncc\Objects\Package\ExecutionUnit;
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
use ncc\Objects\RemotePackageInput;
use ncc\Objects\RepositoryQueryResults;
use ncc\Objects\RepositoryQueryResults\Files;
use ncc\Objects\Vault\Entry;
use ncc\ThirdParty\jelix\Version\Parser;
use ncc\ThirdParty\jelix\Version\VersionComparator;
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
use PharData;
use ncc\ThirdParty\Symfony\Process\ExecutableFinder;
use ncc\ThirdParty\Symfony\Process\Process;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Throwable;
use ZipArchive;
/**
* @author Zi Xing Narrakas
@ -584,40 +594,96 @@
/**
* @param string $path
* @return string
* @throws Exception
* @return string|null
* @throws ArchiveException
* @throws UnsupportedArchiveException
*/
public static function extractArchive(string $path): ?string
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $path);
finfo_close($finfo);
$executable_finder = new ExecutableFinder();
$unzip_executable = $executable_finder->find('unzip');
$tar_executable = $executable_finder->find('tar');
$out_path = dirname($path);
$filesystem = new Filesystem();
if ($mimeType == 'application/zip')
if(!$filesystem->exists($out_path))
$filesystem->mkdir($out_path);
RuntimeCache::setFileAsTemporary($out_path);
$mimeType = mime_content_type($path);
$supportedTypes = [];
if($unzip_executable !== null)
{
$zip = new ZipArchive;
$res = $zip->open($path);
if ($res === TRUE)
$supportedTypes = array_merge($supportedTypes, [
'application/zip',
'application/x-zip',
'application/x-zip-compressed',
'application/octet-stream',
'application/x-compress',
'application/x-compressed',
'multipart/x-zip'
]);
}
else
{
if(RuntimeCache::get('warning_zip_shown') !== true)
{
$zip->extractTo(dirname($path));
$zip->close();
return dirname($path);
Console::out('unzip executable not found. ZIP archives will not be supported.');
RuntimeCache::set('warning_zip_shown', true);
}
}
if ($mimeType == 'application/x-tar' || $mimeType == 'application/tar')
if($tar_executable !== null)
{
$phar = new PharData($path);
$phar->extractTo(dirname($path), null, true);
return dirname($path);
$supportedTypes = array_merge($supportedTypes, [
'application/x-tar',
'application/x-gzip',
'application/x-bzip2',
'application/x-xz'
]);
}
elseif ($mimeType == 'application/x-gzip' || $mimeType == 'application/gzip')
else
{
$phar = new PharData($path);
$phar->decompress();
return dirname($path);
if(RuntimeCache::get('warning_tar_shown') !== true)
{
Console::outWarning('tar executable not found. TAR archives will not be supported.');
RuntimeCache::set('warning_tar_shown', true);
}
}
return null;
if (!in_array($mimeType, $supportedTypes))
throw new UnsupportedArchiveException("Unsupported archive type: $mimeType");
switch($mimeType)
{
case 'application/zip':
$command = [$unzip_executable, $path, '-d', $out_path];
break;
case 'application/x-tar':
$command = [$tar_executable, '--verbose', '-xf', $path, '-C', $out_path];
break;
case 'application/x-gzip':
$command = [$tar_executable, '--verbose', '-xzf', $path, '-C', $out_path];
break;
case 'application/x-bzip2':
$command = [$tar_executable, '--verbose', '-xjf', $path, '-C', $out_path];
break;
}
Console::out("Extracting archive $path");
$process = new Process($command);
// display the output of the command
$process->run(function ($type, $buffer) {
Console::outVerbose($buffer);
});
if (!$process->isSuccessful())
throw new ArchiveException($process->getErrorOutput());
return $out_path;
}
/**
@ -649,20 +715,207 @@
* @param $version
* @return string
*/
public static function convertToSemVer($version)
public static function convertToSemVer($version): string
{
$parts = explode('.', $version);
$major = $parts[0];
$minor = $parts[1];
$patch = $parts[2];
$buildmetadata = $parts[3];
if(stripos($version, 'v') === 0)
$version = substr($version, 1);
if(!Validate::version($version))
{
$parts = explode('.', $version);
$major = (string)null;
$minor = (string)null;
$patch = (string)null;
// Assemble the SemVer compatible string
$semver = "$major.$minor.$patch+$buildmetadata";
$buildmetadata = (string)null;
if(count($parts) >= 1)
$major = $parts[0];
if(count($parts) >= 2)
$minor = $parts[1];
if(count($parts) >= 3)
$patch = $parts[2];
return $semver;
// Assemble the SemVer compatible string
$version = "$major.$minor.$patch";
}
if(!Validate::version($version))
return '1.0.0';
return $version;
}
/**
* Returns a complete RepositoryQueryResults object
*
* @param RemotePackageInput $packageInput
* @param DefinedRemoteSource $definedRemoteSource
* @param Entry|null $entry
* @return RepositoryQueryResults
*/
public static function getRepositoryQueryResults(RemotePackageInput $packageInput, DefinedRemoteSource $definedRemoteSource, ?Entry $entry): RepositoryQueryResults
{
$results = new RepositoryQueryResults();
switch($definedRemoteSource->Type)
{
case DefinedRemoteSourceType::Github:
$source = GithubService::class;
break;
case DefinedRemoteSourceType::Gitlab:
$source = GitlabService::class;
break;
default:
return $results;
}
// Check if the specified version is a release
try
{
Console::outVerbose(sprintf('Attempting to fetch source code from %s', $definedRemoteSource->Host));
$release_results = $source::getRelease($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$release_results = null;
unset($e);
}
// If the specified version is a release, download the source code
if($release_results !== null)
{
$results->ReleaseName = ($release_results->ReleaseName ?? null);
$results->ReleaseDescription = ($release_results->ReleaseDescription ?? null);
$results->Files = self::mergeFilesResults($release_results->Files, ($results->Files ?? null));
if($release_results->Version !== null)
$results->Version = $release_results->Version;
}
try
{
$git_results = $source::getGitRepository($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
$git_results = null;
unset($e);
}
if($git_results !== null)
{
if($results->ReleaseName == null)
{
$results->ReleaseName = ($git_results->ReleaseName ?? null);
}
elseif($git_results->ReleaseName !== null)
{
if(strlen($git_results->ReleaseName) > strlen($results->ReleaseName))
$results->ReleaseName = $git_results->ReleaseName;
}
if($results->ReleaseDescription == null)
{
$results->ReleaseDescription = ($git_results->ReleaseDescription ?? null);
}
elseif($git_results->ReleaseDescription !== null)
{
if(strlen($git_results->ReleaseDescription) > strlen($results->ReleaseDescription))
$results->ReleaseDescription = $git_results->ReleaseDescription;
}
if($results->Version == null)
{
$results->Version = ($git_results->Version ?? null);
}
elseif($git_results->Version !== null)
{
// Version compare
if(VersionComparator::compareVersion($git_results->Version, $results->Version) > 0)
$results->Version = $git_results->Version;
}
$results->Files = self::mergeFilesResults($git_results->Files, ($results->Files ?? null));
}
try
{
$ncc_package_results = $source::getNccPackage($packageInput, $definedRemoteSource, $entry);
}
catch(Exception $e)
{
unset($e);
$ncc_package_results = null;
}
if($ncc_package_results !== null)
{
if($results->ReleaseName == null)
{
$results->ReleaseName = ($ncc_package_results->ReleaseName ?? null);
}
elseif($ncc_package_results->ReleaseName !== null)
{
if(strlen($ncc_package_results->ReleaseName) > strlen($results->ReleaseName))
$results->ReleaseName = $ncc_package_results->ReleaseName;
}
if($results->ReleaseDescription == null)
{
$results->ReleaseDescription = ($ncc_package_results->ReleaseDescription ?? null);
}
elseif($ncc_package_results->ReleaseDescription !== null)
{
if(strlen($ncc_package_results->ReleaseDescription) > strlen($results->ReleaseDescription))
$results->ReleaseDescription = $ncc_package_results->ReleaseDescription;
}
if($results->Version == null)
{
$results->Version = ($ncc_package_results->Version ?? null);
}
elseif($ncc_package_results->Version !== null)
{
// Version compare
if(VersionComparator::compareVersion($ncc_package_results->Version, $results->Version) > 0)
$results->Version = $ncc_package_results->Version;
}
$results->Files = self::mergeFilesResults($ncc_package_results->Files, ($results->Files ?? null));
}
return $results;
}
/**
* Merges the given Files object with another Files object
*
* @param Files $input
* @param Files|null $selected
* @return Files
*/
private static function mergeFilesResults(RepositoryQueryResults\Files $input, ?RepositoryQueryResults\Files $selected=null): RepositoryQueryResults\Files
{
if($selected == null)
$selected = new RepositoryQueryResults\Files();
if($input->GitSshUrl !== null)
$selected->GitSshUrl = $input->GitSshUrl;
if($input->GitHttpUrl !== null)
$selected->GitHttpUrl = $input->GitHttpUrl;
if($input->SourceUrl !== null)
$selected->SourceUrl = $input->SourceUrl;
if($input->TarballUrl !== null)
$selected->TarballUrl = $input->TarballUrl;
if($input->ZipballUrl !== null)
$selected->ZipballUrl = $input->ZipballUrl;
if($input->PackageUrl !== null)
$selected->PackageUrl = $input->PackageUrl;
return $selected;
}
}