Skip to content

Commit 085b4ca

Browse files
authored
Merge pull request #324 from asgrim/handle-sudo-prompts-better
Handle sudo prompts better in non-interactive terminals
2 parents b91377b + a604f3a commit 085b4ca

File tree

6 files changed

+46
-18
lines changed

6 files changed

+46
-18
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ jobs:
151151
run: vendor/bin/behat --tags="~@non-windows"
152152
- name: Run Behat on non-Windows
153153
if: matrix.operating-system != 'windows-latest'
154-
run: vendor/bin/behat
154+
run: sudo vendor/bin/behat
155155

156156
coding-standards:
157157
runs-on: ubuntu-latest

src/Container.php

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,9 @@
4646
use Symfony\Component\Console\Output\OutputInterface;
4747
use Symfony\Component\EventDispatcher\EventDispatcher;
4848

49-
use function defined;
50-
use function fopen;
5149
use function getcwd;
5250
use function str_starts_with;
5351

54-
use const STDIN;
55-
5652
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */
5753
final class Container
5854
{
@@ -65,14 +61,7 @@ public static function factory(): ContainerInterface
6561
static function () {
6662
$input = new ArgvInput();
6763

68-
$stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
69-
$noInteractionEnv = ComposerPlatform::getEnv('COMPOSER_NO_INTERACTION');
70-
if (
71-
$noInteractionEnv === false
72-
|| $noInteractionEnv === '1'
73-
|| $stdin === false
74-
|| ! ComposerPlatform::isTty($stdin)
75-
) {
64+
if (! Platform::isInteractive()) {
7665
$input->setInteractive(false);
7766
}
7867

src/File/Sudo.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace Php\Pie\File;
66

7+
use Php\Pie\Platform;
8+
use Php\Pie\Platform\TargetPlatform;
79
use Symfony\Component\Process\ExecutableFinder;
8-
use Throwable;
910

1011
use function is_string;
1112

@@ -29,6 +30,10 @@ public static function find(): string
2930
throw SudoNotFoundOnSystem::new();
3031
}
3132

33+
if (! TargetPlatform::isRunningAsRoot() && ! Platform::isInteractive()) {
34+
throw SudoRequiresInteractiveTerminal::fromSudo($sudo);
35+
}
36+
3237
self::$memoizedSudo = $sudo;
3338
}
3439

@@ -41,7 +46,7 @@ public static function exists(): bool
4146
self::find();
4247

4348
return true;
44-
} catch (Throwable) {
49+
} catch (SudoNotFoundOnSystem) {
4550
return false;
4651
}
4752
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Pie\File;
6+
7+
use RuntimeException;
8+
9+
use function sprintf;
10+
11+
class SudoRequiresInteractiveTerminal extends RuntimeException
12+
{
13+
public static function fromSudo(string $sudoPath): self
14+
{
15+
return new self(sprintf(
16+
'PIE needed to elevate privileges with %s, but you are running in a non-interactive terminal, so prompting for a password is not possible.',
17+
$sudoPath,
18+
));
19+
}
20+
}

src/Installing/UnixInstall.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */
2121
final class UnixInstall implements Install
2222
{
23-
private const MAKE_INSTALL_TIMEOUT_SECS = 60; // 1 minute
23+
private const MAKE_INSTALL_TIMEOUT_SECS = 300; // 5 minutes
2424

2525
public function __construct(private readonly SetupIniFile $setupIniFile)
2626
{
@@ -45,11 +45,11 @@ public function __invoke(
4545

4646
// If the target directory isn't writable, or a .so file already exists and isn't writable, try to use sudo
4747
if (
48-
Sudo::exists()
49-
&& (
48+
(
5049
! is_writable($targetExtensionPath)
5150
|| (file_exists($expectedSharedObjectLocation) && ! is_writable($expectedSharedObjectLocation))
5251
)
52+
&& Sudo::exists()
5353
) {
5454
$output->writeln(sprintf(
5555
'<comment>Cannot write to %s, so using sudo to elevate privileges.</comment>',

src/Platform.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,31 @@
1010
use RuntimeException;
1111

1212
use function array_keys;
13+
use function defined;
14+
use function fopen;
1315
use function implode;
1416
use function md5;
1517
use function rtrim;
1618
use function strpos;
1719
use function strtr;
1820

1921
use const DIRECTORY_SEPARATOR;
22+
use const STDIN;
2023

2124
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */
2225
class Platform
2326
{
27+
public static function isInteractive(): bool
28+
{
29+
$stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
30+
$noInteractionEnv = ComposerPlatform::getEnv('COMPOSER_NO_INTERACTION');
31+
32+
return $noInteractionEnv !== false
33+
&& $noInteractionEnv !== '1'
34+
&& $stdin !== false
35+
&& ComposerPlatform::isTty($stdin);
36+
}
37+
2438
private static function useXdg(): bool
2539
{
2640
foreach (array_keys($_SERVER) as $key) {

0 commit comments

Comments
 (0)