Skip to content

Commit 0bdae45

Browse files
authored
Merge pull request #38 from factorio-item-browser/feature/update-factorio
feature/update-factorio
2 parents 74fc60c + 4070c6c commit 0bdae45

24 files changed

+1768
-929
lines changed

composer.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@
7373
"test-unit": "phpunit --testsuite unit-test --colors=always --coverage-html=test/coverage --coverage-clover=test/coverage/clover.xml",
7474
"test-serialize": "phpunit --testsuite serializer-test --colors=always",
7575
"post-autoload-dump": [
76-
"mkdir -p data/cache data/factorio data/log data/mods data/temp data/instances",
77-
"chmod 0777 data/cache data/factorio data/log data/mods data/temp data/instances"
76+
"mkdir -m a=rwx -p data/cache data/factorio data/factorio/full data/factorio/headless data/log data/mods data/temp data/instances"
7877
],
7978
"test": [
8079
"@composer validate --strict",

composer.lock

Lines changed: 424 additions & 332 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/autoload/commands.global.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
'commands' => [
1818
CommandName::DOWNLOAD_FACTORIO => Command\DownloadFactorioCommand::class,
1919
CommandName::PROCESS => Command\ProcessCommand::class,
20+
CommandName::UPDATE_FACTORIO => Command\UpdateFactorioCommand::class,
2021
],
2122
];

config/autoload/dependencies.global.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939
Command\ProcessStep\ParserStep::class => AutoWireFactory::class,
4040
Command\ProcessStep\RenderIconsStep::class => AutoWireFactory::class,
4141
Command\ProcessStep\UploadStep::class => AutoWireFactory::class,
42-
43-
Factorio\FactorioDownloader::class => AutoWireFactory::class,
42+
Command\UpdateFactorioCommand::class => AutoWireFactory::class,
4443

4544
Helper\HashCalculator::class => AutoWireFactory::class,
4645
Helper\ZipArchiveExtractor::class => AutoWireFactory::class,
@@ -82,6 +81,7 @@
8281
Serializer\Handler\ConstructorHandler::class => AutoWireFactory::class,
8382
Serializer\Handler\RawHandler::class => AutoWireFactory::class,
8483

84+
Service\FactorioDownloadService::class => AutoWireFactory::class,
8585
Service\FactorioExecutionService::class => AutoWireFactory::class,
8686
Service\ModDownloadService::class => AutoWireFactory::class,
8787
Service\ModFileService::class => AutoWireFactory::class,
@@ -104,9 +104,11 @@
104104
'int $numberOfParallelDownloads' => readConfig(ConfigKey::MAIN, ConfigKey::PARALLEL_DOWNLOADS),
105105
'int $numberOfParallelRenderProcesses' => readConfig(ConfigKey::MAIN, ConfigKey::PARALLEL_RENDERS),
106106

107+
'string $factorioApiToken' => readConfig(ModConfigKey::MAIN, ModConfigKey::OPTIONS, ModConfigKey::OPTION_TOKEN),
108+
'string $factorioApiUsername' => readConfig(ModConfigKey::MAIN, ModConfigKey::OPTIONS, ModConfigKey::OPTION_USERNAME),
109+
'string $fullFactorioDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_FACTORIO_FULL),
107110
'string $factorioDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_FACTORIO),
108-
'string $factorioDownloadToken' => readConfig(ModConfigKey::MAIN, ModConfigKey::OPTIONS, ModConfigKey::OPTION_TOKEN),
109-
'string $factorioDownloadUsername' => readConfig(ModConfigKey::MAIN, ModConfigKey::OPTIONS, ModConfigKey::OPTION_USERNAME),
111+
'string $headlessFactorioDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_FACTORIO_HEADLESS),
110112
'string $instancesDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_INSTANCES),
111113
'string $logsDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_LOGS),
112114
'string $modsDirectory' => readConfig(ConfigKey::MAIN, ConfigKey::DIRECTORIES, ConfigKey::DIRECTORY_MODS),

config/autoload/development/export.local.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
ConfigKey::MAIN => [
1818
ConfigKey::DIRECTORIES => [
1919
// ConfigKey::DIRECTORY_CACHE => 'data/cache',
20-
ConfigKey::DIRECTORY_FACTORIO => 'data/factorio',
20+
ConfigKey::DIRECTORY_FACTORIO_FULL => 'data/factorio/full',
21+
ConfigKey::DIRECTORY_FACTORIO_HEADLESS => 'data/factorio/headless',
2122
ConfigKey::DIRECTORY_INSTANCES => 'data/instances',
2223
ConfigKey::DIRECTORY_LOGS => 'data/log',
2324
ConfigKey::DIRECTORY_MODS => 'data/mods',

src/Command/DownloadFactorioCommand.php

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
namespace FactorioItemBrowser\Export\Command;
66

77
use FactorioItemBrowser\Export\Constant\CommandName;
8-
use FactorioItemBrowser\Export\Factorio\FactorioDownloader;
8+
use FactorioItemBrowser\Export\Output\Console;
9+
use FactorioItemBrowser\Export\Service\FactorioDownloadService;
910
use Symfony\Component\Console\Command\Command;
1011
use Symfony\Component\Console\Input\InputArgument;
1112
use Symfony\Component\Console\Input\InputInterface;
1213
use Symfony\Component\Console\Output\OutputInterface;
14+
use Symfony\Component\Filesystem\Filesystem;
1315

1416
/**
1517
* The process for downloading the Factorio game itself.
@@ -19,13 +21,31 @@
1921
*/
2022
class DownloadFactorioCommand extends Command
2123
{
22-
protected FactorioDownloader $factorioDownloader;
24+
protected Console $console;
25+
protected FactorioDownloadService $factorioDownloadService;
26+
protected Filesystem $fileSystem;
2327

24-
public function __construct(FactorioDownloader $factorioDownloader)
25-
{
28+
protected string $fullFactorioDirectory;
29+
protected string $headlessFactorioDirectory;
30+
protected string $tempDirectory;
31+
32+
public function __construct(
33+
Console $console,
34+
FactorioDownloadService $factorioDownloadService,
35+
Filesystem $fileSystem,
36+
string $fullFactorioDirectory,
37+
string $headlessFactorioDirectory,
38+
string $tempDirectory,
39+
) {
2640
parent::__construct();
2741

28-
$this->factorioDownloader = $factorioDownloader;
42+
$this->console = $console;
43+
$this->factorioDownloadService = $factorioDownloadService;
44+
$this->fileSystem = $fileSystem;
45+
46+
$this->fullFactorioDirectory = (string) realpath($fullFactorioDirectory);
47+
$this->headlessFactorioDirectory = (string) realpath($headlessFactorioDirectory);
48+
$this->tempDirectory = (string) realpath($tempDirectory);
2949
}
3050

3151
protected function configure(): void
@@ -41,8 +61,71 @@ protected function configure(): void
4161
protected function execute(InputInterface $input, OutputInterface $output): int
4262
{
4363
$version = strval($input->getArgument('version'));
64+
$archiveFileFull = $this->tempDirectory . "/factorio_${version}_full.tar.xz";
65+
$archiveFileHeadless = $this->tempDirectory . "/factorio_${version}_headless.tar.xz";
66+
$tempDirectoryFull = $this->tempDirectory . "/factorio_${version}_full";
67+
$tempDirectoryHeadless = $this->tempDirectory . "/factorio_${version}_headless";
68+
69+
$this->console->writeHeadline("Downloading and installing Factorio version {$version}");
70+
71+
$this->console->writeAction('Downloading full variant of Factorio');
72+
$downloadFullProcess = $this->factorioDownloadService->createFactorioDownloadProcess(
73+
FactorioDownloadService::VARIANT_FULL,
74+
$version,
75+
$archiveFileFull,
76+
);
77+
$downloadFullProcess->start();
78+
79+
$this->console->writeAction('Downloading headless variant of Factorio');
80+
$downloadHeadlessProcess = $this->factorioDownloadService->createFactorioDownloadProcess(
81+
FactorioDownloadService::VARIANT_HEADLESS,
82+
$version,
83+
$archiveFileHeadless,
84+
);
85+
$downloadHeadlessProcess->run();
86+
if ($downloadHeadlessProcess->getExitCode() !== 0) {
87+
$this->console->writeMessage('<fg=red>Download of headless version failed!</>');
88+
return 1;
89+
}
90+
$this->console->writeAction('Extracting headless variant of Factorio');
91+
$extractHeadlessProcess = $this->factorioDownloadService->createFactorioExtractProcess(
92+
$archiveFileHeadless,
93+
$tempDirectoryHeadless,
94+
);
95+
$extractHeadlessProcess->run();
96+
if ($extractHeadlessProcess->getExitCode() !== 0) {
97+
$this->console->writeMessage('<fg=red>Extracting headless version failed!</>');
98+
return 1;
99+
}
100+
101+
$downloadFullProcess->wait();
102+
if ($downloadFullProcess->getExitCode() !== 0) {
103+
$this->console->writeMessage('<fg=red>Download of full version failed!</>');
104+
return 1;
105+
}
106+
107+
$this->console->writeAction('Extracting full variant of Factorio');
108+
$extractFullProcess = $this->factorioDownloadService->createFactorioExtractProcess(
109+
$archiveFileFull,
110+
$tempDirectoryFull,
111+
);
112+
$extractFullProcess->run();
113+
if ($extractFullProcess->getExitCode() !== 0) {
114+
$this->console->writeMessage('<fg=red>Extracting full version failed!</>');
115+
return 1;
116+
}
117+
118+
$this->console->writeAction('Switching Factorio releases');
119+
$this->fileSystem->remove($this->headlessFactorioDirectory);
120+
$this->fileSystem->rename($tempDirectoryHeadless, $this->headlessFactorioDirectory);
121+
$this->fileSystem->remove($this->fullFactorioDirectory);
122+
$this->fileSystem->rename($tempDirectoryFull, $this->fullFactorioDirectory);
123+
124+
$this->console->writeAction('Cleaning up');
125+
$this->fileSystem->remove($archiveFileHeadless);
126+
$this->fileSystem->remove($archiveFileFull);
44127

45-
$this->factorioDownloader->download($version);
128+
$this->console->writeMessage('Done.');
46129
return 0;
47130
}
48131
}

src/Command/UpdateFactorioCommand.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FactorioItemBrowser\Export\Command;
6+
7+
use BluePsyduck\FactorioModPortalClient\Entity\Version;
8+
use FactorioItemBrowser\CombinationApi\Client\ClientInterface;
9+
use FactorioItemBrowser\CombinationApi\Client\Constant\JobPriority;
10+
use FactorioItemBrowser\CombinationApi\Client\Exception\ClientException;
11+
use FactorioItemBrowser\CombinationApi\Client\Request\Job\CreateRequest;
12+
use FactorioItemBrowser\Common\Constant\Constant;
13+
use FactorioItemBrowser\Common\Constant\Defaults;
14+
use FactorioItemBrowser\Export\Constant\CommandName;
15+
use FactorioItemBrowser\Export\Exception\CommandException;
16+
use FactorioItemBrowser\Export\Exception\ExportException;
17+
use FactorioItemBrowser\Export\Output\Console;
18+
use FactorioItemBrowser\Export\Process\CommandProcess;
19+
use FactorioItemBrowser\Export\Service\FactorioDownloadService;
20+
use FactorioItemBrowser\Export\Service\ModFileService;
21+
use Symfony\Component\Console\Command\Command;
22+
use Symfony\Component\Console\Input\InputInterface;
23+
use Symfony\Component\Console\Output\OutputInterface;
24+
25+
/**
26+
* The command for updating Factorio to its latest version.
27+
*
28+
* @author BluePsyduck <[email protected]>
29+
* @license http://opensource.org/licenses/GPL-3.0 GPL v3
30+
*/
31+
class UpdateFactorioCommand extends Command
32+
{
33+
protected ClientInterface $combinationApiClient;
34+
protected Console $console;
35+
protected FactorioDownloadService $factorioDownloadService;
36+
protected ModFileService $modFileService;
37+
38+
public function __construct(
39+
ClientInterface $combinationApiClient,
40+
Console $console,
41+
FactorioDownloadService $factorioDownloadService,
42+
ModFileService $modFileService,
43+
) {
44+
parent::__construct();
45+
46+
$this->combinationApiClient = $combinationApiClient;
47+
$this->console = $console;
48+
$this->factorioDownloadService = $factorioDownloadService;
49+
$this->modFileService = $modFileService;
50+
}
51+
52+
protected function configure(): void
53+
{
54+
parent::configure();
55+
56+
$this->setName(CommandName::UPDATE_FACTORIO);
57+
$this->setDescription('Updates the Factorio game to its latest version.');
58+
}
59+
60+
/**
61+
* @param InputInterface $input
62+
* @param OutputInterface $output
63+
* @return int
64+
* @throws ExportException
65+
*/
66+
protected function execute(InputInterface $input, OutputInterface $output): int
67+
{
68+
$currentVersion = $this->modFileService->getInfo(Constant::MOD_NAME_BASE)->version;
69+
$this->console->writeMessage(sprintf('Current version: <fg=green>%s</>', $currentVersion));
70+
71+
$latestVersion = $this->factorioDownloadService->getLatestVersion();
72+
$this->console->writeMessage(sprintf('Latest version: <fg=green>%s</>', $latestVersion));
73+
74+
if ((new Version($latestVersion))->compareTo($currentVersion) <= 0) {
75+
$this->console->writeMessage('Already up-to-date. Done.');
76+
return 0;
77+
}
78+
79+
$this->console->writeAction('Downloading new version of Factorio');
80+
$process = $this->createDownloadProcess($latestVersion);
81+
$process->run(function (string $type, string $message) use ($output): void {
82+
$output->write($message);
83+
});
84+
85+
if ($process->getExitCode() !== 0) {
86+
$this->console->writeMessage('<fg=red>Factorio download failed.</>');
87+
return 1;
88+
}
89+
90+
$this->createExportJob();
91+
return 0;
92+
}
93+
94+
/**
95+
* @param string $version
96+
* @return CommandProcess<string>
97+
*/
98+
protected function createDownloadProcess(string $version): CommandProcess
99+
{
100+
return new CommandProcess(CommandName::DOWNLOAD_FACTORIO, [$version]);
101+
}
102+
103+
/**
104+
* @throws CommandException
105+
*/
106+
protected function createExportJob(): void
107+
{
108+
$request = new CreateRequest();
109+
$request->combinationId = Defaults::COMBINATION_ID;
110+
$request->priority = JobPriority::ADMIN;
111+
112+
try {
113+
$this->combinationApiClient->sendRequest($request);
114+
} catch (ClientException $e) {
115+
throw new CommandException('Request to Combination API failed.', 500, $e);
116+
}
117+
}
118+
}

src/Constant/CommandName.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,9 @@ interface CommandName
2121
* The name of the processing command.
2222
*/
2323
public const PROCESS = 'process';
24+
25+
/**
26+
* The name of the command for updating Factorio to its latest version.
27+
*/
28+
public const UPDATE_FACTORIO = 'update-factorio';
2429
}

src/Constant/ConfigKey.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ interface ConfigKey
3232
*/
3333
public const DIRECTORY_FACTORIO = 'factorio';
3434

35+
/**
36+
* The key holding the directory of the installed full Factorio game.
37+
*/
38+
public const DIRECTORY_FACTORIO_FULL = 'factorio-full';
39+
40+
/**
41+
* The key holding the directory of the installed headless Factorio game.
42+
*/
43+
public const DIRECTORY_FACTORIO_HEADLESS = 'factorio-headless';
44+
3545
/**
3646
* The key holding the instances directory.
3747
*/

0 commit comments

Comments
 (0)