Skip to content

Commit

Permalink
Merge pull request #134 from woocommerce/24-02/qit-config-dir
Browse files Browse the repository at this point in the history
Fix QIT config path in Windows
  • Loading branch information
Luc45 authored Feb 29, 2024
2 parents 8703ace + 847ffa5 commit f768cae
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 40 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ src-tmp/
.phpunit.result.cache
./qit
_tests/**/*.zip
_tests/**/*.txt
_tests/**/*.txt
dev/
Binary file modified qit
Binary file not shown.
64 changes: 25 additions & 39 deletions src/src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,56 +166,42 @@ public static function get_qit_dir(): string {

// Allow override.
if ( ! empty( getenv( 'QIT_HOME' ) ) ) {
if ( ! file_exists( getenv( 'QIT_HOME' ) ) ) {
throw new \RuntimeException( sprintf( 'The QIT_HOME environment variable is defined, but points to a non-existing directory: %s', getenv( 'QIT_CLI_CONFIG_DIR' ) ) );
}

return $normalize_path( getenv( 'QIT_HOME' ) );
}

// Windows.
if ( is_windows() ) {
$parent_config_dir = getenv( 'QIT_HOME' );
} elseif ( is_windows() ) {
if ( empty( getenv( 'APPDATA' ) ) ) {
throw new \RuntimeException( 'The APPDATA or QIT_HOME environment variables must be defined.' );
throw new \RuntimeException( 'The APPDATA or QIT_HOME environment variables must be defined in Windows.' );
}

return $normalize_path( getenv( 'APPDATA' ) ) . 'woo-qit-cli';
}

if ( empty( getenv( 'HOME' ) ) ) {
throw new \RuntimeException( 'The HOME or QIT_HOME environment variables must be defined.' );
}

$home = $normalize_path( getenv( 'HOME' ) );
$dirs = [];

if ( static::use_xdg() ) {
$xdg_config = getenv( 'XDG_CONFIG_HOME' );
if ( ! $xdg_config ) {
$xdg_config = $home . '.config';
$parent_config_dir = getenv( 'APPDATA' );
} elseif ( ! empty( getenv( 'HOME' ) ) ) {
$home = $normalize_path( getenv( 'HOME' ) );
if ( static::use_xdg() ) {
$xdg_config = getenv( 'XDG_CONFIG_HOME' ) ?: $home . '.config';
$parent_config_dir = $xdg_config;
} else {
$parent_config_dir = $home;
}

$dirs[] = $xdg_config . '/woo-qit-cli/';
} else {
throw new \RuntimeException( 'The HOME, APPDATA, or QIT_HOME environment variables must be defined.' );
}

$dirs[] = $home . 'woo-qit-cli/';

foreach ( $dirs as $dir ) {
if ( is_dir( $dir ) ) {
return $dir;
}
// Normalize and append 'woo-qit-cli/' to the parent directory.
$qit_dir = $normalize_path( $parent_config_dir ) . 'woo-qit-cli/';

$dir_created = mkdir( $dir, 0700, true );

if ( $dir_created ) {
return $dir;
}
// Create the directory if it does not exist.
if ( ! is_dir( $qit_dir ) && ! mkdir( $qit_dir, 0700, true ) ) {
throw new \RuntimeException( "Unable to create the QIT CLI directory: $qit_dir" );
}

throw new \RuntimeException( "You need to set an environment variable 'QIT_HOME' pointing to a writable directory where the QIT CLI can write it's config file. Do NOT use a directory inside your plugin, as the config file will hold sensitive information that should not be included in your plugin." );
return $qit_dir;
}


protected static function use_xdg(): bool {
if ( defined( 'UNIT_TESTS' ) && UNIT_TESTS ) {
if ( App::getVar( 'MIMICK_XDG' ) ) {
return true;
}
}
foreach ( array_keys( $_SERVER ) as $key ) {
if ( strpos( $key, 'XDG_' ) === 0 ) {
return true;
Expand Down
5 changes: 5 additions & 0 deletions src/src/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
namespace QIT_CLI;

function is_windows(): bool {
if ( defined( 'UNIT_TESTS' ) && UNIT_TESTS ) {
if ( App::getVar( 'MIMICK_WINDOWS' ) ) {
return true;
}
}
return defined( 'PHP_WINDOWS_VERSION_BUILD' );
}

Expand Down
110 changes: 110 additions & 0 deletions src/tests/ConfigTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

use PHPUnit\Framework\TestCase;
use QIT_CLI\App;
use QIT_CLI\Config;

class ConfigTest extends TestCase {
private $testDir;
private static $originalEnvVars;

protected function setUp(): void {
if ( is_null( static::$originalEnvVars ) ) {
static::$originalEnvVars = [
'QIT_HOME' => getenv( 'QIT_HOME' ),
'APPDATA' => getenv( 'APPDATA' ),
'HOME' => getenv( 'HOME' ),
'XDG_CONFIG_HOME' => getenv( 'XDG_CONFIG_HOME' ),
];
}

// Reset environment variables to a default state for testing.
putenv( 'QIT_HOME=' );
putenv( 'APPDATA=' );
putenv( 'HOME=' );
putenv( 'XDG_CONFIG_HOME=' );

$this->testDir = __DIR__ . '/data/config/';
}

protected function tearDown(): void {
// Restore original environment variables.
foreach ( static::$originalEnvVars as $var => $value ) {
if ( $value === false ) {
putenv( $var );
} else {
putenv( "$var=$value" );
}
}
App::offsetUnset( 'MIMICK_WINDOWS' );
App::offsetUnset( 'MIMICK_XDG' );
}

public function test_get_qit_dir_with_qit_home_override(): void {
$expectedDir = $this->testDir . 'woo-qit-cli/';

foreach ( [ 'windows', 'unix' ] as $os ) {
if ( $os === 'windows' ) {
App::setVar( 'MIMICK_WINDOWS', true );
} else {
App::offsetUnset( 'MIMICK_WINDOWS' );
}

// Regular.
putenv( 'QIT_HOME=' . $this->testDir );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );

// Missing trailing slash.
putenv( 'QIT_HOME=' . rtrim( $this->testDir, '/' ) );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );

// Windows directory separator - Non windows.
putenv( 'QIT_HOME=' . str_replace( '/', '\\', $this->testDir ) );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );

// Windows directory separator missing trailing slash - Non windows.
putenv( 'QIT_HOME=' . rtrim( str_replace( '/', '\\', $this->testDir ), '\\' ) );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );
}
}

public function test_get_qit_dir_on_windows(): void {
App::setVar( 'MIMICK_WINDOWS', true );

putenv( 'APPDATA=' . $this->testDir );
$expectedDir = $this->testDir . 'woo-qit-cli/';
$this->assertEquals( $expectedDir, Config::get_qit_dir() );

// Simulate Windows environment
putenv( 'APPDATA=' . str_replace( '/', '\\', $this->testDir ) );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );
}

public function test_get_qit_dir_with_home(): void {
putenv( 'HOME=' . $this->testDir );
$expectedDir = $this->testDir . 'woo-qit-cli/';
$this->assertEquals( $expectedDir, Config::get_qit_dir() );

// Simulate Windows separator.
putenv( 'HOME=' . str_replace( '/', '\\', $this->testDir ) );
$this->assertEquals( $expectedDir, Config::get_qit_dir() );
}

public function test_get_qit_dir_with_home_and_xdg(): void {
putenv( 'HOME=' . $this->testDir );
putenv( 'XDG_CONFIG_HOME=' . $this->testDir . '.config' );
App::setVar( 'MIMICK_XDG', true );
$expectedDir = $this->testDir . '.config/woo-qit-cli/';
$this->assertEquals( $expectedDir, Config::get_qit_dir() );
}

public function test_get_qit_dir_throws_if_needed(): void {
putenv( 'QIT_HOME' );
putenv( 'APPDATA' );
putenv( 'HOME' );
putenv( 'XDG_CONFIG_HOME' );

$this->expectException( \RuntimeException::class );
Config::get_qit_dir();
}
}

0 comments on commit f768cae

Please sign in to comment.