JSON schema updates (#12123)
* Add composer-lock-schema, update composer-repository-schema with new properties, add lock schema validation in diagnose Fixes #7823 * Add ref to composer.json schema in the lock onepull/12103/head^2
parent
d37dd5fff1
commit
95b9b54f0c
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft-04/schema#",
|
||||
"title": "Composer Lock File",
|
||||
"type": "object",
|
||||
"required": [ "content-hash", "packages", "packages-dev" ],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"_readme": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Informational text for humans reading the file"
|
||||
},
|
||||
"content-hash": {
|
||||
"type": "string",
|
||||
"description": "Hash of all relevant properties of the composer.json that was used to create this lock file."
|
||||
},
|
||||
"packages": {
|
||||
"type": "array",
|
||||
"description": "An array of packages that are required.",
|
||||
"items": {
|
||||
"$ref": "./composer-schema.json",
|
||||
"required": ["name", "version"]
|
||||
}
|
||||
},
|
||||
"packages-dev": {
|
||||
"type": "array",
|
||||
"description": "An array of packages that are required in require-dev.",
|
||||
"items": {
|
||||
"$ref": "./composer-schema.json"
|
||||
}
|
||||
},
|
||||
"aliases": {
|
||||
"type": "array",
|
||||
"description": "Inline aliases defined in the root package.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [ "package", "version", "alias", "alias_normalized" ],
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"alias": {
|
||||
"type": "string"
|
||||
},
|
||||
"alias_normalized": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"minimum-stability": {
|
||||
"type": "string",
|
||||
"description": "The minimum-stability used to generate this lock file."
|
||||
},
|
||||
"stability-flags": {
|
||||
"type": "object",
|
||||
"description": "Root package stability flags changing the minimum-stability for specific packages.",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"prefer-stable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the --prefer-stable flag was used when building this lock file."
|
||||
},
|
||||
"prefer-lowest": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the --prefer-lowest flag was used when building this lock file."
|
||||
},
|
||||
"platform": {
|
||||
"type": "object",
|
||||
"description": "Platform requirements of the root package.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"platform-dev": {
|
||||
"type": "object",
|
||||
"description": "Platform dev-requirements of the root package.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"platform-overrides": {
|
||||
"type": "object",
|
||||
"description": "Platform config overrides of the root package.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"plugin-api-version": {
|
||||
"type": "string",
|
||||
"description": "The composer-plugin-api version that was used to generate this lock file."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft-04/schema#",
|
||||
"description": "A representation of packages metadata.",
|
||||
"title": "Composer Package Repository",
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{ "required": [ "packages" ] },
|
||||
{ "required": [ "providers" ] },
|
||||
{ "required": [ "provider-includes", "providers-url" ] }
|
||||
{ "required": [ "provider-includes", "providers-url" ] },
|
||||
{ "required": [ "metadata-url" ] }
|
||||
],
|
||||
"properties": {
|
||||
"packages": {
|
||||
|
@ -13,19 +14,48 @@
|
|||
"description": "A hashmap of package names in the form of <vendor>/<name>.",
|
||||
"additionalProperties": { "$ref": "#/definitions/versions" }
|
||||
},
|
||||
"providers-url": {
|
||||
"metadata-url": {
|
||||
"type": "string",
|
||||
"description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
|
||||
"description": "Endpoint to retrieve package metadata data from, in Composer v2 format, e.g. '/p2/%package%.json'."
|
||||
},
|
||||
"provider-includes": {
|
||||
"type": "object",
|
||||
"description": "A hashmap of provider listings.",
|
||||
"additionalProperties": { "$ref": "#/definitions/provider" }
|
||||
"available-packages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify all the package names that your repository contains here."
|
||||
},
|
||||
"providers": {
|
||||
"type": "object",
|
||||
"description": "A hashmap of package names in the form of <vendor>/<name>.",
|
||||
"additionalProperties": { "$ref": "#/definitions/provider" }
|
||||
"available-package-patterns": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify package name patterns containing wildcards (*) that your repository contains here."
|
||||
},
|
||||
"security-advisories": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["metadata", "api-url"],
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"type": "boolean",
|
||||
"description": "Whether metadata files contain security advisory data or whether it should always be queried using the API URL."
|
||||
},
|
||||
"api-url": {
|
||||
"type": "string",
|
||||
"description": "Endpoint to call to retrieve security advisories data."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata-changes-url": {
|
||||
"type": "string",
|
||||
"description": "Endpoint to retrieve package metadata updates from. This should receive a timestamp since last call to be able to return new changes. e.g. '/metadata/changes.json'."
|
||||
},
|
||||
"providers-api": {
|
||||
"type": "string",
|
||||
"description": "Endpoint to retrieve package names providing a given name from, e.g. '/providers/%package%.json'."
|
||||
},
|
||||
"notify-batch": {
|
||||
"type": "string",
|
||||
|
@ -35,9 +65,73 @@
|
|||
"type": "string",
|
||||
"description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
|
||||
},
|
||||
"list": {
|
||||
"type": "string",
|
||||
"description": "Endpoint that provides a full list of packages present in the repository. It should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring. e.g. '/list.json'."
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["message", "versions"],
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A message that will be output by Composer as a warning when this source is consulted."
|
||||
},
|
||||
"versions": {
|
||||
"type": "string",
|
||||
"description": "A version constraint to limit to which Composer versions the warning should be shown."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"infos": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["message", "versions"],
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A message that will be output by Composer as info when this source is consulted."
|
||||
},
|
||||
"versions": {
|
||||
"type": "string",
|
||||
"description": "A version constraint to limit to which Composer versions the info should be shown."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"providers-url": {
|
||||
"type": "string",
|
||||
"description": "DEPRECATED: Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
|
||||
},
|
||||
"provider-includes": {
|
||||
"type": "object",
|
||||
"description": "DEPRECATED: A hashmap of provider listings.",
|
||||
"additionalProperties": { "$ref": "#/definitions/provider" }
|
||||
},
|
||||
"providers": {
|
||||
"type": "object",
|
||||
"description": "DEPRECATED: A hashmap of package names in the form of <vendor>/<name>.",
|
||||
"additionalProperties": { "$ref": "#/definitions/provider" }
|
||||
},
|
||||
"warning": {
|
||||
"type": "string",
|
||||
"description": "A message that will be output by Composer as a warning when this source is consulted."
|
||||
"description": "DEPRECATED: A message that will be output by Composer as a warning when this source is consulted."
|
||||
},
|
||||
"warning-versions": {
|
||||
"type": "string",
|
||||
"description": "DEPRECATED: A version constraint to limit to which Composer versions the warning should be shown."
|
||||
},
|
||||
"info": {
|
||||
"type": "string",
|
||||
"description": "DEPRECATED: A message that will be output by Composer as a info when this source is consulted."
|
||||
},
|
||||
"info-versions": {
|
||||
"type": "string",
|
||||
"description": "DEPRECATED: A version constraint to limit to which Composer versions the info should be shown."
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft-04/schema#",
|
||||
"title": "Package",
|
||||
"title": "Composer Package",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
|
@ -19,6 +19,8 @@ use Composer\Config;
|
|||
use Composer\Downloader\TransportException;
|
||||
use Composer\IO\BufferIO;
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Json\JsonValidationException;
|
||||
use Composer\Package\Locker;
|
||||
use Composer\Package\RootPackage;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Pcre\Preg;
|
||||
|
@ -89,6 +91,12 @@ EOT
|
|||
|
||||
$io->write('Checking composer.json: ', false);
|
||||
$this->outputResult($this->checkComposerSchema());
|
||||
|
||||
if ($composer->getLocker()->isLocked()) {
|
||||
$io->write('Checking composer.lock: ', false);
|
||||
$this->outputResult($this->checkComposerLockSchema($composer->getLocker()));
|
||||
}
|
||||
|
||||
$this->process = $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io);
|
||||
} else {
|
||||
$this->process = new ProcessExecutor($io);
|
||||
|
@ -267,6 +275,27 @@ EOT
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|true
|
||||
*/
|
||||
private function checkComposerLockSchema(Locker $locker)
|
||||
{
|
||||
$json = $locker->getJsonFile();
|
||||
|
||||
try {
|
||||
$json->validateSchema(JsonFile::LOCK_SCHEMA);
|
||||
} catch (JsonValidationException $e) {
|
||||
$output = '';
|
||||
foreach ($e->getErrors() as $error) {
|
||||
$output .= '<error>'.$error.'</error>'.PHP_EOL;
|
||||
}
|
||||
|
||||
return trim($output);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkGit(): string
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
|
|
|
@ -32,6 +32,7 @@ class JsonFile
|
|||
public const LAX_SCHEMA = 1;
|
||||
public const STRICT_SCHEMA = 2;
|
||||
public const AUTH_SCHEMA = 3;
|
||||
public const LOCK_SCHEMA = 4;
|
||||
|
||||
/** @deprecated Use \JSON_UNESCAPED_SLASHES */
|
||||
public const JSON_UNESCAPED_SLASHES = 64;
|
||||
|
@ -41,6 +42,7 @@ class JsonFile
|
|||
public const JSON_UNESCAPED_UNICODE = 256;
|
||||
|
||||
public const COMPOSER_SCHEMA_PATH = __DIR__ . '/../../../res/composer-schema.json';
|
||||
public const LOCK_SCHEMA_PATH = __DIR__ . '/../../../res/composer-lock-schema.json';
|
||||
|
||||
public const INDENT_DEFAULT = ' ';
|
||||
|
||||
|
@ -228,8 +230,12 @@ class JsonFile
|
|||
{
|
||||
$isComposerSchemaFile = false;
|
||||
if (null === $schemaFile) {
|
||||
$isComposerSchemaFile = true;
|
||||
$schemaFile = self::COMPOSER_SCHEMA_PATH;
|
||||
if ($schema === self::LOCK_SCHEMA) {
|
||||
$schemaFile = self::LOCK_SCHEMA_PATH;
|
||||
} else {
|
||||
$isComposerSchemaFile = true;
|
||||
$schemaFile = self::COMPOSER_SCHEMA_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepend with file:// only when not using a special schema already (e.g. in the phar)
|
||||
|
|
|
@ -73,6 +73,14 @@ class Locker
|
|||
$this->process = $process ?? new ProcessExecutor($io);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getJsonFile(): JsonFile
|
||||
{
|
||||
return $this->lockFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the md5 hash of the sorted content of the composer file.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue