From ba42b63704b2f84a378f51ec4b45df32dc86790f Mon Sep 17 00:00:00 2001 From: sten Date: Wed, 27 Sep 2023 10:06:20 +0100 Subject: [PATCH] Update ArcanistComposerLinter.php to check content-hash instead of hash Summary: The 'hash' key in composer.json files was removed by composer version 1.3.0 in December 2016, in favour of the 'content-hash' key. Update the code to validate the content-hash instead. Fixes T15647 Test Plan: * Update a composer.json file, without running 'composer update' * Run 'arc lint' and confirm it warns you that the composer.lock file is out of date * Run 'composer update' * Run 'arc lint' and confirm it returns OKAY Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15647 Differential Revision: https://we.phorge.it/D25442 --- src/lint/linter/ArcanistComposerLinter.php | 69 ++++++++++++++++++- .../__tests__/xml/languages-6.lint-test | 2 +- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/lint/linter/ArcanistComposerLinter.php b/src/lint/linter/ArcanistComposerLinter.php index a9eded3e..c46657e0 100644 --- a/src/lint/linter/ArcanistComposerLinter.php +++ b/src/lint/linter/ArcanistComposerLinter.php @@ -37,11 +37,12 @@ final class ArcanistComposerLinter extends ArcanistLinter { } private function lintComposerJson($path) { - $composer_hash = md5(Filesystem::readFile(dirname($path).'/composer.json')); + $composer_hash = self::getContentHash( + Filesystem::readFile(dirname($path).'/composer.json')); $composer_lock = phutil_json_decode( Filesystem::readFile(dirname($path).'/composer.lock')); - if ($composer_hash !== $composer_lock['hash']) { + if ($composer_hash !== $composer_lock['content-hash']) { $this->raiseLintAtPath( self::LINT_OUT_OF_DATE, pht( @@ -52,4 +53,68 @@ final class ArcanistComposerLinter extends ArcanistLinter { } } + /** + * Returns the md5 hash of the sorted content of the composer.json file. + * + * This function copied from + * https://github.com/ + * composer/composer/blob/1.5.2/src/Composer/Package/Locker.php + * and has the following license: + * + * Copyright (c) Nils Adermann, Jordi Boggiano + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * + * @param string $composer_file_contents The contents of the composer file. + * + * @return string + */ + public static function getContentHash($composer_file_contents) { + $content = json_decode($composer_file_contents, true); + + $relevant_keys = array( + 'name', + 'version', + 'require', + 'require-dev', + 'conflict', + 'replace', + 'provide', + 'minimum-stability', + 'prefer-stable', + 'repositories', + 'extra', + ); + + $relevant_content = array(); + + foreach (array_intersect($relevant_keys, array_keys($content)) as $key) { + $relevant_content[$key] = $content[$key]; + } + if (isset($content['config']['platform'])) { + $relevant_content['config']['platform'] = $content['config']['platform']; + } + + ksort($relevant_content); + + return md5(json_encode($relevant_content)); + } + } diff --git a/src/lint/linter/__tests__/xml/languages-6.lint-test b/src/lint/linter/__tests__/xml/languages-6.lint-test index f652fbb8..7f14c97f 100644 --- a/src/lint/linter/__tests__/xml/languages-6.lint-test +++ b/src/lint/linter/__tests__/xml/languages-6.lint-test @@ -3,5 +3,5 @@ ~~~~~~~~~~ -error:3:16:XML76:LibXML Error +error:3:12:XML76:LibXML Error error:4:1:XML5:LibXML Error