Skip to content

Instantly share code, notes, and snippets.

@xperseguers
Last active March 23, 2024 18:21
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xperseguers/ce58e2d27f1115278bf06e5a8eb4b983 to your computer and use it in GitHub Desktop.
Save xperseguers/ce58e2d27f1115278bf06e5a8eb4b983 to your computer and use it in GitHub Desktop.
Create composer patch from a pending TYPO3 patch on Gerrit

Following structure is expected for your TYPO3 project (adapt script if it differs):

.
├── composer.json
├── composer.lock
├── patches
│   ├── ...
│   └── ...
└── scripts
    └── download-patch-from-gerrit.phpsh

Usage:

./scripts/download-patch-from-gerrit.phpsh <some-id>

where <some-id> is a Gerrit ID, like 68720 in the Gerrit URL https://review.typo3.org/c/Packages/TYPO3.CMS/+/68720.

Running the script with this sample ID 68720 will show:

$ ./scripts/download-patch-from-gerrit.phpsh 68720
Subject is 'Prevent possible bypass of new password validation'
Created patch '/path/to/project/scripts/../patches/typo3-cms-extbase-68720.patch'
Created patch '/path/to/project/scripts/../patches/typo3-cms-felogin-68720.patch'

Please extend your composer.json with following block:

{
    "extra": {
        "patches": {
            "typo3/cms-extbase": {
                "Prevent possible bypass of new password validation": "patches/typo3-cms-extbase-68720.patch"
            },
            "typo3/cms-felogin": {
                "Prevent possible bypass of new password validation": "patches/typo3-cms-felogin-68720.patch"
            }
        }
    }
}

then run "composer update --lock".

Note: you may need to require composer package cweagans/composer-patches first.

#!/usr/bin/php
<?php
$gerritId = null;
$showUsage = count($argv) < 2;
$patchesDirectory = __DIR__ . '/../patches/';
if (!$showUsage) {
$gerritId = (int)$argv[1];
}
if ($showUsage || empty($gerritId)) {
$usage = [
'NAME',
"\t" . basename($argv[0]) . ' -- downloads a patch from Gerrit',
'',
'SYNOPSIS',
"\t" . basename($argv[0] . ' <id>'),
'',
'DESCRIPTION',
"\tThis will download the latest patchset from",
"\thttps://review.typo3.org/c/Packages/TYPO3.CMS/+/id then",
"\tsplit it for the various typo3/cms-* packages and update",
"\tyour composer.json",
];
echo implode("\n", $usage) . "\n\n";
exit(1);
}
$change = file_get_contents('https://review.typo3.org/changes/' . $gerritId);
// Fix garbage at the beginning
if (strpos($change, ")]}'") === 0) {
$change = json_decode(trim(substr($change, 4)), true);
}
if (empty($change['subject'])) {
echo "Change $gerritId was not found.\n";
exit(2);
}
$subject = preg_replace('/^\\[.*?\] /', '', $change['subject']);
echo "Subject is '$subject'\n";
$patch = base64_decode(file_get_contents('https://review.typo3.org/changes/' . $gerritId . '/revisions/current/patch'));
$patchMessage = null;
$patches = [];
do {
$nextPatchPos = strpos($patch, 'diff --git', 1);
if ($nextPatchPos === false) {
$buffer = $patch;
$patch = '';
} else {
$buffer = substr($patch, 0, $nextPatchPos);
$patch = substr($patch, $nextPatchPos);
}
if ($patchMessage === null) {
$patchMessage = $buffer;
continue;
}
if (!preg_match('#^diff --git a/typo3/sysext/([^/]+)/([^ ]+)#', $buffer, $matches)) {
// TODO: continue as well if patching a Test file?
continue;
}
$sysext = $matches[1];
$package = 'typo3/cms-' . str_replace('_', '-', $sysext);
if (!isset($patches[$package])) {
$patches[$package] = [$patchMessage];
}
// Fix the patch
$prefix = 'typo3/sysext/' . $matches[1];
$file = $matches[2];
$buffer = str_replace(' a/' . $prefix . '/' . $file, ' a/' . $file, $buffer);
$buffer = str_replace(' b/' . $prefix . '/' . $file, ' b/' . $file, $buffer);
$patches[$package][] = $buffer;
} while (!empty($patch));
$composerChanges = [];
foreach ($patches as $package => $chunks) {
$content = implode('', $chunks);
$patchFileName = str_replace('/', '-', $package) . '-' . $gerritId . '.patch';
file_put_contents($patchesDirectory . $patchFileName, $content);
echo "Created patch '" . $patchesDirectory . $patchFileName . "'\n";
$composerChanges[$package] = [
$subject => 'patches/' . $patchFileName,
];
}
echo "\nPlease extend your composer.json with following block:\n\n";
echo json_encode(['extra' => ['patches' => $composerChanges]], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
echo "\n\nthen run \"composer update --lock\".\n\n";
@mbrodala
Copy link

You should suggest composer update --lock instead since you don't want to update all packages.

@xperseguers
Copy link
Author

@mbrodala done. Thanks for the hint (and the mentioning in Slack)

@mbrodala
Copy link

Thanks for the update; can you do the same in the README? ;-)

@josefglatz
Copy link

What if you add a check whether cweagans package is installed?

@mbrodala
Copy link

You may want to give gilbertsoft/typo3-core-patches a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment