Skip to content

Commit

Permalink
Reading via git executable
Browse files Browse the repository at this point in the history
- added method `GitDirectory::executeGitCommand()`
- added boolean parameter `$useBinary` into constructor of the class `GetHeadCommandHandler`
- added boolean parameter `$useBinary` into constructor of the class `GetLatestTagCommandHandler`
- added boolean paramter `$useBinary` into the method `LocalGitRepository::createDefault()`
- added boolean paramter `$useBinary` into the method `Export\Config::createDefault()`
- Nette DI extensions reigsters command handlers with parameter `useBinary = true` by default
- fixed tests
  • Loading branch information
tg666 committed Aug 26, 2023
1 parent 59dc3d7 commit 3b25d8f
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 20 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
"tracy/tracy": "^2.6.0"
},
"require-dev": {
"czproject/git-php": "^4.2",
"friendsofphp/php-cs-fixer": "^3.13",
"nette/application": "^3.1.0",
"nette/bootstrap": "^3.1",
"nette/di": "^3.0.10",
"symfony/console": "^5.4 | ^6.0",
"nette/tester": "^2.4.3",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-nette": "^1.1",
"roave/security-advisories": "dev-latest"
"roave/security-advisories": "dev-latest",
"symfony/console": "^5.4 | ^6.0"
},
"suggest": {
"nette/di": "For an integration with the Nette Framework.",
Expand Down
8 changes: 6 additions & 2 deletions src/Bridge/Nette/DI/TracyGitVersionExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ public function getConfigSchema(): Schema
'source_name' => Expect::string(GitRepositoryInterface::SOURCE_GIT_DIRECTORY),
'command_handlers' => Expect::arrayOf(Expect::anyOf(Expect::type(Statement::class), Expect::string()), 'string')
->default([
GetHeadCommand::class => new Statement(GetHeadCommandHandler::class),
GetLatestTagCommand::class => new Statement(GetLatestTagCommandHandler::class),
GetHeadCommand::class => new Statement(GetHeadCommandHandler::class, [
'useBinary' => true,
]),
GetLatestTagCommand::class => new Statement(GetLatestTagCommandHandler::class, [
'useBinary' => true,
]),
])
->mergeDefaults()
->before(static function (array $items) {
Expand Down
6 changes: 3 additions & 3 deletions src/Export/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public static function create(): self
return new self();
}

public static function createDefault(): self
public static function createDefault(bool $useBinary = true): self
{
return self::create()
->setGitDirectory(GitDirectory::createAutoDetected())
->addCommandHandlers([
GetHeadCommand::class => new GetHeadCommandHandler(),
GetLatestTagCommand::class => new GetLatestTagCommandHandler(),
GetHeadCommand::class => new GetHeadCommandHandler(null, $useBinary),
GetLatestTagCommand::class => new GetLatestTagCommandHandler(null, $useBinary),
])
->addExporters([
new HeadExporter(),
Expand Down
2 changes: 1 addition & 1 deletion src/Export/PartialExporter/LatestTagExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace SixtyEightPublishers\TracyGitVersion\Export\PartialExporter;

use SixtyEightPublishers\TracyGitVersion\Exception\BadMethodCallException;
use SixtyEightPublishers\TracyGitVersion\Exception\UnhandledCommandException;
use SixtyEightPublishers\TracyGitVersion\Export\Config;
use SixtyEightPublishers\TracyGitVersion\Export\ExporterInterface;
use SixtyEightPublishers\TracyGitVersion\Exception\UnhandledCommandException;
use SixtyEightPublishers\TracyGitVersion\Repository\Command\GetLatestTagCommand;
use SixtyEightPublishers\TracyGitVersion\Repository\Entity\Tag;
use SixtyEightPublishers\TracyGitVersion\Repository\GitRepositoryInterface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use SixtyEightPublishers\TracyGitVersion\Repository\Command\GetHeadCommand;
use SixtyEightPublishers\TracyGitVersion\Repository\Entity\CommitHash;
use SixtyEightPublishers\TracyGitVersion\Repository\Entity\Head;
use SixtyEightPublishers\TracyGitVersion\Repository\LocalDirectory\GitDirectory;
use function explode;
use function file_get_contents;
use function is_readable;
Expand All @@ -18,10 +19,27 @@

final class GetHeadCommandHandler extends AbstractLocalDirectoryCommandHandler
{
private bool $useBinary;

public function __construct(?GitDirectory $gitDirectory = null, bool $useBinary = false)
{
parent::__construct($gitDirectory);

$this->useBinary = $useBinary;
}

/**
* @throws GitDirectoryException
*/
public function __invoke(GetHeadCommand $command): Head
{
return $this->useBinary ? $this->readUsingBinary() : $this->readFromDirectory();
}

/**
* @throws GitDirectoryException
*/
private function readFromDirectory(): Head
{
$headFile = $this->getGitDirectory() . DIRECTORY_SEPARATOR . 'HEAD';

Expand All @@ -43,4 +61,31 @@ public function __invoke(GetHeadCommand $command): Head
is_readable($commitFile) && false !== ($commitHash = @file_get_contents($commitFile)) ? new CommitHash(trim($commitHash)) : null,
);
}

/**
* @throws GitDirectoryException
*/
private function readUsingBinary(): Head
{
$commitOutput = $this->getGitDirectory()->executeGitCommand([
'rev-parse',
'HEAD',
]);

if (0 !== $commitOutput['code']) {
return new Head(null, null);
}

$branchOutput = $this->getGitDirectory()->executeGitCommand([
'rev-parse',
'--abbrev-ref',
'HEAD',
]);

if (0 !== $branchOutput['code'] || 'HEAD' === $branchOutput['out']) {
return new Head(null, new CommitHash($commitOutput['out']));
}

return new Head($branchOutput['out'], new CommitHash($commitOutput['out']));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use SixtyEightPublishers\TracyGitVersion\Repository\Command\GetLatestTagCommand;
use SixtyEightPublishers\TracyGitVersion\Repository\Entity\CommitHash;
use SixtyEightPublishers\TracyGitVersion\Repository\Entity\Tag;
use SixtyEightPublishers\TracyGitVersion\Repository\LocalDirectory\GitDirectory;
use function current;
use function file_exists;
use function file_get_contents;
Expand All @@ -22,10 +23,27 @@

final class GetLatestTagCommandHandler extends AbstractLocalDirectoryCommandHandler
{
private bool $useBinary;

public function __construct(?GitDirectory $gitDirectory = null, bool $useBinary = false)
{
parent::__construct($gitDirectory);

$this->useBinary = $useBinary;
}

/**
* @throws GitDirectoryException
*/
public function __invoke(GetLatestTagCommand $getLatestTag): ?Tag
{
return $this->useBinary ? $this->readUsingBinary() : $this->readFromDirectory();
}

/**
* @throws GitDirectoryException
*/
private function readFromDirectory(): ?Tag
{
$tagsDirectory = sprintf('%s%srefs%stags', $this->getGitDirectory(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR);

Expand Down Expand Up @@ -64,4 +82,39 @@ public function __invoke(GetLatestTagCommand $getLatestTag): ?Tag

return new Tag((string) key($latestTagNames), new CommitHash(trim((string) @file_get_contents(current($latestTagNames)))));
}

/**
* @throws GitDirectoryException
*/
private function readUsingBinary(): ?Tag
{
$tagOutput = $this->getGitDirectory()->executeGitCommand([
'describe',
'--tags',
'$(' . $this->getGitDirectory()->createGitCommand([
'rev-list',
'--tags',
'--max-count',
'1',
]) . ')',
]);

if (0 !== $tagOutput['code']) {
return null;
}

$tag = $tagOutput['out'];

$commitOutput = $this->getGitDirectory()->executeGitCommand([
'show-ref',
'-s',
$tag,
]);

if (0 !== $commitOutput['code']) {
return null;
}

return new Tag($tag, new CommitHash($commitOutput['out']));
}
}
60 changes: 60 additions & 0 deletions src/Repository/LocalDirectory/GitDirectory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
namespace SixtyEightPublishers\TracyGitVersion\Repository\LocalDirectory;

use SixtyEightPublishers\TracyGitVersion\Exception\GitDirectoryException;
use function array_merge;
use function dirname;
use function fclose;
use function file_exists;
use function implode;
use function is_dir;
use function proc_close;
use function proc_open;
use function realpath;
use function stream_get_contents;
use function trim;

final class GitDirectory
{
Expand Down Expand Up @@ -71,6 +78,59 @@ public function __toString(): string
throw GitDirectoryException::gitDirectoryNotFound($workingDirectory);
}

public function createGitCommand(array $command): string
{
$gitDir = (string) $this;
$parts = array_merge(
[
'git',
'--git-dir',
$gitDir,
'--work-tree',
dirname($gitDir),
],
$command,
);

return implode(' ', $parts);
}

/**
* @param array<int, string> $command
*
* @return array{
* code: int,
* out: string,
* err: string,
* }
*/
public function executeGitCommand(array $command): array
{
$process = proc_open(
$this->createGitCommand($command),
[
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
],
$pipes,
__DIR__,
null,
);

$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);

$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);

return [
'code' => proc_close($process),
'out' => trim($stdout),
'err' => trim($stderr),
];
}

/**
* @throws GitDirectoryException
*/
Expand Down
6 changes: 3 additions & 3 deletions src/Repository/LocalGitRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public function __construct(GitDirectory $gitDirectory, array $handlers = [], st
parent::__construct($handlers);
}

public static function createDefault(?string $workingDirectory = null, string $directoryName = '.git'): self
public static function createDefault(?string $workingDirectory = null, string $directoryName = '.git', bool $useBinary = true): self
{
return new self(
GitDirectory::createAutoDetected($workingDirectory, $directoryName),
[
GetHeadCommand::class => new GetHeadCommandHandler(),
GetLatestTagCommand::class => new GetLatestTagCommandHandler(),
GetHeadCommand::class => new GetHeadCommandHandler(null, $useBinary),
GetLatestTagCommand::class => new GetLatestTagCommandHandler(null, $useBinary),
],
);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Export/LocalDirectoryExporterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class LocalDirectoryExporterTest extends TestCase
public function testWithDefaultConfig(): void
{
$exporter = new LocalDirectoryExporter();
$config = Config::createDefault();
$config = Config::createDefault(false);

# directory must be overridden
$config->setGitDirectory(GitDirectory::createFromGitDirectory(__DIR__ . '/../files/test-git'));
Expand All @@ -39,7 +39,7 @@ public function testWithDefaultConfig(): void
public function testWithDefaultConfigAndDetachedHead(): void
{
$exporter = new LocalDirectoryExporter();
$config = Config::createDefault();
$config = Config::createDefault(false);

# directory must be override
$config->setGitDirectory(GitDirectory::createFromGitDirectory(__DIR__ . '/../files/test-git-detached'));
Expand Down
49 changes: 49 additions & 0 deletions tests/GitHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace SixtyEightPublishers\TracyGitVersion\Tests;

use CzProject\GitPhp\Git;
use CzProject\GitPhp\GitRepository;
use Nette\Utils\FileSystem;

final class GitHelper
{
public static function init(): GitRepository
{
$git = new Git();
$tempDir = \sys_get_temp_dir() . '/' . \uniqid('68publishers:TracyGitVersionPanel:GitDirectoryTest', true);
FileSystem::createDir($tempDir);

$repo = $git->init($tempDir);
$repo->execute('config', 'user.email', 'test@68publishers.io');
$repo->execute('config', 'user.name', 'Test SixtyEightPublishers');

return $repo;
}

public static function destroy(GitRepository $repository): void
{
FileSystem::delete($repository->getRepositoryPath());
}

public static function createFile(GitRepository $repository, string $name, string $contents): void
{
$filename = \rtrim($repository->getRepositoryPath(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . \ltrim($name, DIRECTORY_SEPARATOR);

FileSystem::write($filename, $contents);

$repository->addFile($name);
}

public static function commit(GitRepository $repository, string $commitMessage): void
{
$repository->commit($commitMessage);
}

public static function createTag(GitRepository $repository, string $tag): void
{
$repository->createTag($tag);
}
}
Loading

0 comments on commit 3b25d8f

Please sign in to comment.