[RFC][docs] Add pattern matching docs (#27686)

* [docs] add pattern matching docs

* Add more examples

* Improve default-registry documentation
This commit is contained in:
Victor Romero 2022-12-19 12:19:38 -08:00 committed by GitHub
parent 4c76cc0af7
commit a22a711815
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,6 +16,7 @@ use, please read [this documentation](../maintainers/registries.md).
- [Registry Objects: `"baseline"`](#registry-objects-baseline)
- [Registry Objects: `"repository"`](#registry-objects-repository)
- [Registry Objects: `"path"`](#registry-objects-path)
- [Registry Objects: `"packages"`](#registry-objects-packages)
- [Configuration: `"default-registry"`](#configuration-default-registry)
- [Configuration: `"registries"`](#configuration-registries)
- [Configuration: `"overlay-ports"`](#configuration-overlay-ports)
@ -74,21 +75,64 @@ This should be a string, of any repository format that git understands:
This should be a path; it can be either absolute or relative; relative paths
will be based at the directory the `vcpkg-configuration.json` lives in.
#### Registry Objects: `"packages"`
With exception of the default registry and artifacts registries. All registries
must declare the packages they provide using the `"packages"` array.
Each entry in the array must be:
* a package name, or
* a package prefix.
Package names may contain only lowercase letters, digits, and `-`. Package names cannot start or end with `-`.
Package prefixes must follow these rules:
* Use the wildcard character: `*`
* `*` matches zero or more port name characters (lowercase letters, digits, and `-`).
* Contain only one wildcard (`*`)
* The wildcard (`*`) must be the last character in the pattern.
* All characters before the wildcard `*` must be valid port name characters.
Examples of valid patterns:
* `*`: Matches all port names
* `b*`: Matches ports that start with the letter `b`
* `boost-*`: Matches ports that start with the prefix `boost-`
Examples of invalid patterns:
* `*a` (`*` must be the last character in the prefix)
* `a**` (only one `*` is allowed)
* `a+` (`+` is not a valid wildcard)
* `a?` (`?` is not a valid wildcard)
See [package name resolution](#package-name-resolution) for more details.
### Configuration: `"default-registry"`
The `"default-registry"` field should be a registry object. It defines
the registry that is used for all packages that are not claimed by any
package registries. It may also be `null`, in which case no packages that
are not claimed by package registries may be installed.
The default registry is used as a fallback when resolving package names,
if no other registry matches the package name, the default registry will be selected.
Users can set the default registry to `null`, in which case, if no other registry matches
a package name the install will fail.
The default registry is either a registry object without a `"packages"` array
(since it will automatically match any non-resolved package names) or `null`.
If `vcpkg-configuration.json` does not declare a `"default-registry"`, vcpkg will
automatically set the default registry to the `"builtin-registry"`.
The `"builtin-registry"` is the local instance of `https://github.com/Microsoft/vcpkg`.
This is necessary so that a manifest with no explicit registry configuration can resolve
port names in the official vcpkg catalog. The `"builtin-baseline"` property in `vcpkg.json`
can be used to set the baseline for the `"builtin-registry"`.
### Configuration: `"registries"`
The `"registries"` field should be an array of registry objects, each of
which additionally contain a `"packages"` field, which should be an array of
package names. These define the package registries, which are used for
the specific packages named by the `"packages"` field.
The `"registries"` field is used to define additional port and/or artifact registries.
The `"packages"` fields of all the package registries must be disjoint.
Port registries are also required to declare a list of packages they provide using the `"packages"` array.
Using additional port registries also requires that a baseline is provided for the default registry
or that the default registry is set to null. If using the `"builtin-registry"` you can set the baseline
using the `"builtin-baseline"` field in `vcpkg.json`.
### Configuration: `"overlay-ports"`
@ -140,20 +184,180 @@ overlay triplets from your custom directories. The following
## Package Name Resolution
The way package name resolution works in vcpkg is fairly distinct from many
package managers. It is very carefully designed to _never_ implicitly choose
the registry that a package is fetched from. Just from
`vcpkg-configuration.json`, one can tell exactly from which registry a
package definition will be fetched from.
Package name resolution in vcpkg is designed to be predictable and easy to understand. Given a
`vcpkg-configuration.json` file, it should be simple to tell which registry will provide any given port name.
The name resolution algorithm is as follows:
When resolving a port name to a registry, we prioritize as follows:
1. Exact match
2. Pattern match
* Longer prefixes have higher priority, e.g.: when resolving `boost`, `boost*` > `b*` > `*`
3. Default registry
4. If the default registry has been set to null, emit an error
- If the name matches an [overlay](#overlays-resolution), use that overlay; otherwise
- If there is a package registry that claims the package name,
use that registry; otherwise
- If there is a default registry defined, use that registry; otherwise
- If the default registry is set to `null`, error out; otherwise
- use the built-in registry.
Package names have higher priority than prefixes even if they both match the same amount of characters.
For example, when resolving `boost`: `boost` > `boost*`.
If there is a tie in priority, vcpkg will use the first registry that declares the package name or prefix.
_This makes the order in which registries are declared in the `"registries"` array important._
### Example #1: Package name resolution
`vcpkg-configuration.json`
```json
{
"registries": [
{
"kind": "git",
"repository": "https://github.com/northwindtraders/vcpkg-registry",
"baseline": "dacf4de488094a384ca2c202b923ccc097956e0c",
"packages": ["bei*"]
},
{
"kind": "git",
"repository": "https://github.com/vicroms/vcpkg-registry",
"baseline": "dacf4de488094a384ca2c202b923ccc097956e0c",
"packages": ["beicode", "bei*"]
}
]
}
```
`vcpkg.json`
```json
{
"dependencies": [
"beicode",
"beison",
"fmt"
],
"builtin-baseline": "7e7c62d863b1bf599c1d104b76cd8b74475844d4"
}
```
Given this configuration, each package name resolves to:
* `beicode`: from registry `https://github.com/vicroms/vcpkg-registry` (exact match on `beicode`)
* `beison`: from registry `https://github.com/northwindtraders/vcpkg-registry` (pattern match on `beison` and declared first in `"registries"` array)
* `fmt`: from default registry (no matches)
Because multiple registries declare `bei*`, vcpkg will also emit the following warning:
```no-highlight
Found the following problems in configuration (path/to/vcpkg-configuration.json):
$ (a configuration object): warning: Package "bei*" is duplicated.
First declared in:
location: $.registries[0].packages[0]
registry: https://github.com/northwindtraders/vcpkg-registry
The following redeclarations will be ignored:
location: $.registries[1].packages[1]
registry: https://github.com/vicroms/vcpkg-registry
```
### Example #2: Overriding the default registry
There are two ways for a user to override the default registry.
One way is to use the `"default-registry"` object:
```json
{
"default-registry": {
"kind": "git",
"repository": "https://github.com/Microsoft/vcpkg",
"baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3"
}
}
```
The other way is to set the `"default-registry"` object to null and
use the `"*"` pattern in the first registry of the `"registries"` array.
```json
{
"default-registry": null,
"registries": [
{
"kind": "git",
"repository": "https://github.com/Microsoft/vcpkg",
"baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3",
"packages": ["*"]
}
]
}
```
An advantage of the second form is that you can add more entries to the packages array, while the
`"default-registry"` object doesn't allow you to define a packages array at all. This difference
becomes important in cases where you need to ensure that a package comes from the default registry, like
in the example below.
### Example #3: Ensuring correct name resolution
Let's consider a registry that provides the Qt Framework libraries.
`vcpkg-configuration.json`
```json
{
"default-registry": {
"kind": "git",
"repository": "https://github.com/Microsoft/vcpkg",
"baseline": "7e7c62d863b1bf599c1d104b76cd8b74475844d4"
},
"registries": [
{
"kind": "git",
"repository": "https://github.com/custom-qt/custom-qt-registry",
"baseline": "adfc4de488094a384ca2c202b923ccc097956e0c",
"packages": ["qt*"]
}
]
}
```
And the following project dependencies:
`vcpkg.json`
```json
{
"dependencies": [
"qt5",
"qt-advanced-docking-system",
"qtkeychain"
]
}
```
The `"qt*"` pattern matches all port names in `vcpkg.json`. But there is a problem!
The ports `qt-advanced-docking-system` and `qtkeychain` are not part of the official Qt Framework libraries,
and since vcpkg won't be able to find the ports in the custom registry the installation will fail.
The obvious solution is to make sure that these packages come from the default registry instead,
we can accomplish that by changing the way we declare the default registry and adding `qt-advanced-docking-system`
and `qtkeychain` to its `"packages"` array:
`vcpkg-configuration.json`
```json
{
"default-registry": null,
"registries": [
{
"kind": "git",
"repository": "https://github.com/Microsoft/vcpkg",
"baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3",
"packages": ["*", "qt-advanced-docking-system", "qtkeychain"]
},
{
"kind": "git",
"repository": "https://github.com/custom-qt/custom-qt-registry",
"baseline": "adfc4de488094a384ca2c202b923ccc097956e0c",
"packages": ["qt*"]
}
]
}
```
Because exact matches are preferred over pattern matches, this configuration will make
`qt-advanced-docking-system` and `qtkeychain` resolve to the default registry.
### Overlays Resolution