diff --git a/src/Artifact.php b/src/Artifact.php index b14b317..eff9c66 100644 --- a/src/Artifact.php +++ b/src/Artifact.php @@ -13,6 +13,7 @@ * * @SuppressWarnings(PHPMD.TooManyMethods) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.TooManyFields) */ class Artifact { @@ -22,125 +23,91 @@ class Artifact { const GIT_REMOTE_NAME = 'dst'; /** - * Git runner. - * - * @var GitArtifactGit + * Represent to current repository. */ - protected GitArtifactGit $git; + protected GitArtifactGitRepository $gitRepository; /** - * Represent to current repository. - * - * @var GitArtifactGitRepository + * Source path of git repository. */ - protected GitArtifactGitRepository $gitRepository; + protected string $sourcePathGitRepository = ''; /** * Mode in which current build is going to run. * * Available modes: branch, force-push, diff. - * - * @var string */ protected string $mode; /** * Original branch in current repository. - * - * @var string|null */ - protected ?string $originalBranch = NULL; + protected string $originalBranch = ''; /** * Destination branch with optional tokens. - * - * @var string|null */ - protected ?string $destinationBranch = NULL; + protected string $destinationBranch = ''; /** * Local branch where artifact will be built. - * - * @var string|null */ - protected ?string $artifactBranch = NULL; + protected string $artifactBranch = ''; /** * Remote name. - * - * @var string|null */ - protected ?string $remoteName = NULL; + protected string $remoteName = ''; /** * Remote URL includes uri or local path. - * - * @var string|null */ - protected ?string $remoteUrl = NULL; + protected string $remoteUrl = ''; /** * Gitignore file to be used during artifact creation. * * If not set, the current `.gitignore` will be used, if any. - * - * @var string|null */ protected ?string $gitignoreFile = NULL; /** * Commit message with optional tokens. - * - * @var string|null */ - protected ?string $message = NULL; + protected string $message = ''; /** * Flag to specify if push is required or should be using dry run. - * - * @var bool */ protected bool $needsPush = FALSE; /** * Flag to specify if cleanup is required to run after the build. - * - * @var bool */ protected bool $needCleanup = TRUE; /** * Path to report file. - * - * @var string|null */ - protected ?string $reportFile = NULL; + protected string $reportFile = ''; /** * Flag to show changes made to the repo by the build in the output. - * - * @var bool */ protected bool $showChanges = FALSE; /** * Artifact build result. - * - * @var bool */ protected bool $result = FALSE; /** * Flag to print debug information. - * - * @var bool */ protected bool $debug = FALSE; /** * Internal option to set current timestamp. - * - * @var int */ protected int $now; @@ -155,12 +122,14 @@ class Artifact { * Output. */ public function __construct( - GitArtifactGit $git, + /** + * Git runner. + */ + protected GitArtifactGit $git, Filesystem $fsFileSystem, protected OutputInterface $output, ) { $this->fsFileSystem = $fsFileSystem; - $this->git = $git; } /** @@ -208,9 +177,9 @@ public function artifact(string $remote, array $opts = [ ]): void { try { $error = NULL; - $this->checkRequirements(); $this->resolveOptions($remote, $opts); + // Now we have all what we need. // Let process artifact function. $this->printDebug('Debug messages enabled'); @@ -232,7 +201,7 @@ public function artifact(string $remote, array $opts = [ $error = $exception->getMessage(); } - if ($this->reportFile) { + if (!empty($this->reportFile)) { $this->dumpReport(); } @@ -249,6 +218,16 @@ public function artifact(string $remote, array $opts = [ } } + /** + * Get source path git repository. + * + * @return string + * Source path. + */ + public function getSourcePathGitRepository(): string { + return $this->sourcePathGitRepository; + } + /** * Branch mode. * @@ -290,7 +269,7 @@ protected function prepareArtifact(): void { // Remove sub-repositories. $this->removeSubReposInGitRepository(); // Disable local exclude. - $this->disableLocalExclude($this->gitRepository->getRepositoryPath()); + $this->disableLocalExclude($this->getSourcePathGitRepository()); // Add files. $this->addAllFilesInGitRepository(); // Remove other files. @@ -339,14 +318,13 @@ protected function addAllFilesInGitRepository(): void { if (!empty($this->gitignoreFile)) { $this->replaceGitignoreInGitRepository($this->gitignoreFile); $this->gitRepository->addAllChanges(); - $this->removeIgnoredFiles($this->gitRepository->getRepositoryPath()); + $this->removeIgnoredFiles($this->getSourcePathGitRepository()); } else { $this->gitRepository->addAllChanges(); } } - /** * Cleanup after build. * @@ -354,7 +332,7 @@ protected function addAllFilesInGitRepository(): void { */ protected function cleanup(): void { $this - ->restoreLocalExclude($this->gitRepository->getRepositoryPath()); + ->restoreLocalExclude($this->getSourcePathGitRepository()); $this ->gitRepository @@ -377,7 +355,7 @@ protected function cleanup(): void { protected function doPush(): void { try { $options = $this->mode === self::modeForcePush() ? ['--force'] : []; - $refSpec = "refs/heads/$this->artifactBranch:refs/heads/$this->destinationBranch"; + $refSpec = sprintf('refs/heads/%s:refs/heads/%s', $this->artifactBranch, $this->destinationBranch); $this ->gitRepository ->push([$this->remoteName, $refSpec], $options); @@ -401,10 +379,12 @@ protected function doPush(): void { /** * Resolve and validate CLI options values into internal values. * + * @param string $remote + * Remote URL. * @param array $options * Array of CLI options. * - * @throws \Exception + * @throws \CzProject\GitPhp\GitException * * @phpstan-ignore-next-line */ @@ -416,7 +396,7 @@ protected function resolveOptions(string $remote, array $options): void { $this->showChanges = !empty($options['show-changes']); $this->needCleanup = empty($options['no-cleanup']); $this->needsPush = !empty($options['push']); - $this->reportFile = empty($options['report']) ? NULL : $options['report']; + $this->reportFile = empty($options['report']) ? '' : $options['report']; $this->now = empty($options['now']) ? time() : (int) $options['now']; $this->debug = !empty($options['debug']); $this->remoteName = self::GIT_REMOTE_NAME; @@ -424,8 +404,8 @@ protected function resolveOptions(string $remote, array $options): void { $this->setMode($options['mode'], $options); // Handle some complex options. - // Get git repository source from option. $srcPath = empty($options['src']) ? $this->fsGetRootDir() : $this->fsGetAbsolutePath($options['src']); + $this->sourcePathGitRepository = $srcPath; // Setup Git repository from source path. $this->initGitRepository($srcPath); // Set original, destination, artifact branch name. @@ -468,7 +448,7 @@ protected function showInfo(): void { $lines[] = ('----------------------------------------------------------------------'); $lines[] = (' Build timestamp: ' . date('Y/m/d H:i:s', $this->now)); $lines[] = (' Mode: ' . $this->mode); - $lines[] = (' Source repository: ' . $this->gitRepository->getRepositoryPath()); + $lines[] = (' Source repository: ' . $this->getSourcePathGitRepository()); $lines[] = (' Remote repository: ' . $this->remoteUrl); $lines[] = (' Remote branch: ' . $this->destinationBranch); $lines[] = (' Gitignore file: ' . ($this->gitignoreFile ?: 'No')); @@ -486,7 +466,7 @@ protected function dumpReport(): void { $lines[] = '----------------------------------------------------------------------'; $lines[] = ' Build timestamp: ' . date('Y/m/d H:i:s', $this->now); $lines[] = ' Mode: ' . $this->mode; - $lines[] = ' Source repository: ' . $this->gitRepository->getRepositoryPath(); + $lines[] = ' Source repository: ' . $this->getSourcePathGitRepository(); $lines[] = ' Remote repository: ' . $this->remoteUrl; $lines[] = ' Remote branch: ' . $this->destinationBranch; $lines[] = ' Gitignore file: ' . ($this->gitignoreFile ?: 'No'); @@ -631,7 +611,7 @@ protected function checkRequirements(): void { * Path to new gitignore to replace current file with. */ protected function replaceGitignoreInGitRepository(string $filename): void { - $path = $this->gitRepository->getRepositoryPath(); + $path = $this->getSourcePathGitRepository(); $this->printDebug('Replacing .gitignore: %s with %s', $path . DIRECTORY_SEPARATOR . '.gitignore', $filename); $this->fsFileSystem->copy($filename, $path . DIRECTORY_SEPARATOR . '.gitignore', TRUE); $this->fsFileSystem->remove($filename); @@ -746,7 +726,7 @@ protected function restoreLocalExclude(string $path): void { * If removal command finished with an error. */ protected function removeIgnoredFiles(string $location, string $gitignorePath = NULL): void { - $location = $this->gitRepository->getRepositoryPath(); + $location = $this->getSourcePathGitRepository(); $gitignorePath = $gitignorePath ?: $location . DIRECTORY_SEPARATOR . '.gitignore'; $gitignoreContent = file_get_contents($gitignorePath); @@ -761,7 +741,7 @@ protected function removeIgnoredFiles(string $location, string $gitignorePath = $files = $this ->gitRepository - ->lsFiles(['--directory', '-i', '-c', "--exclude-from=$gitignorePath"]); + ->lsFiles(['--directory', '-i', '-c', '--exclude-from=' . $gitignorePath]); if (!empty($files)) { $files = array_filter($files); @@ -788,7 +768,7 @@ protected function removeOtherFilesInGitRepository(): void { if (!empty($files)) { $files = array_filter($files); foreach ($files as $file) { - $fileName = $this->gitRepository->getRepositoryPath() . DIRECTORY_SEPARATOR . $file; + $fileName = $this->getSourcePathGitRepository() . DIRECTORY_SEPARATOR . $file; $this->printDebug('Removing other file %s', $fileName); $this->fsFileSystem->remove($fileName); } @@ -806,7 +786,7 @@ protected function removeSubReposInGitRepository(): void { ->ignoreDotFiles(FALSE) ->ignoreVCS(FALSE) ->depth('>0') - ->in($this->gitRepository->getRepositoryPath()); + ->in($this->getSourcePathGitRepository()); $dirs = iterator_to_array($dirs->directories()); diff --git a/src/Commands/ArtifactCommand.php b/src/Commands/ArtifactCommand.php index 4149a4c..c822771 100644 --- a/src/Commands/ArtifactCommand.php +++ b/src/Commands/ArtifactCommand.php @@ -4,15 +4,8 @@ namespace DrevOps\GitArtifact\Commands; -use CzProject\GitPhp\Git; use DrevOps\GitArtifact\Artifact; use DrevOps\GitArtifact\GitArtifactGit; -use DrevOps\GitArtifact\GitArtifactGitRepository; -use GitWrapper\EventSubscriber\GitLoggerEventSubscriber; -use GitWrapper\GitWrapper; -use Monolog\Handler\StreamHandler; -use Monolog\Level; -use Monolog\Logger; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -96,22 +89,10 @@ protected function configure(): void { * @throws \Exception */ protected function execute(InputInterface $input, OutputInterface $output): int { - -// $optionDebug = $input->getOption('debug'); -// -// if (($optionDebug || $output->isDebug())) { -// $logger = new Logger('git'); -// $logger->pushHandler(new StreamHandler('php://stdout', Level::Debug)); -// } - $fileSystem = new Filesystem(); $git = new GitArtifactGit(); -// $repo = $git->open('.'); -// $repo->setRemoteUrl('aaaa' , 'asd'); -// die; $artifact = new Artifact($git, $fileSystem, $output); $remote = $input->getArgument('remote'); - // @phpstan-ignore-next-line $artifact->artifact($remote, $input->getOptions()); diff --git a/src/FilesystemTrait.php b/src/FilesystemTrait.php index 8fd91e8..7df9a7e 100644 --- a/src/FilesystemTrait.php +++ b/src/FilesystemTrait.php @@ -14,8 +14,6 @@ trait FilesystemTrait { /** * Current directory where call originated. - * - * @var string */ protected string $fsRootDir; diff --git a/src/GitArtifactGit.php b/src/GitArtifactGit.php index 3ae7ed0..63f9f9c 100644 --- a/src/GitArtifactGit.php +++ b/src/GitArtifactGit.php @@ -1,18 +1,20 @@ runner); diff --git a/src/GitArtifactGitRepository.php b/src/GitArtifactGitRepository.php index 49e6d18..1bd17c6 100644 --- a/src/GitArtifactGitRepository.php +++ b/src/GitArtifactGitRepository.php @@ -15,15 +15,11 @@ class GitArtifactGitRepository extends GitRepository { /** * Filesystem. - * - * @var \Symfony\Component\Filesystem\Filesystem */ protected Filesystem $fileSystem; /** * Logger. - * - * @var \Psr\Log\LoggerInterface */ protected LoggerInterface $logger; @@ -62,6 +58,10 @@ public function switchToBranch(string $branchName, bool $createNew = FALSE): Git * @throws \CzProject\GitPhp\GitException */ public function removeBranch($name, bool $force = FALSE): GitArtifactGitRepository { + if (empty($name)) { + return $this; + } + if (!$force) { return parent::removeBranch($name); } @@ -111,6 +111,7 @@ public function lsFiles(array $options = [], array $files = []): ?array { /** * Remove remote by name. + * * We need override this method because parent method does not work. * * @param string $name @@ -122,10 +123,45 @@ public function lsFiles(array $options = [], array $files = []): ?array { * @throws \CzProject\GitPhp\GitException */ public function removeRemote($name): GitArtifactGitRepository { - $this->run('remote', 'remove', $name); + if ($this->isRemoteExists($name)) { + $this->run('remote', 'remove', $name); + } + return $this; } + /** + * Get remote list. + * + * @return array|null + * Remotes. + * + * @throws \CzProject\GitPhp\GitException + */ + public function getRemotes(): ?array { + return $this->extractFromCommand(['remote']); + } + + /** + * Check remote is existing or not by remote name. + * + * @param string $remoteName + * Remote name to check. + * + * @return bool + * Exist or not. + * + * @throws \CzProject\GitPhp\GitException + */ + public function isRemoteExists(string $remoteName): bool { + $remotes = $this->getRemotes(); + if (empty($remotes)) { + return FALSE; + } + + return in_array($remoteName, $remotes); + } + /** * Check if provided location is a URI. * diff --git a/tests/phpunit/Unit/AbstractUnitTestCase.php b/tests/phpunit/Unit/AbstractUnitTestCase.php index 298c677..a29d95d 100644 --- a/tests/phpunit/Unit/AbstractUnitTestCase.php +++ b/tests/phpunit/Unit/AbstractUnitTestCase.php @@ -5,7 +5,6 @@ use DrevOps\GitArtifact\Artifact; use DrevOps\GitArtifact\GitArtifactGit; use DrevOps\GitArtifact\Tests\AbstractTestCase; -use GitWrapper\GitWrapper; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Filesystem\Filesystem;