1.0.0 Alpha Release #59

Merged
netkas merged 213 commits from v1.0.0_alpha into master 2023-01-29 23:27:58 +00:00
18 changed files with 505 additions and 22 deletions
Showing only changes of commit cccbe3f934 - Show all commits

17
.idea/php.xml generated
View file

@ -1,11 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <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"> <component name="PhpIncludePathManager">
<include_path> <include_path>
<path value="/usr/share/php" /> <path value="/usr/share/php" />
</include_path> </include_path>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1"> <component name="PhpProjectSharedConfiguration" php_language_level="8.2">
<option name="suggestChangeDefaultLanguageLevel" value="false" /> <option name="suggestChangeDefaultLanguageLevel" value="false" />
</component> </component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project> </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 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'; 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'; 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 Github = 'github';
const All = [
self::Git,
self::Gitlab,
self::Github
];
} }

View file

@ -2,6 +2,8 @@
namespace ncc\Abstracts; namespace ncc\Abstracts;
use ncc\Exceptions\GitlabServiceException;
/** /**
* @author Zi Xing Narrakas * @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2022. Nosial - All Rights Reserved. * @copyright Copyright (C) 2022-2022. Nosial - All Rights Reserved.
@ -278,6 +280,22 @@
*/ */
const UnsupportedRemoteSourceTypeException = -1753; const UnsupportedRemoteSourceTypeException = -1753;
/**
* @see GitCloneException
*/
const GitCloneException = -1754;
/**
* @see GitCheckoutException
*/
const GitCheckoutException = -1755;
/**
* @see GitlabServiceException
*/
const GitlabServiceException = -1756;
/** /**
* All the exception codes from NCC * All the exception codes from NCC
*/ */
@ -334,6 +352,9 @@
self::UserAbortedOperationException, self::UserAbortedOperationException,
self::MissingDependencyException, self::MissingDependencyException,
self::HttpException, 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 * The current version of the package lock structure file format
*/ */
const PackageLockVersion = '1.0.0'; 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(['cache'], 'Manages the system cache'),
new CliHelpSection(['cred'], 'Manages credentials'), new CliHelpSection(['cred'], 'Manages credentials'),
new CliHelpSection(['config'], 'Changes NCC configuration values'), new CliHelpSection(['config'], 'Changes NCC configuration values'),
new CliHelpSection(['source'], 'Manages remote sources'),
]); ]);
} }

View file

@ -122,6 +122,10 @@
ConfigMenu::start(self::$args); ConfigMenu::start(self::$args);
exit(0); exit(0);
case 'source':
SourcesMenu::start(self::$args);
exit(0);
case '1': case '1':
case 'help': case 'help':
HelpMenu::start(self::$args); 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\UnsupportedCompilerExtensionException;
use ncc\Exceptions\UnsupportedRunnerException; use ncc\Exceptions\UnsupportedRunnerException;
use ncc\Exceptions\UserAbortedOperationException; use ncc\Exceptions\UserAbortedOperationException;
use ncc\Interfaces\RemoteSourceInterface; use ncc\Interfaces\ServiceSourceInterface;
use ncc\Managers\ProjectManager; use ncc\Managers\ProjectManager;
use ncc\Objects\ComposerLock; use ncc\Objects\ComposerLock;
use ncc\Objects\ProjectConfiguration; use ncc\Objects\ProjectConfiguration;
@ -47,7 +47,7 @@
use ncc\Utilities\RuntimeCache; use ncc\Utilities\RuntimeCache;
use SplFileInfo; use SplFileInfo;
class ComposerSource implements RemoteSourceInterface class ComposerSourceBuiltin implements ServiceSourceInterface
{ {
/** /**
* Attempts to acquire the package from the composer repository and * 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; $package_path = $base_dir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->Name;
// Generate the package configuration // Generate the package configuration
$project_configuration = ComposerSource::generateProjectConfiguration($package->Name, $composer_lock); $project_configuration = ComposerSourceBuiltin::generateProjectConfiguration($package->Name, $composer_lock);
// Process the source files // Process the source files
if ($package->Autoload !== null) 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; public $Authentication;
/**
* An array of curl options to set
*
* @var array
*/
public $Options;
public function __construct() public function __construct()
{ {
$this->Type = HttpRequestType::GET; $this->Type = HttpRequestType::GET;
@ -50,6 +57,7 @@
$this->Headers = [ $this->Headers = [
'User-Agent: ncc/1.0' 'User-Agent: ncc/1.0'
]; ];
$this->Options = [];
} }
/** /**
@ -64,7 +72,8 @@
'url' => $this->Url, 'url' => $this->Url,
'headers' => $this->Headers, 'headers' => $this->Headers,
'body' => $this->Body, 'body' => $this->Body,
'authentication' => $this->Authentication 'authentication' => $this->Authentication,
'options' => $this->Options
]; ];
} }
@ -82,6 +91,7 @@
$request->Headers = $data['headers']; $request->Headers = $data['headers'];
$request->Body = $data['body']; $request->Body = $data['body'];
$request->Authentication = $data['authentication']; $request->Authentication = $data['authentication'];
$request->Options = $data['options'];
return $request; return $request;
} }
} }

View file

@ -484,4 +484,26 @@
} }
return $randomString; 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_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
foreach($httpRequest->Options as $option => $value)
curl_setopt($curl, $option, $value);
switch($httpRequest->Type) switch($httpRequest->Type)
{ {
case HttpRequestType::GET: case HttpRequestType::GET:

View file

@ -173,6 +173,17 @@
return self::getDataPath($scope, $win32) . DIRECTORY_SEPARATOR . 'package.lck'; 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) * Returns an array of all the package lock files the current user can access (For global-cross referencing)
* *