Skip to content

Commit

Permalink
Configuration::runGitCommand() now respects base-dir (#466)
Browse files Browse the repository at this point in the history
This resolves a problem when having the configuration file not within the repository itself (eg. in CI environments).

Now the configuration is using the `base-path` for running all git commands.
  • Loading branch information
discordier authored Jul 28, 2020
1 parent 21dac17 commit e708d75
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 21 deletions.
44 changes: 23 additions & 21 deletions src/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ static function (string $excludedPath) use ($basePath): string {
$privateKeyPath = self::retrievePrivateKeyPath($raw, $basePath, $signingAlgorithm, $logger);
$privateKeyPassphrase = self::retrievePrivateKeyPassphrase($raw, $signingAlgorithm, $logger);

$replacements = self::retrieveReplacements($raw, $file, $logger);
$replacements = self::retrieveReplacements($raw, $file, $basePath, $logger);

return new self(
$file,
Expand Down Expand Up @@ -2206,8 +2206,12 @@ private static function retrievePrivateKeyPassphrase(
/**
* @return scalar[]
*/
private static function retrieveReplacements(stdClass $raw, ?string $file, ConfigurationLogger $logger): array
{
private static function retrieveReplacements(
stdClass $raw,
?string $file,
string $path,
ConfigurationLogger $logger
): array {
self::checkIfDefaultValue($logger, $raw, self::REPLACEMENTS_KEY, new stdClass());

if (null === $file) {
Expand All @@ -2217,23 +2221,23 @@ private static function retrieveReplacements(stdClass $raw, ?string $file, Confi
$replacements = isset($raw->{self::REPLACEMENTS_KEY}) ? (array) $raw->{self::REPLACEMENTS_KEY} : [];

if (null !== ($git = self::retrievePrettyGitPlaceholder($raw, $logger))) {
$replacements[$git] = self::retrievePrettyGitTag($file);
$replacements[$git] = self::retrievePrettyGitTag($path);
}

if (null !== ($git = self::retrieveGitHashPlaceholder($raw, $logger))) {
$replacements[$git] = self::retrieveGitHash($file);
$replacements[$git] = self::retrieveGitHash($path);
}

if (null !== ($git = self::retrieveGitShortHashPlaceholder($raw, $logger))) {
$replacements[$git] = self::retrieveGitHash($file, true);
$replacements[$git] = self::retrieveGitHash($path, true);
}

if (null !== ($git = self::retrieveGitTagPlaceholder($raw, $logger))) {
$replacements[$git] = self::retrieveGitTag($file);
$replacements[$git] = self::retrieveGitTag($path);
}

if (null !== ($git = self::retrieveGitVersionPlaceholder($raw, $logger))) {
$replacements[$git] = self::retrieveGitVersion($file);
$replacements[$git] = self::retrieveGitVersion($path);
}

/**
Expand Down Expand Up @@ -2279,14 +2283,14 @@ private static function retrieveGitHashPlaceholder(stdClass $raw, ConfigurationL
*
* @return string the commit hash
*/
private static function retrieveGitHash(string $file, bool $short = false): string
private static function retrieveGitHash(string $path, bool $short = false): string
{
return self::runGitCommand(
sprintf(
'git log --pretty="%s" -n1 HEAD',
$short ? '%h' : '%H'
),
$file
$path
);
}

Expand All @@ -2307,14 +2311,14 @@ private static function retrievePlaceholder(stdClass $raw, ConfigurationLogger $
return $raw->{$key} ?? null;
}

private static function retrieveGitTag(string $file): string
private static function retrieveGitTag(string $path): string
{
return self::runGitCommand('git describe --tags HEAD', $file);
return self::runGitCommand('git describe --tags HEAD', $path);
}

private static function retrievePrettyGitTag(string $file): string
private static function retrievePrettyGitTag(string $path): string
{
$version = self::retrieveGitTag($file);
$version = self::retrieveGitTag($path);

if (preg_match('/^(?<tag>.+)-\d+-g(?<hash>[a-f0-9]{7})$/', $version, $matches)) {
return sprintf('%s@%s', $matches['tag'], $matches['hash']);
Expand All @@ -2328,18 +2332,18 @@ private static function retrieveGitVersionPlaceholder(stdClass $raw, Configurati
return self::retrievePlaceholder($raw, $logger, self::GIT_VERSION_KEY);
}

private static function retrieveGitVersion(string $file): ?string
private static function retrieveGitVersion(string $path): ?string
{
try {
return self::retrieveGitTag($file);
return self::retrieveGitTag($path);
} catch (RuntimeException $exception) {
try {
return self::retrieveGitHash($file, true);
return self::retrieveGitHash($path, true);
} catch (RuntimeException $exception) {
throw new RuntimeException(
sprintf(
'The tag or commit hash could not be retrieved from "%s": %s',
dirname($file),
$path,
$exception->getMessage()
),
0,
Expand Down Expand Up @@ -2714,10 +2718,8 @@ private static function retrievePhpScoperConfig(stdClass $raw, string $basePath,
*
* @return string The trimmed output from the command
*/
private static function runGitCommand(string $command, string $file): string
private static function runGitCommand(string $command, string $path): string
{
$path = dirname($file);

$process = Process::fromShellCommandline($command, $path);

if (0 === $process->run()) {
Expand Down
73 changes: 73 additions & 0 deletions tests/Configuration/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,79 @@ public function test_the_replacement_map_can_be_configured(): void
$this->assertSame([], $this->config->getWarnings());
}

public function test_the_replacement_map_can_be_configured_when_base_path_is_different_directory(): void
{
// Make another directory level to have config not in base-path.
$basePath = $this->tmp . DIRECTORY_SEPARATOR . 'subdir';
mkdir($basePath);
rename(self::DEFAULT_FILE, $basePath . DIRECTORY_SEPARATOR . self::DEFAULT_FILE);
chdir($basePath);
touch('test');
exec('git init');
exec('git config user.name "Test User"');
exec('git config user.email test@test.test');
exec('git config commit.gpgsign false');
exec('git add test');
exec('git commit -m "Adding test file."');
exec('git tag 1.0.0');
chdir($this->tmp);

$this->setConfig([
'base-path' => $basePath,
'files' => [self::DEFAULT_FILE],
'git' => 'git',
'git-commit' => 'git_commit',
'git-commit-short' => 'git_commit_short',
'git-tag' => 'git_tag',
'git-version' => 'git_version',
]);

$values = $this->config->getReplacements();

$this->assertSame('1.0.0', $values['@git@']);
$this->assertRegExp('/^[a-f0-9]{40}$/', $values['@git_commit@']);
$this->assertRegExp('/^[a-f0-9]{7}$/', $values['@git_commit_short@']);
$this->assertSame('1.0.0', $values['@git_tag@']);
$this->assertSame('1.0.0', $values['@git_version@']);
$this->assertCount(5, $values);

$this->assertSame([], $this->config->getRecommendations());
$this->assertSame([], $this->config->getWarnings());

chdir($basePath);
touch('foo');
exec('git add foo');
exec('git commit -m "Adding another test file."');
chdir($this->tmp);

$this->setConfig([
'base-path' => $basePath,
'files' => [self::DEFAULT_FILE],
'git' => 'git',
'git-commit' => 'git_commit',
'git-commit-short' => 'git_commit_short',
'git-tag' => 'git_tag',
'git-version' => 'git_version',
]);

$values = $this->config->getReplacements();

$this->assertRegExp('/^.+@[a-f0-9]{7}$/', $values['@git@']);
$this->assertRegExp('/^[a-f0-9]{40}$/', $values['@git_commit@']);
$this->assertRegExp('/^[a-f0-9]{7}$/', $values['@git_commit_short@']);
$this->assertRegExp('/^.+-\d+-g[a-f0-9]{7}$/', $values['@git_tag@']);
$this->assertRegExp('/^.+-\d+-g[a-f0-9]{7}$/', $values['@git_version@']);
$this->assertCount(5, $values);

// Some process does not release the git files
if ($this->isWindows()) {
exec('rd /S /Q .git');
}

$this->assertSame([], $this->config->getRecommendations());
$this->assertSame([], $this->config->getWarnings());
}

public function test_a_recommendation_is_given_if_the_default_replacements_setting_is_provided(): void
{
$this->setConfig([
Expand Down

0 comments on commit e708d75

Please sign in to comment.