git-php icon indicating copy to clipboard operation
git-php copied to clipboard

Setting environment variables for git command

Open craftydomops opened this issue 2 years ago • 2 comments

Hi there,

Is it possible to set the environment variables for the git commands?

I would like to set GIT_SSH_COMMAND like here: https://stackoverflow.com/a/29754018

Is this possible? Can you give me any example?

Thanks, Dom

craftydomops avatar Oct 23 '23 02:10 craftydomops

Hi, currently not, but you can prepare custom Runner https://github.com/czproject/git-php/blob/master/src/Runners/CliRunner.php and send PR :)

I think Runner can be very simple:

namespace CzProject\GitPhp\Runners;

use CzProject\GitPhp\IRunner;

class EnvironmentVarsRunner implements IRunner
{
  private $env;
  private $runner;

  public function __construct(array $env, IRunner $runner)
  {
    $this->env = $env;
    $this->runner = $runner;
  }

  public function run($cwd, array $args, array $env = NULL)
  {
     if ($env === NULL) {
        $env = $this->env;
     } else {
        $env = array_merge($this->env, $env);
     }

     return $this->runner->run($cwd, $args, $env);
  }
}

// usage:
$cliRunner = new CzProject\GitPhp\Runners\CliRunner;
$envRunner = new CzProject\GitPhp\Runners\EnvironmentVarsRunner([
  'GIT_SSH_COMMAND' => '...',
], $cliRunner);
$git = new CzProject\GitPhp\Git($envRunner);

janpecha avatar Oct 26 '23 06:10 janpecha

Thanks, I made this;

<?php

namespace App\Git;

use CzProject\GitPhp\Runners\CliRunner;
use CzProject\GitPhp\RunnerResult;
use CzProject\GitPhp\GitException;

class SshRunner extends CliRunner
{
    /**
     * @var string|null
     */
    private ?string $sshKeyFile = null;

    /**
     * @var string|null
     */
    private ?string $knownHostsFile = null;

    /**
     * Destructor to clean up temporary files
     */
    public function __destruct()
    {
        $this->cleanupTemporaryFiles();
    }

    /**
     * Run git command with SSH key from environment variable
     *
     * @param string $cwd
     * @param array $args
     * @param array|null $env
     * @return RunnerResult
     */
    public function run($cwd, array $args, ?array $env = NULL)
    {
        // Get SSH key from environment variable
        $sshKey = getenv('SSH_PRIVATE_KEY');

        if ($sshKey) {
            // Create environment variables array if not provided
            if ($env === NULL) {
                $env = [];
            }

            // Set up SSH key and known hosts files
            $this->setupSshFiles($sshKey);

            // Set GIT_SSH_COMMAND environment variable to use the SSH key
            $env['GIT_SSH_COMMAND'] = sprintf(
                'ssh -i %s -o UserKnownHostsFile=%s -o StrictHostKeyChecking=yes',
                $this->sshKeyFile,
                $this->knownHostsFile
            );
        }

        // Call parent run method with the environment variables
        return parent::run($cwd, $args, $env);
    }

    /**
     * Set up SSH key and known hosts files
     *
     * @param string $sshKey
     * @return void
     * @throws GitException
     */
    private function setupSshFiles(string $sshKey): void
    {
        // Create temporary directory for SSH files
        $tempDir = sys_get_temp_dir() . '/git_ssh_' . uniqid();
        if (!mkdir($tempDir, 0700, true)) {
            throw new GitException("Unable to create temporary directory for SSH files");
        }

        // Create SSH key file
        $this->sshKeyFile = $tempDir . '/id_rsa';
        file_put_contents($this->sshKeyFile, $sshKey);
        chmod($this->sshKeyFile, 0600);

        // Create known hosts file
        $this->knownHostsFile = $tempDir . '/known_hosts';
        file_put_contents($this->knownHostsFile, "putyourknownhostshere");
        chmod($this->knownHostsFile, 0600);
    }

    /**
     * Clean up temporary files
     *
     * @return void
     */
    private function cleanupTemporaryFiles(): void
    {
        // Clean up SSH key file
        if ($this->sshKeyFile !== null && file_exists($this->sshKeyFile)) {
            unlink($this->sshKeyFile);
            $this->sshKeyFile = null;
        }

        // Clean up known hosts file
        if ($this->knownHostsFile !== null && file_exists($this->knownHostsFile)) {
            unlink($this->knownHostsFile);
            $this->knownHostsFile = null;

            // Remove parent directory
            $tempDir = dirname($this->knownHostsFile);
            if (is_dir($tempDir)) {
                rmdir($tempDir);
            }
        }
    }
}

peterjaap avatar Apr 24 '25 08:04 peterjaap