Skip to content

Commit ba0ea5b

Browse files
authored
Refactor lock component to a single class (#773)
1 parent 1c439a0 commit ba0ea5b

File tree

10 files changed

+284
-147
lines changed

10 files changed

+284
-147
lines changed

src/SPC/builder/BuilderBase.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use SPC\exception\WrongUsageException;
1313
use SPC\store\Config;
1414
use SPC\store\FileSystem;
15+
use SPC\store\LockFile;
1516
use SPC\store\SourceManager;
1617
use SPC\util\CustomExt;
1718

@@ -350,15 +351,11 @@ public function getPHPVersion(): string
350351
public function getPHPVersionFromArchive(?string $file = null): false|string
351352
{
352353
if ($file === null) {
353-
$lock = file_exists(DOWNLOAD_PATH . '/.lock.json') ? file_get_contents(DOWNLOAD_PATH . '/.lock.json') : false;
354-
if ($lock === false) {
355-
return false;
356-
}
357-
$lock = json_decode($lock, true);
358-
$file = $lock['php-src']['filename'] ?? null;
359-
if ($file === null) {
354+
$lock = LockFile::get('php-src');
355+
if ($lock === null) {
360356
return false;
361357
}
358+
$file = LockFile::getLockFullPath($lock);
362359
}
363360
if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) {
364361
return $match[1];

src/SPC/builder/LibraryBase.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use SPC\store\Config;
1111
use SPC\store\Downloader;
1212
use SPC\store\FileSystem;
13+
use SPC\store\LockFile;
1314
use SPC\store\SourceManager;
1415
use SPC\util\GlobalValueTrait;
1516

@@ -46,12 +47,11 @@ public function __construct(?string $source_dir = null)
4647
*/
4748
public function setup(bool $force = false): int
4849
{
49-
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
5050
$source = Config::getLib(static::NAME, 'source');
5151
// if source is locked as pre-built, we just tryInstall it
5252
$pre_built_name = Downloader::getPreBuiltLockName($source);
53-
if (isset($lock[$pre_built_name]) && ($lock[$pre_built_name]['lock_as'] ?? SPC_DOWNLOAD_SOURCE) === SPC_DOWNLOAD_PRE_BUILT) {
54-
return $this->tryInstall($lock[$pre_built_name], $force);
53+
if (($lock = LockFile::get($pre_built_name)) && $lock['lock_as'] === SPC_DOWNLOAD_PRE_BUILT) {
54+
return $this->tryInstall($lock, $force);
5555
}
5656
return $this->tryBuild($force);
5757
}

src/SPC/command/DeleteDownloadCommand.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use SPC\exception\WrongUsageException;
1010
use SPC\store\Downloader;
1111
use SPC\store\FileSystem;
12+
use SPC\store\LockFile;
1213
use Symfony\Component\Console\Attribute\AsCommand;
1314
use Symfony\Component\Console\Input\InputArgument;
1415
use Symfony\Component\Console\Input\InputInterface;
@@ -46,39 +47,38 @@ public function handle(): int
4647
return static::SUCCESS;
4748
}
4849
$chosen_sources = $sources;
49-
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
5050

5151
$deleted_sources = [];
5252
foreach ($chosen_sources as $source) {
5353
$source = trim($source);
5454
foreach ([$source, Downloader::getPreBuiltLockName($source)] as $name) {
55-
if (isset($lock[$name])) {
55+
if (LockFile::get($name)) {
5656
$deleted_sources[] = $name;
5757
}
5858
}
5959
}
6060

6161
foreach ($deleted_sources as $lock_name) {
62+
$lock = LockFile::get($lock_name);
6263
// remove download file/dir if exists
63-
if ($lock[$lock_name]['source_type'] === SPC_SOURCE_ARCHIVE) {
64-
if (file_exists($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock[$lock_name]['filename']))) {
64+
if ($lock['source_type'] === SPC_SOURCE_ARCHIVE) {
65+
if (file_exists($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock['filename']))) {
6566
logger()->info('Deleting file ' . $path);
6667
unlink($path);
6768
} else {
6869
logger()->warning("Source/Package [{$lock_name}] file not found, skip deleting file.");
6970
}
7071
} else {
71-
if (is_dir($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock[$lock_name]['dirname']))) {
72+
if (is_dir($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock['dirname']))) {
7273
logger()->info('Deleting dir ' . $path);
7374
FileSystem::removeDir($path);
7475
} else {
7576
logger()->warning("Source/Package [{$lock_name}] directory not found, skip deleting dir.");
7677
}
7778
}
7879
// remove locked sources
79-
unset($lock[$lock_name]);
80+
LockFile::put($lock_name, null);
8081
}
81-
FileSystem::writeFile(DOWNLOAD_PATH . '/.lock.json', json_encode($lock, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
8282
logger()->info('Delete success!');
8383
return static::SUCCESS;
8484
} catch (DownloaderException $e) {

src/SPC/command/SwitchPhpVersionCommand.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use SPC\store\Config;
88
use SPC\store\Downloader;
99
use SPC\store\FileSystem;
10+
use SPC\store\LockFile;
1011
use Symfony\Component\Console\Attribute\AsCommand;
1112
use Symfony\Component\Console\Input\InputArgument;
1213
use Symfony\Component\Console\Input\InputOption;
@@ -40,16 +41,9 @@ public function handle(): int
4041
}
4142
}
4243

43-
// detect if downloads/.lock.json exists
44-
$lock_file = DOWNLOAD_PATH . '/.lock.json';
45-
// parse php-src part of lock file
46-
$lock_data = json_decode(file_get_contents($lock_file), true);
47-
// get php-src downloaded file name
48-
$php_src = $lock_data['php-src'];
49-
$file = DOWNLOAD_PATH . '/' . ($php_src['filename'] ?? '.donot.delete.me');
50-
if (file_exists($file)) {
44+
if (LockFile::isLockFileExists('php-src')) {
5145
$this->output->writeln('<info>Removing old PHP source...</info>');
52-
unlink($file);
46+
LockFile::put('php-src', null);
5347
}
5448

5549
// Download new PHP source

src/SPC/command/dev/PackLibCommand.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use SPC\exception\WrongUsageException;
1515
use SPC\store\Config;
1616
use SPC\store\FileSystem;
17+
use SPC\store\LockFile;
1718
use SPC\util\DependencyUtil;
1819
use Symfony\Component\Console\Attribute\AsCommand;
1920
use Symfony\Component\Console\Input\InputArgument;
@@ -47,9 +48,8 @@ public function handle(): int
4748
$lib->setup();
4849
} else {
4950
// Get lock info
50-
$lock = json_decode(file_get_contents(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
5151
$source = Config::getLib($lib->getName(), 'source');
52-
if (!isset($lock[$source]) || ($lock[$source]['lock_as'] ?? SPC_DOWNLOAD_SOURCE) === SPC_DOWNLOAD_PRE_BUILT) {
52+
if (($lock = LockFile::get($source)) === null || ($lock['lock_as'] === SPC_DOWNLOAD_PRE_BUILT)) {
5353
logger()->critical("The library {$lib->getName()} is downloaded as pre-built, we need to build it instead of installing pre-built.");
5454
return static::FAILURE;
5555
}

src/SPC/store/Downloader.php

Lines changed: 15 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -208,34 +208,7 @@ public static function downloadFile(string $name, string $url, string $filename,
208208
if ($download_as === SPC_DOWNLOAD_PRE_BUILT) {
209209
$name = self::getPreBuiltLockName($name);
210210
}
211-
self::lockSource($name, ['source_type' => SPC_SOURCE_ARCHIVE, 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $download_as]);
212-
}
213-
214-
/**
215-
* Try to lock source.
216-
*
217-
* @param string $name Source name
218-
* @param array{
219-
* source_type: string,
220-
* dirname: ?string,
221-
* filename: ?string,
222-
* move_path: ?string,
223-
* lock_as: int
224-
* } $data Source data
225-
* @throws FileSystemException
226-
*/
227-
public static function lockSource(string $name, array $data): void
228-
{
229-
if (!file_exists(FileSystem::convertPath(DOWNLOAD_PATH . '/.lock.json'))) {
230-
$lock = [];
231-
} else {
232-
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
233-
}
234-
// calculate hash
235-
$hash = self::getLockSourceHash($data);
236-
$data['hash'] = $hash;
237-
$lock[$name] = $data;
238-
FileSystem::writeFile(DOWNLOAD_PATH . '/.lock.json', json_encode($lock, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
211+
LockFile::lockSource($name, ['source_type' => SPC_SOURCE_ARCHIVE, 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $download_as]);
239212
}
240213

241214
/**
@@ -281,7 +254,7 @@ public static function downloadGit(string $name, string $url, string $branch, ?s
281254
}
282255
// Lock
283256
logger()->debug("Locking git source {$name}");
284-
self::lockSource($name, ['source_type' => SPC_SOURCE_GIT, 'dirname' => $name, 'move_path' => $move_path, 'lock_as' => $lock_as]);
257+
LockFile::lockSource($name, ['source_type' => SPC_SOURCE_GIT, 'dirname' => $name, 'move_path' => $move_path, 'lock_as' => $lock_as]);
285258

286259
/*
287260
// 复制目录过去
@@ -377,7 +350,7 @@ public static function downloadPackage(string $name, ?array $pkg = null, bool $f
377350
case 'local':
378351
// Local directory, do nothing, just lock it
379352
logger()->debug("Locking local source {$name}");
380-
self::lockSource($name, [
353+
LockFile::lockSource($name, [
381354
'source_type' => SPC_SOURCE_LOCAL,
382355
'dirname' => $pkg['dirname'],
383356
'move_path' => $pkg['extract'] ?? null,
@@ -493,7 +466,7 @@ public static function downloadSource(string $name, ?array $source = null, bool
493466
case 'local':
494467
// Local directory, do nothing, just lock it
495468
logger()->debug("Locking local source {$name}");
496-
self::lockSource($name, [
469+
LockFile::lockSource($name, [
497470
'source_type' => SPC_SOURCE_LOCAL,
498471
'dirname' => $source['dirname'],
499472
'move_path' => $source['extract'] ?? null,
@@ -617,43 +590,6 @@ public static function getPreBuiltLockName(string $source): string
617590
return "{$source}-" . PHP_OS_FAMILY . '-' . getenv('GNU_ARCH') . '-' . (getenv('SPC_LIBC') ?: 'default') . '-' . (SystemUtil::getLibcVersionIfExists() ?? 'default');
618591
}
619592

620-
/**
621-
* Get the hash of the lock source based on the lock options.
622-
*
623-
* @param array $lock_options Lock options
624-
* @return string Hash of the lock source
625-
* @throws RuntimeException
626-
*/
627-
public static function getLockSourceHash(array $lock_options): string
628-
{
629-
$result = match ($lock_options['source_type']) {
630-
SPC_SOURCE_ARCHIVE => sha1_file(DOWNLOAD_PATH . '/' . $lock_options['filename']),
631-
SPC_SOURCE_GIT => exec('cd ' . escapeshellarg(DOWNLOAD_PATH . '/' . $lock_options['dirname']) . ' && ' . SPC_GIT_EXEC . ' rev-parse HEAD'),
632-
SPC_SOURCE_LOCAL => 'LOCAL HASH IS ALWAYS DIFFERENT',
633-
default => filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN) ? '' : throw new RuntimeException("Unknown source type: {$lock_options['source_type']}"),
634-
};
635-
if ($result === false && !filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN)) {
636-
throw new RuntimeException("Failed to get hash for source: {$lock_options['source_type']}");
637-
}
638-
return $result ?: '';
639-
}
640-
641-
/**
642-
* @param array $lock_options Lock options
643-
* @param string $destination Target directory
644-
* @throws FileSystemException
645-
* @throws RuntimeException
646-
*/
647-
public static function putLockSourceHash(array $lock_options, string $destination): void
648-
{
649-
$hash = self::getLockSourceHash($lock_options);
650-
if ($lock_options['source_type'] === SPC_SOURCE_LOCAL) {
651-
logger()->debug("Source [{$lock_options['dirname']}] is local, no hash will be written.");
652-
return;
653-
}
654-
FileSystem::writeFile("{$destination}/.spc-hash", $hash);
655-
}
656-
657593
/**
658594
* Register CTRL+C event for different OS.
659595
*
@@ -689,33 +625,24 @@ private static function getRetryAttempts(): int
689625

690626
/**
691627
* @throws FileSystemException
628+
* @throws WrongUsageException
692629
*/
693630
private static function isAlreadyDownloaded(string $name, bool $force, int $download_as = SPC_DOWNLOAD_SOURCE): bool
694631
{
695-
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
696-
$lock = [];
697-
} else {
698-
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
699-
}
700-
// If lock file exists, skip downloading for source mode
701-
if (!$force && $download_as === SPC_DOWNLOAD_SOURCE && isset($lock[$name])) {
702-
if (
703-
$lock[$name]['source_type'] === SPC_SOURCE_ARCHIVE && file_exists(DOWNLOAD_PATH . '/' . $lock[$name]['filename']) ||
704-
$lock[$name]['source_type'] === SPC_SOURCE_GIT && is_dir(DOWNLOAD_PATH . '/' . $lock[$name]['dirname'])
705-
) {
706-
logger()->notice("Source [{$name}] already downloaded: " . ($lock[$name]['filename'] ?? $lock[$name]['dirname']));
632+
// If the lock file exists, skip downloading for source mode
633+
$lock_item = LockFile::get($name);
634+
if (!$force && $download_as === SPC_DOWNLOAD_SOURCE && $lock_item !== null) {
635+
if (file_exists($path = LockFile::getLockFullPath($lock_item))) {
636+
logger()->notice("Source [{$name}] already downloaded: {$path}");
707637
return true;
708638
}
709639
}
710-
// If lock file exists for current arch and glibc target, skip downloading
711-
712-
if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && isset($lock[$lock_name = self::getPreBuiltLockName($name)])) {
640+
$lock_name = self::getPreBuiltLockName($name);
641+
$lock_item = LockFile::get($lock_name);
642+
if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && $lock_item !== null) {
713643
// lock name with env
714-
if (
715-
$lock[$lock_name]['source_type'] === SPC_SOURCE_ARCHIVE && file_exists(DOWNLOAD_PATH . '/' . $lock[$lock_name]['filename']) ||
716-
$lock[$lock_name]['source_type'] === SPC_SOURCE_GIT && is_dir(DOWNLOAD_PATH . '/' . $lock[$lock_name]['dirname'])
717-
) {
718-
logger()->notice("Pre-built content [{$name}] already downloaded: " . ($lock[$lock_name]['filename'] ?? $lock[$lock_name]['dirname']));
644+
if (file_exists($path = LockFile::getLockFullPath($lock_item))) {
645+
logger()->notice("Pre-built content [{$name}] already downloaded: {$path}");
719646
return true;
720647
}
721648
}

0 commit comments

Comments
 (0)