diff --git a/.gitlab-ci.yml.old b/.gitlab-ci.yml.old deleted file mode 100644 index d8868dd..0000000 --- a/.gitlab-ci.yml.old +++ /dev/null @@ -1,72 +0,0 @@ -build: - image: php:8.1 - - before_script: - # Install some stuff that the image doesn't come with - - apt update -yqq - - apt install git libpq-dev libzip-dev zip make wget gnupg -yqq - - # Install phive - - wget -O phive.phar https://phar.io/releases/phive.phar - - wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc - - gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 - - gpg --verify phive.phar.asc phive.phar - - chmod +x phive.phar - - mv phive.phar /usr/local/bin/phive - - # install phpab - - phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C - script: - - make tar - rules: - - if: $CI_COMMIT_BRANCH - -release: - image: php:8.1 - - before_script: - # Install some stuff that the image doesn't come with - - apt update -yqq - - apt install git libpq-dev libzip-dev zip make wget gnupg -yqq - - # Install phive - - wget -O phive.phar https://phar.io/releases/phive.phar - - wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc - - gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 - - gpg --verify phive.phar.asc phive.phar - - chmod +x phive.phar - - mv phive.phar /usr/local/bin/phive - - # install phpab - - phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C - script: - - make redist - - mkdir ncc_$CI_COMMIT_TAG - - cp -r build/src/* ncc_$CI_COMMIT_TAG/ - artifacts: - paths: - - ncc_$CI_COMMIT_TAG/ - rules: - - if: $CI_COMMIT_TAG - -ncc-docker-build: - image: docker:latest - services: - - docker:dind - before_script: - - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - script: - - | - if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then - tag="" - echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" - else - tag=":$CI_COMMIT_REF_SLUG" - echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" - fi - - docker build --no-cache --pull -t "$CI_REGISTRY_IMAGE${tag}" . - - docker push "$CI_REGISTRY_IMAGE${tag}" - rules: - - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_BRANCH == 'dev' - exists: - - Dockerfile diff --git a/src/ncc/CLI/Management/PackageManagerMenu.php b/src/ncc/CLI/Management/PackageManagerMenu.php index 6c45308..4d38d0b 100644 --- a/src/ncc/CLI/Management/PackageManagerMenu.php +++ b/src/ncc/CLI/Management/PackageManagerMenu.php @@ -26,6 +26,7 @@ use ncc\Classes\PackageReader; use ncc\Enums\ConsoleColors; use ncc\Enums\RegexPatterns; + use ncc\Enums\Scopes; use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\IOException; use ncc\Exceptions\OperationException; @@ -37,6 +38,7 @@ use ncc\Objects\RemotePackageInput; use ncc\Utilities\Console; use ncc\Utilities\Functions; + use ncc\Utilities\Resolver; class PackageManagerMenu { @@ -129,6 +131,12 @@ */ private static function installPackage(array $args): int { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + Console::outError('You cannot install packages in a user scope, please run this command as root', true, 1); + return 1; + } + $package = $args['package'] ?? $args['p'] ?? null; $authentication = $args['authentication'] ?? $args['a'] ?? null; $authentication_entry = null; @@ -348,6 +356,12 @@ */ private static function uninstallPackage($args): int { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + Console::outError('You cannot uninstall packages in a user scope, please run this command as root', true, 1); + return 1; + } + $package = $args['package'] ?? $args['p'] ?? null; $version = $args['version'] ?? $args['v'] ?? null; @@ -372,20 +386,26 @@ */ private static function uninstallAllPackages(): int { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + Console::outError('You cannot uninstall all packages in a user scope, please run this command as root', true, 1); + return 1; + } + + $package_manager = new PackageManager(); + if(count($package_manager->getInstalledPackages()) === 0) + { + Console::out('No packages installed'); + return 0; + } + if(!Console::getBooleanInput('Are you sure you want to uninstall all packages?')) { Console::out('Uninstallation aborted'); return 0; } - $results = (new PackageManager())->uninstallAll(); - - foreach($results as $package) - { - Console::out(sprintf(' %s', $package)); - } - - Console::out(sprintf('Uninstalled %d packages', count($results))); + Console::out(sprintf('Uninstalled %d packages', count($package_manager->uninstallAll()))); return 0; } @@ -401,6 +421,12 @@ */ private static function fixBrokenPackages(array $args): int { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + Console::outError('You cannot fix broken packages in a user scope, please run this command as root', true, 1); + return 1; + } + $package_manager = new PackageManager(); $results = $package_manager->getMissingPackages(); $auto_yes = isset($args['y']); diff --git a/src/ncc/Classes/GitlabExtension/GitlabRepository.php b/src/ncc/Classes/GitlabExtension/GitlabRepository.php index 303bb91..c50adde 100644 --- a/src/ncc/Classes/GitlabExtension/GitlabRepository.php +++ b/src/ncc/Classes/GitlabExtension/GitlabRepository.php @@ -82,6 +82,7 @@ private static function getTags(RepositoryConfiguration $repository, string $group, string $project, ?AuthenticationInterface $authentication=null): array { $curl = curl_init(); + $project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig") $endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/repository/tags?order_by=updated&sort=desc', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project)); $headers = [ 'Content-Type: application/json', @@ -160,6 +161,7 @@ } $curl = curl_init(); + $project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig") $endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/repository/archive.zip?sha=%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($tag)); $headers = [ 'User-Agent: ncc' @@ -212,6 +214,7 @@ private static function getReleases(RepositoryConfiguration $repository, string $group, string $project, ?AuthenticationInterface $authentication=null): array { $curl = curl_init(); + $project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig") $endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases?order_by=released_at&sort=desc', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project)); $headers = [ 'Content-Type: application/json', @@ -286,6 +289,7 @@ } $curl = curl_init(); + $project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig") $endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($release)); $headers = [ 'Content-Type: application/json', @@ -349,6 +353,7 @@ } $curl = curl_init(); + $project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig") $endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($release)); $headers = [ 'Content-Type: application/json', diff --git a/src/ncc/Classes/PackagistExtension/PackagistRepository.php b/src/ncc/Classes/PackagistExtension/PackagistRepository.php index e90344e..d555d07 100644 --- a/src/ncc/Classes/PackagistExtension/PackagistRepository.php +++ b/src/ncc/Classes/PackagistExtension/PackagistRepository.php @@ -151,6 +151,11 @@ return Comparator::lessThanOrEqualTo($a, $b) ? 1 : -1; }); + if($versions[0] === null) + { + throw new NetworkException(sprintf('Failed to resolve latest version for %s/%s', $vendor, $project)); + } + return $versions[0]; } diff --git a/src/ncc/Classes/Runtime.php b/src/ncc/Classes/Runtime.php index 0f92c88..44448f2 100644 --- a/src/ncc/Classes/Runtime.php +++ b/src/ncc/Classes/Runtime.php @@ -32,6 +32,7 @@ use ncc\Exceptions\ImportException; use ncc\Exceptions\IOException; use ncc\Exceptions\NotSupportedException; + use ncc\Exceptions\OperationException; use ncc\Exceptions\PathNotFoundException; use ncc\Extensions\ZiProto\ZiProto; use ncc\Managers\PackageManager; @@ -64,8 +65,9 @@ * @return mixed * @throws ConfigurationException * @throws IOException - * @throws PathNotFoundException * @throws NotSupportedException + * @throws PathNotFoundException + * @throws OperationException */ public static function execute(string $package): int { @@ -133,7 +135,9 @@ * @param string $package * @param string $version * @return string + * @throws ConfigurationException * @throws IOException + * @throws ImportException * @throws PathNotFoundException */ private static function importFromSystem(string $package, string $version=Versions::LATEST): string @@ -148,6 +152,13 @@ self::$imported_packages[$package] = $entry->getPath($version); + // Import dependencies recursively + foreach($entry->getVersion($version)->getDependencies() as $dependency) + { + /** @noinspection UnusedFunctionResultInspection */ + self::import($dependency->getName(), $dependency->getVersion()); + } + return $package; } @@ -157,7 +168,9 @@ * @param string $package_path * @return string * @throws ConfigurationException + * @throws IOException * @throws ImportException + * @throws PathNotFoundException */ private static function importFromPackage(string $package_path): string { @@ -191,6 +204,15 @@ }; } + // Import dependencies recursively + foreach($package_reader->getDependencies() as $dependency) + { + $dependency = $package_reader->getDependency($dependency); + + /** @noinspection UnusedFunctionResultInspection */ + self::import($dependency->getName(), $dependency->getVersion()); + } + return $package_reader->getAssembly()->getPackage(); } diff --git a/src/ncc/Managers/PackageManager.php b/src/ncc/Managers/PackageManager.php index 0047b87..0d076ff 100644 --- a/src/ncc/Managers/PackageManager.php +++ b/src/ncc/Managers/PackageManager.php @@ -38,6 +38,7 @@ use ncc\Enums\Options\ComponentDecodeOptions; use ncc\Enums\Options\InitializeProjectOptions; use ncc\Enums\RegexPatterns; + use ncc\Enums\Scopes; use ncc\Enums\Types\ProjectType; use ncc\Exceptions\ConfigurationException; use ncc\Exceptions\IOException; @@ -144,6 +145,11 @@ */ public function install(string|PackageReader $input, ?AuthenticationInterface $authentication=null): array { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + throw new OperationException('You must have root privileges to install packages'); + } + // If the input is a PackageReader, we can install it directly if($input instanceof PackageReader) { @@ -176,6 +182,11 @@ */ public function uninstall(string $package_name, ?string $version=null): array { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + throw new OperationException('You must have root privileges to uninstall packages'); + } + if(!$this->package_lock->entryExists($package_name, $version)) { throw new OperationException(sprintf('Cannot uninstall package %s, it is not installed', $package_name)); @@ -218,6 +229,11 @@ */ public function uninstallAll(): array { + if(Resolver::resolveScope() !== Scopes::SYSTEM) + { + throw new OperationException('You must have root privileges to uninstall packages'); + } + $results = []; foreach($this->package_lock->getEntries() as $entry) { @@ -385,7 +401,7 @@ throw new OperationException(sprintf('Cannot install remote package %s, the repository %s does not exist on this system', $input, $input->getRepository())); } - Console::out(sprintf('Fetching package %s=%s from %s', $input->getPackage(), $input->getVersion(), $input->getRepository())); + Console::out(sprintf('Fetching package %s/%s=%s from %s', $input->getVendor(), $input->getPackage(), $input->getVersion(), $input->getRepository())); try { @@ -614,10 +630,10 @@ [BuildConfigurationOptions::OUTPUT_FILE => PathFinder::getCachePath() . DIRECTORY_SEPARATOR . hash('sha1', $archive) . '.ncc'] ); - unlink($package_path); - ShutdownHandler::declareTemporaryPath($source_directory); - return PathFinder::getCachePath() . DIRECTORY_SEPARATOR . basename($package_path); + ShutdownHandler::declareTemporaryPath($package_path); + + return $package_path; } catch(Exception $e) { @@ -638,11 +654,10 @@ [BuildConfigurationOptions::OUTPUT_FILE => PathFinder::getCachePath() . DIRECTORY_SEPARATOR . hash('sha1', $archive) . '.ncc'] ); - copy($package_path, PathFinder::getCachePath() . DIRECTORY_SEPARATOR . basename($package_path)); - unlink($package_path); - + ShutdownHandler::declareTemporaryPath($package_path); ShutdownHandler::declareTemporaryPath($source_directory); - return PathFinder::getCachePath() . DIRECTORY_SEPARATOR . basename($package_path); + + return $package_path; } catch(Exception $e) { diff --git a/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php b/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php index 11c9478..6ec6cd5 100644 --- a/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php +++ b/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php @@ -430,7 +430,7 @@ $results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name; $results[($bytecode ? Functions::cbc('build_type') : 'build_type')] = $this->build_type; $results[($bytecode ? Functions::cbc('output_path') : 'output_path')] = $this->output_path; - $results[($bytecode ? Functions::cbc('output_name') : 'output_path')] = $this->output_name; + $results[($bytecode ? Functions::cbc('output_name') : 'output_name')] = $this->output_name; if(count($this->options) > 0) {