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:
parent
b3c8779313
commit
cccbe3f934
18 changed files with 505 additions and 22 deletions
17
.idea/php.xml
generated
17
.idea/php.xml
generated
|
@ -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>
|
17
src/ncc/Abstracts/BuiltinRemoteSourceType.php
Normal file
17
src/ncc/Abstracts/BuiltinRemoteSourceType.php
Normal 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
|
||||
];
|
||||
}
|
|
@ -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
|
||||
];
|
||||
}
|
|
@ -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
|
||||
];
|
||||
}
|
|
@ -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';
|
||||
}
|
|
@ -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';
|
||||
}
|
|
@ -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'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
220
src/ncc/CLI/SourcesMenu.php
Normal 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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
19
src/ncc/Exceptions/GitCheckoutException.php
Normal file
19
src/ncc/Exceptions/GitCheckoutException.php
Normal 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;
|
||||
}
|
||||
}
|
20
src/ncc/Exceptions/GitCloneException.php
Normal file
20
src/ncc/Exceptions/GitCloneException.php
Normal 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;
|
||||
}
|
||||
}
|
20
src/ncc/Exceptions/GitlabServiceException.php
Normal file
20
src/ncc/Exceptions/GitlabServiceException.php
Normal 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;
|
||||
}
|
||||
}
|
75
src/ncc/Objects/DefinedRemoteSource.php
Normal file
75
src/ncc/Objects/DefinedRemoteSource.php
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue