Added 'Latest' to \ncc\Abstracts > Versions

Added SourcesMenu.php
Updated \ncc\Utilities > PathFinder
Added 'source' menu to \ncc\CLI
Added method \ncc\Utilities\Functions > getTmpDir()
Updated \ncc\CLI > HelpMenu
Updated \ncc\Utilities > HttpClient
Updated \ncc\Objects > HttpRequest
Updated php.xml for .idea
Added \ncc\Exception > GitlabServiceException
Added \ncc\Exceptions > GitCloneException
Added \ncc\Exceptions > GitCheckoutException
Updated \ncc\Abstracts > ExceptionCodes
Updated \ncc\Abstracts > DefinedRemoteSourceType
Added \ncc\Objects > DefinedRemoteSource
Renamed ComposerSource to \ncc\Classes\ComposerExtension > ComposerSourceBuiltin
Renamed RemoteSource to \ncc\Abstracts > BuiltinRemoteSourceType
This commit is contained in:
Netkas 2022-12-14 20:02:57 -05:00
parent b3c8779313
commit cccbe3f934
18 changed files with 505 additions and 22 deletions

17
.idea/php.xml generated
View file

@ -1,11 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="/usr/share/php" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1">
<component name="PhpProjectSharedConfiguration" php_language_level="8.2">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

View file

@ -0,0 +1,17 @@
<?php
namespace ncc\Abstracts;
abstract class BuiltinRemoteSourceType
{
/**
* The remote source indicates the package is to be
* fetched using the composer utility.
*/
const Composer = 'composer';
const All = [
self::Composer
];
}

View file

@ -4,9 +4,45 @@
abstract class DefinedRemoteSourceType
{
/**
* The remote source is from a generic remote git server
* (Will search for packages with /group/package)
*
* For example if the host is git.example.com and the package is
* group/package, the package will be fetched from
* https://git.example.com/group/package.git
*
* The git client will be used to fetch the package
* but NCC will not be able to easily check for updates
* without having to pull the entire repository
*/
const Git = 'git';
/**
* THe remote source is from gitlab or a custom gitlab instance
*
* Will use an API wrapper to interact with the gitlab instance
* to fetch the package and check for updates without having to
* pull the entire repository
*
* Will still use git to fetch the package from the gitlab instance
*/
const Gitlab = 'gitlab';
/**
* The remote source is from GitHub
*
* Will use an API wrapper to interact with the GitHub instance
* to fetch the package and check for updates without having to
* pull the entire repository
*
* Will still use git to fetch the package from the GitHub instance
*/
const Github = 'github';
const All = [
self::Git,
self::Gitlab,
self::Github
];
}

View file

@ -2,6 +2,8 @@
namespace ncc\Abstracts;
use ncc\Exceptions\GitlabServiceException;
/**
* @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2022. Nosial - All Rights Reserved.
@ -278,6 +280,22 @@
*/
const UnsupportedRemoteSourceTypeException = -1753;
/**
* @see GitCloneException
*/
const GitCloneException = -1754;
/**
* @see GitCheckoutException
*/
const GitCheckoutException = -1755;
/**
* @see GitlabServiceException
*/
const GitlabServiceException = -1756;
/**
* All the exception codes from NCC
*/
@ -334,6 +352,9 @@
self::UserAbortedOperationException,
self::MissingDependencyException,
self::HttpException,
self::UnsupportedRemoteSourceTypeException
self::UnsupportedRemoteSourceTypeException,
self::GitCloneException,
self::GitCheckoutException,
self::GitlabServiceException
];
}

View file

@ -1,16 +0,0 @@
<?php
namespace ncc\Abstracts;
abstract class RemoteSource
{
/**
* The remote source is from composer
*/
const Composer = 'composer';
/**
* The remote source is from a git repository
*/
const Git = 'git';
}

View file

@ -18,4 +18,9 @@
* The current version of the package lock structure file format
*/
const PackageLockVersion = '1.0.0';
/**
* Generic version of the package structure file format (latest)
*/
const Latest = 'latest';
}

View file

@ -75,6 +75,7 @@
new CliHelpSection(['cache'], 'Manages the system cache'),
new CliHelpSection(['cred'], 'Manages credentials'),
new CliHelpSection(['config'], 'Changes NCC configuration values'),
new CliHelpSection(['source'], 'Manages remote sources'),
]);
}

View file

@ -122,6 +122,10 @@
ConfigMenu::start(self::$args);
exit(0);
case 'source':
SourcesMenu::start(self::$args);
exit(0);
case '1':
case 'help':
HelpMenu::start(self::$args);

220
src/ncc/CLI/SourcesMenu.php Normal file
View file

@ -0,0 +1,220 @@
<?php
namespace ncc\CLI;
use Exception;
use ncc\Abstracts\Scopes;
use ncc\Exceptions\IOException;
use ncc\Managers\RemoteSourcesManager;
use ncc\Objects\CliHelpSection;
use ncc\Objects\DefinedRemoteSource;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\Resolver;
class SourcesMenu
{
/**
* Displays the main help menu
*
* @param $args
* @return void
*/
public static function start($args): void
{
if(isset($args['add']))
{
try
{
self::addEntry($args);
}
catch(Exception $e)
{
Console::outException('Error while adding entry.', $e, 1);
}
return;
}
if(isset($args['remove']))
{
try
{
self::removeEntry($args);
}
catch(Exception $e)
{
Console::outException('Cannot remove entry.', $e, 1);
}
return;
}
if(isset($args['list']))
{
try
{
self::listEntries();
}
catch(Exception $e)
{
Console::outException('Cannot list entries.', $e, 1);
}
return;
}
self::displayOptions();
}
/**
* @return void
*/
public static function listEntries(): void
{
$source_manager = new RemoteSourcesManager();
$sources = $source_manager->getSources();
if(count($sources) == 0)
{
Console::out('No remote sources defined.', 1);
return;
}
Console::out('Remote sources:', 1);
foreach($sources as $source)
{
Console::out(' - ' . $source->Name . ' (' . $source->Host . ')', 1);
}
Console::out('Total: ' . count($sources), 1);
}
/**
* @param $args
* @return void
*/
public static function addEntry($args): void
{
if(Resolver::resolveScope() !== Scopes::System)
{
Console::outError('Insufficient permissions to add entry.', true, 1);
return;
}
$name = $args['name'] ?? null;
$type = $args['type'] ?? null;
$host = $args['host'] ?? null;
$ssl = $args['ssl'] ?? null;
if($name == null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'name'), true, 1);
return;
}
if($type == null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'type'), true, 1);
return;
}
if($host == null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'host'), true, 1);
return;
}
if($ssl !== null)
{
$ssl = Functions::cbool($ssl);
}
$source_manager = new RemoteSourcesManager();
$source = new DefinedRemoteSource();
$source->Name = $name;
$source->Type = $type;
$source->Host = $host;
$source->SSL = $ssl;
if(!$source_manager->addRemoteSource($source))
{
Console::outError(sprintf('Cannot add entry \'%s\', it already exists', $name), true, 1);
return;
}
try
{
$source_manager->save();
}
catch (IOException $e)
{
Console::outException('Cannot save remote sources file.', $e, 1);
return;
}
Console::out(sprintf('Entry \'%s\' added successfully.', $name));
}
/**
* Removes an existing entry from the vault.
*
* @param $args
* @return void
*/
private static function removeEntry($args): void
{
$ResolvedScope = Resolver::resolveScope();
if($ResolvedScope !== Scopes::System)
Console::outError('Insufficient permissions to remove entries');
$name = $args['name'] ?? null;
if($name == null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'name'), true, 1);
return;
}
$source_manager = new RemoteSourcesManager();
if(!$source_manager->deleteRemoteSource($name))
{
Console::outError(sprintf('Cannot remove entry \'%s\', it does not exist', $name), true, 1);
return;
}
try
{
$source_manager->save();
}
catch (IOException $e)
{
Console::outException('Cannot save remote sources file.', $e, 1);
return;
}
Console::out(sprintf('Entry \'%s\' removed successfully.', $name));
}
/**
* Displays the main options section
*
* @return void
*/
private static function displayOptions(): void
{
Console::out('Usage: ncc sources {command} [options]');
Console::out('Options:');
Console::outHelpSections([
new CliHelpSection(['help'], 'Displays this help menu about the sources command'),
new CliHelpSection(['add'], 'Adds a new entry to the list of remote sources (See below)'),
new CliHelpSection(['remove', '--name'], 'Removes an entry from the list'),
new CliHelpSection(['list'], 'Lists all entries defined as remote sources'),
]);
Console::out((string)null);
}
}

View file

@ -30,7 +30,7 @@
use ncc\Exceptions\UnsupportedCompilerExtensionException;
use ncc\Exceptions\UnsupportedRunnerException;
use ncc\Exceptions\UserAbortedOperationException;
use ncc\Interfaces\RemoteSourceInterface;
use ncc\Interfaces\ServiceSourceInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ComposerLock;
use ncc\Objects\ProjectConfiguration;
@ -47,7 +47,7 @@
use ncc\Utilities\RuntimeCache;
use SplFileInfo;
class ComposerSource implements RemoteSourceInterface
class ComposerSourceBuiltin implements ServiceSourceInterface
{
/**
* Attempts to acquire the package from the composer repository and
@ -134,7 +134,7 @@
{
$package_path = $base_dir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->Name;
// Generate the package configuration
$project_configuration = ComposerSource::generateProjectConfiguration($package->Name, $composer_lock);
$project_configuration = ComposerSourceBuiltin::generateProjectConfiguration($package->Name, $composer_lock);
// Process the source files
if ($package->Autoload !== null)

View file

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

View file

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

View file

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

View file

@ -0,0 +1,75 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects;
use ncc\Abstracts\DefinedRemoteSourceType;
use ncc\Utilities\Functions;
class DefinedRemoteSource
{
/**
* The unique name of the remote source. (e.g. 'github')
* Allows packages to be fetched using the name of the remote source.
* eg: 'vendor/package:master@custom_source'
*
* @var string
*/
public $Name;
/**
* The type of service NCC should use with this source (git, gitlab, github, etc...).
*
* @var string|DefinedRemoteSourceType
*/
public $Type;
/**
* The host of the service NCC should use with this source (gitlab.com, github.com, git.example.com:8080 etc...).
*
* @var string
*/
public $Host;
/**
* If SSL should be used when connecting to the service
*
* @var bool
*/
public $SSL;
/**
* Returns an array representation of the object
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [
($bytecode ? Functions::cbc('name') : 'name') => $this->Name,
($bytecode ? Functions::cbc('type') : 'type') => $this->Type,
($bytecode ? Functions::cbc('host') : 'host') => $this->Host,
($bytecode ? Functions::cbc('ssl') : 'ssl') => $this->SSL
];
}
/**
* Constructs object from an array representation.
*
* @param array $data
* @return static
*/
public static function fromArray(array $data): self
{
$definedRemoteSource = new self();
$definedRemoteSource->Name = Functions::array_bc($data, 'name');
$definedRemoteSource->Type = Functions::array_bc($data, 'type');
$definedRemoteSource->Host = Functions::array_bc($data, 'host');
$definedRemoteSource->SSL = Functions::array_bc($data, 'ssl');
return $definedRemoteSource;
}
}

View file

@ -43,6 +43,13 @@
*/
public $Authentication;
/**
* An array of curl options to set
*
* @var array
*/
public $Options;
public function __construct()
{
$this->Type = HttpRequestType::GET;
@ -50,6 +57,7 @@
$this->Headers = [
'User-Agent: ncc/1.0'
];
$this->Options = [];
}
/**
@ -64,7 +72,8 @@
'url' => $this->Url,
'headers' => $this->Headers,
'body' => $this->Body,
'authentication' => $this->Authentication
'authentication' => $this->Authentication,
'options' => $this->Options
];
}
@ -82,6 +91,7 @@
$request->Headers = $data['headers'];
$request->Body = $data['body'];
$request->Authentication = $data['authentication'];
$request->Options = $data['options'];
return $request;
}
}

View file

@ -484,4 +484,26 @@
}
return $randomString;
}
/**
* Returns a path to a temporary directory
*
* @param bool $create
* @param bool $set_as_tmp
* @return string
* @throws InvalidScopeException
*/
public static function getTmpDir(bool $create=true, bool $set_as_tmp=true): string
{
$path = PathFinder::getCachePath() . DIRECTORY_SEPARATOR . self::randomString(16);
if($create)
{
$filesystem = new Filesystem();
/** @noinspection PhpRedundantOptionalArgumentInspection */
$filesystem->mkdir($path, 0777);
}
if($set_as_tmp)
RuntimeCache::setFileAsTemporary($path);
return $path;
}
}

View file

@ -28,6 +28,9 @@
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
foreach($httpRequest->Options as $option => $value)
curl_setopt($curl, $option, $value);
switch($httpRequest->Type)
{
case HttpRequestType::GET:

View file

@ -173,6 +173,17 @@
return self::getDataPath($scope, $win32) . DIRECTORY_SEPARATOR . 'package.lck';
}
/**
* @param string $scope
* @param bool $win32
* @return string
* @throws InvalidScopeException
*/
public static function getRemouteSources(string $scope=Scopes::Auto, bool $win32=false): string
{
return self::getDataPath($scope, $win32) . DIRECTORY_SEPARATOR . 'sources';
}
/**
* Returns an array of all the package lock files the current user can access (For global-cross referencing)
*