mirror of
https://github.com/pestphp/pest.git
synced 2026-06-08 20:22:17 +02:00
wip
This commit is contained in:
@ -312,6 +312,7 @@ final readonly class BaselineSync
|
|||||||
{
|
{
|
||||||
$artifactSize = $this->artifactSize($repo, $runId);
|
$artifactSize = $this->artifactSize($repo, $runId);
|
||||||
|
|
||||||
|
$this->output->writeln('');
|
||||||
$this->renderChild($artifactSize !== null
|
$this->renderChild($artifactSize !== null
|
||||||
? sprintf(
|
? sprintf(
|
||||||
'Downloading TIA baseline (%s) from %s…',
|
'Downloading TIA baseline (%s) from %s…',
|
||||||
@ -333,10 +334,11 @@ final readonly class BaselineSync
|
|||||||
$process->start();
|
$process->start();
|
||||||
|
|
||||||
$startedAt = microtime(true);
|
$startedAt = microtime(true);
|
||||||
|
$tick = 0;
|
||||||
|
|
||||||
while ($process->isRunning()) {
|
while ($process->isRunning()) {
|
||||||
$this->renderDownloadProgress($runCacheDir, $artifactSize, $startedAt);
|
$this->renderDownloadProgress($startedAt, $tick++);
|
||||||
usleep(250_000);
|
usleep(120_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
$process->wait();
|
$process->wait();
|
||||||
@ -402,30 +404,18 @@ final readonly class BaselineSync
|
|||||||
return is_numeric($size) ? (int) $size : null;
|
return is_numeric($size) ? (int) $size : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderDownloadProgress(string $dir, ?int $totalBytes, float $startedAt): void
|
private function renderDownloadProgress(float $startedAt, int $tick): void
|
||||||
{
|
{
|
||||||
$current = $this->dirSize($dir);
|
static $frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
||||||
$elapsed = max(0.001, microtime(true) - $startedAt);
|
|
||||||
$speed = (int) ($current / $elapsed);
|
|
||||||
|
|
||||||
if ($totalBytes !== null && $totalBytes > 0) {
|
$elapsed = max(0.0, microtime(true) - $startedAt);
|
||||||
$percent = min(99, (int) floor(($current / $totalBytes) * 100));
|
$frame = $frames[$tick % count($frames)];
|
||||||
$message = sprintf(
|
|
||||||
' <fg=gray>%s / %s (%d%%, %s/s)</>',
|
|
||||||
$this->formatSize($current),
|
|
||||||
$this->formatSize($totalBytes),
|
|
||||||
$percent,
|
|
||||||
$this->formatSize($speed),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$message = sprintf(
|
|
||||||
' <fg=gray>%s (%s/s)</>',
|
|
||||||
$this->formatSize($current),
|
|
||||||
$this->formatSize($speed),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->output->write("\r\033[K".$message);
|
$this->output->write(sprintf(
|
||||||
|
"\r\033[K <fg=gray>%s %.1fs elapsed</>",
|
||||||
|
$frame,
|
||||||
|
$elapsed,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function clearProgressLine(): void
|
private function clearProgressLine(): void
|
||||||
|
|||||||
@ -4,12 +4,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Pest\Plugins\Tia;
|
namespace Pest\Plugins\Tia;
|
||||||
|
|
||||||
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
final readonly class Fingerprint
|
final readonly class Fingerprint
|
||||||
{
|
{
|
||||||
private const int SCHEMA_VERSION = 15;
|
private const int SCHEMA_VERSION = 17;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{
|
* @return array{
|
||||||
@ -23,8 +25,8 @@ final readonly class Fingerprint
|
|||||||
'structural' => [
|
'structural' => [
|
||||||
'schema' => self::SCHEMA_VERSION,
|
'schema' => self::SCHEMA_VERSION,
|
||||||
'composer_lock' => self::composerLockHash($projectRoot),
|
'composer_lock' => self::composerLockHash($projectRoot),
|
||||||
'phpunit_xml' => self::hashIfExists($projectRoot.'/phpunit.xml'),
|
'phpunit_xml' => self::trackedHash($projectRoot, 'phpunit.xml'),
|
||||||
'phpunit_xml_dist' => self::hashIfExists($projectRoot.'/phpunit.xml.dist'),
|
'phpunit_xml_dist' => self::trackedHash($projectRoot, 'phpunit.xml.dist'),
|
||||||
// 'pest_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseFactory.php'),
|
// 'pest_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseFactory.php'),
|
||||||
// 'pest_method_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseMethodFactory.php'),
|
// 'pest_method_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseMethodFactory.php'),
|
||||||
'vite_config' => self::viteConfigHash($projectRoot),
|
'vite_config' => self::viteConfigHash($projectRoot),
|
||||||
@ -160,6 +162,10 @@ final readonly class Fingerprint
|
|||||||
$parts = [];
|
$parts = [];
|
||||||
|
|
||||||
foreach (JsModuleGraph::VITE_CONFIG_NAMES as $name) {
|
foreach (JsModuleGraph::VITE_CONFIG_NAMES as $name) {
|
||||||
|
if (! self::isTrackedByGit($projectRoot, $name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$hash = self::contentHashOrNull($projectRoot.'/'.$name);
|
$hash = self::contentHashOrNull($projectRoot.'/'.$name);
|
||||||
|
|
||||||
if ($hash !== null) {
|
if ($hash !== null) {
|
||||||
@ -175,6 +181,10 @@ final readonly class Fingerprint
|
|||||||
$parts = [];
|
$parts = [];
|
||||||
|
|
||||||
foreach (['tsconfig.json', 'tsconfig.app.json', 'jsconfig.json'] as $name) {
|
foreach (['tsconfig.json', 'tsconfig.app.json', 'jsconfig.json'] as $name) {
|
||||||
|
if (! self::isTrackedByGit($projectRoot, $name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$hash = self::hashIfExists($projectRoot.'/'.$name);
|
$hash = self::hashIfExists($projectRoot.'/'.$name);
|
||||||
|
|
||||||
if ($hash !== null) {
|
if ($hash !== null) {
|
||||||
@ -230,7 +240,7 @@ final readonly class Fingerprint
|
|||||||
|
|
||||||
private static function composerLockHash(string $projectRoot): ?string
|
private static function composerLockHash(string $projectRoot): ?string
|
||||||
{
|
{
|
||||||
return self::hashIfExists($projectRoot.'/composer.lock');
|
return self::trackedHash($projectRoot, 'composer.lock');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function packageLockHash(string $projectRoot): ?string
|
private static function packageLockHash(string $projectRoot): ?string
|
||||||
@ -238,7 +248,7 @@ final readonly class Fingerprint
|
|||||||
$parts = [];
|
$parts = [];
|
||||||
|
|
||||||
foreach (['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lock', 'bun.lockb'] as $name) {
|
foreach (['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lock', 'bun.lockb'] as $name) {
|
||||||
$hash = self::hashIfExists($projectRoot.'/'.$name);
|
$hash = self::trackedHash($projectRoot, $name);
|
||||||
|
|
||||||
if ($hash !== null) {
|
if ($hash !== null) {
|
||||||
$parts[] = $name.':'.$hash;
|
$parts[] = $name.':'.$hash;
|
||||||
@ -248,6 +258,49 @@ final readonly class Fingerprint
|
|||||||
return $parts === [] ? null : hash('xxh128', implode("\n", $parts));
|
return $parts === [] ? null : hash('xxh128', implode("\n", $parts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function trackedHash(string $projectRoot, string $relativePath): ?string
|
||||||
|
{
|
||||||
|
if (! self::isTrackedByGit($projectRoot, $relativePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::hashIfExists($projectRoot.'/'.$relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when the file exists and is not gitignored.
|
||||||
|
*
|
||||||
|
* Gitignored lockfiles (e.g. `package-lock.json` excluded from the repo)
|
||||||
|
* regenerate per-machine with OS-specific optional deps, which would
|
||||||
|
* otherwise force a fingerprint mismatch on every fetched baseline.
|
||||||
|
*/
|
||||||
|
private static function isTrackedByGit(string $projectRoot, string $relativePath): bool
|
||||||
|
{
|
||||||
|
if (! is_file($projectRoot.'/'.$relativePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $cache = [];
|
||||||
|
|
||||||
|
$key = $projectRoot."\0".$relativePath;
|
||||||
|
|
||||||
|
if (isset($cache[$key])) {
|
||||||
|
return $cache[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_dir($projectRoot.'/.git') && ! is_file($projectRoot.'/.git')) {
|
||||||
|
return $cache[$key] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$finder = (new Finder())
|
||||||
|
->in($projectRoot)
|
||||||
|
->depth('== 0')
|
||||||
|
->name($relativePath)
|
||||||
|
->ignoreVCSIgnored(true);
|
||||||
|
|
||||||
|
return $cache[$key] = $finder->hasResults();
|
||||||
|
}
|
||||||
|
|
||||||
private static function composerJsonHash(string $projectRoot): ?string
|
private static function composerJsonHash(string $projectRoot): ?string
|
||||||
{
|
{
|
||||||
$path = $projectRoot.'/composer.json';
|
$path = $projectRoot.'/composer.json';
|
||||||
|
|||||||
Reference in New Issue
Block a user