From d39136fd6b0d083c9e434c57e120946fddb63088 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 2 Feb 2024 12:22:30 +0800 Subject: [PATCH 001/164] Update macos runner (#1165) --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e73ec00b..c10e54829 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -249,11 +249,11 @@ jobs: matrix: include: - target: aarch64-apple-darwin - os: macOS-latest + os: macos-14 # M1 CPU - target: debian-x86_64 os: ubuntu-latest - target: x86_64-apple-darwin - os: macOS-latest + os: macos-12 # x64 CPU - target: x86_64-pc-windows-msvc os: windows-latest ext: '.exe' @@ -341,6 +341,7 @@ jobs: - name: Start HTTP Server (MacOS, no Docker) if: runner.os == 'macos' run: | + mkdir -p /usr/local/etc/nginx cat << EOF > /usr/local/etc/nginx/nginx.conf worker_processes 1; events { From bdce8bb592d10d3b74563c6ac82cec005f8cae97 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 2 Feb 2024 00:52:06 -0500 Subject: [PATCH 002/164] Update AWS Lambda docs --- docs/src/run-with-lambda.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/src/run-with-lambda.md b/docs/src/run-with-lambda.md index 59641418a..e7c462705 100644 --- a/docs/src/run-with-lambda.md +++ b/docs/src/run-with-lambda.md @@ -1,10 +1,10 @@ -## Using with AWS Lambda +## Using with AWS Lambda - v0.14+ -Martin can be run in AWS Lambda. This is useful if you want to serve tiles from a serverless environment, while accessing "nearby" data from a PostgreSQL database or PMTiles file in S3, without exposing the raw file to the world to prevent download abuse and improve performance. +Martin can run in AWS Lambda. This is useful if you want to serve tiles from a serverless environment, while accessing "nearby" data from a PostgreSQL database or PMTiles file in S3, without exposing the raw file to the world to prevent download abuse and improve performance. -Some very brief context: Lambda has two deployment models, zip file and container-based. When using zip file deployment, the online code editor is available, in which we can edit the .yaml configuration. When using container-based deployment, we can pass our configuration on the command line or environment variables. +Lambda has two deployment models: zip file and container-based. When using zip file deployment, there is an online code editor to edit the yaml configuration. When using container-based deployment, we can pass our configuration on the command line or environment variables. -Everything can be performed from AWS CloudShell, otherwise you will need to install the AWS CLI and the AWS SAM CLI, and configure authentication. The CloudShell also runs in a particular AWS region. +Everything can be performed via AWS CloudShell, or you can install the AWS CLI and the AWS SAM CLI, and configure authentication. The CloudShell also runs in a particular AWS region. ### Container deployment @@ -15,29 +15,33 @@ $ docker pull ghcr.io/maplibre/martin:latest --platform linux/arm64 $ aws ecr create-repository --repository-name martin […] "repositoryUri": "493749042871.dkr.ecr.us-east-2.amazonaws.com/martin", + # Read the repositoryUri which includes your account number $ docker tag ghcr.io/maplibre/martin:latest 493749042871.dkr.ecr.us-east-2.amazonaws.com/martin:latest $ aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 493749042871.dkr.ecr.us-east-2.amazonaws.com $ docker push 493749042871.dkr.ecr.us-east-2.amazonaws.com/martin:latest ``` -Now you can go to the [Lambda console](https://console.aws.amazon.com/lambda) and create your function. +Open [Lambda console](https://console.aws.amazon.com/lambda) and create your function: 1. Click “Create function”. 2. Choose “Container image”. -3. Put something in “Function name”. (Note: This is an internal identifier, not exposed in the function URL.) -4. Click “Browse images”, and select your repository and the tag. (If you can’t find it, see if you’re in the same region?) -5. Expand “Container image overrides”, and under CMD put the URL of a .pmtiles file. -6. Set “Architecture” to arm64 to match the platform that we pulled. (Lambda has better ARM CPUs than x86.) +3. Put something in “Function name”. + * **Note**: This is an internal identifier, not exposed in the function URL. +4. Click “Browse images”, and select your repository and the tag. + * If you cannot find it, see if you are in the same region? +5. Expand “Container image overrides”, and under CMD put the URL of a `.pmtiles` file. +6. Set “Architecture” to `arm64` to match the platform that we pulled. Lambda has better ARM CPUs than x86. 7. Click “Create function”. 8. Find the “Configuration” tab, select “Function URL”, “Create function URL”. 9. Set “Auth type” to `NONE` - * Do not enable CORS. Martin already has CORS support, so it will create duplicate headers and break CORS. -10. Click on the “Function URL”. If it works, hooray! If it doesn’t, open the “Monitor” tab, “View CloudWatch logs”, find the most recent Log stream. + * Do not enable `CORS`. Martin already has `CORS` support, so it will create incorrect duplicate headers. +10. Click on the “Function URL”. +11. To debug an issue, open the “Monitor” tab, “View CloudWatch logs”, find the most recent Log stream. ### Zip deployment -It’s possible to deploy the entire codebase from the AWS console, but we will use Serverless Application Model. Our function will consist of a “Layer”, containing the Martin binary, and our function itself will contain the configuration in .yaml format. +It’s possible to deploy the entire codebase from the AWS console, but we will use Serverless Application Model. Our function will consist of a “Layer”, containing the Martin binary, and our function itself will contain the configuration in yaml format. #### The layer @@ -56,7 +60,7 @@ Every zip-based Lambda function runs a file called `bootstrap`. cat <src/bootstrap #!/bin/sh set -eu -exec martin -c ${_HANDLER}.yaml +exec martin --config ${_HANDLER}.yaml EOF ``` @@ -121,7 +125,7 @@ Add your configuration file in the function source code: ### TODO -This support is preliminary; there are features to add to Martin, configuration to tweak, and documentation to write. +AWS Lambda support is preliminary; there are features to add to Martin, configuration to tweak, and documentation to improve. Your help is welcome. * Lambda has a default timeout of 3 seconds, and 128 MB of memory, maybe this is suboptimal. * Document how to connect to a PostgreSQL database on RDS. From 35d8e257033e371babc201a6a95e49a69f6139f0 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 5 Feb 2024 14:26:38 -0500 Subject: [PATCH 003/164] upgrade to pmtiles v0.7.0 (#1173) remove reqwest deps, and use the reexport --- Cargo.lock | 60 +++++++++++++++++++-------------------- Cargo.toml | 3 +- martin/Cargo.toml | 3 +- martin/src/pmtiles/mod.rs | 6 ++-- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10ddd067c..60b2a660e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,9 +36,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.5.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129d4c88e98860e1758c5de288d1632b07970a16d59bdf7b8d66053d582bb71f" +checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743" dependencies = [ "actix-codec", "actix-rt", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.4.1" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e43428f3bf11dee6d166b00ec2df4e3aa8cc1606aaa0b7433c146852e2f4e03b" +checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984" dependencies = [ "actix-codec", "actix-http", @@ -292,9 +292,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -1757,9 +1757,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2134,7 +2134,6 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "reqwest", "rustls 0.22.2", "rustls-native-certs 0.7.0", "rustls-pemfile 2.0.0", @@ -2246,9 +2245,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -2694,9 +2693,9 @@ dependencies = [ [[package]] name = "pmtiles" -version = "0.5.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0b1fa428f190cde32998618ceb127c6596bcc2902f6f8bc0ade1e2db35b58d" +checksum = "6e641f75ae1304ce63e7f90635eb4bd18c76e245892b5935289ac73d4c539014" dependencies = [ "async-compression", "async-recursion", @@ -3317,7 +3316,7 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.1", + "rustls-webpki 0.102.2", "subtle", "zeroize", ] @@ -3368,9 +3367,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9d979b3ce68192e42760c7810125eb6cf2ea10efae545a156063e61f314e2a" +checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf" [[package]] name = "rustls-webpki" @@ -3384,9 +3383,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.1" +version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ "ring", "rustls-pki-types", @@ -4160,13 +4159,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] @@ -4205,9 +4203,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", @@ -4236,9 +4234,9 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", "arrayvec", @@ -4251,9 +4249,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ "arrayref", "bytemuck", @@ -4287,9 +4285,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -4472,9 +4470,9 @@ dependencies = [ [[package]] name = "treediff" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" dependencies = [ "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index daf579550..df4f9f30a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,14 +54,13 @@ mbtiles = { path = "./mbtiles", version = "0.9.0" } moka = { version = "0.12", features = ["future"] } num_cpus = "1" pbf_font_tools = { version = "2.5.0", features = ["freetype"] } -pmtiles = { version = "0.5", features = ["http-async", "mmap-async-tokio", "tilejson"] } +pmtiles = { version = "0.7", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } postgis = "0.9" postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] } postgres-protocol = "0.6" pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" -reqwest = { version = "0.11", default-features = false, features = ["rustls-tls-native-roots"] } rstest = "0.18" rustls = "0.22" rustls-native-certs = "0.7" diff --git a/martin/Cargo.toml b/martin/Cargo.toml index 91d3f0a6f..2f02e2c23 100644 --- a/martin/Cargo.toml +++ b/martin/Cargo.toml @@ -64,7 +64,7 @@ default = ["fonts", "lambda", "mbtiles", "pmtiles", "postgres", "sprites"] fonts = ["dep:bit-set", "dep:pbf_font_tools"] lambda = ["dep:lambda-web"] mbtiles = ["dep:mbtiles"] -pmtiles = ["dep:pmtiles", "dep:reqwest"] +pmtiles = ["dep:pmtiles"] postgres = ["dep:deadpool-postgres", "dep:json-patch", "dep:postgis", "dep:postgres", "dep:postgres-protocol", "dep:semver", "dep:tokio-postgres-rustls"] sprites = ["dep:spreet", "tokio/fs"] bless-tests = [] @@ -95,7 +95,6 @@ postgis = { workspace = true, optional = true } postgres-protocol = { workspace = true, optional = true } postgres = { workspace = true, optional = true } regex.workspace = true -reqwest = { workspace = true, optional = true } rustls-native-certs.workspace = true rustls-pemfile.workspace = true rustls.workspace = true diff --git a/martin/src/pmtiles/mod.rs b/martin/src/pmtiles/mod.rs index b24389a39..9605e73b2 100644 --- a/martin/src/pmtiles/mod.rs +++ b/martin/src/pmtiles/mod.rs @@ -11,10 +11,8 @@ use log::{trace, warn}; use martin_tile_utils::{Encoding, Format, TileInfo}; use pmtiles::async_reader::AsyncPmTilesReader; use pmtiles::cache::{DirCacheResult, DirectoryCache}; -use pmtiles::http::HttpBackend; -use pmtiles::mmap::MmapBackend; -use pmtiles::{Compression, Directory, TileType}; -use reqwest::Client; +use pmtiles::reqwest::Client; +use pmtiles::{Compression, Directory, HttpBackend, MmapBackend, TileType}; use serde::{Deserialize, Serialize}; use tilejson::TileJSON; use url::Url; From b4dd29d5ba1d4a21545da1862bfb9fede427ba13 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 5 Feb 2024 21:49:36 -0500 Subject: [PATCH 004/164] justfile improvement and deps --- Cargo.lock | 4 ++-- justfile | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60b2a660e..6829ba742 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1634,9 +1634,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "hex" diff --git a/justfile b/justfile index ac5576d69..aa26bdad6 100644 --- a/justfile +++ b/justfile @@ -344,7 +344,14 @@ install-sqlx: (cargo-install "cargo-sqlx" "sqlx-cli" "--no-default-features" "-- # Check if a certain Cargo command is installed, and install it if needed [private] cargo-install $COMMAND $INSTALL_CMD="" *ARGS="": - @if ! command -v $COMMAND &> /dev/null; then \ - echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" ;\ - cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }} ;\ + #!/usr/bin/env sh + set -eu + if [ ! command -v $COMMAND &> /dev/null ]; then + if [ ! command -v cargo-binstall &> /dev/null ]; then + echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" + cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }} + else + echo "$COMMAND could not be found. Installing it with cargo binstall ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" + cargo binstall ${INSTALL_CMD:-$COMMAND} {{ ARGS }} + fi fi From b9917a2294515829e7da3ed678e64ba05cbb64e6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 5 Feb 2024 22:07:43 -0500 Subject: [PATCH 005/164] fix justfile --- justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/justfile b/justfile index aa26bdad6..58478441b 100644 --- a/justfile +++ b/justfile @@ -346,8 +346,8 @@ install-sqlx: (cargo-install "cargo-sqlx" "sqlx-cli" "--no-default-features" "-- cargo-install $COMMAND $INSTALL_CMD="" *ARGS="": #!/usr/bin/env sh set -eu - if [ ! command -v $COMMAND &> /dev/null ]; then - if [ ! command -v cargo-binstall &> /dev/null ]; then + if ! command -v $COMMAND &> /dev/null; then + if ! command -v cargo-binstall &> /dev/null; then echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }} else From 0f3cfaa1afa2a6c224b7e2fc8fdad2be1b87d72e Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 6 Feb 2024 01:33:35 -0500 Subject: [PATCH 006/164] fix it again --- justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/justfile b/justfile index 58478441b..0a30903ea 100644 --- a/justfile +++ b/justfile @@ -346,8 +346,8 @@ install-sqlx: (cargo-install "cargo-sqlx" "sqlx-cli" "--no-default-features" "-- cargo-install $COMMAND $INSTALL_CMD="" *ARGS="": #!/usr/bin/env sh set -eu - if ! command -v $COMMAND &> /dev/null; then - if ! command -v cargo-binstall &> /dev/null; then + if ! command -v $COMMAND > /dev/null; then + if ! command -v cargo-binstall > /dev/null; then echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }} else From 8aa3dce8cfbe548685e83939e01839352fd34388 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 6 Feb 2024 19:18:14 -0500 Subject: [PATCH 007/164] Better bounds debugging (#1180) Add debug logging for bounds -- seems like this has been a big point of contention / slow startups --- martin/src/pg/query_tables.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/martin/src/pg/query_tables.rs b/martin/src/pg/query_tables.rs index d67455b4c..23a13c15a 100644 --- a/martin/src/pg/query_tables.rs +++ b/martin/src/pg/query_tables.rs @@ -115,23 +115,35 @@ pub async fn table_to_query( if info.bounds.is_none() { match bounds_type { BoundsCalcType::Skip => {} - BoundsCalcType::Quick | BoundsCalcType::Calc => { + BoundsCalcType::Calc => { + debug!("Computing {} table bounds for {id}", info.format_id()); + info.bounds = calc_bounds(&pool, &schema, &table, &geometry_column, srid).await?; + } + BoundsCalcType::Quick => { + debug!( + "Computing {} table bounds with {}s timeout for {id}", + info.format_id(), + DEFAULT_BOUNDS_TIMEOUT.as_secs() + ); let bounds = calc_bounds(&pool, &schema, &table, &geometry_column, srid); - if bounds_type == BoundsCalcType::Calc { - info.bounds = bounds.await?; + pin_mut!(bounds); + if let Ok(bounds) = timeout(DEFAULT_BOUNDS_TIMEOUT, &mut bounds).await { + info.bounds = bounds?; } else { - pin_mut!(bounds); - if let Ok(bounds) = timeout(DEFAULT_BOUNDS_TIMEOUT, &mut bounds).await { - info.bounds = bounds?; - } else { - warn!( + warn!( "Timeout computing {} bounds for {id}, aborting query. Use --auto-bounds=calc to wait until complete, or check the table for missing indices.", info.format_id(), ); - } } } } + + if let Some(bounds) = info.bounds { + debug!( + "The computed bounds for {id} from {} are {bounds}", + info.format_id() + ); + } } let properties = if let Some(props) = &info.properties { From 04e53a7577f509b9431d59f1ec4de3922f3baed8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 7 Feb 2024 16:00:51 +0800 Subject: [PATCH 008/164] Update mbtiles-copy.md (#1181) Update `apply-diff` to `apply-patch` in `mbtiles-copy.md` --- docs/src/mbtiles-copy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/mbtiles-copy.md b/docs/src/mbtiles-copy.md index 0e8098edb..c65e6ddfd 100644 --- a/docs/src/mbtiles-copy.md +++ b/docs/src/mbtiles-copy.md @@ -43,7 +43,7 @@ Apply the diff file generated from `copy` command above to an mbtiles file. The Note that the `agg_tiles_hash_in_diff` metadata value will be renamed to `agg_tiles_hash` when applying the diff. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. ```shell -mbtiles apply_diff src_file.mbtiles diff_file.mbtiles +mbtiles apply-patch src_file.mbtiles diff_file.mbtiles ``` #### Applying diff with SQLite From 0b4e3f95cfbee0bf2427daf19b01e82e57b5b1a8 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 7 Feb 2024 13:01:24 -0500 Subject: [PATCH 009/164] write! perf optimization - use write_str (#1182) --- martin-tile-utils/src/lib.rs | 18 +++++++++--------- martin/src/bin/martin-cp.rs | 4 ++-- martin/src/pg/query_functions.rs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/martin-tile-utils/src/lib.rs b/martin-tile-utils/src/lib.rs index 9df4fd498..43b7705a1 100644 --- a/martin-tile-utils/src/lib.rs +++ b/martin-tile-utils/src/lib.rs @@ -75,14 +75,14 @@ impl Format { impl Display for Format { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Self::Gif => write!(f, "gif"), - Self::Jpeg => write!(f, "jpeg"), - Self::Json => write!(f, "json"), - Self::Mvt => write!(f, "mvt"), - Self::Png => write!(f, "png"), - Self::Webp => write!(f, "webp"), - } + f.write_str(match *self { + Self::Gif => "gif", + Self::Jpeg => "jpeg", + Self::Json => "json", + Self::Mvt => "mvt", + Self::Png => "png", + Self::Webp => "webp", + }) } } @@ -194,7 +194,7 @@ impl Display for TileInfo { if let Some(encoding) = self.encoding.content_encoding() { write!(f, "; encoding={encoding}")?; } else if self.encoding != Encoding::Uncompressed { - write!(f, "; uncompressed")?; + f.write_str("; uncompressed")?; } Ok(()) } diff --git a/martin/src/bin/martin-cp.rs b/martin/src/bin/martin-cp.rs index d24031ea9..35c75d6ce 100644 --- a/martin/src/bin/martin-cp.rs +++ b/martin/src/bin/martin-cp.rs @@ -253,9 +253,9 @@ impl Display for Progress { let left = self.total - done; if left == 0 { - write!(f, " | done") + f.write_str(" | done") } else if done == 0 { - write!(f, " | ??? left") + f.write_str(" | ??? left") } else { let left = Duration::from_secs_f32(elapsed_s * left as f32 / done as f32); write!(f, " | {left:.0?} left") diff --git a/martin/src/pg/query_functions.rs b/martin/src/pg/query_functions.rs index f1ec01a99..898cbdf09 100644 --- a/martin/src/pg/query_functions.rs +++ b/martin/src/pg/query_functions.rs @@ -70,13 +70,13 @@ pub async fn query_available_function(pool: &PgPool) -> PgResult 0 { - write!(query, ", ").unwrap(); + query.push_str(", "); } // This could also be done as "{name} => ${index}::{typ}" // where the name must be passed through escape_identifier write!(query, "${index}::{typ}", index = idx + 1).unwrap(); } - write!(query, ")").unwrap(); + query.push(')'); // TODO: Rewrite as a if-let chain: if Some(names) = output_record_names && output_type == "record" { ... } let ret_inf = if let (Some(names), "record") = (output_record_names, output_type.as_str()) { From 0aa6bd73fc09370d27a2f5cb843925dd29e70f99 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 7 Feb 2024 15:30:30 -0500 Subject: [PATCH 010/164] bump deps, minor CI cleanup --- .github/workflows/ci.yml | 8 +++----- .github/workflows/grcov.yml | 2 +- Cargo.lock | 40 ++++++++++++++++++------------------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c10e54829..6502f62f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,8 +50,7 @@ jobs: -c "exec docker-entrypoint.sh postgres -c ssl=on -c ssl_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem -c ssl_key_file=/etc/ssl/private/ssl-cert-snakeoil.key" steps: - uses: taiki-e/install-action@v2 - with: - tool: just + with: { tool: just } - name: Checkout sources uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -108,8 +107,7 @@ jobs: steps: - uses: taiki-e/install-action@v2 - with: - tool: cross + with: { tool: cross } - name: Checkout sources uses: actions/checkout@v4 with: @@ -362,7 +360,7 @@ jobs: } } EOF - + brew services info nginx brew services start nginx sleep 2 diff --git a/.github/workflows/grcov.yml b/.github/workflows/grcov.yml index 4c587eb27..9d0326b8c 100644 --- a/.github/workflows/grcov.yml +++ b/.github/workflows/grcov.yml @@ -55,7 +55,7 @@ jobs: override: true - name: Cleanup GCDA files - run: rm -rf martin/target/debug/deps/*.gcda + run: rm -rf martin/target/debug/deps/*.gcda - name: Run tests run: cargo test diff --git a/Cargo.lock b/Cargo.lock index 6829ba742..f9fe79437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -574,9 +574,9 @@ checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" -version = "1.14.1" +version = "1.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" +checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" [[package]] name = "byteorder" @@ -1920,9 +1920,9 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -4563,9 +4563,9 @@ checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-vo" @@ -4735,9 +4735,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4745,9 +4745,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", @@ -4760,9 +4760,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -4772,9 +4772,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4782,9 +4782,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", @@ -4795,15 +4795,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", From 79a89125edd6529177b00bca8d09fc9e9fb898a5 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 8 Feb 2024 11:08:47 +0800 Subject: [PATCH 011/164] Add `mbtiles diff` command (#1068) Implement `mbtiles diff a.mbtiles b.mbtiles diff.mbtiles` command This should behave exactly the same as `mbtiles copy a.mbtiles --diff-with-file b.mbtiles diff.mbtiles`. --------- Co-authored-by: Yuri Astrakhan --- docs/src/mbtiles-diff.md | 26 +++++++++++++++++++ mbtiles/src/bin/mbtiles.rs | 52 +++++++++++++++++++++++++++++++++++++- tests/test.sh | 6 ++++- 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 docs/src/mbtiles-diff.md diff --git a/docs/src/mbtiles-diff.md b/docs/src/mbtiles-diff.md new file mode 100644 index 000000000..9f24356c8 --- /dev/null +++ b/docs/src/mbtiles-diff.md @@ -0,0 +1,26 @@ +# Diffing MBTiles + +## `mbtiles diff` + +Diff command compares two mbtiles files `A` and `B`, and generates a diff (delta) file. +If the diff file is [applied](mbtiles-copy.md#mbtiles-apply-patch) to `A`, it will produce `B`. +The diff file will contain all tiles that are different between the two files +(modifications, insertions, and deletions as `NULL` values), for both the tile and metadata tables. +The only exception is `agg_tiles_has` metadata value. It will be renamed to `agg_tiles_hash_in_diff` and a +new `agg_tiles_hash` will be generated for the diff file itself. + +```shell +# This command will comapre `a.mbtiles` and `b.mbtiles`, and generate a new diff file `diff.mbtiles`. +mbtiles diff a.mbtiles b.mbtiles diff.mbtiles + +# If diff.mbtiles is applied to a.mbtiles, it will produce b.mbtiles +mbtiles apply-diff a.mbtiles diff.mbtiles b2.mbtiles + +# b.mbtiles and b2.mbtiles should now be the same +# Validate both files and see that their hash values are identical +mbtiles validate b.mbtiles +[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for b.mbtiles + +mbtiles validate b2.mbtiles +[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for b2.mbtiles +``` diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index 0f9074071..bc8702396 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -52,6 +52,13 @@ enum Commands { /// Value to set, or nothing if the key should be deleted. value: Option, }, + /// Compare two files A and B, and generate a new diff file. If the diff file is applied to A, it will produce B. + #[command(name = "diff")] + Diff { + file_a: PathBuf, + file_b: PathBuf, + diff: PathBuf, + }, /// Copy tiles from one mbtiles file to another. #[command(name = "copy", alias = "cp")] Copy(CopyArgs), @@ -212,6 +219,28 @@ async fn main_int() -> anyhow::Result<()> { println!("MBTiles file summary for {mbt}"); println!("{}", mbt.summary(&mut conn).await?); } + Commands::Diff { + file_a, + file_b, + diff, + } => { + let opts = MbtilesCopier { + src_file: file_a, + diff_with_file: Some(file_b), + dst_file: diff, + copy: CopyType::All, + skip_agg_tiles_hash: false, + on_duplicate: Some(CopyDuplicateMode::Override), + dst_type_cli: None, + dst_type: None, + min_zoom: None, + max_zoom: None, + zoom_levels: vec![], + bbox: vec![], + apply_patch: None, + }; + opts.run().await?; + } } Ok(()) @@ -253,7 +282,7 @@ mod tests { use mbtiles::CopyDuplicateMode; use super::*; - use crate::Commands::{ApplyPatch, Copy, MetaGetValue, MetaSetValue, Validate}; + use crate::Commands::{ApplyPatch, Copy, Diff, MetaGetValue, MetaSetValue, Validate}; use crate::{Args, IntegrityCheckType}; #[test] @@ -524,4 +553,25 @@ mod tests { } ); } + + #[test] + fn test_diff() { + assert_eq!( + Args::parse_from([ + "mbtiles", + "diff", + "file-a.mbtiles", + "file-b.mbtiles", + "../delta.mbtiles", + ]), + Args { + verbose: false, + command: Diff { + file_a: PathBuf::from("file-a.mbtiles"), + file_b: PathBuf::from("file-b.mbtiles"), + diff: PathBuf::from("../delta.mbtiles"), + } + } + ); + } } diff --git a/tests/test.sh b/tests/test.sh index e53580ce1..6371cc76f 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -458,7 +458,11 @@ if [[ "$MBTILES_BIN" != "-" ]]; then "$TEST_TEMP_DIR/world_cities_diff.mbtiles" \ --diff-with-file ./tests/fixtures/mbtiles/world_cities_modified.mbtiles \ 2>&1 | tee "$TEST_OUT_DIR/copy_diff.txt" - + $MBTILES_BIN diff \ + ./tests/fixtures/mbtiles/world_cities.mbtiles \ + ./tests/fixtures/mbtiles/world_cities_modified.mbtiles \ + "$TEST_TEMP_DIR/world_cities_diff2.mbtiles" \ + 2>&1 | tee "$TEST_OUT_DIR/copy_diff2.txt" if command -v sqlite3 > /dev/null; then # Apply this diff to the original version of the file cp ./tests/fixtures/mbtiles/world_cities.mbtiles "$TEST_TEMP_DIR/world_cities_copy.mbtiles" From 7421a99c8308259f1cf86cce8b4071d36a714cde Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 8 Feb 2024 00:35:31 -0500 Subject: [PATCH 012/164] feature: improve diff cmd with copy opts (#1183) * add most of the `mbtiles copy` options to the `mbtiles diff` command * reworked the book --- Cargo.lock | 13 ++- docs/src/SUMMARY.md | 7 +- docs/src/mbtiles-copy.md | 35 ++----- docs/src/mbtiles-diff.md | 50 ++++++--- martin/src/srv/server.rs | 1 + mbtiles/src/bin/mbtiles.rs | 208 ++++++++++++++++++++++--------------- mbtiles/src/copier.rs | 3 +- mbtiles/src/patcher.rs | 16 +-- 8 files changed, 185 insertions(+), 148 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9fe79437..507902360 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2388,19 +2388,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -2420,9 +2419,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index bd7d57b55..ac0d5e000 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -26,8 +26,9 @@ - [Recipes](recipes.md) - [Tools](tools.md) - [martin-cp bulk tile generation](martin-cp.md) - - [MBTiles Info and Metadata](mbtiles-meta.md) - - [MBTiles Copying / Diffing](mbtiles-copy.md) - - [MBTiles Validation](mbtiles-validation.md) + - [MBTiles Metadata](mbtiles-meta.md) - [MBTiles Schemas](mbtiles-schema.md) + - [Copying MBTiles](mbtiles-copy.md) + - [Diffing/Patching MBTiles](mbtiles-diff.md) + - [Validating MBTiles](mbtiles-validation.md) - [Development](development.md) diff --git a/docs/src/mbtiles-copy.md b/docs/src/mbtiles-copy.md index c65e6ddfd..29a3a46a6 100644 --- a/docs/src/mbtiles-copy.md +++ b/docs/src/mbtiles-copy.md @@ -18,13 +18,13 @@ mbtiles copy normalized.mbtiles dst.mbtiles \ ## `mbtiles copy --diff-with-file` -Copy command can also be used to compare two mbtiles files and generate a delta (diff) file. The diff file can be applied to the `src_file.mbtiles` elsewhere, to avoid copying/transmitting the entire modified dataset. The delta file will contain all tiles that are different between the two files (modifications, insertions, and deletions as `NULL` values), for both the tile and metadata tables. - -There is one exception: `agg_tiles_hash` metadata value will be renamed to `agg_tiles_hash_in_diff`, and a new `agg_tiles_hash` will be generated for the diff file itself. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-diff` command will automatically rename the `agg_tiles_hash_in_diff` value back to `agg_tiles_hash` when applying the diff. +This option is identical to using [`mbtiles diff ...`](mbtiles-diff.md). The following commands two are equivalent: ```shell -mbtiles copy src_file.mbtiles diff_file.mbtiles \ - --diff-with-file modified_file.mbtiles +mbtiles diff file1.mbtiles file2.mbtiles diff.mbtiles + +mbtiles copy file1.mbtiles diff.mbtiles \ + --diff-with-file file2.mbtiles ``` ## `mbtiles copy --apply-patch` @@ -33,28 +33,5 @@ Copy a source file to destination while also applying the diff file generated by ```shell mbtiles copy src_file.mbtiles dst_file.mbtiles \ - --apply-patch diff_file.mbtiles -``` - -## `mbtiles apply-patch` - -Apply the diff file generated from `copy` command above to an mbtiles file. The diff file can be applied to the `src_file.mbtiles` elsewhere, to avoid copying/transmitting the entire modified dataset. - -Note that the `agg_tiles_hash_in_diff` metadata value will be renamed to `agg_tiles_hash` when applying the diff. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. - -```shell -mbtiles apply-patch src_file.mbtiles diff_file.mbtiles -``` - -#### Applying diff with SQLite - -Another way to apply the diff is to use the `sqlite3` command line tool directly. This SQL will delete all tiles from `src_file.mbtiles` that are set to `NULL` in `diff_file.mbtiles`, and then insert or update all new tiles from `diff_file.mbtiles` into `src_file.mbtiles`, where both files are of `flat` type. The name of the diff file is passed as a query parameter to the sqlite3 command line tool, and then used in the SQL statements. Note that this does not update the `agg_tiles_hash` metadata value, so it will be incorrect after the diff is applied. - -```shell -sqlite3 src_file.mbtiles \ - -bail \ - -cmd ".parameter set @diffDbFilename diff_file.mbtiles" \ - "ATTACH DATABASE @diffDbFilename AS diffDb;" \ - "DELETE FROM tiles WHERE (zoom_level, tile_column, tile_row) IN (SELECT zoom_level, tile_column, tile_row FROM diffDb.tiles WHERE tile_data ISNULL);" \ - "INSERT OR REPLACE INTO tiles (zoom_level, tile_column, tile_row, tile_data) SELECT * FROM diffDb.tiles WHERE tile_data NOTNULL;" + --apply-patch diff.mbtiles ``` diff --git a/docs/src/mbtiles-diff.md b/docs/src/mbtiles-diff.md index 9f24356c8..8adb65804 100644 --- a/docs/src/mbtiles-diff.md +++ b/docs/src/mbtiles-diff.md @@ -2,25 +2,45 @@ ## `mbtiles diff` -Diff command compares two mbtiles files `A` and `B`, and generates a diff (delta) file. -If the diff file is [applied](mbtiles-copy.md#mbtiles-apply-patch) to `A`, it will produce `B`. -The diff file will contain all tiles that are different between the two files -(modifications, insertions, and deletions as `NULL` values), for both the tile and metadata tables. -The only exception is `agg_tiles_has` metadata value. It will be renamed to `agg_tiles_hash_in_diff` and a -new `agg_tiles_hash` will be generated for the diff file itself. +Copy command can also be used to compare two mbtiles files and generate a delta (diff) file. The diff file can be [applied](#mbtiles-apply-patch) to the `src_file.mbtiles` elsewhere, to avoid copying/transmitting the entire modified dataset. The delta file will contain all tiles that are different between the two files (modifications, insertions, and deletions as `NULL` values), for both the tile and metadata tables. + +There is one exception: `agg_tiles_hash` metadata value will be renamed to `agg_tiles_hash_in_diff`, and a new `agg_tiles_hash` will be generated for the diff file itself. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-diff` command will automatically rename the `agg_tiles_hash_in_diff` value back to `agg_tiles_hash` when applying the diff. ```shell -# This command will comapre `a.mbtiles` and `b.mbtiles`, and generate a new diff file `diff.mbtiles`. -mbtiles diff a.mbtiles b.mbtiles diff.mbtiles +# This command will compare `file1.mbtiles` and `file2.mbtiles`, and generate a new diff file `diff.mbtiles`. +mbtiles diff file1.mbtiles file2.mbtiles diff.mbtiles -# If diff.mbtiles is applied to a.mbtiles, it will produce b.mbtiles -mbtiles apply-diff a.mbtiles diff.mbtiles b2.mbtiles +# If diff.mbtiles is applied to file1.mbtiles, it will produce file2.mbtiles +mbtiles apply-diff file1.mbtiles diff.mbtiles file2a.mbtiles -# b.mbtiles and b2.mbtiles should now be the same +# file2.mbtiles and file2a.mbtiles should now be the same # Validate both files and see that their hash values are identical -mbtiles validate b.mbtiles -[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for b.mbtiles +mbtiles validate file2.mbtiles +[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for file2.mbtiles + +mbtiles validate file2a.mbtiles +[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for file2a.mbtiles +``` + +## `mbtiles apply-patch` + +Apply the diff file generated with the `mbtiles diff` command above to an MBTiles file. The diff file can be applied to the `src_file.mbtiles` that has been previously downloaded to avoid copying/transmitting the entire modified dataset again. The `src_file.mbtiles` will modified in-place. It is also possible to apply the diff file while copying the source file to a new destination file, by using the [`mbtiles copy --apply-patch`](mbtiles-copy.md#mbtiles-copy---apply-patch) command. + +Note that the `agg_tiles_hash_in_diff` metadata value will be renamed to `agg_tiles_hash` when applying the diff. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. -mbtiles validate b2.mbtiles -[INFO ] The agg_tiles_hashes=E95C1081447FB25674DCC1EB97F60C26 has been verified for b2.mbtiles +```shell +mbtiles apply-patch src_file.mbtiles diff_file.mbtiles +``` + +#### Applying diff with SQLite + +Another way to apply the diff is to use the `sqlite3` command line tool directly. This SQL will delete all tiles from `src_file.mbtiles` that are set to `NULL` in `diff_file.mbtiles`, and then insert or update all new tiles from `diff_file.mbtiles` into `src_file.mbtiles`, where both files are of `flat` type. The name of the diff file is passed as a query parameter to the sqlite3 command line tool, and then used in the SQL statements. Note that this does not update the `agg_tiles_hash` metadata value, so it will be incorrect after the diff is applied. + +```shell +sqlite3 src_file.mbtiles \ + -bail \ + -cmd ".parameter set @diffDbFilename diff_file.mbtiles" \ + "ATTACH DATABASE @diffDbFilename AS diffDb;" \ + "DELETE FROM tiles WHERE (zoom_level, tile_column, tile_row) IN (SELECT zoom_level, tile_column, tile_row FROM diffDb.tiles WHERE tile_data ISNULL);" \ + "INSERT OR REPLACE INTO tiles (zoom_level, tile_column, tile_row, tile_data) SELECT * FROM diffDb.tiles WHERE tile_data NOTNULL;" ``` diff --git a/martin/src/srv/server.rs b/martin/src/srv/server.rs index cf89cc605..b0c1caa16 100755 --- a/martin/src/srv/server.rs +++ b/martin/src/srv/server.rs @@ -150,6 +150,7 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server .workers(worker_processes) .run() .err_into(); + Ok((Box::pin(server), listen_addresses)) } diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index bc8702396..fc3d7228f 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -54,11 +54,7 @@ enum Commands { }, /// Compare two files A and B, and generate a new diff file. If the diff file is applied to A, it will produce B. #[command(name = "diff")] - Diff { - file_a: PathBuf, - file_b: PathBuf, - diff: PathBuf, - }, + Diff(DiffArgs), /// Copy tiles from one mbtiles file to another. #[command(name = "copy", alias = "cp")] Copy(CopyArgs), @@ -66,9 +62,9 @@ enum Commands { #[command(name = "apply-patch", alias = "apply-diff")] ApplyPatch { /// MBTiles file to apply diff to - src_file: PathBuf, + base_file: PathBuf, /// Diff file - diff_file: PathBuf, + patch_file: PathBuf, }, /// Update metadata to match the content of the file #[command(name = "meta-update", alias = "update-meta")] @@ -102,6 +98,34 @@ pub struct CopyArgs { src_file: PathBuf, /// MBTiles file to write to dst_file: PathBuf, + #[command(flatten)] + pub options: SharedCopyOpts, + /// Compare source file with this file, and only copy non-identical tiles to destination. + /// Use `mbtiles diff` as a more convenient way to generate this file. + /// It should be later possible to run `mbtiles apply-diff` to merge it in. + #[arg(long, conflicts_with("apply_patch"))] + diff_with_file: Option, + /// Compare source file with this file, and only copy non-identical tiles to destination. + /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. + #[arg(long, conflicts_with("diff_with_file"))] + apply_patch: Option, +} + +#[derive(Clone, Default, PartialEq, Debug, clap::Args)] +pub struct DiffArgs { + /// First MBTiles file to compare + file1: PathBuf, + /// Second MBTiles file to compare + file2: PathBuf, + /// Output file to write the resulting difference to + diff: PathBuf, + + #[command(flatten)] + pub options: SharedCopyOpts, +} + +#[derive(Clone, Default, PartialEq, Debug, clap::Args)] +pub struct SharedCopyOpts { /// Limit what gets copied. /// When copying tiles only, the agg_tiles_hash will still be updated unless --skip-agg-tiles-hash is set. #[arg(long, value_name = "TYPE", default_value_t=CopyType::default())] @@ -124,19 +148,40 @@ pub struct CopyArgs { /// Bounding box to copy, in the format `min_lon,min_lat,max_lon,max_lat`. Can be used multiple times. #[arg(long)] bbox: Vec, - /// Compare source file with this file, and only copy non-identical tiles to destination. - /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. - #[arg(long, conflicts_with("apply_patch"))] - diff_with_file: Option, - /// Compare source file with this file, and only copy non-identical tiles to destination. - /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. - #[arg(long, conflicts_with("diff_with_file"))] - apply_patch: Option, /// Skip generating a global hash for mbtiles validation. By default, `mbtiles` will compute `agg_tiles_hash` metadata value. #[arg(long)] skip_agg_tiles_hash: bool, } +impl SharedCopyOpts { + #[must_use] + pub fn into_copier( + self, + src_file: PathBuf, + dst_file: PathBuf, + diff_with_file: Option, + apply_patch: Option, + ) -> MbtilesCopier { + MbtilesCopier { + src_file, + dst_file, + diff_with_file, + apply_patch, + // Shared + copy: self.copy, + dst_type_cli: self.mbtiles_type, + on_duplicate: self.on_duplicate, + min_zoom: self.min_zoom, + max_zoom: self.max_zoom, + zoom_levels: self.zoom_levels, + bbox: self.bbox, + skip_agg_tiles_hash: self.skip_agg_tiles_hash, + // Constants + dst_type: None, // Taken from dst_type_cli + } + } +} + #[tokio::main] async fn main() { let env = env_logger::Env::default().default_filter_or("mbtiles=info"); @@ -165,29 +210,26 @@ async fn main_int() -> anyhow::Result<()> { Commands::MetaSetValue { file, key, value } => { meta_set_value(file.as_path(), &key, value.as_deref()).await?; } - Commands::Copy(opts) => { - let opts = MbtilesCopier { - src_file: opts.src_file, - dst_file: opts.dst_file, - copy: opts.copy, - dst_type_cli: opts.mbtiles_type, - dst_type: None, - on_duplicate: opts.on_duplicate, - min_zoom: opts.min_zoom, - max_zoom: opts.max_zoom, - zoom_levels: opts.zoom_levels, - bbox: opts.bbox, - diff_with_file: opts.diff_with_file, - apply_patch: opts.apply_patch, - skip_agg_tiles_hash: opts.skip_agg_tiles_hash, - }; - opts.run().await?; + Commands::Copy(args) => { + let copier = args.options.into_copier( + args.src_file, + args.dst_file, + args.diff_with_file, + args.apply_patch, + ); + copier.run().await?; + } + Commands::Diff(args) => { + let copier = args + .options + .into_copier(args.file1, args.diff, Some(args.file2), None); + copier.run().await?; } Commands::ApplyPatch { - src_file, - diff_file, + base_file, + patch_file, } => { - apply_patch(src_file, diff_file).await?; + apply_patch(base_file, patch_file).await?; } Commands::UpdateMetadata { file, update_zoom } => { let mbt = Mbtiles::new(file.as_path())?; @@ -219,28 +261,6 @@ async fn main_int() -> anyhow::Result<()> { println!("MBTiles file summary for {mbt}"); println!("{}", mbt.summary(&mut conn).await?); } - Commands::Diff { - file_a, - file_b, - diff, - } => { - let opts = MbtilesCopier { - src_file: file_a, - diff_with_file: Some(file_b), - dst_file: diff, - copy: CopyType::All, - skip_agg_tiles_hash: false, - on_duplicate: Some(CopyDuplicateMode::Override), - dst_type_cli: None, - dst_type: None, - min_zoom: None, - max_zoom: None, - zoom_levels: vec![], - bbox: vec![], - apply_patch: None, - }; - opts.run().await?; - } } Ok(()) @@ -329,8 +349,11 @@ mod tests { command: Copy(CopyArgs { src_file: PathBuf::from("src_file"), dst_file: PathBuf::from("dst_file"), - min_zoom: Some(1), - max_zoom: Some(100), + options: SharedCopyOpts { + min_zoom: Some(1), + max_zoom: Some(100), + ..Default::default() + }, ..Default::default() }) } @@ -391,7 +414,10 @@ mod tests { command: Copy(CopyArgs { src_file: PathBuf::from("src_file"), dst_file: PathBuf::from("dst_file"), - zoom_levels: vec![3, 7, 1], + options: SharedCopyOpts { + zoom_levels: vec![3, 7, 1], + ..Default::default() + }, ..Default::default() }) } @@ -437,7 +463,10 @@ mod tests { command: Copy(CopyArgs { src_file: PathBuf::from("src_file"), dst_file: PathBuf::from("dst_file"), - on_duplicate: Some(CopyDuplicateMode::Override), + options: SharedCopyOpts { + on_duplicate: Some(CopyDuplicateMode::Override), + ..Default::default() + }, ..Default::default() }) } @@ -453,13 +482,43 @@ mod tests { command: Copy(CopyArgs { src_file: PathBuf::from("src_file"), dst_file: PathBuf::from("dst_file"), - copy: CopyType::Metadata, + options: SharedCopyOpts { + copy: CopyType::Metadata, + ..Default::default() + }, ..Default::default() }) } ); } + #[test] + fn test_diff() { + assert_eq!( + Args::parse_from([ + "mbtiles", + "diff", + "file1.mbtiles", + "file2.mbtiles", + "../delta.mbtiles", + "--on-duplicate", + "override" + ]), + Args { + verbose: false, + command: Diff(DiffArgs { + file1: PathBuf::from("file1.mbtiles"), + file2: PathBuf::from("file2.mbtiles"), + diff: PathBuf::from("../delta.mbtiles"), + options: SharedCopyOpts { + on_duplicate: Some(CopyDuplicateMode::Override), + ..Default::default() + }, + }) + } + ); + } + #[test] fn test_meta_get_no_arguments() { assert_eq!( @@ -531,8 +590,8 @@ mod tests { Args { verbose: false, command: ApplyPatch { - src_file: PathBuf::from("src_file"), - diff_file: PathBuf::from("diff_file"), + base_file: PathBuf::from("src_file"), + patch_file: PathBuf::from("diff_file"), } } ); @@ -553,25 +612,4 @@ mod tests { } ); } - - #[test] - fn test_diff() { - assert_eq!( - Args::parse_from([ - "mbtiles", - "diff", - "file-a.mbtiles", - "file-b.mbtiles", - "../delta.mbtiles", - ]), - Args { - verbose: false, - command: Diff { - file_a: PathBuf::from("file-a.mbtiles"), - file_b: PathBuf::from("file-b.mbtiles"), - diff: PathBuf::from("../delta.mbtiles"), - } - } - ); - } } diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index ed304b674..31b1766ab 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -63,7 +63,8 @@ pub struct MbtilesCopier { /// Bounding box to copy, in the format `min_lon,min_lat,max_lon,max_lat`. Can be used multiple times. pub bbox: Vec, /// Compare source file with this file, and only copy non-identical tiles to destination. - /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. + /// Use `mbtiles diff` as a more convenient way to generate this file. + /// It should be later possible to run `mbtiles apply-diff` to merge it in. pub diff_with_file: Option, /// Compare source file with this file, and only copy non-identical tiles to destination. /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. diff --git a/mbtiles/src/patcher.rs b/mbtiles/src/patcher.rs index 063333208..1e1777fa9 100644 --- a/mbtiles/src/patcher.rs +++ b/mbtiles/src/patcher.rs @@ -7,18 +7,18 @@ use crate::queries::detach_db; use crate::MbtType::{Flat, FlatWithHash, Normalized}; use crate::{MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_IN_DIFF}; -pub async fn apply_patch(src_file: PathBuf, patch_file: PathBuf) -> MbtResult<()> { - let src_mbt = Mbtiles::new(src_file)?; +pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<()> { + let base_mbt = Mbtiles::new(base_file)?; let patch_mbt = Mbtiles::new(patch_file)?; let patch_type = patch_mbt.open_and_detect_type().await?; - let mut conn = src_mbt.open().await?; - let src_type = src_mbt.detect_type(&mut conn).await?; + let mut conn = base_mbt.open().await?; + let base_type = base_mbt.detect_type(&mut conn).await?; patch_mbt.attach_to(&mut conn, "patchDb").await?; - info!("Applying patch file {patch_mbt} ({patch_type}) to {src_mbt} ({src_type})"); - let select_from = get_select_from(src_type, patch_type); - let (main_table, insert1, insert2) = get_insert_sql(src_type, select_from); + info!("Applying patch file {patch_mbt} ({patch_type}) to {base_mbt} ({base_type})"); + let select_from = get_select_from(base_type, patch_type); + let (main_table, insert1, insert2) = get_insert_sql(base_type, select_from); query(&format!("{insert1} WHERE tile_data NOTNULL")) .execute(&mut conn) @@ -40,7 +40,7 @@ pub async fn apply_patch(src_file: PathBuf, patch_file: PathBuf) -> MbtResult<() .execute(&mut conn) .await?; - if src_type.is_normalized() { + if base_type.is_normalized() { debug!("Removing unused tiles from the images table (normalized schema)"); query("DELETE FROM images WHERE tile_id NOT IN (SELECT tile_id FROM map)") .execute(&mut conn) From cae21189ac9967e0a321126cc57089bbe48a0216 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 03:34:44 +0000 Subject: [PATCH 013/164] chore(deps): Bump serde_with from 3.6.0 to 3.6.1 (#1186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.6.0 to 3.6.1.
Release notes

Sourced from serde_with's releases.

serde_with v3.6.1

Changed

  • Eliminate dependency on serde's "derive" feature by @​dtolnay (#694) This allows parallel compilation of serde and serde_derive which can speed up the wallclock time. It requires that downstream crates do not use the "derive" feature either.
Commits
  • 76cf252 Bump version to v3.6.1 (#696)
  • 6872fa8 Bump version to v3.6.1
  • 6211d20 Eliminate dependency on serde's "derive" feature (#694)
  • 5e6a115 Eliminate dependency on serde's "derive" feature
  • d145a45 Update ahash to 0.8.7 to accommodate stdsimd change in nightly (#695)
  • 2b17850 Update ahash to 0.8.7 to accommodate stdsimd change in nightly
  • caba452 Bump the github-actions group with 1 update (#693)
  • 54a665d Bump the github-actions group with 1 update
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_with&package-manager=cargo&previous-version=3.6.0&new-version=3.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 507902360..305bf6598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3555,9 +3555,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" dependencies = [ "base64 0.21.7", "chrono", @@ -3565,6 +3565,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.2.2", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -3572,9 +3573,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" dependencies = [ "darling", "proc-macro2", From 209d8b473503c5980e4bd9c97eb19e0ef90a1b9a Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 9 Feb 2024 03:43:27 -0500 Subject: [PATCH 014/164] Bump lock --- Cargo.lock | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 305bf6598..d9a113487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -574,9 +574,9 @@ checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" -version = "1.14.2" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" [[package]] name = "byteorder" @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" dependencies = [ "clap_builder", "clap_derive", @@ -710,21 +710,21 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", @@ -734,9 +734,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "color_quant" @@ -985,7 +985,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 2.0.48", ] @@ -1132,18 +1132,18 @@ dependencies = [ [[package]] name = "enum-display" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d4df33d54dd1959d177a0e2c2f4e5a8637a3054aa56861ed7e173ad2043fe2" +checksum = "02058bb25d8d0605829af88230427dd5cd50661590bd2b09d1baf7c64c417f24" dependencies = [ "enum-display-macro", ] [[package]] name = "enum-display-macro" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ce3a36047ede676eb0d2721d065beed8410cf4f113f489604d2971331cb378" +checksum = "d4be2cf2fe7b971b1865febbacd4d8df544aa6bd377cca011a6d69dcf4c60d94" dependencies = [ "convert_case 0.6.0", "quote", @@ -1870,12 +1870,12 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "fe8f25ce1159c7740ff0b9b2f5cdf4a8428742ba7c112b9f20f22cd5219c7dab" dependencies = [ "hermit-abi", - "rustix", + "libc", "windows-sys 0.52.0", ] @@ -1905,9 +1905,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -4022,6 +4022,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "structmeta" version = "0.2.0" From a54b2d7c8cbe2c67137b281e99ecaef7caf22e16 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 9 Feb 2024 03:59:31 -0500 Subject: [PATCH 015/164] minor linting --- justfile | 2 +- martin/src/pg/builder.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index 0a30903ea..5d10ea7b5 100644 --- a/justfile +++ b/justfile @@ -313,7 +313,7 @@ check-doc: # Run cargo clippy clippy: - cargo clippy --workspace --all-targets --bins --tests --lib --benches -- -D warnings + cargo clippy --workspace --all-targets --bins --tests --lib --benches --examples -- -D warnings # Validate markdown URLs with markdown-link-check clippy-md: diff --git a/martin/src/pg/builder.rs b/martin/src/pg/builder.rs index 09a9fca69..4b88f2f93 100644 --- a/martin/src/pg/builder.rs +++ b/martin/src/pg/builder.rs @@ -157,8 +157,7 @@ impl PgBuilder { if let Some(auto_tables) = &self.auto_tables { let schemas = auto_tables .schemas - .as_ref() - .cloned() + .clone() .unwrap_or_else(|| db_tables_info.keys().cloned().collect()); info!( "Auto-publishing tables in schemas [{}] as '{}' sources", @@ -256,8 +255,7 @@ impl PgBuilder { if let Some(auto_funcs) = &self.auto_functions { let schemas = auto_funcs .schemas - .as_ref() - .cloned() + .clone() .unwrap_or_else(|| db_funcs_info.keys().cloned().collect()); info!( "Auto-publishing functions in schemas [{}] as '{}' sources", From 7be4360b7c751a012770187a9514b3602bc99c06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 02:58:08 +0000 Subject: [PATCH 016/164] chore(deps): Bump thiserror from 1.0.56 to 1.0.57 (#1190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.56 to 1.0.57.
Release notes

Sourced from thiserror's releases.

1.0.57

  • Generate more efficient Display impl for error message which do not contain any interpolated value (#286, thanks @​nyurik)
Commits
  • 1d106b1 Release 1.0.57
  • 8a5c4d1 Use write_str when args only consists of trailing comma
  • f790bee Phrase flag in terms of whether core::fmt machinery is required
  • d43b759 Ignore needless_raw_string_hashes pedantic clippy lint in test
  • d09c418 Touch up PR 286
  • 097251d Merge pull request #286 from nyurik/litstr
  • cd79876 optimize by avoiding second fmt.value() call
  • d7e738e Optimize simple literals for Display::fmt
  • 0717de3 Update ui test suite to nightly-2024-02-08
  • c7c7547 Update ui test suite to nightly-2024-01-31
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=thiserror&package-manager=cargo&previous-version=1.0.56&new-version=1.0.57)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9a113487..ccd6f03b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4177,18 +4177,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", From 7c56e50440bb9165348d7535cbca3f1cde2c266a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 02:59:51 +0000 Subject: [PATCH 017/164] chore(deps): Bump pbf_font_tools from 2.5.0 to 2.5.1 (#1191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pbf_font_tools](https://github.com/stadiamaps/sdf_font_tools) from 2.5.0 to 2.5.1.
Release notes

Sourced from pbf_font_tools's releases.

tools-v2.5.1

What's Changed

Full Changelog: https://github.com/stadiamaps/sdf_font_tools/compare/cli-v1.4.1...sdf-v1.0.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pbf_font_tools&package-manager=cargo&previous-version=2.5.0&new-version=2.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccd6f03b5..d0d75b613 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2540,9 +2540,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbf_font_tools" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67768bb2719d708e2de28cec7271dae35c717122c0fa4d9f8558ef5e7fa83db7" +checksum = "badfb0f3113910e4bde7e68975d0c2b85d2b48c3e68842c0cebbb80430e9f61c" dependencies = [ "futures", "glob", diff --git a/Cargo.toml b/Cargo.toml index df4f9f30a..eb672a33f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ martin-tile-utils = { path = "./martin-tile-utils", version = "0.4.0" } mbtiles = { path = "./mbtiles", version = "0.9.0" } moka = { version = "0.12", features = ["future"] } num_cpus = "1" -pbf_font_tools = { version = "2.5.0", features = ["freetype"] } +pbf_font_tools = { version = "2.5.1", features = ["freetype"] } pmtiles = { version = "0.7", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } postgis = "0.9" postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] } From bb02dcc09bcc24bbd860de6b1f57e41f203e70c8 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 13 Feb 2024 18:18:05 -0500 Subject: [PATCH 018/164] bump locks, fix freetype breaking change --- Cargo.lock | 71 +++++++++++++++++++++-------------------- martin/src/fonts/mod.rs | 2 +- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0d75b613..76cffe026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,9 +214,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" dependencies = [ "cfg-if", "getrandom", @@ -616,9 +616,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -660,9 +660,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", @@ -845,9 +845,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -1108,9 +1108,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" dependencies = [ "serde", ] @@ -1174,9 +1174,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e7cf40684ae96ade6232ed84582f40ce0a66efcd43a5117aef610534f8e0b8" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" dependencies = [ "anstream", "anstyle", @@ -1374,23 +1374,24 @@ dependencies = [ [[package]] name = "freetype-rs" -version = "0.32.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59c337e64822dd56a3a83ed75a662a470736bdb3a9fabfb588dff276b94a4e0" +checksum = "b1fad2be0bf06af23adddcf6cd143c94ff0ba3b329691f92d1a38dae5c5aeebf" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "freetype-sys", "libc", ] [[package]] name = "freetype-sys" -version = "0.17.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643148ca6cbad6bec384b52fbe1968547d578c4efe83109e035c43a71734ff88" +checksum = "8b4dbbf4b8447b92e62282bf26760e7221f4f7ac15b9b10b3c99e4033379dbe0" dependencies = [ "cc", "libc", + "pkg-config", ] [[package]] @@ -1581,7 +1582,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.2", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", @@ -1634,9 +1635,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hex" @@ -1813,9 +1814,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1836,7 +1837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "indexmap 2.2.2", + "indexmap 2.2.3", "is-terminal", "itoa", "log", @@ -1870,9 +1871,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe8f25ce1159c7740ff0b9b2f5cdf4a8428742ba7c112b9f20f22cd5219c7dab" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", "libc", @@ -2473,7 +2474,7 @@ dependencies = [ "bitvec", "crossbeam-channel", "filetime", - "indexmap 2.2.2", + "indexmap 2.2.3", "libdeflater", "log", "rayon", @@ -2692,9 +2693,9 @@ dependencies = [ [[package]] name = "pmtiles" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e641f75ae1304ce63e7f90635eb4bd18c76e245892b5935289ac73d4c539014" +checksum = "92175e077dcbf7a8b9b0269f69b6d62b887b6b1ce57163d040cbda93c879957c" dependencies = [ "async-compression", "async-recursion", @@ -3366,9 +3367,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf" +checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7" [[package]] name = "rustls-webpki" @@ -3449,9 +3450,9 @@ dependencies = [ [[package]] name = "sdf_glyph_renderer" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b05c114d181e20b509e03b05856cc5823bc6189d581c276fe37c5ebc5e3b3b9" +checksum = "5ef220f6a4fff0c984e9fb3ab12cb5c86960b5bb6ec3b30dd7173e3bf603d94f" dependencies = [ "freetype-rs", "thiserror", @@ -3563,7 +3564,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.2", + "indexmap 2.2.3", "serde", "serde_derive", "serde_json", @@ -3589,7 +3590,7 @@ version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.2.2", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -3823,7 +3824,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.2", + "indexmap 2.2.3", "log", "memchr", "once_cell", diff --git a/martin/src/fonts/mod.rs b/martin/src/fonts/mod.rs index c776f1ca6..fb04a60c1 100644 --- a/martin/src/fonts/mod.rs +++ b/martin/src/fonts/mod.rs @@ -80,7 +80,7 @@ fn get_available_codepoints(face: &mut Face) -> Option { let mut count = 0; for cp in 0..=MAX_UNICODE_CP { - if face.get_char_index(cp) != 0 { + if face.get_char_index(cp).is_ok() { codepoints.insert(cp); count += 1; if first.is_none() { From 8c61515d9c6fdc724e8635ac62a85a88227593b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 02:44:31 +0000 Subject: [PATCH 019/164] chore(deps): Bump clap from 4.5.0 to 4.5.1 (#1197) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.0 to 4.5.1.
Release notes

Sourced from clap's releases.

v4.5.1

[4.5.1] - 2024-02-16

Fixes

  • (error) Include suggestion to add -- even if there is a "did you mean" so long as last or trailing_var_arg is used
Changelog

Sourced from clap's changelog.

[4.5.1] - 2024-02-16

Fixes

  • (error) Include suggestion to add -- even if there is a "did you mean" so long as last or trailing_var_arg is used
Commits
  • 0c01b55 chore: Release
  • 08e0b5b docs: Update changelog
  • f2c4e6e Merge pull request #5359 from poliorcetics/ab/push-szymvyzpmnqx
  • e782775 fix(complete): Handle newlines in command/arg descriptions
  • fba7c85 test(complete): Show newline issue
  • 8a7a13a chore: Release
  • 7b3a3e1 docs: Update changelog
  • 7b624ca Merge pull request #5356 from epage/escape
  • 446328a fix(error): Include -- in more cases
  • 7de6df8 test(error): Show existing last behavior
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.0&new-version=4.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76cffe026..345fa272b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -710,9 +710,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", From 3e30c438bbc98e3712b7672422288144b6afa7d8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 19 Feb 2024 19:21:37 +0800 Subject: [PATCH 020/164] Add `--preferred-encoding (gzip|brotli)` to use when tile is not pre-encoded by source (#1189) Try to fix #1178 - [x] Add optional `--preferred-encoding` to cli, `br` `brotli` and `gzip` are allowed - [x] Add optional `preferred-encoding` to config, `br` `brotli` and `gzip` are allowed - [x] Add test - [x] Update doc --- docs/src/config-file.md | 3 ++ docs/src/run-with-cli.md | 5 ++ martin/benches/bench.rs | 2 +- martin/src/args/mod.rs | 1 + martin/src/args/root.rs | 24 ++++++++++ martin/src/args/srv.rs | 18 ++++++++ martin/src/bin/martin-cp.rs | 1 + martin/src/srv/config.rs | 36 ++++++++++++++- martin/src/srv/server.rs | 14 +++--- martin/src/srv/tiles.rs | 81 +++++++++++++++++++++++++++++---- martin/tests/mb_server_test.rs | 2 + martin/tests/pg_server_test.rs | 3 ++ martin/tests/pmt_server_test.rs | 2 + 13 files changed, 176 insertions(+), 16 deletions(-) diff --git a/docs/src/config-file.md b/docs/src/config-file.md index 542677de1..3efc08bd8 100644 --- a/docs/src/config-file.md +++ b/docs/src/config-file.md @@ -27,6 +27,9 @@ worker_processes: 8 # Amount of memory (in MB) to use for caching tiles [default: 512, 0 to disable] cache_size_mb: 1024 +# If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli. +preferred_encoding: gzip + # Database configuration. This can also be a list of PG configs. postgres: # Database connection string. You can use env vars too, for example: diff --git a/docs/src/run-with-cli.md b/docs/src/run-with-cli.md index fd921c138..b52935580 100644 --- a/docs/src/run-with-cli.md +++ b/docs/src/run-with-cli.md @@ -31,6 +31,11 @@ Options: -W, --workers Number of web server workers + --preferred-encoding + Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli + + [possible values: brotli, gzip] + -b, --auto-bounds Specify how bounds should be computed for the spatial PG tables. [DEFAULT: quick] diff --git a/martin/benches/bench.rs b/martin/benches/bench.rs index 27f4904b2..ceb4a6946 100644 --- a/martin/benches/bench.rs +++ b/martin/benches/bench.rs @@ -58,7 +58,7 @@ impl Source for NullSource { } async fn process_tile(sources: &TileSources) { - let src = DynTileSource::new(sources, "null", Some(0), "", None, None).unwrap(); + let src = DynTileSource::new(sources, "null", Some(0), "", None, None, None).unwrap(); src.get_http_response(TileCoord { z: 0, x: 0, y: 0 }) .await .unwrap(); diff --git a/martin/src/args/mod.rs b/martin/src/args/mod.rs index f3bb5e81e..0e58bd7ab 100644 --- a/martin/src/args/mod.rs +++ b/martin/src/args/mod.rs @@ -13,4 +13,5 @@ mod root; pub use root::{Args, ExtraArgs, MetaArgs}; mod srv; +pub use srv::PreferredEncoding; pub use srv::SrvArgs; diff --git a/martin/src/args/root.rs b/martin/src/args/root.rs index 7fc81d1be..7bcda8103 100644 --- a/martin/src/args/root.rs +++ b/martin/src/args/root.rs @@ -160,7 +160,9 @@ pub fn parse_file_args( #[cfg(test)] mod tests { + use super::*; + use crate::args::PreferredEncoding; use crate::test_utils::FauxEnv; use crate::MartinError::UnrecognizableConnections; @@ -215,6 +217,28 @@ mod tests { assert_eq!(args, (cfg, meta)); } + #[test] + fn cli_encoding_arguments() { + let config1 = parse(&["martin", "--preferred-encoding", "brotli"]); + let config2 = parse(&["martin", "--preferred-encoding", "br"]); + let config3 = parse(&["martin", "--preferred-encoding", "gzip"]); + let config4 = parse(&["martin"]); + + assert_eq!( + config1.unwrap().0.srv.preferred_encoding, + Some(PreferredEncoding::Brotli) + ); + assert_eq!( + config2.unwrap().0.srv.preferred_encoding, + Some(PreferredEncoding::Brotli) + ); + assert_eq!( + config3.unwrap().0.srv.preferred_encoding, + Some(PreferredEncoding::Gzip) + ); + assert_eq!(config4.unwrap().0.srv.preferred_encoding, None); + } + #[test] fn cli_bad_arguments() { for params in [ diff --git a/martin/src/args/srv.rs b/martin/src/args/srv.rs index b436151b3..e7b743583 100644 --- a/martin/src/args/srv.rs +++ b/martin/src/args/srv.rs @@ -1,4 +1,6 @@ use crate::srv::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; +use clap::ValueEnum; +use serde::{Deserialize, Serialize}; #[derive(clap::Args, Debug, PartialEq, Default)] #[command(about, version)] @@ -10,6 +12,19 @@ pub struct SrvArgs { /// Number of web server workers #[arg(short = 'W', long)] pub workers: Option, + /// Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli. + #[arg(long)] + pub preferred_encoding: Option, +} + +#[derive(PartialEq, Eq, Default, Debug, Clone, Copy, Serialize, Deserialize, ValueEnum)] +#[serde(rename_all = "lowercase")] +pub enum PreferredEncoding { + #[default] + #[serde(alias = "br")] + #[clap(alias("br"))] + Brotli, + Gzip, } impl SrvArgs { @@ -24,5 +39,8 @@ impl SrvArgs { if self.workers.is_some() { srv_config.worker_processes = self.workers; } + if self.preferred_encoding.is_some() { + srv_config.preferred_encoding = self.preferred_encoding; + } } } diff --git a/martin/src/bin/martin-cp.rs b/martin/src/bin/martin-cp.rs index 35c75d6ce..ecb3a291f 100644 --- a/martin/src/bin/martin-cp.rs +++ b/martin/src/bin/martin-cp.rs @@ -283,6 +283,7 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinCpResult<()> args.url_query.as_deref().unwrap_or_default(), Some(parse_encoding(args.encoding.as_str())?), None, + None, )?; // parallel async below uses move, so we must only use copyable types let src = &src; diff --git a/martin/src/srv/config.rs b/martin/src/srv/config.rs index 0db8db587..bef288160 100644 --- a/martin/src/srv/config.rs +++ b/martin/src/srv/config.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use crate::args::PreferredEncoding; + pub const KEEP_ALIVE_DEFAULT: u64 = 75; pub const LISTEN_ADDRESSES_DEFAULT: &str = "0.0.0.0:3000"; @@ -9,6 +11,7 @@ pub struct SrvConfig { pub keep_alive: Option, pub listen_addresses: Option, pub worker_processes: Option, + pub preferred_encoding: Option, } #[cfg(test)] @@ -19,18 +22,49 @@ mod tests { use crate::test_utils::some; #[test] - fn parse_empty_config() { + fn parse_config() { + assert_eq!( + serde_yaml::from_str::(indoc! {" + keep_alive: 75 + listen_addresses: '0.0.0.0:3000' + worker_processes: 8 + "}) + .unwrap(), + SrvConfig { + keep_alive: Some(75), + listen_addresses: some("0.0.0.0:3000"), + worker_processes: Some(8), + preferred_encoding: None, + } + ); + assert_eq!( + serde_yaml::from_str::(indoc! {" + keep_alive: 75 + listen_addresses: '0.0.0.0:3000' + worker_processes: 8 + preferred_encoding: br + "}) + .unwrap(), + SrvConfig { + keep_alive: Some(75), + listen_addresses: some("0.0.0.0:3000"), + worker_processes: Some(8), + preferred_encoding: Some(PreferredEncoding::Brotli), + } + ); assert_eq!( serde_yaml::from_str::(indoc! {" keep_alive: 75 listen_addresses: '0.0.0.0:3000' worker_processes: 8 + preferred_encoding: brotli "}) .unwrap(), SrvConfig { keep_alive: Some(75), listen_addresses: some("0.0.0.0:3000"), worker_processes: Some(8), + preferred_encoding: Some(PreferredEncoding::Brotli), } ); } diff --git a/martin/src/srv/server.rs b/martin/src/srv/server.rs index b0c1caa16..c187662e7 100755 --- a/martin/src/srv/server.rs +++ b/martin/src/srv/server.rs @@ -108,6 +108,13 @@ type Server = Pin>>>; pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server, String)> { let catalog = Catalog::new(&state)?; + let keep_alive = Duration::from_secs(config.keep_alive.unwrap_or(KEEP_ALIVE_DEFAULT)); + let worker_processes = config.worker_processes.unwrap_or_else(num_cpus::get); + let listen_addresses = config + .listen_addresses + .clone() + .unwrap_or_else(|| LISTEN_ADDRESSES_DEFAULT.to_owned()); + let factory = move || { let cors_middleware = Cors::default() .allow_any_origin() @@ -124,6 +131,7 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server let app = app.app_data(Data::new(state.fonts.clone())); app.app_data(Data::new(catalog.clone())) + .app_data(Data::new(config.clone())) .wrap(cors_middleware) .wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly)) .wrap(middleware::Logger::default()) @@ -136,12 +144,6 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server return Ok((Box::pin(server), "(aws lambda)".into())); } - let keep_alive = Duration::from_secs(config.keep_alive.unwrap_or(KEEP_ALIVE_DEFAULT)); - let worker_processes = config.worker_processes.unwrap_or_else(num_cpus::get); - let listen_addresses = config - .listen_addresses - .unwrap_or_else(|| LISTEN_ADDRESSES_DEFAULT.to_owned()); - let server = HttpServer::new(factory) .bind(listen_addresses.clone()) .map_err(|e| BindingError(e, listen_addresses.clone()))? diff --git a/martin/src/srv/tiles.rs b/martin/src/srv/tiles.rs index f25829966..c5195b87c 100755 --- a/martin/src/srv/tiles.rs +++ b/martin/src/srv/tiles.rs @@ -10,8 +10,10 @@ use log::trace; use martin_tile_utils::{Encoding, Format, TileInfo}; use serde::Deserialize; +use crate::args::PreferredEncoding; use crate::source::{Source, TileSources, UrlQuery}; use crate::srv::server::map_internal_error; +use crate::srv::SrvConfig; use crate::utils::cache::get_or_insert_cached_value; use crate::utils::{ decode_brotli, decode_gzip, encode_brotli, encode_gzip, CacheKey, CacheValue, MainCache, @@ -19,12 +21,18 @@ use crate::utils::{ }; use crate::{Tile, TileCoord, TileData}; -static SUPPORTED_ENCODINGS: &[HeaderEnc] = &[ +static PREFER_BROTLI_ENC: &[HeaderEnc] = &[ HeaderEnc::brotli(), HeaderEnc::gzip(), HeaderEnc::identity(), ]; +static PREFER_GZIP_ENC: &[HeaderEnc] = &[ + HeaderEnc::gzip(), + HeaderEnc::brotli(), + HeaderEnc::identity(), +]; + #[derive(Deserialize, Clone)] pub struct TileRequest { source_ids: String, @@ -36,6 +44,7 @@ pub struct TileRequest { #[route("/{source_ids}/{z}/{x}/{y}", method = "GET", method = "HEAD")] async fn get_tile( req: HttpRequest, + srv_config: Data, path: Path, sources: Data, cache: Data, @@ -46,6 +55,7 @@ async fn get_tile( Some(path.z), req.query_string(), req.get_header::(), + srv_config.preferred_encoding, cache.as_ref().as_ref(), )?; @@ -62,7 +72,8 @@ pub struct DynTileSource<'a> { pub info: TileInfo, pub query_str: Option<&'a str>, pub query_obj: Option, - pub encodings: Option, + pub accept_enc: Option, + pub preferred_enc: Option, pub cache: Option<&'a MainCache>, } @@ -72,7 +83,8 @@ impl<'a> DynTileSource<'a> { source_ids: &str, zoom: Option, query: &'a str, - encodings: Option, + accept_enc: Option, + preferred_enc: Option, cache: Option<&'a MainCache>, ) -> ActixResult { let (sources, use_url_query, info) = sources.get_sources(source_ids, zoom)?; @@ -93,7 +105,8 @@ impl<'a> DynTileSource<'a> { info, query_str, query_obj, - encodings, + accept_enc, + preferred_enc, cache, }) } @@ -169,7 +182,7 @@ impl<'a> DynTileSource<'a> { fn recompress(&self, tile: TileData) -> ActixResult { let mut tile = Tile::new(tile, self.info); - if let Some(accept_enc) = &self.encodings { + if let Some(accept_enc) = &self.accept_enc { if self.info.encoding.is_encoded() { // already compressed, see if we can send it as is, or need to re-compress if !accept_enc.iter().any(|e| { @@ -183,10 +196,15 @@ impl<'a> DynTileSource<'a> { tile = decode(tile)?; } } + if tile.info.encoding == Encoding::Uncompressed { + let ordered_encodings = match self.preferred_enc { + Some(PreferredEncoding::Gzip) => PREFER_GZIP_ENC, + Some(PreferredEncoding::Brotli) | None => PREFER_BROTLI_ENC, + }; + // only apply compression if the content supports it - if let Some(HeaderEnc::Known(enc)) = - accept_enc.negotiate(SUPPORTED_ENCODINGS.iter()) + if let Some(HeaderEnc::Known(enc)) = accept_enc.negotiate(ordered_encodings.iter()) { // (re-)compress the tile into the preferred encoding tile = encode(tile, enc)?; @@ -251,6 +269,53 @@ mod tests { use super::*; use crate::srv::server::tests::TestSource; + #[actix_rt::test] + async fn test_encoding_preference() { + let source = TestSource { + id: "test_source", + tj: tilejson! { tiles: vec![] }, + data: vec![1_u8, 2, 3], + }; + let sources = TileSources::new(vec![vec![Box::new(source)]]); + + for (accept_encodings, prefered_encoding, result_encoding) in [ + ( + Some(AcceptEncoding(vec![ + "gzip;q=1".parse().unwrap(), + "br;q=1".parse().unwrap(), + ])), + Some(PreferredEncoding::Brotli), + Encoding::Brotli, + ), + ( + Some(AcceptEncoding(vec![ + "gzip;q=1".parse().unwrap(), + "br;q=0.5".parse().unwrap(), + ])), + Some(PreferredEncoding::Brotli), + Encoding::Gzip, + ), + ] { + let src = DynTileSource::new( + &sources, + "test_source", + None, + "", + accept_encodings, + prefered_encoding, + None, + ) + .unwrap(); + let xyz = TileCoord { z: 0, x: 0, y: 0 }; + let data = &src.get_tile_content(xyz).await.unwrap().data; + let decoded = match result_encoding { + Encoding::Gzip => decode_gzip(data), + Encoding::Brotli => decode_brotli(data), + _ => panic!("Unexpected encoding"), + }; + assert_eq!(vec![1_u8, 2, 3], decoded.unwrap()); + } + } #[actix_rt::test] async fn test_tile_content() { let non_empty_source = TestSource { @@ -278,7 +343,7 @@ mod tests { ("empty,non-empty", vec![1_u8, 2, 3]), ("empty,non-empty,empty", vec![1_u8, 2, 3]), ] { - let src = DynTileSource::new(&sources, source_id, None, "", None, None).unwrap(); + let src = DynTileSource::new(&sources, source_id, None, "", None, None, None).unwrap(); let xyz = TileCoord { z: 0, x: 0, y: 0 }; assert_eq!(expected, &src.get_tile_content(xyz).await.unwrap().data); } diff --git a/martin/tests/mb_server_test.rs b/martin/tests/mb_server_test.rs index b38d490b6..9af72bc9a 100644 --- a/martin/tests/mb_server_test.rs +++ b/martin/tests/mb_server_test.rs @@ -4,6 +4,7 @@ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; use martin::decode_gzip; +use martin::srv::SrvConfig; use tilejson::TileJSON; pub mod utils; @@ -24,6 +25,7 @@ macro_rules! create_app { )) .app_data(actix_web::web::Data::new(::martin::NO_MAIN_CACHE)) .app_data(actix_web::web::Data::new(state.tiles)) + .app_data(actix_web::web::Data::new(SrvConfig::default())) .configure(::martin::srv::router), ) .await diff --git a/martin/tests/pg_server_test.rs b/martin/tests/pg_server_test.rs index 55b7f37a3..c63c11a7d 100644 --- a/martin/tests/pg_server_test.rs +++ b/martin/tests/pg_server_test.rs @@ -6,6 +6,7 @@ use actix_web::test::{call_and_read_body_json, call_service, read_body, TestRequ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; +use martin::srv::SrvConfig; use martin::OptOneMany; use tilejson::TileJSON; @@ -28,6 +29,7 @@ macro_rules! create_app { )) .app_data(actix_web::web::Data::new(::martin::NO_MAIN_CACHE)) .app_data(actix_web::web::Data::new(state.tiles)) + .app_data(actix_web::web::Data::new(SrvConfig::default())) .configure(::martin::srv::router), ) .await @@ -1089,6 +1091,7 @@ tables: )) .app_data(actix_web::web::Data::new(::martin::NO_MAIN_CACHE)) .app_data(actix_web::web::Data::new(state.tiles)) + .app_data(actix_web::web::Data::new(SrvConfig::default())) .configure(::martin::srv::router), ) .await; diff --git a/martin/tests/pmt_server_test.rs b/martin/tests/pmt_server_test.rs index 9a6e7ce46..422d82cde 100644 --- a/martin/tests/pmt_server_test.rs +++ b/martin/tests/pmt_server_test.rs @@ -4,6 +4,7 @@ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; use martin::decode_gzip; +use martin::srv::SrvConfig; use tilejson::TileJSON; pub mod utils; @@ -24,6 +25,7 @@ macro_rules! create_app { )) .app_data(actix_web::web::Data::new(::martin::NO_MAIN_CACHE)) .app_data(actix_web::web::Data::new(state.tiles)) + .app_data(actix_web::web::Data::new(SrvConfig::default())) .configure(::martin::srv::router), ) .await From ecf7a12f23388a753590674dcb487ab9854111b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 02:51:31 +0000 Subject: [PATCH 021/164] chore(deps): Bump serde_yaml from 0.9.31 to 0.9.32 (#1200) Bumps [serde_yaml](https://github.com/dtolnay/serde-yaml) from 0.9.31 to 0.9.32.
Release notes

Sourced from serde_yaml's releases.

0.9.32

  • Fix unused_imports warnings when compiled by rustc 1.78
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_yaml&package-manager=cargo&previous-version=0.9.31&new-version=0.9.32)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 345fa272b..6fde628a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3586,9 +3586,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.31" +version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ "indexmap 2.2.3", "itoa", From 9076cf917adade2030406f5313fca17ecf81fdf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 02:55:05 +0000 Subject: [PATCH 022/164] chore(deps): Bump serde_json from 1.0.113 to 1.0.114 (#1201) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.113 to 1.0.114.
Release notes

Sourced from serde_json's releases.

v1.0.114

  • Fix unused_imports warnings when compiled by rustc 1.78
Commits
  • e1b3a6d Release 1.0.114
  • 6fb7026 Work around prelude redundant import warnings
  • 34a04c5 Ignore incompatible_msrv clippy false positives in test
  • ca05f69 Remove unused Float::is_sign_negative trait method
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.113&new-version=1.0.114)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fde628a7..26eb4a4cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3512,9 +3512,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", From 3727d21de1bb1cc856b54dd70330cbb77448c88c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 02:58:34 +0000 Subject: [PATCH 023/164] chore(deps): Bump anyhow from 1.0.79 to 1.0.80 (#1204) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.80.
Release notes

Sourced from anyhow's releases.

1.0.80

  • Fix unused_imports warnings when compiled by rustc 1.78
Commits
  • 5443719 Release 1.0.80
  • dfc7bc0 Work around prelude redundant import warnings
  • 6e4f86b Import from alloc not std, where possible
  • f885a13 Ignore incompatible_msrv clippy false positives in test
  • fefbcbc Ignore incompatible_msrv clippy lint
  • 78f2d81 Update ui test suite to nightly-2024-02-08
  • edd88d3 Update ui test suite to nightly-2024-01-31
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.79&new-version=1.0.80)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26eb4a4cc..28d022135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "approx" From c29606a24e768e6a84b97e9bcfd185dd416d36cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 03:01:54 +0000 Subject: [PATCH 024/164] chore(deps): Bump semver from 1.0.21 to 1.0.22 (#1202) Bumps [semver](https://github.com/dtolnay/semver) from 1.0.21 to 1.0.22.
Release notes

Sourced from semver's releases.

1.0.22

  • Fix unused_imports warnings when compiled by rustc 1.78
Commits
  • c8ad1bf Release 1.0.22
  • f76db8d Resolve redundant import warning
  • f32b420 Ignore incompatible_msrv clippy lint for conditionally compiled code
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=semver&package-manager=cargo&previous-version=1.0.21&new-version=1.0.22)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28d022135..91329f4f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3483,9 +3483,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] From a48ab6e4bf5b2a1d6af9993f45d0dc87050dff88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:04:38 -0500 Subject: [PATCH 025/164] chore(deps): Bump insta from 1.34.0 to 1.35.1 (#1203) Bumps [insta](https://github.com/mitsuhiko/insta) from 1.34.0 to 1.35.1.
Changelog

Sourced from insta's changelog.

1.35.1

  • Fixed a bug with diffs showing bogus newlines.

1.35.0

  • Fixed a crash when a file named .config was in the root.
  • Added new alternative match .. { ... } syntax to redactions for better rustfmt support. (#428)
  • The --package parameter can be supplied multiple times now. (#427)
  • Leading newlines in snapshots are now ignored to resolve issues with inline snapshots that were never able to match. (#444)
  • cargo insta test now accepts the --test parameter multiple times. (#437)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=insta&package-manager=cargo&previous-version=1.34.0&new-version=1.35.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91329f4f5..851f4e1f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1850,9 +1850,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.34.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +checksum = "7c985c1bef99cf13c58fade470483d81a2bfe846ebde60ed28cc2dddec2df9e2" dependencies = [ "console", "lazy_static", From 2bf2212aa0f34cae47b9c0fc6aee4ccee2d10329 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:05:07 -0500 Subject: [PATCH 026/164] chore(deps): Bump rustls-pemfile from 2.0.0 to 2.1.0 (#1196) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rustls-pemfile](https://github.com/rustls/pemfile) from 2.0.0 to 2.1.0.
Release notes

Sourced from rustls-pemfile's releases.

2.1.0

Headlines

  • Adds the csr function and the Item::Csr variant to support loading DER encoded Certificate Signing Requests (CSRs) from PEM inputs.

What's Changed

New Contributors

Full Changelog: https://github.com/rustls/pemfile/compare/v/2.0.0...v/2.1.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls-pemfile&package-manager=cargo&previous-version=2.0.0&new-version=2.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 851f4e1f8..e9d931afd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2137,7 +2137,7 @@ dependencies = [ "regex", "rustls 0.22.2", "rustls-native-certs 0.7.0", - "rustls-pemfile 2.0.0", + "rustls-pemfile 2.1.0", "semver", "serde", "serde_json", @@ -3340,7 +3340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.0.0", + "rustls-pemfile 2.1.0", "rustls-pki-types", "schannel", "security-framework", @@ -3357,9 +3357,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" +checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" dependencies = [ "base64 0.21.7", "rustls-pki-types", From e30467891df3b668d17a31e5a569f397e0e9b975 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 19 Feb 2024 22:08:33 -0500 Subject: [PATCH 027/164] Bump lock --- Cargo.lock | 105 +++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9d931afd..8656a94aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -214,9 +214,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" +checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" dependencies = [ "cfg-if", "getrandom", @@ -278,9 +278,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -384,7 +384,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -406,7 +406,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -417,7 +417,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -562,9 +562,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" [[package]] name = "bytecount" @@ -729,7 +729,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -962,14 +962,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "darling" -version = "0.20.5" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8" +checksum = "c376d08ea6aa96aafe61237c7200d1241cb177b7d3a542d791f2d118e9cbb955" dependencies = [ "darling_core", "darling_macro", @@ -977,27 +977,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.5" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3" +checksum = "33043dcd19068b8192064c704b3f83eb464f91f1ff527b44a4e2b08d9cdb8855" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "darling_macro" -version = "0.20.5" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77" +checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be" dependencies = [ "darling_core", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1159,7 +1159,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1479,7 +1479,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2530,7 +2530,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2621,7 +2621,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2659,9 +2659,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" @@ -2714,9 +2714,9 @@ dependencies = [ [[package]] name = "png" -version = "0.17.11" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -3171,16 +3171,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3243,7 +3244,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.48", + "syn 2.0.50", "unicode-ident", ] @@ -3410,9 +3411,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -3492,22 +3493,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -3581,7 +3582,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4038,7 +4039,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4049,7 +4050,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4116,9 +4117,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -4193,7 +4194,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4317,7 +4318,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4463,7 +4464,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -4761,7 +4762,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-shared", ] @@ -4795,7 +4796,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5098,7 +5099,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -5118,7 +5119,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] From 95c18dcf6b7d3f06d34317489aaedb4d1028a89c Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 25 Feb 2024 18:45:35 +0800 Subject: [PATCH 028/164] Update nginx path of windows runner in CI.yml (#1210) --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6502f62f4..d75ff9bc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -394,22 +394,22 @@ jobs: # Replace the default Nginx configuration file echo "$nginxConf" - Set-Content -Path "C:\tools\nginx-1.25.3\conf\nginx.conf" -Value $nginxConf - Get-Content -Path "C:\tools\nginx-1.25.3\conf\nginx.conf" + Set-Content -Path "C:\tools\nginx-1.25.4\conf\nginx.conf" -Value $nginxConf + Get-Content -Path "C:\tools\nginx-1.25.4\conf\nginx.conf" # Start Nginx #Get-Service -ErrorAction SilentlyContinue #Get-CimInstance -ClassName Win32_Service Set-Service nginx -StartupType manual Start-Service nginx - #Start-Process -FilePath "C:\tools\nginx-1.25.3\nginx.exe" - dir C:\tools\nginx-1.25.3\logs\ + #Start-Process -FilePath "C:\tools\nginx-1.25.4\nginx.exe" + dir C:\tools\nginx-1.25.4\logs\ Start-Sleep -Seconds 5 netstat -a # Print Nginx Error Logs (on Windows systems) #nginx -t - Get-Content -Path "C:\tools\nginx-1.25.3\logs\error.log" + Get-Content -Path "C:\tools\nginx-1.25.4\logs\error.log" dir D:\a\martin\martin\ - name: Start postgres uses: nyurik/action-setup-postgis@v1.1 From fba9af874929dc90abc7aa7fc3d324d42bbfae76 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 25 Feb 2024 05:46:59 -0500 Subject: [PATCH 029/164] Bump locks, blessed expected tests (#1212) --- Cargo.lock | 113 ++++++++++----------- justfile | 2 +- tests/expected/configured/spr_cmp.png | Bin 785 -> 787 bytes tests/expected/configured/spr_cmp_2x.png | Bin 1567 -> 1569 bytes tests/expected/configured/spr_mysrc.png | Bin 189 -> 191 bytes tests/expected/configured/spr_mysrc_2x.png | Bin 344 -> 344 bytes tests/expected/configured/spr_src1.png | Bin 758 -> 758 bytes tests/fixtures/sprites/expected/all_1.png | Bin 785 -> 787 bytes tests/fixtures/sprites/expected/all_2.png | Bin 1567 -> 1569 bytes tests/fixtures/sprites/expected/src1_1.png | Bin 758 -> 758 bytes tests/fixtures/sprites/expected/src2_1.png | Bin 189 -> 191 bytes tests/fixtures/sprites/expected/src2_2.png | Bin 344 -> 344 bytes 12 files changed, 53 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8656a94aa..1edb3ba38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -562,9 +562,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.0" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "bytecount" @@ -644,11 +644,10 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24" dependencies = [ - "jobserver", "libc", ] @@ -668,7 +667,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -967,9 +966,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c376d08ea6aa96aafe61237c7200d1241cb177b7d3a542d791f2d118e9cbb955" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -977,9 +976,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33043dcd19068b8192064c704b3f83eb464f91f1ff527b44a4e2b08d9cdb8855" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", @@ -991,9 +990,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.6" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", @@ -1496,9 +1495,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" @@ -1635,9 +1634,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" [[package]] name = "hex" @@ -1904,15 +1903,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - [[package]] name = "jpeg-decoder" version = "0.3.1" @@ -2021,18 +2011,19 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libdeflate-sys" -version = "1.19.0" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67921a7f85100c1559efc3d1c7c472091b7da05f304b4bbd5356f075e97f1cc2" +checksum = "b7654050a14083995afdf189c4d895b59bc6c8195407c24db4df4c3878b3679d" dependencies = [ "cc", + "pkg-config", ] [[package]] name = "libdeflater" -version = "1.19.0" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a31b22f662350ec294b13859f935aea772ba7b2bc8776269f4a5627308eab7d" +checksum = "6ae43f79441cf19e744fba2aa762e4b6a9016970137e67d3a45eec96ed11bb27" dependencies = [ "libdeflate-sys", ] @@ -3717,12 +3708,12 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4550,9 +4541,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -4565,9 +4556,9 @@ checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" [[package]] name = "unicode-script" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc" +checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" [[package]] name = "unicode-segmentation" @@ -4882,7 +4873,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -4900,7 +4891,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -4920,17 +4911,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", ] [[package]] @@ -4941,9 +4932,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" [[package]] name = "windows_aarch64_msvc" @@ -4953,9 +4944,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" [[package]] name = "windows_i686_gnu" @@ -4965,9 +4956,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" [[package]] name = "windows_i686_msvc" @@ -4977,9 +4968,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" [[package]] name = "windows_x86_64_gnu" @@ -4989,9 +4980,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" [[package]] name = "windows_x86_64_gnullvm" @@ -5001,9 +4992,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" [[package]] name = "windows_x86_64_msvc" @@ -5013,9 +5004,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" [[package]] name = "winreg" diff --git a/justfile b/justfile index 5d10ea7b5..1faab0040 100644 --- a/justfile +++ b/justfile @@ -181,7 +181,7 @@ test-int: clean-test install-sqlx test-lambda: tests/test-aws-lambda.sh -# Run integration tests and save its output as the new expected output +# Run integration tests and save its output as the new expected output (ordering is important, but in some cases run `bless-tests` before others) bless: restart clean-test bless-insta-martin bless-insta-mbtiles bless-tests bless-int # Bless integration tests diff --git a/tests/expected/configured/spr_cmp.png b/tests/expected/configured/spr_cmp.png index ffb3546925d2136c95e615982d07ad025b0077b1..197c70d09170009358a804c09136a9b17b727ff5 100644 GIT binary patch delta 702 zcmV;v0zv(e29pMmBmvryB_RPakw+wdVfPY5FNt_49;A9KD9?H2?XnIo%Q90Ep&xwg z&dmEZ@0)ou6U`5xX``GK&K4&SE$U19>E7HOA9^u)di7~$0BX5Z^L_EcKEGHT!x)UM z=2G8LtEm7PU{3M@#26;((ZtvK6Zp1Ng-^9IEaZ%O$>>Xzjp(srDxO5*JNDs!7{*{M zY8Ix3*HxLQa6(Al*F3=4#l(pg<+&+9&Es)>Rn|nB6C}x;x_@^0)JmWM4{_DzCyqB!D`O(Uxu(EKOCyv9 zV+Bkw6jQOR>}up?O^B=VFcocogfT%hWsS5H8Zkv91M%H(wtp{(iTCc={#P3{vPM85 zE&Qf8!5b$JAw?r-uB(keh|=nQBUta=ByW$NfSo$dQfvVdeQO?Ap=e8tLmj;NJWggRwKi(fzVUOx2s+DX(|MEAFj-{dsX7Zf3^d z!PQIHc8M1!9@i>v^t96BmrzM3B0R}2l&~*f-#P!$(Wo%fR$!v72`Cz|iKX)7x}S*; zk8(e;3{@IoDp!Lxe8t(wm9eAnYWfWRiA3VNvp0}fS{apQ3Q~U>y9Q+Dzc(S2S>T?b z7^a0on~vZ$YHz-l44J}zJ!4ZJ3;E-1@$*vJ4#DJ1I}LgV&WMz@17MsMyz;UBPOBc4=fep)WlT?r zv}im_{Z7ISIjwqt=iT;fRuG;M;Y0#Ct$NtvQaiI2G%lxA4@M;|k)(E#+IrBqlvXjs kSps_MLE}=|Ep#FN05WOX$sKl12mk;807*qoM6N<$f`JKHIsgCw delta 700 zcmV;t0z>_i29XAkBmvlwB_RQ_kw+wdA$tj;mqa`i57K%pD9?H2?XnJrWtmqJ!4E!m zXXbs$`)1zEtkw>oX`_NA!KNS(>(m!-r+agEeCWmG>D8yH0jOjWjraKr``X3g7{*|1 zIg|K~T8#r_z;KfHA;uW89!-3$K7nsbW%yJn!a~NZ7RNDU>N?!nW4i!m*=jz@u=;P370vIP|27L zoaMz^=O|%+F3(K?Y95d4tEwiFf}lvlsrzS_Pp$YG@DNvRe&ToowJIh;f@=&$ni`=n z7|CIRftZM-RaYacYC>L>hly~1Er4(TGhe zqGNKiBS$vxhn45Euxm$;YoxFDfP3>}493n3hxe-*vA8$8Q(o`#SKM2F`}5*F+)RzZ zgR7UY?Gi6eJgzxz^d#%?ODH8{A(7-4O1Ldw-#P!0^Fy)4V4|f-$eWRgrQ+m9I};xs zWqx28avCu>SA#ZuNf3~wv7_*6`V4+VBJthX8%Qjz6sMV-(nn+0fXw{!CZsa+-7^$p zXu;5;BY2J4TdyTUmUPd5*wkkP{PULl^Gezd!4gb*+DS?#q@?Wt48c0RUl&{#tO=%h zv|FEim1eI_&$6IRvzetnpg4m^%Wq- i&{OvtSJM7R7veWEY1+w8yORk30000sK2^7zXf1c1zMwi}Au@qm)u(ZEOoFB(|wY zBq)_)B1EgzZLn6OQbW~(5_CkT*88RU{=x1{HYF_CotK;(k01K`z~SXN$&=Zc?1J55 zk4>JNky6e~9!ntL)FshaJcNKliw*JSDX>|`=4G4t6EU=z6ZJ6K>dnS5c6q#UbG23% zbL@(e3>vr4a#~z-JvSN$(B?qnhU>W|o&(2_t_Ug(!FQ>XB?BdYx=KyJ?3@fWX+haq zRqOan>~UR{tO^*7%LtQD7T3Lwb|il%Jv^Wi?e7A^h@k(BhEZMs&`STay z+rD#Wn^#hjEHkPkgtZgZ}r+EZ@U4nAA}kIp`|_e zuDi<{ePEg3F9eUiviXU-p!J;*o{jnkS5(7$wY5$2J%#@-k>By6 zxNB4F812P>10vaE>kz6~=6H%9kpWuS}Hz zAX)Y&$CUD=h;m8Tjyk8sIFKZdgJe$qG^AX1nNqDXitG7knsWLNWji_rSMw!$Q!mod z<{Z~=h-pekr{F43QmsdAszcN2wGNQeZ;+%ybP6saU8Ogb%Kq%og=Q9=?z5y=jO*Wb z=4KXKor0@KN%)df49?N%J~n;|zC5Lab94$WyFw{wV^pz&b94$ehiK|Ba5zuo1ZPvq u=Tu0mIKkPR^4aMkQ88@?XG40=|Ixo(3b=jzso?Mc0000vDv delta 902 zcmV;119|+R44(|JcLINtNklsK2^7zXf1c1u#I#dyhLqm)u(ZEOoFB(^~$ z5|m0Y5u(-VHdw1ssiA5?2|A)v>-|!F|6q3}n-Z4n&fA;rwrJS8SHh_Rr7e!;~5CRS@HN=~zz-Ap=kZl%D#L#A5)N3zmHyXp(rx{TyGpen*)vOuIH+F4jf5c5mZXTcd?Tu10{dBN=?A*oD4N-LD^nY z>-bFUbItXvF-pc|gh?n%8(znT=wRI|*_dZ^M9S!+y1ibli;im5_3ejXkdy{`_lGZu z5Z{PP!!WQ)(x7DNIkAeAX$F~fN7!Z{PDABxphl49XDPrmXTJ;4@AOuljtU|+yeDmiy4NAERDM)m1+KjsE(2 z)m5&jvt=^CzO4ZL%U`(rh?n|cv?v)Cp$%=i`z-gvEW^CjYmdC`2E2X{X8ebi_Tanj z9&hx4WrDvDJo?JkC+@Dx*TmU=a9AtSV8w#gcSd+N>mOWpJ@3`lw>b9{{$C>9@uIk6 zOY9o$#RW&ppeM41AA3(&*@zAcy)t3AR=ts2>3FV^=qOK~0&usf)nPFi3!Tl7f-cfn zW>L0T%)~l>$2>G5W*RgwlAV*Dx$MY5=y#J41r&dli5x@Py%|aYND*D2oFVOAit@ly zL{G&^`;%iz`BFr=1Z+p0(_$P* zkjFtHN8}h%HoHuzRvE?hd^Alt{X*G}PQlfDi{8`=bhJ6g^#@{x($Oin3X}j~t4(!i zM!kO50do2S5>$vz!9}F2^rlkTpB*~i%%an~EGeo@1<~%@%%W3p6)6E3>w2Bj)%_*OqE)o^fc5pVN c_xvCI3tS4geFRkVJOBUy07*qoM6N<$f_FlwtBz zaWGV+xTKaF{L9qu>0A3NRcPPi3J7{;BN&B2N4DW+x0=q6Mc9OgVsID2B15*z#|=+| ztfA!aM0bo%O#iN zM&WyV{Q&a%(&VM!4|t3yvL+nHL&fFDNu!HXy#J)(u$agwxVcDE6Z@@i1pRLDra11m zDam`H@THAZk<_pYrB^9D;0pqJOyYCTXNxvp3HIc_AYjj%_(DQAADP|OBGgVkAY+zGnWf+@{%7$4 X@xtlDO$A=t00000NkvXXu0mjfNwtGI delta 273 zcmV+s0q*|T0@wnOEq_4`!!Qgy2!T)tWw1gBgg_XBhQS753|0mmgO_;O>x|B zQv!%Y;Y%B-BB@~)O0QCQz!wDcn8fFv-xhZitzkgHQzqW~G#iP1xy8tWmV76?aZ#l* zoQ@Sl9oUQpl&UClH<8CCYxGzY(mzstcMIXOG_0RDpHC{B1j=v zYeZBK#E40>^pHi0AfgG?OGQi%S}8qbFGci{6%WOORF4JaId6Fr#_cZawv*)24?cEh z=grP<-@KXCyabvy%w6Vga09tc&k|na-rgM@csYK0_k{|4u9jdntJjKpPpqVej}?;91RC%08TMfe#^RXS ziNQ4|Oqm-3`o1O!zZNGzzq@x4ihA@Wsi$-(e`0c5ByYO!qZ3s;(_@Rzw6xS1Y-2Ujm)Ti8B8 z@tBZL=#vVse`zQB2cSdWM2%<)rsMEE=ZBk}(+(52T ze9Ocr3rw_W;wr%~0<*Z|BA)JBqPq0*80{!ST1>VE^=IfgLE|#2mvaZ1QbB`!rEFR4 z*m!`_+rlG9{>;pmyB1zl9QC40MhA_HXGw^%vE?pi9)1;OYPX002ovPDHLk FV1ffWTs{B* delta 723 zcmV;^0xbRZ1@;AyFMrce9LICjsq~-+PyS=jb_f-A@nk_S&O?K1*qFk~M8;5Q1sMeA ztcVJNSTU`R9TH>+BHA*&OvLt}ld(f`8KRd)JPZ%Ac^oJ|-!J@LiCIF7P1?(T@FjWg z{oZ?@{NC^VB6t}H!YGr<)MNsZPJJ1#d2jEI551f`z4|Oa0Dm<(yYfM~u+PgE$Iu6T zt8(@S&UFJ3IfReUM|93dm~Zu`@O`lgpKBGEm!*1H>PuCm_%S7$%%Jcc`)~|>&==>- zPYrK4VN@mvsQZG=@N01c)Vq5Zp)4hTD}!-x)1#rozm{gNwfu2zyD(fOfvhG=EBMt5 zx6aYV{#u%y0)L$IWIVmfVRB5+rbM0>&o7@^_Jgnsqc}Hl+{!nEi7~B(0Mr!7%7cj# zZWKt_M1e=A$QKPON)NN~Mi3a1#(|n40%=a5f#hyD+rM`cK<}RIf3T zVwtd4=v=7Ro=nZ9Vr;Xow6Uk&+&TZr?T2cH0AmUcQ>4ViVr6o}3+Cfv`6nK)8;}@g zbSSY^o`10F*im>reFlHFD17I+gTf=ryFr!O`niT~1l4UAkK^;tDe@78U}nJtM3n46aGqG?PyTRTTUF`-K)GU@bwooSt^!Bn8WjzQEZ5;{GrOa?`!NPR$l zV$?9}^yF<|su7GxU?x+V`_p?QrrQ=z(T&n<$4u6w@dEX8=thKE7HOA9^u)di7~$0BX5Z^L_EcKEGHT!x)UM z=2G8LtEm7PU{3M@#26;((ZtvK6Zp1Ng-^9IEaZ%O$>>Xzjp(srDxO5*JNDs!7{*{M zY8Ix3*HxLQa6(Al*F3=4#l(pg<+&+9&Es)>Rn|nB6C}x;x_@^0)JmWM4{_DzCyqB!D`O(Uxu(EKOCyv9 zV+Bkw6jQOR>}up?O^B=VFcocogfT%hWsS5H8Zkv91M%H(wtp{(iTCc={#P3{vPM85 zE&Qf8!5b$JAw?r-uB(keh|=nQBUta=ByW$NfSo$dQfvVdeQO?Ap=e8tLmj;NJWggRwKi(fzVUOx2s+DX(|MEAFj-{dsX7Zf3^d z!PQIHc8M1!9@i>v^t96BmrzM3B0R}2l&~*f-#P!$(Wo%fR$!v72`Cz|iKX)7x}S*; zk8(e;3{@IoDp!Lxe8t(wm9eAnYWfWRiA3VNvp0}fS{apQ3Q~U>y9Q+Dzc(S2S>T?b z7^a0on~vZ$YHz-l44J}zJ!4ZJ3;E-1@$*vJ4#DJ1I}LgV&WMz@17MsMyz;UBPOBc4=fep)WlT?r zv}im_{Z7ISIjwqt=iT;fRuG;M;Y0#Ct$NtvQaiI2G%lxA4@M;|k)(E#+IrBqlvXjs kSps_MLE}=|Ep#FN05WOX$sKl12mk;807*qoM6N<$f`JKHIsgCw delta 700 zcmV;t0z>_i29XAkBmvlwB_RQ_kw+wdA$tj;mqa`i57K%pD9?H2?XnJrWtmqJ!4E!m zXXbs$`)1zEtkw>oX`_NA!KNS(>(m!-r+agEeCWmG>D8yH0jOjWjraKr``X3g7{*|1 zIg|K~T8#r_z;KfHA;uW89!-3$K7nsbW%yJn!a~NZ7RNDU>N?!nW4i!m*=jz@u=;P370vIP|27L zoaMz^=O|%+F3(K?Y95d4tEwiFf}lvlsrzS_Pp$YG@DNvRe&ToowJIh;f@=&$ni`=n z7|CIRftZM-RaYacYC>L>hly~1Er4(TGhe zqGNKiBS$vxhn45Euxm$;YoxFDfP3>}493n3hxe-*vA8$8Q(o`#SKM2F`}5*F+)RzZ zgR7UY?Gi6eJgzxz^d#%?ODH8{A(7-4O1Ldw-#P!0^Fy)4V4|f-$eWRgrQ+m9I};xs zWqx28avCu>SA#ZuNf3~wv7_*6`V4+VBJthX8%Qjz6sMV-(nn+0fXw{!CZsa+-7^$p zXu;5;BY2J4TdyTUmUPd5*wkkP{PULl^Gezd!4gb*+DS?#q@?Wt48c0RUl&{#tO=%h zv|FEim1eI_&$6IRvzetnpg4m^%Wq- i&{OvtSJM7R7veWEY1+w8yORk30000sK2^7zXf1c1zMwi}Au@qm)u(ZEOoFB(|wY zBq)_)B1EgzZLn6OQbW~(5_CkT*88RU{=x1{HYF_CotK;(k01K`z~SXN$&=Zc?1J55 zk4>JNky6e~9!ntL)FshaJcNKliw*JSDX>|`=4G4t6EU=z6ZJ6K>dnS5c6q#UbG23% zbL@(e3>vr4a#~z-JvSN$(B?qnhU>W|o&(2_t_Ug(!FQ>XB?BdYx=KyJ?3@fWX+haq zRqOan>~UR{tO^*7%LtQD7T3Lwb|il%Jv^Wi?e7A^h@k(BhEZMs&`STay z+rD#Wn^#hjEHkPkgtZgZ}r+EZ@U4nAA}kIp`|_e zuDi<{ePEg3F9eUiviXU-p!J;*o{jnkS5(7$wY5$2J%#@-k>By6 zxNB4F812P>10vaE>kz6~=6H%9kpWuS}Hz zAX)Y&$CUD=h;m8Tjyk8sIFKZdgJe$qG^AX1nNqDXitG7knsWLNWji_rSMw!$Q!mod z<{Z~=h-pekr{F43QmsdAszcN2wGNQeZ;+%ybP6saU8Ogb%Kq%og=Q9=?z5y=jO*Wb z=4KXKor0@KN%)df49?N%J~n;|zC5Lab94$WyFw{wV^pz&b94$ehiK|Ba5zuo1ZPvq u=Tu0mIKkPR^4aMkQ88@?XG40=|Ixo(3b=jzso?Mc0000vDv delta 902 zcmV;119|+R44(|JcLINtNklsK2^7zXf1c1u#I#dyhLqm)u(ZEOoFB(^~$ z5|m0Y5u(-VHdw1ssiA5?2|A)v>-|!F|6q3}n-Z4n&fA;rwrJS8SHh_Rr7e!;~5CRS@HN=~zz-Ap=kZl%D#L#A5)N3zmHyXp(rx{TyGpen*)vOuIH+F4jf5c5mZXTcd?Tu10{dBN=?A*oD4N-LD^nY z>-bFUbItXvF-pc|gh?n%8(znT=wRI|*_dZ^M9S!+y1ibli;im5_3ejXkdy{`_lGZu z5Z{PP!!WQ)(x7DNIkAeAX$F~fN7!Z{PDABxphl49XDPrmXTJ;4@AOuljtU|+yeDmiy4NAERDM)m1+KjsE(2 z)m5&jvt=^CzO4ZL%U`(rh?n|cv?v)Cp$%=i`z-gvEW^CjYmdC`2E2X{X8ebi_Tanj z9&hx4WrDvDJo?JkC+@Dx*TmU=a9AtSV8w#gcSd+N>mOWpJ@3`lw>b9{{$C>9@uIk6 zOY9o$#RW&ppeM41AA3(&*@zAcy)t3AR=ts2>3FV^=qOK~0&usf)nPFi3!Tl7f-cfn zW>L0T%)~l>$2>G5W*RgwlAV*Dx$MY5=y#J41r&dli5x@Py%|aYND*D2oFVOAit@ly zL{G&^`;%iz`BFr=1Z+p0(_$P* zkjFtHN8}h%HoHuzRvE?hd^Alt{X*G}PQlfDi{8`=bhJ6g^#@{x($Oin3X}j~t4(!i zM!kO50do2S5>$vz!9}F2^rlkTpB*~i%%an~EGeo@1<~%@%%W3p6)6E3>w2Bj)%_*OqE)o^fc5pVN c_xvCI3tS4geFRkVJOBUy07*qoM6N<$f_FlmzstcMIXOG_0RDpHC{B1j=v zYeZBK#E40>^pHi0AfgG?OGQi%S}8qbFGci{6%WOORF4JaId6Fr#_cZawv*)24?cEh z=grP<-@KXCyabvy%w6Vga09tc&k|na-rgM@csYK0_k{|4u9jdntJjKpPpqVej}?;91RC%08TMfe#^RXS ziNQ4|Oqm-3`o1O!zZNGzzq@x4ihA@Wsi$-(e`0c5ByYO!qZ3s;(_@Rzw6xS1Y-2Ujm)Ti8B8 z@tBZL=#vVse`zQB2cSdWM2%<)rsMEE=ZBk}(+(52T ze9Ocr3rw_W;wr%~0<*Z|BA)JBqPq0*80{!ST1>VE^=IfgLE|#2mvaZ1QbB`!rEFR4 z*m!`_+rlG9{>;pmyB1zl9QC40MhA_HXGw^%vE?pi9)1;OYPX002ovPDHLk FV1ffWTs{B* delta 723 zcmV;^0xbRZ1@;AyFMrce9LICjsq~-+PyS=jb_f-A@nk_S&O?K1*qFk~M8;5Q1sMeA ztcVJNSTU`R9TH>+BHA*&OvLt}ld(f`8KRd)JPZ%Ac^oJ|-!J@LiCIF7P1?(T@FjWg z{oZ?@{NC^VB6t}H!YGr<)MNsZPJJ1#d2jEI551f`z4|Oa0Dm<(yYfM~u+PgE$Iu6T zt8(@S&UFJ3IfReUM|93dm~Zu`@O`lgpKBGEm!*1H>PuCm_%S7$%%Jcc`)~|>&==>- zPYrK4VN@mvsQZG=@N01c)Vq5Zp)4hTD}!-x)1#rozm{gNwfu2zyD(fOfvhG=EBMt5 zx6aYV{#u%y0)L$IWIVmfVRB5+rbM0>&o7@^_Jgnsqc}Hl+{!nEi7~B(0Mr!7%7cj# zZWKt_M1e=A$QKPON)NN~Mi3a1#(|n40%=a5f#hyD+rM`cK<}RIf3T zVwtd4=v=7Ro=nZ9Vr;Xow6Uk&+&TZr?T2cH0AmUcQ>4ViVr6o}3+Cfv`6nK)8;}@g zbSSY^o`10F*im>reFlHFD17I+gTf=ryFr!O`niT~1l4UAkK^;tDe@78U}nJtM3n46aGqG?PyTRTTUF`-K)GU@bwooSt^!Bn8WjzQEZ5;{GrOa?`!NPR$l zV$?9}^yF<|su7GxU?x+V`_p?QrrQ=z(T&n<$4u6w@dEX8=thKwtBz zaWGV+xTKaF{L9qu>0A3NRcPPi3J7{;BN&B2N4DW+x0=q6Mc9OgVsID2B15*z#|=+| ztfA!aM0bo%O#iN zM&WyV{Q&a%(&VM!4|t3yvL+nHL&fFDNu!HXy#J)(u$agwxVcDE6Z@@i1pRLDra11m zDam`H@THAZk<_pYrB^9D;0pqJOyYCTXNxvp3HIc_AYjj%_(DQAADP|OBGgVkAY+zGnWf+@{%7$4 X@xtlDO$A=t00000NkvXXu0mjfNwtGI delta 273 zcmV+s0q*|T0@wnOEq_4`!!Qgy2!T)tWw1gBgg_XBhQS753|0mmgO_;O>x|B zQv!%Y;Y%B-BB@~)O0QCQz!wDcn8fFv-xhZitzkgHQzqW~G#iP1xy8tWmV76?aZ#l* zoQ@Sl9oUQpl&UClH<8CCYxGzY( Date: Mon, 26 Feb 2024 15:12:55 -0500 Subject: [PATCH 030/164] CI fix: Wait for "docker-build-test" to use cross-build artifacts (#1215) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d75ff9bc1..034de2bda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,7 +294,7 @@ jobs: test-aws-lambda: name: Test AWS Lambda runs-on: ubuntu-latest - needs: [ build ] + needs: [ docker-build-test ] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -477,7 +477,7 @@ jobs: test-with-svc: name: Test postgis:${{ matrix.img_ver }} sslmode=${{ matrix.sslmode }} runs-on: ubuntu-latest - needs: [ build ] + needs: [ build, docker-build-test ] strategy: fail-fast: true matrix: From 73b9bb96107019baa800f7e4eca22329ab1db531 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 02:29:02 +0000 Subject: [PATCH 031/164] chore(deps): Bump ctor from 0.2.6 to 0.2.7 (#1217) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.2.6 to 0.2.7.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ctor&package-manager=cargo&previous-version=0.2.6&new-version=0.2.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1edb3ba38..1e59adfbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -956,9 +956,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", "syn 2.0.50", From 16a54e1c333a3fad4498870a7eb8b3b2854bbe23 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 27 Feb 2024 02:40:20 -0500 Subject: [PATCH 032/164] Use --locked with cargo install (#1216) This will prevent installation issues in case dependencies break semver promise Fixes #1211 --- .cargo-husky/hooks/pre-push | 2 +- .github/workflows/ci.yml | 2 +- Cargo.lock | 82 ++++++++++++++++++------------------- docs/src/development.md | 2 +- docs/src/installation.md | 2 +- docs/src/tools.md | 2 +- justfile | 8 ++-- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/.cargo-husky/hooks/pre-push b/.cargo-husky/hooks/pre-push index 81070dbec..a4882fdbd 100755 --- a/.cargo-husky/hooks/pre-push +++ b/.cargo-husky/hooks/pre-push @@ -16,7 +16,7 @@ set -e if ! command -v just > /dev/null; then echo "Command 'just' is not installed. See https://github.com/casey/just#readme for installation instructions, or use" echo "" - echo " cargo install just" + echo " cargo install just --locked" echo "" exit 1 fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 034de2bda..c49249597 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -269,7 +269,7 @@ jobs: run: | set -x sudo apt-get install -y dpkg dpkg-dev liblzma-dev - cargo install cargo-deb + cargo install cargo-deb --locked cargo deb -v -p martin --output target/debian/debian-x86_64.deb mkdir -p target_releases mv target/debian/debian-x86_64.deb target_releases/ diff --git a/Cargo.lock b/Cargo.lock index 1e59adfbe..4dbb58982 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -384,7 +384,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -406,7 +406,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -417,7 +417,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -644,9 +644,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" dependencies = [ "libc", ] @@ -728,7 +728,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -961,7 +961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -985,7 +985,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -996,7 +996,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -1158,7 +1158,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -1478,7 +1478,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -1590,9 +1590,9 @@ dependencies = [ [[package]] name = "half" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" dependencies = [ "cfg-if", "crunchy", @@ -2521,7 +2521,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -2612,7 +2612,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -2829,9 +2829,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" +checksum = "58678a64de2fced2bdec6bca052a6716a0efe692d6e3f53d1bda6a1def64cfc0" dependencies = [ "once_cell", "protobuf-support", @@ -2840,9 +2840,9 @@ dependencies = [ [[package]] name = "protobuf-codegen" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e85514a216b1c73111d9032e26cc7a5ecb1bb3d4d9539e91fb72a4395060f78" +checksum = "32777b0b3f6538d9d2e012b3fad85c7e4b9244b5958d04a6415f4333782b7a77" dependencies = [ "anyhow", "once_cell", @@ -2855,9 +2855,9 @@ dependencies = [ [[package]] name = "protobuf-parse" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d6fbd6697c9e531873e81cec565a85e226b99a0f10e1acc079be057fe2fcba" +checksum = "96cb37955261126624a25b5e6bda40ae34cf3989d52a783087ca6091b29b5642" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -2871,9 +2871,9 @@ dependencies = [ [[package]] name = "protobuf-support" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" +checksum = "e1ed294a835b0f30810e13616b1cd34943c6d1e84a8f3b0dcfe466d256c3e7e7" dependencies = [ "thiserror", ] @@ -3235,7 +3235,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.50", + "syn 2.0.51", "unicode-ident", ] @@ -3359,9 +3359,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7" +checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" [[package]] name = "rustls-webpki" @@ -3499,7 +3499,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -3573,7 +3573,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4030,7 +4030,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4041,7 +4041,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4108,9 +4108,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" dependencies = [ "proc-macro2", "quote", @@ -4185,7 +4185,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4309,7 +4309,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4455,7 +4455,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -4753,7 +4753,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", "wasm-bindgen-shared", ] @@ -4787,7 +4787,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5090,7 +5090,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] @@ -5110,7 +5110,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.51", ] [[package]] diff --git a/docs/src/development.md b/docs/src/development.md index 26126405b..b3bc71147 100644 --- a/docs/src/development.md +++ b/docs/src/development.md @@ -30,7 +30,7 @@ sudo apt install -y build-essential pkg-config jq file Install [Just](https://github.com/casey/just#readme) (improved makefile processor). Note that some Linux and Homebrew distros have outdated versions of Just, so you should install it from source: ```shell, ignore -cargo install just +cargo install just --locked ``` When developing MBTiles SQL code, you may need to use `just prepare-sqlite` whenever SQL queries are modified. Run `just` to see all available commands. diff --git a/docs/src/installation.md b/docs/src/installation.md index 706bda634..70d6b289f 100644 --- a/docs/src/installation.md +++ b/docs/src/installation.md @@ -21,7 +21,7 @@ You can download martin from [GitHub releases page](https://github.com/maplibre/ If you [install Rust](https://www.rust-lang.org/tools/install), you can build martin from source with Cargo: ```shell -cargo install martin +cargo install martin --locked martin --help ``` diff --git a/docs/src/tools.md b/docs/src/tools.md index a7b13e662..df4ea78fb 100644 --- a/docs/src/tools.md +++ b/docs/src/tools.md @@ -12,6 +12,6 @@ Martin project contains additional tooling to help manage the data servable with Use `mbtiles --help` to see a list of available commands, and `mbtiles --help` to see help for a specific command. -This tool can be installed by compiling the latest released version with `cargo install mbtiles`, or by downloading a pre-built binary from the [releases page](https://github.com/maplibre/martin/releases/latest). +This tool can be installed by compiling the latest released version with `cargo install mbtiles --locked`, or by downloading a pre-built binary from the [releases page](https://github.com/maplibre/martin/releases/latest). The `mbtiles` utility builds on top of the [MBTiles specification](https://github.com/mapbox/mbtiles-spec). It adds a few additional conventions to ensure that the content of the tile data is valid, and can be used for reliable diffing and patching of the tilesets. diff --git a/justfile b/justfile index 1faab0040..c7c43f175 100644 --- a/justfile +++ b/justfile @@ -348,10 +348,10 @@ cargo-install $COMMAND $INSTALL_CMD="" *ARGS="": set -eu if ! command -v $COMMAND > /dev/null; then if ! command -v cargo-binstall > /dev/null; then - echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" - cargo install ${INSTALL_CMD:-$COMMAND} {{ ARGS }} + echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} --locked {{ ARGS }}" + cargo install ${INSTALL_CMD:-$COMMAND} --locked {{ ARGS }} else - echo "$COMMAND could not be found. Installing it with cargo binstall ${INSTALL_CMD:-$COMMAND} {{ ARGS }}" - cargo binstall ${INSTALL_CMD:-$COMMAND} {{ ARGS }} + echo "$COMMAND could not be found. Installing it with cargo binstall ${INSTALL_CMD:-$COMMAND} --locked {{ ARGS }}" + cargo binstall ${INSTALL_CMD:-$COMMAND} --locked {{ ARGS }} fi fi From e0c960a1b6e5993a8c402f2b77b65e19893b706b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 27 Feb 2024 02:48:06 -0500 Subject: [PATCH 033/164] test: add tests for empty mbtiles (#1218) They all seem to pass, but good to ensure we test the usecase of empty mbtiles --- mbtiles/tests/copy.rs | 23 ++++++ .../copy__databases@flat__empty-no-hash.snap | 32 +++++++++ .../copy__databases@flat__empty.snap | 32 +++++++++ .../copy__databases@hash__empty-no-hash.snap | 40 +++++++++++ .../copy__databases@hash__empty.snap | 40 +++++++++++ .../copy__databases@norm__empty-no-hash.snap | 71 +++++++++++++++++++ .../copy__databases@norm__empty.snap | 71 +++++++++++++++++++ 7 files changed, 309 insertions(+) create mode 100644 mbtiles/tests/snapshots/copy__databases@flat__empty-no-hash.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@flat__empty.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@hash__empty-no-hash.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@hash__empty.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@norm__empty-no-hash.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@norm__empty.snap diff --git a/mbtiles/tests/copy.rs b/mbtiles/tests/copy.rs index 88f93691b..3f3318524 100644 --- a/mbtiles/tests/copy.rs +++ b/mbtiles/tests/copy.rs @@ -187,6 +187,29 @@ fn databases() -> Databases { let mut result = Databases::default(); for &mbt_typ in &[Flat, FlatWithHash, Normalized] { let typ = shorten(mbt_typ); + + let (raw_empty_mbt, mut raw_empty_cn) = + new_file_no_hash!(databases, mbt_typ, "", "", "{typ}__empty-no-hash"); + let dmp = dump(&mut raw_empty_cn).await.unwrap(); + assert_snapshot!(&dmp, "{typ}__empty-no-hash"); + result.add("empty_no_hash", mbt_typ, dmp, raw_empty_mbt, raw_empty_cn); + + let (empty_mbt, mut empty_cn) = open!(databases, "{typ}__empty"); + let raw_empty_mbt = result.mbtiles("empty_no_hash", mbt_typ); + let opt = MbtilesCopier { + src_file: path(raw_empty_mbt), + dst_file: path(&empty_mbt), + ..Default::default() + }; + opt.run().await.unwrap(); + let dmp = dump(&mut empty_cn).await.unwrap(); + assert_snapshot!(&dmp, "{typ}__empty"); + let hash = empty_mbt.validate(Off, Verify).await.unwrap(); + allow_duplicates! { + assert_display_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); + } + result.add("empty", mbt_typ, dmp, empty_mbt, empty_cn); + let (raw_mbt, mut raw_cn) = new_file_no_hash!( databases, mbt_typ, diff --git a/mbtiles/tests/snapshots/copy__databases@flat__empty-no-hash.snap b/mbtiles/tests/snapshots/copy__databases@flat__empty-no-hash.snap new file mode 100644 index 000000000..04eb098b1 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@flat__empty-no-hash.snap @@ -0,0 +1,32 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = [] + +[[]] +type = 'table' +tbl_name = 'tiles' +sql = ''' +CREATE TABLE tiles ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles' diff --git a/mbtiles/tests/snapshots/copy__databases@flat__empty.snap b/mbtiles/tests/snapshots/copy__databases@flat__empty.snap new file mode 100644 index 000000000..3e8eb17a9 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@flat__empty.snap @@ -0,0 +1,32 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'table' +tbl_name = 'tiles' +sql = ''' +CREATE TABLE tiles ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles' diff --git a/mbtiles/tests/snapshots/copy__databases@hash__empty-no-hash.snap b/mbtiles/tests/snapshots/copy__databases@hash__empty-no-hash.snap new file mode 100644 index 000000000..75bf60d90 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@hash__empty-no-hash.snap @@ -0,0 +1,40 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = [] + +[[]] +type = 'table' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE TABLE tiles_with_hash ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + tile_hash text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles_with_hash' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT zoom_level, tile_column, tile_row, tile_data FROM tiles_with_hash''' diff --git a/mbtiles/tests/snapshots/copy__databases@hash__empty.snap b/mbtiles/tests/snapshots/copy__databases@hash__empty.snap new file mode 100644 index 000000000..f23bd8a89 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@hash__empty.snap @@ -0,0 +1,40 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'table' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE TABLE tiles_with_hash ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + tile_hash text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles_with_hash' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT zoom_level, tile_column, tile_row, tile_data FROM tiles_with_hash''' diff --git a/mbtiles/tests/snapshots/copy__databases@norm__empty-no-hash.snap b/mbtiles/tests/snapshots/copy__databases@norm__empty-no-hash.snap new file mode 100644 index 000000000..f663988dd --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@norm__empty-no-hash.snap @@ -0,0 +1,71 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'images' +sql = ''' +CREATE TABLE images ( + tile_id text NOT NULL PRIMARY KEY, + tile_data blob)''' +values = [] + +[[]] +type = 'table' +tbl_name = 'map' +sql = ''' +CREATE TABLE map ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_id text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = [] + +[[]] +type = 'index' +tbl_name = 'images' + +[[]] +type = 'index' +tbl_name = 'map' + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data + FROM map + JOIN images ON images.tile_id = map.tile_id''' + +[[]] +type = 'view' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE VIEW tiles_with_hash AS + SELECT + map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data, + images.tile_id AS tile_hash + FROM map + JOIN images ON images.tile_id = map.tile_id''' diff --git a/mbtiles/tests/snapshots/copy__databases@norm__empty.snap b/mbtiles/tests/snapshots/copy__databases@norm__empty.snap new file mode 100644 index 000000000..0170e862f --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@norm__empty.snap @@ -0,0 +1,71 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'images' +sql = ''' +CREATE TABLE images ( + tile_id text NOT NULL PRIMARY KEY, + tile_data blob)''' +values = [] + +[[]] +type = 'table' +tbl_name = 'map' +sql = ''' +CREATE TABLE map ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_id text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'index' +tbl_name = 'images' + +[[]] +type = 'index' +tbl_name = 'map' + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data + FROM map + JOIN images ON images.tile_id = map.tile_id''' + +[[]] +type = 'view' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE VIEW tiles_with_hash AS + SELECT + map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data, + images.tile_id AS tile_hash + FROM map + JOIN images ON images.tile_id = map.tile_id''' From 99cd99eb51260d55cbb8386aa8b764b1e941c412 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 28 Feb 2024 00:10:29 +0800 Subject: [PATCH 034/164] Add --base-path CLI option to override the URL path in the tilejson (#1205) Override URL path in the tilejson's `tiles` field when used behind a proxy that is not setting `X-Rewrite-URL` header Fixes #1185 --- docs/src/config-file.md | 4 ++++ docs/src/run-with-cli.md | 4 +++- martin/src/args/mod.rs | 3 +-- martin/src/args/srv.rs | 9 ++++++++- martin/src/config.rs | 6 +++++- martin/src/srv/config.rs | 4 ++++ martin/src/srv/tiles_info.rs | 21 ++++++++++++--------- martin/src/utils/error.rs | 3 +++ martin/src/utils/utilities.rs | 35 +++++++++++++++++++++++++++++++++++ 9 files changed, 75 insertions(+), 14 deletions(-) diff --git a/docs/src/config-file.md b/docs/src/config-file.md index 3efc08bd8..cc2670ac4 100644 --- a/docs/src/config-file.md +++ b/docs/src/config-file.md @@ -21,6 +21,10 @@ keep_alive: 75 # The socket address to bind [default: 0.0.0.0:3000] listen_addresses: '0.0.0.0:3000' + +# Set TileJSON URL path prefix, ignoring X-Rewrite-URL header. Must begin with a `/` +base_path: /tiles + # Number of web server workers worker_processes: 8 diff --git a/docs/src/run-with-cli.md b/docs/src/run-with-cli.md index b52935580..da3241c1c 100644 --- a/docs/src/run-with-cli.md +++ b/docs/src/run-with-cli.md @@ -27,7 +27,9 @@ Options: -l, --listen-addresses The socket address to bind. [DEFAULT: 0.0.0.0:3000] - + --base-path + Set TileJSON URL path prefix, ignoring X-Rewrite-URL header. Must begin with a `/`. Examples: `/`, `/tiles` + -W, --workers Number of web server workers diff --git a/martin/src/args/mod.rs b/martin/src/args/mod.rs index 0e58bd7ab..a563833a8 100644 --- a/martin/src/args/mod.rs +++ b/martin/src/args/mod.rs @@ -13,5 +13,4 @@ mod root; pub use root::{Args, ExtraArgs, MetaArgs}; mod srv; -pub use srv::PreferredEncoding; -pub use srv::SrvArgs; +pub use srv::{PreferredEncoding, SrvArgs}; diff --git a/martin/src/args/srv.rs b/martin/src/args/srv.rs index e7b743583..a3eddb725 100644 --- a/martin/src/args/srv.rs +++ b/martin/src/args/srv.rs @@ -1,7 +1,8 @@ -use crate::srv::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; use clap::ValueEnum; use serde::{Deserialize, Serialize}; +use crate::srv::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; + #[derive(clap::Args, Debug, PartialEq, Default)] #[command(about, version)] pub struct SrvArgs { @@ -9,6 +10,9 @@ pub struct SrvArgs { pub keep_alive: Option, #[arg(help = format!("The socket address to bind. [DEFAULT: {}]", LISTEN_ADDRESSES_DEFAULT), short, long)] pub listen_addresses: Option, + /// Set TileJSON URL path prefix, ignoring X-Rewrite-URL header. Must begin with a `/`. Examples: `/`, `/tiles` + #[arg(long)] + pub base_path: Option, /// Number of web server workers #[arg(short = 'W', long)] pub workers: Option, @@ -42,5 +46,8 @@ impl SrvArgs { if self.preferred_encoding.is_some() { srv_config.preferred_encoding = self.preferred_encoding; } + if self.base_path.is_some() { + srv_config.base_path = self.base_path; + } } } diff --git a/martin/src/config.rs b/martin/src/config.rs index 1377c096e..8be723a91 100644 --- a/martin/src/config.rs +++ b/martin/src/config.rs @@ -19,7 +19,7 @@ use crate::source::{TileInfoSources, TileSources}; #[cfg(feature = "sprites")] use crate::sprites::{SpriteConfig, SpriteSources}; use crate::srv::{SrvConfig, RESERVED_KEYWORDS}; -use crate::utils::{CacheValue, MainCache, OptMainCache}; +use crate::utils::{parse_base_path, CacheValue, MainCache, OptMainCache}; use crate::MartinError::{ConfigLoadError, ConfigParseError, ConfigWriteError, NoSources}; use crate::{IdResolver, MartinResult, OptOneMany}; @@ -71,6 +71,10 @@ impl Config { let mut res = UnrecognizedValues::new(); copy_unrecognized_config(&mut res, "", &self.unrecognized); + if let Some(path) = &self.srv.base_path { + self.srv.base_path = Some(parse_base_path(path)?); + } + #[cfg(feature = "postgres")] for pg in self.postgres.iter_mut() { res.extend(pg.finalize()?); diff --git a/martin/src/srv/config.rs b/martin/src/srv/config.rs index bef288160..f40fbbc33 100644 --- a/martin/src/srv/config.rs +++ b/martin/src/srv/config.rs @@ -10,6 +10,7 @@ pub const LISTEN_ADDRESSES_DEFAULT: &str = "0.0.0.0:3000"; pub struct SrvConfig { pub keep_alive: Option, pub listen_addresses: Option, + pub base_path: Option, pub worker_processes: Option, pub preferred_encoding: Option, } @@ -35,6 +36,7 @@ mod tests { listen_addresses: some("0.0.0.0:3000"), worker_processes: Some(8), preferred_encoding: None, + base_path: None, } ); assert_eq!( @@ -50,6 +52,7 @@ mod tests { listen_addresses: some("0.0.0.0:3000"), worker_processes: Some(8), preferred_encoding: Some(PreferredEncoding::Brotli), + base_path: None } ); assert_eq!( @@ -65,6 +68,7 @@ mod tests { listen_addresses: some("0.0.0.0:3000"), worker_processes: Some(8), preferred_encoding: Some(PreferredEncoding::Brotli), + base_path: None, } ); } diff --git a/martin/src/srv/tiles_info.rs b/martin/src/srv/tiles_info.rs index e8445f82e..049a27c44 100755 --- a/martin/src/srv/tiles_info.rs +++ b/martin/src/srv/tiles_info.rs @@ -9,6 +9,7 @@ use serde::Deserialize; use tilejson::{tilejson, TileJSON}; use crate::source::{Source, TileSources}; +use crate::srv::SrvConfig; #[derive(Deserialize)] pub struct SourceIDsRequest { @@ -26,17 +27,19 @@ async fn get_source_info( req: HttpRequest, path: Path, sources: Data, + srv_config: Data, ) -> ActixResult { let sources = sources.get_sources(&path.source_ids, None)?.0; - // Get `X-REWRITE-URL` header value, and extract its `path` component. - // If the header is not present or cannot be parsed as a URL, return the request path. - let tiles_path = req - .headers() - .get("x-rewrite-url") - .and_then(|v| v.to_str().ok()) - .and_then(|v| v.parse::().ok()) - .map_or_else(|| req.path().to_owned(), |v| v.path().to_owned()); + let tiles_path = if let Some(base_path) = &srv_config.base_path { + format!("{base_path}/{}", path.source_ids) + } else { + req.headers() + .get("x-rewrite-url") + .and_then(|v| v.to_str().ok()) + .and_then(|v| v.parse::().ok()) + .map_or_else(|| req.path().to_owned(), |v| v.path().to_owned()) + }; let query_string = req.query_string(); let path_and_query = if query_string.is_empty() { @@ -155,7 +158,7 @@ pub fn merge_tilejson(sources: &[&dyn Source], tiles_url: String) -> TileJSON { pub mod tests { use std::collections::BTreeMap; - use tilejson::{tilejson, Bounds, VectorLayer}; + use tilejson::{Bounds, VectorLayer}; use super::*; use crate::srv::server::tests::TestSource; diff --git a/martin/src/utils/error.rs b/martin/src/utils/error.rs index 2843eb452..0687356c8 100644 --- a/martin/src/utils/error.rs +++ b/martin/src/utils/error.rs @@ -43,6 +43,9 @@ pub enum MartinError { #[error("Unable to bind to {1}: {0}")] BindingError(io::Error, String), + #[error("Base path must be a valid URL path, and must begin with a '/' symbol, but is '{0}'")] + BasePathError(String), + #[error("Unable to load config file {}: {0}", .1.display())] ConfigLoadError(io::Error, PathBuf), diff --git a/martin/src/utils/utilities.rs b/martin/src/utils/utilities.rs index 1bdb177ba..7cc1156b1 100644 --- a/martin/src/utils/utilities.rs +++ b/martin/src/utils/utilities.rs @@ -1,8 +1,12 @@ use std::io::{Read as _, Write as _}; +use actix_web::http::Uri; use flate2::read::GzDecoder; use flate2::write::GzEncoder; +use crate::MartinError::BasePathError; +use crate::MartinResult; + pub fn decode_gzip(data: &[u8]) -> Result, std::io::Error> { let mut decoder = GzDecoder::new(data); let mut decompressed = Vec::new(); @@ -28,3 +32,34 @@ pub fn encode_brotli(data: &[u8]) -> Result, std::io::Error> { encoder.write_all(data)?; Ok(encoder.into_inner()) } + +pub fn parse_base_path(path: &str) -> MartinResult { + if !path.starts_with('/') { + return Err(BasePathError(path.to_string())); + } + if let Ok(uri) = path.parse::() { + return Ok(uri.path().trim_end_matches('/').to_string()); + } + Err(BasePathError(path.to_string())) +} + +#[cfg(test)] +pub mod tests { + use crate::utils::parse_base_path; + #[test] + fn test_parse_base_path() { + for (path, expected) in [ + ("/", Some("")), + ("//", Some("")), + ("/foo/bar", Some("/foo/bar")), + ("/foo/bar/", Some("/foo/bar")), + ("", None), + ("foo/bar", None), + ] { + match expected { + Some(v) => assert_eq!(v, parse_base_path(path).unwrap()), + None => assert!(parse_base_path(path).is_err()), + } + } + } +} From b492145bc8fffa5ad79afa33a1bf16982eda1754 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Feb 2024 02:31:47 +0000 Subject: [PATCH 035/164] chore(deps): Bump log from 0.4.20 to 0.4.21 (#1221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [log](https://github.com/rust-lang/log) from 0.4.20 to 0.4.21.
Changelog

Sourced from log's changelog.

[0.4.21] - 2024-02-27

What's Changed

New Contributors

Commits
  • 3ccdc28 Merge pull request #617 from rust-lang/cargo/0.4.21
  • 6153cb2 prepare for 0.4.21 release
  • f0f7494 Merge pull request #613 from rust-lang/feat/kv-cleanup
  • 2b220bf clean up structured logging example
  • 646e9ab use original Visitor name for VisitValue
  • cf85c38 add needed subfeatures to kv_unstable
  • 73e9539 fix up capturing of :err
  • 31bb4b0 move error macros together
  • ad91711 support field shorthand in macros
  • 90a347b restore removed APIs as deprecated
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=log&package-manager=cargo&previous-version=0.4.20&new-version=0.4.21)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4dbb58982..ab1e50629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2086,9 +2086,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "martin" From fcaffcbe49e542c66a38ba2567b8256efc9f336e Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 29 Feb 2024 20:56:48 -0500 Subject: [PATCH 036/164] Fix martin `--auto-bounds` silently ignored with `--config` (#1223) When starting martin with both `--auto-bounds` and `--config`, the auto-bounds param was silently ignored, but now it will notify of the override. Also includes a few minor formatting changes --- Cargo.lock | 1 + martin/Cargo.toml | 5 +++-- martin/src/args/pg.rs | 32 +++++++++++++++++++++----------- martin/src/args/srv.rs | 4 ++-- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab1e50629..f042f3f27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2106,6 +2106,7 @@ dependencies = [ "criterion", "ctor", "deadpool-postgres", + "enum-display", "env_logger", "flate2", "futures", diff --git a/martin/Cargo.toml b/martin/Cargo.toml index 2f02e2c23..874f95d43 100644 --- a/martin/Cargo.toml +++ b/martin/Cargo.toml @@ -79,11 +79,13 @@ bit-set = { workspace = true, optional = true } brotli.workspace = true clap.workspace = true deadpool-postgres = { workspace = true, optional = true } +enum-display.workspace = true env_logger.workspace = true flate2.workspace = true futures.workspace = true itertools.workspace = true json-patch = { workspace = true, optional = true } +lambda-web = { workspace = true, optional = true } log.workspace = true martin-tile-utils.workspace = true mbtiles = { workspace = true, optional = true } @@ -92,8 +94,8 @@ num_cpus.workspace = true pbf_font_tools = { workspace = true, optional = true } pmtiles = { workspace = true, optional = true } postgis = { workspace = true, optional = true } -postgres-protocol = { workspace = true, optional = true } postgres = { workspace = true, optional = true } +postgres-protocol = { workspace = true, optional = true } regex.workspace = true rustls-native-certs.workspace = true rustls-pemfile.workspace = true @@ -110,7 +112,6 @@ tilejson.workspace = true tokio = { workspace = true, features = ["io-std"] } tokio-postgres-rustls = { workspace = true, optional = true } url.workspace = true -lambda-web = { workspace = true, optional = true } [dev-dependencies] cargo-husky.workspace = true diff --git a/martin/src/args/pg.rs b/martin/src/args/pg.rs index a0da3a005..26f0b8950 100644 --- a/martin/src/args/pg.rs +++ b/martin/src/args/pg.rs @@ -1,6 +1,7 @@ use std::time::Duration; use clap::ValueEnum; +use enum_display::EnumDisplay; use log::{info, warn}; use serde::{Deserialize, Serialize}; @@ -13,8 +14,11 @@ use crate::utils::{OptBoolObj, OptOneMany}; // Must match the help string for BoundsType::Quick pub const DEFAULT_BOUNDS_TIMEOUT: Duration = Duration::from_secs(5); -#[derive(PartialEq, Eq, Default, Debug, Clone, Copy, Serialize, Deserialize, ValueEnum)] +#[derive( + PartialEq, Eq, Default, Debug, Clone, Copy, Serialize, Deserialize, ValueEnum, EnumDisplay, +)] #[serde(rename_all = "lowercase")] +#[enum_display(case = "Kebab")] pub enum BoundsCalcType { /// Compute table geometry bounds, but abort if it takes longer than 5 seconds. #[default] @@ -37,7 +41,7 @@ pub struct PgArgs { /// If a spatial PG table has SRID 0, then this default SRID will be used as a fallback. #[arg(short, long)] pub default_srid: Option, - #[arg(help = format!("Maximum Postgres connections pool size [DEFAULT: {}]", POOL_SIZE_DEFAULT), short, long)] + #[arg(help = format!("Maximum Postgres connections pool size [DEFAULT: {POOL_SIZE_DEFAULT}]"), short, long)] pub pool_size: Option, /// Limit the number of features in a tile from a PG table source. #[arg(short, long)] @@ -76,29 +80,35 @@ impl PgArgs { } } + /// Apply CLI parameters from `self` to the configuration loaded from the config file `pg_config` pub fn override_config<'a>(self, pg_config: &mut OptOneMany, env: &impl Env<'a>) { - if self.default_srid.is_some() { - info!("Overriding configured default SRID to {} on all Postgres connections because of a CLI parameter", self.default_srid.unwrap()); + if let Some(default_srid) = self.default_srid { + info!("Overriding configured default SRID to {default_srid} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { c.default_srid = self.default_srid; }); } - if self.pool_size.is_some() { - info!("Overriding configured pool size to {} on all Postgres connections because of a CLI parameter", self.pool_size.unwrap()); + if let Some(pool_size) = self.pool_size { + info!("Overriding configured pool size to {pool_size} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { c.pool_size = self.pool_size; }); } - if self.max_feature_count.is_some() { - info!("Overriding maximum feature count to {} on all Postgres connections because of a CLI parameter", self.max_feature_count.unwrap()); + if let Some(auto_bounds) = self.auto_bounds { + info!("Overriding auto_bounds to {auto_bounds} on all Postgres connections because of a CLI parameter"); + pg_config.iter_mut().for_each(|c| { + c.auto_bounds = self.auto_bounds; + }); + } + if let Some(max_feature_count) = self.max_feature_count { + info!("Overriding maximum feature count to {max_feature_count} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { c.max_feature_count = self.max_feature_count; }); } - - if self.ca_root_file.is_some() { + if let Some(ref ca_root_file) = self.ca_root_file { info!("Overriding root certificate file to {} on all Postgres connections because of a CLI parameter", - self.ca_root_file.as_ref().unwrap().display()); + ca_root_file.display()); pg_config.iter_mut().for_each(|c| { c.ssl_certificates.ssl_root_cert = self.ca_root_file.clone(); }); diff --git a/martin/src/args/srv.rs b/martin/src/args/srv.rs index a3eddb725..ac07e755a 100644 --- a/martin/src/args/srv.rs +++ b/martin/src/args/srv.rs @@ -6,9 +6,9 @@ use crate::srv::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; #[derive(clap::Args, Debug, PartialEq, Default)] #[command(about, version)] pub struct SrvArgs { - #[arg(help = format!("Connection keep alive timeout. [DEFAULT: {}]", KEEP_ALIVE_DEFAULT), short, long)] + #[arg(help = format!("Connection keep alive timeout. [DEFAULT: {KEEP_ALIVE_DEFAULT}]"), short, long)] pub keep_alive: Option, - #[arg(help = format!("The socket address to bind. [DEFAULT: {}]", LISTEN_ADDRESSES_DEFAULT), short, long)] + #[arg(help = format!("The socket address to bind. [DEFAULT: {LISTEN_ADDRESSES_DEFAULT}]"), short, long)] pub listen_addresses: Option, /// Set TileJSON URL path prefix, ignoring X-Rewrite-URL header. Must begin with a `/`. Examples: `/`, `/tiles` #[arg(long)] From b58ca4f5218296c91806575f6e5a959261616f82 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 29 Feb 2024 23:25:08 -0500 Subject: [PATCH 037/164] Refactor to ensure values are not forgotten (#1224) --- martin/src/args/pg.rs | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/martin/src/args/pg.rs b/martin/src/args/pg.rs index 26f0b8950..d3224672d 100644 --- a/martin/src/args/pg.rs +++ b/martin/src/args/pg.rs @@ -82,35 +82,44 @@ impl PgArgs { /// Apply CLI parameters from `self` to the configuration loaded from the config file `pg_config` pub fn override_config<'a>(self, pg_config: &mut OptOneMany, env: &impl Env<'a>) { - if let Some(default_srid) = self.default_srid { - info!("Overriding configured default SRID to {default_srid} on all Postgres connections because of a CLI parameter"); + // This ensures that if a new parameter is added to the struct, it will not be forgotten here + let Self { + default_srid, + pool_size, + auto_bounds, + max_feature_count, + ca_root_file, + } = self; + + if let Some(value) = default_srid { + info!("Overriding configured default SRID to {value} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { - c.default_srid = self.default_srid; + c.default_srid = default_srid; }); } - if let Some(pool_size) = self.pool_size { - info!("Overriding configured pool size to {pool_size} on all Postgres connections because of a CLI parameter"); + if let Some(value) = pool_size { + info!("Overriding configured pool size to {value} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { - c.pool_size = self.pool_size; + c.pool_size = pool_size; }); } - if let Some(auto_bounds) = self.auto_bounds { - info!("Overriding auto_bounds to {auto_bounds} on all Postgres connections because of a CLI parameter"); + if let Some(value) = auto_bounds { + info!("Overriding auto_bounds to {value} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { - c.auto_bounds = self.auto_bounds; + c.auto_bounds = auto_bounds; }); } - if let Some(max_feature_count) = self.max_feature_count { - info!("Overriding maximum feature count to {max_feature_count} on all Postgres connections because of a CLI parameter"); + if let Some(value) = max_feature_count { + info!("Overriding maximum feature count to {value} on all Postgres connections because of a CLI parameter"); pg_config.iter_mut().for_each(|c| { - c.max_feature_count = self.max_feature_count; + c.max_feature_count = max_feature_count; }); } - if let Some(ref ca_root_file) = self.ca_root_file { + if let Some(ref value) = ca_root_file { info!("Overriding root certificate file to {} on all Postgres connections because of a CLI parameter", - ca_root_file.display()); + value.display()); pg_config.iter_mut().for_each(|c| { - c.ssl_certificates.ssl_root_cert = self.ca_root_file.clone(); + c.ssl_certificates.ssl_root_cert = ca_root_file.clone(); }); } From 4b32ae072b570d1c32bf57dc2f9b8455c35c9156 Mon Sep 17 00:00:00 2001 From: Kian-Meng Ang Date: Sun, 3 Mar 2024 15:54:01 +0800 Subject: [PATCH 038/164] Fix typos (#1225) Found via `typos --hidden --format brief` --- martin-tile-utils/Cargo.toml | 2 +- martin/src/utils/rectangle.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/martin-tile-utils/Cargo.toml b/martin-tile-utils/Cargo.toml index 90d39ce7d..ee910c2b5 100644 --- a/martin-tile-utils/Cargo.toml +++ b/martin-tile-utils/Cargo.toml @@ -4,7 +4,7 @@ lints.workspace = true name = "martin-tile-utils" version = "0.4.1" authors = ["Yuri Astrakhan ", "MapLibre contributors"] -description = "Utilites to help with map tile processing, such as type and compression detection. Used by the MapLibre's Martin tile server." +description = "Utilities to help with map tile processing, such as type and compression detection. Used by the MapLibre's Martin tile server." keywords = ["maps", "tiles", "mvt", "tileserver"] categories = ["science::geo", "parsing"] exclude = [ diff --git a/martin/src/utils/rectangle.rs b/martin/src/utils/rectangle.rs index 738d42011..9d42902e9 100644 --- a/martin/src/utils/rectangle.rs +++ b/martin/src/utils/rectangle.rs @@ -118,7 +118,7 @@ mod tests { } #[test] - fn test_tile_range_is_ovelapping() { + fn test_tile_range_is_overlapping() { let r1 = TileRect::new(0, 0, 0, 0, 0); let r2 = TileRect::new(0, 0, 0, 0, 0); assert!(r1.is_overlapping(&r2)); From 7c14a1528c1cabe906551acb28f53eb11e0ec4b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 02:53:20 +0000 Subject: [PATCH 039/164] chore(deps): Bump rustls-pemfile from 2.1.0 to 2.1.1 (#1226) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rustls-pemfile](https://github.com/rustls/pemfile) from 2.1.0 to 2.1.1.
Release notes

Sourced from rustls-pemfile's releases.

2.1.1

Headlines

  • Leading whitespace in PEM document bodies is now trimmed in addition to trailing whitespace.

What's Changed

Full Changelog: https://github.com/rustls/pemfile/compare/v/2.1.0...v/2.1.1

Commits
  • 77a6c99 Cargo: version 2.1.0 -> 2.1.1
  • 09a08fd proj: add Cargo.lock, use --locked in CI
  • 95152b4 pemfile: also trim leading contiguous content whitespace
  • fc3414f lib: clean up no_std and use of std in test code
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls-pemfile&package-manager=cargo&previous-version=2.1.0&new-version=2.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f042f3f27..d6e47c30c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2129,7 +2129,7 @@ dependencies = [ "regex", "rustls 0.22.2", "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.0", + "rustls-pemfile 2.1.1", "semver", "serde", "serde_json", @@ -3333,7 +3333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.0", + "rustls-pemfile 2.1.1", "rustls-pki-types", "schannel", "security-framework", @@ -3350,9 +3350,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" dependencies = [ "base64 0.21.7", "rustls-pki-types", From c0ec365d5c13444ddea89bd50b51422df4072885 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 4 Mar 2024 02:55:21 -0500 Subject: [PATCH 040/164] Added a test for schema.table.column containing special chars (#1222) This just adds a test for the unusual case of a table with quotes, spaces, and dots in their identifiers. Another similar test should be added for functions. --- martin/tests/pg_server_test.rs | 3 + martin/tests/pg_table_source_test.rs | 3 + tests/expected/auto/catalog_auto.json | 4 ++ tests/expected/auto/save_config.yaml | 14 ++++ .../martin-cp/flat-with-hash_save_config.yaml | 14 ++++ .../expected/martin-cp/flat_save_config.yaml | 14 ++++ .../martin-cp/normalized_save_config.yaml | 14 ++++ tests/fixtures/tables/SpacesAndQuotes.sql | 64 +++++++++++++++++++ 8 files changed, 130 insertions(+) create mode 100644 tests/fixtures/tables/SpacesAndQuotes.sql diff --git a/martin/tests/pg_server_test.rs b/martin/tests/pg_server_test.rs index c63c11a7d..acfd53921 100644 --- a/martin/tests/pg_server_test.rs +++ b/martin/tests/pg_server_test.rs @@ -57,6 +57,9 @@ postgres: fonts: {} sprites: {} tiles: + ".-Points---quote": + content_type: application/x-protobuf + description: Escaping test table MixPoints: content_type: application/x-protobuf description: a description from comment on table diff --git a/martin/tests/pg_table_source_test.rs b/martin/tests/pg_table_source_test.rs index 99043943c..0ed740751 100644 --- a/martin/tests/pg_table_source_test.rs +++ b/martin/tests/pg_table_source_test.rs @@ -18,6 +18,9 @@ async fn table_source() { let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await; assert_yaml_snapshot!(mock.0.tiles.get_catalog(), @r###" --- + ".-Points---quote": + content_type: application/x-protobuf + description: Escaping test table MixPoints: content_type: application/x-protobuf description: a description from comment on table diff --git a/tests/expected/auto/catalog_auto.json b/tests/expected/auto/catalog_auto.json index fd502f77f..85dd21e49 100644 --- a/tests/expected/auto/catalog_auto.json +++ b/tests/expected/auto/catalog_auto.json @@ -1,5 +1,9 @@ { "tiles": { + ".-Points---quote": { + "content_type": "application/x-protobuf", + "description": "Escaping test table" + }, "MixPoints": { "content_type": "application/x-protobuf", "description": "a description from comment on table" diff --git a/tests/expected/auto/save_config.yaml b/tests/expected/auto/save_config.yaml index 20acee04f..5af8c786f 100644 --- a/tests/expected/auto/save_config.yaml +++ b/tests/expected/auto/save_config.yaml @@ -4,6 +4,20 @@ postgres: auto_bounds: calc auto_publish: true tables: + .-Points---quote: + schema: '"Quotes'' and Space.Dot.' + table: . Points" 'quote + srid: 4326 + geometry_column: . "Geom" + bounds: + - -170.94984639004662 + - -84.20025580733805 + - 167.70892858284475 + - 74.23573284753762 + geometry_type: POINT + properties: + ''' id ''': int4 + '.namE ': text MixPoints: schema: MixedCase table: MixPoints diff --git a/tests/expected/martin-cp/flat-with-hash_save_config.yaml b/tests/expected/martin-cp/flat-with-hash_save_config.yaml index bd281bc40..022beec82 100644 --- a/tests/expected/martin-cp/flat-with-hash_save_config.yaml +++ b/tests/expected/martin-cp/flat-with-hash_save_config.yaml @@ -3,6 +3,20 @@ postgres: auto_bounds: calc auto_publish: true tables: + .-Points---quote: + schema: '"Quotes'' and Space.Dot.' + table: . Points" 'quote + srid: 4326 + geometry_column: . "Geom" + bounds: + - -170.94984639004662 + - -84.20025580733805 + - 167.70892858284475 + - 74.23573284753762 + geometry_type: POINT + properties: + ''' id ''': int4 + '.namE ': text MixPoints: schema: MixedCase table: MixPoints diff --git a/tests/expected/martin-cp/flat_save_config.yaml b/tests/expected/martin-cp/flat_save_config.yaml index bd281bc40..022beec82 100644 --- a/tests/expected/martin-cp/flat_save_config.yaml +++ b/tests/expected/martin-cp/flat_save_config.yaml @@ -3,6 +3,20 @@ postgres: auto_bounds: calc auto_publish: true tables: + .-Points---quote: + schema: '"Quotes'' and Space.Dot.' + table: . Points" 'quote + srid: 4326 + geometry_column: . "Geom" + bounds: + - -170.94984639004662 + - -84.20025580733805 + - 167.70892858284475 + - 74.23573284753762 + geometry_type: POINT + properties: + ''' id ''': int4 + '.namE ': text MixPoints: schema: MixedCase table: MixPoints diff --git a/tests/expected/martin-cp/normalized_save_config.yaml b/tests/expected/martin-cp/normalized_save_config.yaml index bd281bc40..022beec82 100644 --- a/tests/expected/martin-cp/normalized_save_config.yaml +++ b/tests/expected/martin-cp/normalized_save_config.yaml @@ -3,6 +3,20 @@ postgres: auto_bounds: calc auto_publish: true tables: + .-Points---quote: + schema: '"Quotes'' and Space.Dot.' + table: . Points" 'quote + srid: 4326 + geometry_column: . "Geom" + bounds: + - -170.94984639004662 + - -84.20025580733805 + - 167.70892858284475 + - 74.23573284753762 + geometry_type: POINT + properties: + ''' id ''': int4 + '.namE ': text MixPoints: schema: MixedCase table: MixPoints diff --git a/tests/fixtures/tables/SpacesAndQuotes.sql b/tests/fixtures/tables/SpacesAndQuotes.sql new file mode 100644 index 000000000..a8f83637f --- /dev/null +++ b/tests/fixtures/tables/SpacesAndQuotes.sql @@ -0,0 +1,64 @@ +DROP SCHEMA IF EXISTS """Quotes' and Space.Dot." CASCADE; +CREATE SCHEMA """Quotes' and Space.Dot."; + +CREATE TABLE """Quotes' and Space.Dot.".". Points"" 'quote" +( + "' id '" SERIAL PRIMARY KEY, + ".namE " TEXT, + ". ""Geom""" GEOMETRY(POINT, 4326) +); + +-- INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" +-- SELECT generate_series(1, 3), +-- md5(random()::text), +-- (ST_DUMP(ST_GENERATEPOINTS(st_transform(st_tileenvelope(18, 235085, 122323), 4326), 3))).Geom; +-- INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" +-- SELECT generate_series(4, 30), +-- md5(random()::text), +-- (ST_DUMP(ST_GENERATEPOINTS(st_transform(st_tileenvelope(0, 0, 0), 4326), 27))).Geom; +-- +-- To dump the data above, uncomment code the above, comment the INSERT code bellow, and run: +-- just restart +-- just pg_dump --data-only --inserts --rows-per-insert=100 --table="""Quotes' and Space.Dot.".". Points"" 'quote" + +INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" +values (1, '02daedc70702ec68753fde38351f5d9d', '0101000020E610000050C4D38CE9DA61401EFC0EC7C3DA2740'), + (2, '7418427ba8a960c3661235f47cc13d46', '0101000020E6100000CC2F4170E9DA6140DEDB02B581DA2740'), + (3, 'd5a11dee7203a09442168eec74c7bea8', '0101000020E6100000008E66E9E6DA614059944356B4DA2740'), + (4, '2368bbc7ba9dcb274f5465ef10ffad1f', '0101000020E6100000B43E295A4CEE6140265634327FFB52C0'), + (5, '140cf506fdf19e0cd451bc0da0ad8b50', '0101000020E610000016551B51B0B033407C3AE7BBE91B3140'), + (6, 'e8d7e0e5b421079203c2f1a84f62d029', '0101000020E61000007CD7F65C2360604055855E6358954F40'), + (7, 'eeea13624e9c7ba34ad7210498061fd9', '0101000020E6100000B5E96FF565874D40328E73C500A951C0'), + (8, '32b066ccc705875a6ba04a4f8fe6ef26', '0101000020E61000002AAF4124655E65C06C3CC08BDE884040'), + (9, '7c304793df1ff378d775106b31a14bea', '0101000020E6100000D0CAD2D7A9790DC000065E0B160843C0'), + (10, 'b936821caa8237e331f26ddf5165784b', '0101000020E6100000CA5016BD8E9563403E9A0372E7932E40'), + (11, '434749fa23d9302d475f7ec190981958', '0101000020E61000004AA2B720B23E45C0E94EBCDB72014740'), + (12, 'fb78b6759036417511bc13e47bc25db8', '0101000020E6100000A35AEF6470684B4006C609806BC74440'), + (13, '730b7f416d91573e5a5d4c32673c716e', '0101000020E61000003BF842670F9B484030FA0AA450DE4D40'), + (14, 'e51f27140b07abdf60b6b0e86271446d', '0101000020E6100000FC54A712989843C0664EB161D4D943C0'), + (15, '1128b472f9ce87958e2b941f732bde55', '0101000020E6100000DBDDCAA1D80B63C0E84F2B8BC8C63DC0'), + (16, 'ff2d28a9b608cb6ef29751c1b7cefc8b', '0101000020E610000082EA2075B2D26440A2B180EAFCEF52C0'), + (17, '6e0d72a4b999f6f993a86af936fde899', '0101000020E610000028E151D6194825C0FD73E0FC5B8615C0'), + (18, '23afce20fa2dd8d8d1f93014447fdba6', '0101000020E6100000B3376FB629D660C017B1393F168F5240'), + (19, '38cb097c70d2ff71e8c8c02855f04166', '0101000020E6100000F1FCE46A01865540EAE8C01038D852C0'), + (20, 'b82d2222d84deecd38a6187a86fd3514', '0101000020E61000005C4A75FF750661C08012B03D84A5EE3F'), + (21, '9efc50c9da5f0da5040c565b2ba838ce', '0101000020E61000008037CA00BD693E4018F8D89279004FC0'), + (22, 'a2dbb89488297ad2c6af9460980479a3', '0101000020E610000092D0FE8AAFF664401EE866F4AF5D3B40'), + (23, '09e3dc819cfd6344bce527be0ef29086', '0101000020E6100000A6235C70F6C053C0C0E86095B8AA0940'), + (24, 'fd59276e15c0577881118df65e3b2b9a', '0101000020E610000078B4CD86D3444240FF879F9C924B4840'), + (25, 'a8a47755660da683c7817634797515e8', '0101000020E6100000B2E72AE85C0143C04487454A6F1F4FC0'), + (26, 'b44bf3139cc2bab31a48b165f63dfaa3', '0101000020E61000008224AB2C6A3364C00C1DD30085CF32C0'), + (27, '48b2e0ae68663d5dc003f20e2cc9dba1', '0101000020E6100000981F49E883D45B405CE9B4808E2637C0'), + (28, '5e27d8b2cbee33e3196aae5e5ec15db2', '0101000020E61000001036BD0CF11F1440600218267D833740'), + (29, 'fd0775c59700ac8c1982aa3efe6cb0c7', '0101000020E6100000D6CF48A3E1A9464077D6BBFDD00C55C0'), + (30, '404175d17b08782edc9d316c378adc86', '0101000020E6100000F9B5A5ADB7265BC0EE07F81F2F284840'); + +CREATE INDEX ON """Quotes' and Space.Dot.".". Points"" 'quote" USING GIST (". ""Geom"""); + +DO $do$ BEGIN + EXECUTE 'COMMENT ON TABLE """Quotes'' and Space.Dot.".". Points"" ''quote" IS $tj$' || $$ + { + "description": "Escaping test table" + } + $$::json || '$tj$'; +END $do$; From 74a5437e4aea0e39964665df7882418d247951e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:45:00 +0000 Subject: [PATCH 041/164] chore(deps): Bump mio from 0.8.10 to 0.8.11 (#1228) Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.10 to 0.8.11.
Changelog

Sourced from mio's changelog.

0.8.11

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mio&package-manager=cargo&previous-version=0.8.10&new-version=0.8.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6e47c30c..d27c22ad5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2248,9 +2248,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", From d3500e93e4e48f6b41fe10d954bb242326a55767 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 02:31:57 +0000 Subject: [PATCH 042/164] chore(deps): Bump env_logger from 0.11.2 to 0.11.3 (#1232) Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.2 to 0.11.3.
Release notes

Sourced from env_logger's releases.

v0.11.3

[0.11.3] - 2024-03-05

Features

  • Experimental support for key-value logging behind unstable-kv
Changelog

Sourced from env_logger's changelog.

[0.11.3] - 2024-03-05

Features

  • Experimental support for key-value logging behind unstable-kv
Commits
  • 98ce803 chore: Release
  • 7a16130 docs: Update changelog
  • e55af6f Merge pull request #137 from tmccombs/structured
  • f6e2d45 feat(kv): Use now-stable kv feature of log crate
  • 9f4a33a feat(kv): Add styling for key in default format
  • 9d26ad5 feat: Add support for Key-Value data in log records
  • 8962096 Merge pull request #314 from rust-cli/renovate/pre-commit-action-3.x
  • 4127228 chore(deps): update pre-commit/action action to v3.0.1
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=env_logger&package-manager=cargo&previous-version=0.11.2&new-version=0.11.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d27c22ad5..2c06b1f96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1173,9 +1173,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ "anstream", "anstyle", From 12d115b8ee256d863e21a18c7aedd7e95e085bda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Mar 2024 03:09:54 +0000 Subject: [PATCH 043/164] chore(deps): Bump clap from 4.5.1 to 4.5.2 (#1235) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.1 to 4.5.2.
Release notes

Sourced from clap's releases.

v4.5.2

[4.5.2] - 2024-03-06

Fixes

  • (macros) Silence a warning
Changelog

Sourced from clap's changelog.

[4.5.2] - 2024-03-06

Fixes

  • (macros) Silence a warning
Commits
  • f65d421 chore: Release
  • 886b272 docs: Update changelog
  • 3ba4297 Merge pull request #5386 from amaanq/static-var-name
  • 2aea950 fix: Use SCREAMING_SNAKE_CASE for static variable authors
  • 690f555 Merge pull request #5382 from clap-rs/renovate/pre-commit-action-3.x
  • a2aa644 chore(deps): update compatible (dev) (#5381)
  • c233de5 chore(deps): update pre-commit/action action to v3.0.1
  • d0028d7 Merge pull request #5371 from BenWiederhake/dev-fix-link-command-trailing_var...
  • 0076cac fix(builder): Don't doc-link to undocumented item
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.1&new-version=4.5.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c06b1f96..6d0974dfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,9 +699,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" dependencies = [ "clap_builder", "clap_derive", @@ -709,9 +709,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", From 656728cde113181444ad8bd8d429cefd42163f03 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 9 Mar 2024 08:30:57 +0800 Subject: [PATCH 044/164] Add test for function with special character (#1231) --- martin/tests/pg_server_test.rs | 3 ++ martin/tests/pg_table_source_test.rs | 3 ++ tests/expected/auto/catalog_auto.json | 4 +++ tests/expected/auto/save_config.yaml | 3 ++ .../martin-cp/flat-with-hash_save_config.yaml | 3 ++ .../expected/martin-cp/flat_save_config.yaml | 3 ++ .../martin-cp/normalized_save_config.yaml | 3 ++ .../functions/function_special_characters.sql | 32 +++++++++++++++++++ 8 files changed, 54 insertions(+) create mode 100644 tests/fixtures/functions/function_special_characters.sql diff --git a/martin/tests/pg_server_test.rs b/martin/tests/pg_server_test.rs index acfd53921..e1a65780a 100644 --- a/martin/tests/pg_server_test.rs +++ b/martin/tests/pg_server_test.rs @@ -57,6 +57,9 @@ postgres: fonts: {} sprites: {} tiles: + "-function.withweired---_-characters": + content_type: application/x-protobuf + description: a function source with special characters ".-Points---quote": content_type: application/x-protobuf description: Escaping test table diff --git a/martin/tests/pg_table_source_test.rs b/martin/tests/pg_table_source_test.rs index 0ed740751..29f93936a 100644 --- a/martin/tests/pg_table_source_test.rs +++ b/martin/tests/pg_table_source_test.rs @@ -18,6 +18,9 @@ async fn table_source() { let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await; assert_yaml_snapshot!(mock.0.tiles.get_catalog(), @r###" --- + "-function.withweired---_-characters": + content_type: application/x-protobuf + description: a function source with special characters ".-Points---quote": content_type: application/x-protobuf description: Escaping test table diff --git a/tests/expected/auto/catalog_auto.json b/tests/expected/auto/catalog_auto.json index 85dd21e49..d3b77b680 100644 --- a/tests/expected/auto/catalog_auto.json +++ b/tests/expected/auto/catalog_auto.json @@ -1,5 +1,9 @@ { "tiles": { + "-function.withweired---_-characters": { + "content_type": "application/x-protobuf", + "description": "a function source with special characters" + }, ".-Points---quote": { "content_type": "application/x-protobuf", "description": "Escaping test table" diff --git a/tests/expected/auto/save_config.yaml b/tests/expected/auto/save_config.yaml index 5af8c786f..a46b295f4 100644 --- a/tests/expected/auto/save_config.yaml +++ b/tests/expected/auto/save_config.yaml @@ -165,6 +165,9 @@ postgres: properties: gid: int4 functions: + -function.withweired---_-characters: + schema: public + function: '"function.withweired$*;_ characters' function_Mixed_Name: schema: MixedCase function: function_Mixed_Name diff --git a/tests/expected/martin-cp/flat-with-hash_save_config.yaml b/tests/expected/martin-cp/flat-with-hash_save_config.yaml index 022beec82..bdbe22a96 100644 --- a/tests/expected/martin-cp/flat-with-hash_save_config.yaml +++ b/tests/expected/martin-cp/flat-with-hash_save_config.yaml @@ -164,6 +164,9 @@ postgres: properties: gid: int4 functions: + -function.withweired---_-characters: + schema: public + function: '"function.withweired$*;_ characters' function_Mixed_Name: schema: MixedCase function: function_Mixed_Name diff --git a/tests/expected/martin-cp/flat_save_config.yaml b/tests/expected/martin-cp/flat_save_config.yaml index 022beec82..bdbe22a96 100644 --- a/tests/expected/martin-cp/flat_save_config.yaml +++ b/tests/expected/martin-cp/flat_save_config.yaml @@ -164,6 +164,9 @@ postgres: properties: gid: int4 functions: + -function.withweired---_-characters: + schema: public + function: '"function.withweired$*;_ characters' function_Mixed_Name: schema: MixedCase function: function_Mixed_Name diff --git a/tests/expected/martin-cp/normalized_save_config.yaml b/tests/expected/martin-cp/normalized_save_config.yaml index 022beec82..bdbe22a96 100644 --- a/tests/expected/martin-cp/normalized_save_config.yaml +++ b/tests/expected/martin-cp/normalized_save_config.yaml @@ -164,6 +164,9 @@ postgres: properties: gid: int4 functions: + -function.withweired---_-characters: + schema: public + function: '"function.withweired$*;_ characters' function_Mixed_Name: schema: MixedCase function: function_Mixed_Name diff --git a/tests/fixtures/functions/function_special_characters.sql b/tests/fixtures/functions/function_special_characters.sql new file mode 100644 index 000000000..aabdfbb95 --- /dev/null +++ b/tests/fixtures/functions/function_special_characters.sql @@ -0,0 +1,32 @@ +DROP FUNCTION IF EXISTS "public"."""function.withweired$*;_ characters"; + +CREATE OR REPLACE FUNCTION "public"."""function.withweired$*;_ characters"("Z" integer, x integer, y integer) +RETURNS TABLE("mVt" bytea, key text) AS $$ + SELECT mvt, md5(mvt) as key FROM ( + SELECT ST_AsMVT(tile, 'public."function.withweired$*;_ characters', 4096, 'geom') as mvt FROM ( + SELECT + ST_AsMVTGeom( + ST_Transform(ST_CurveToLine("Geom"), 3857), + ST_TileEnvelope("Z", x, y), + 4096, 64, true) AS geom + FROM "MixedCase"."MixPoints" + WHERE "Geom" && ST_Transform(ST_TileEnvelope("Z", x, y), 4326) + ) as tile WHERE geom IS NOT NULL) src +$$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE; + +DO $do$ BEGIN + EXECUTE 'COMMENT ON FUNCTION "public"."""function.withweired$*;_ characters" IS $tj$' || $$ + { + "description": "a function source with special characters", + "vector_layers": [ + { + "id": "public.\"function.withweired$*;_ characters", + "fields": { + "TABLE": "", + "Geom": "" + } + } + ] + } + $$::json || '$tj$'; +END $do$; From ac0c4571c7e11280304db7108f39528430d4731e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Mar 2024 03:16:15 -0500 Subject: [PATCH 045/164] chore(deps): Bump softprops/action-gh-release from 1 to 2 (#1239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
Release notes

Sourced from softprops/action-gh-release's releases.

v2.0.0

  • update actions.yml declaration to node20 to address warnings
Changelog

Sourced from softprops/action-gh-release's changelog.

0.1.12

  • fix bug leading to empty strings subsituted for inputs users don't provide breaking api calls #144
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c49249597..a1ad98875 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -722,7 +722,7 @@ jobs: - name: Publish if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: draft: true files: 'target/files/*' From 1c95c60ebd370f788d509f2c479fe87d7da6d81b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 11 Mar 2024 01:14:27 -0400 Subject: [PATCH 046/164] Update lock, insta version deprecation, some test changes (#1240) * Some small test cleanups * A bump to dependencies * Disable sprite generation test - PNGs tests are too flaky * Add an mbtiles copy test for empty diffs --- Cargo.lock | 277 ++++++------ martin/src/pg/tls.rs | 7 +- martin/src/sprites/mod.rs | 12 +- mbtiles/src/copier.rs | 5 +- mbtiles/tests/copy.rs | 425 ++++++++++-------- .../copy__databases@flat__dif_empty.snap | 32 ++ .../copy__databases@hash__dif_empty.snap | 40 ++ .../copy__databases@norm__dif_empty.snap | 71 +++ tests/expected/configured/spr_cmp.png | Bin 787 -> 785 bytes tests/expected/configured/spr_cmp_2x.png | Bin 1569 -> 1567 bytes tests/expected/configured/spr_mysrc.png | Bin 191 -> 189 bytes tests/expected/configured/spr_mysrc_2x.png | Bin 344 -> 344 bytes tests/expected/configured/spr_src1.png | Bin 758 -> 758 bytes 13 files changed, 543 insertions(+), 326 deletions(-) create mode 100644 mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap diff --git a/Cargo.lock b/Cargo.lock index 6d0974dfa..0744241fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -214,9 +214,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -278,9 +278,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -384,7 +384,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -406,7 +406,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -417,7 +417,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -431,11 +431,11 @@ dependencies = [ [[package]] name = "atomic-write-file" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" +checksum = "a8204db279bf648d64fe845bd8840f78b39c8132ed4d6a4194c3b10d4b4cfb0b" dependencies = [ - "nix 0.27.1", + "nix 0.28.0", "rand", ] @@ -562,9 +562,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytecount" @@ -644,10 +644,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.88" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ + "jobserver", "libc", ] @@ -657,17 +658,23 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -728,7 +735,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -891,9 +898,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ "crossbeam-utils", ] @@ -961,7 +968,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -985,7 +992,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -996,7 +1003,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -1158,7 +1165,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -1478,7 +1485,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -1581,7 +1588,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.3", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -1634,9 +1641,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1679,9 +1686,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1813,9 +1820,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1836,7 +1843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "indexmap 2.2.3", + "indexmap 2.2.5", "is-terminal", "itoa", "log", @@ -1849,9 +1856,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.35.1" +version = "1.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c985c1bef99cf13c58fade470483d81a2bfe846ebde60ed28cc2dddec2df9e2" +checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" dependencies = [ "console", "lazy_static", @@ -1903,6 +1910,15 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.1" @@ -1911,9 +1927,9 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -2011,19 +2027,18 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libdeflate-sys" -version = "1.19.2" +version = "1.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7654050a14083995afdf189c4d895b59bc6c8195407c24db4df4c3878b3679d" +checksum = "cc9caa76c8cc6ee8c4efcf8f4514a812ebcad3aa7d3b548efe4d26da1203f177" dependencies = [ "cc", - "pkg-config", ] [[package]] name = "libdeflater" -version = "1.19.2" +version = "1.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ae43f79441cf19e744fba2aa762e4b6a9016970137e67d3a45eec96ed11bb27" +checksum = "265a985bd31e5f22e2b2ac107cbed44c6ccf40ae236e46963cd00dd213e4bd03" dependencies = [ "libdeflate-sys", ] @@ -2304,12 +2319,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.4.2", "cfg-if", + "cfg_aliases", "libc", ] @@ -2466,7 +2482,7 @@ dependencies = [ "bitvec", "crossbeam-channel", "filetime", - "indexmap 2.2.3", + "indexmap 2.2.5", "libdeflater", "log", "rayon", @@ -2522,7 +2538,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -2598,22 +2614,22 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -3020,9 +3036,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -3067,9 +3083,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -3096,9 +3112,9 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" dependencies = [ "base64 0.21.7", "bytes", @@ -3236,7 +3252,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.51", + "syn 2.0.52", "unicode-ident", ] @@ -3500,7 +3516,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -3557,7 +3573,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.3", + "indexmap 2.2.5", "serde", "serde_derive", "serde_json", @@ -3574,7 +3590,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -3583,7 +3599,7 @@ version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ - "indexmap 2.2.3", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -3817,7 +3833,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.3", + "indexmap 2.2.5", "log", "memchr", "once_cell", @@ -4031,7 +4047,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -4042,7 +4058,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -4109,9 +4125,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.51" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -4126,20 +4142,20 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -4159,9 +4175,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", @@ -4186,7 +4202,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -4310,7 +4326,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -4456,7 +4472,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -4710,9 +4726,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4733,11 +4749,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4745,24 +4767,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4772,9 +4794,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4782,28 +4804,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -4829,11 +4851,12 @@ dependencies = [ [[package]] name = "whoami" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e" dependencies = [ - "wasm-bindgen", + "redox_syscall", + "wasite", "web-sys", ] @@ -4874,7 +4897,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -4892,7 +4915,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -4912,17 +4935,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.3", - "windows_aarch64_msvc 0.52.3", - "windows_i686_gnu 0.52.3", - "windows_i686_msvc 0.52.3", - "windows_x86_64_gnu 0.52.3", - "windows_x86_64_gnullvm 0.52.3", - "windows_x86_64_msvc 0.52.3", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -4933,9 +4956,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -4945,9 +4968,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -4957,9 +4980,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -4969,9 +4992,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -4981,9 +5004,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -4993,9 +5016,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -5005,9 +5028,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winreg" @@ -5091,7 +5114,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] @@ -5111,7 +5134,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.52", ] [[package]] diff --git a/martin/src/pg/tls.rs b/martin/src/pg/tls.rs index 3b0297a02..9f28fc664 100644 --- a/martin/src/pg/tls.rs +++ b/martin/src/pg/tls.rs @@ -9,6 +9,7 @@ use deadpool_postgres::tokio_postgres::Config; use log::{info, warn}; use regex::Regex; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::crypto::ring::default_provider; use rustls::crypto::{verify_tls12_signature, verify_tls13_signature}; use rustls::pki_types::{CertificateDer, ServerName, UnixTime}; use rustls::{DigitallySignedStruct, Error, SignatureScheme}; @@ -80,7 +81,7 @@ impl ServerCertVerifier for NoCertificateVerification { message, cert, dss, - &rustls::crypto::ring::default_provider().signature_verification_algorithms, + &default_provider().signature_verification_algorithms, ) } @@ -94,12 +95,12 @@ impl ServerCertVerifier for NoCertificateVerification { message, cert, dss, - &rustls::crypto::ring::default_provider().signature_verification_algorithms, + &default_provider().signature_verification_algorithms, ) } fn supported_verify_schemes(&self) -> Vec { - rustls::crypto::ring::default_provider() + default_provider() .signature_verification_algorithms .supported_schemes() } diff --git a/martin/src/sprites/mod.rs b/martin/src/sprites/mod.rs index 7a0fc8cc4..7dce53c82 100644 --- a/martin/src/sprites/mod.rs +++ b/martin/src/sprites/mod.rs @@ -282,10 +282,14 @@ mod tests { let expected = std::fs::read(path.with_extension("png")) .expect("Unable to open expected PNG file, make sure to bless tests with\n cargo test --features bless-tests\n"); - assert_eq!( - png, expected, - "Make sure to run bless if needed:\n cargo test --features bless-tests\n\n{json}", - ); + // The PNG output is too flaky to be reliably used in a test + if png != expected { + warn!("Generated PNG does not match expected PNG, make sure to bless tests with\n cargo test --features bless-tests\n"); + } + // assert_eq!( + // png, expected, + // "Make sure to run bless if needed:\n cargo test --features bless-tests\n\n{json}", + // ); } } } diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index 31b1766ab..69e842ad9 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -249,6 +249,7 @@ impl MbtileCopierInt { ) joinedMD WHERE name != '{AGG_TILES_HASH_IN_DIFF}'" ); + debug!("Copying metadata, taking into account diff file with {sql}"); } else { sql = format!( " @@ -264,10 +265,6 @@ impl MbtileCopierInt { ) joinedMD WHERE name != '{AGG_TILES_HASH}'" ); - } - if self.options.diff_with_file.is_some() { - debug!("Copying metadata, taking into account diff file with {sql}"); - } else { debug!("Copying metadata, and applying the diff file with {sql}"); } } else { diff --git a/mbtiles/tests/copy.rs b/mbtiles/tests/copy.rs index 3f3318524..f81438d85 100644 --- a/mbtiles/tests/copy.rs +++ b/mbtiles/tests/copy.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::str::from_utf8; use ctor::ctor; -use insta::{allow_duplicates, assert_display_snapshot}; +use insta::{allow_duplicates, assert_snapshot}; use itertools::Itertools as _; use log::info; use martin_tile_utils::xyz_to_bbox; @@ -96,12 +96,32 @@ fn shorten(v: MbtTypeCli) -> &'static str { } } +/// Open an `MBTiles` file, returning both the `MBTiles` and the `SqliteConnection`. async fn open(file: &str) -> MbtResult<(Mbtiles, SqliteConnection)> { let mbtiles = Mbtiles::new(file)?; let conn = mbtiles.open().await?; Ok((mbtiles, conn)) } +/// Run [`MbtilesCopier`], the first two params are source and destination [`Mbtiles`] refs, the rest are optional (key => val)* params. +macro_rules! copy { + ($src_path:expr, $dst_path:expr $( , $key:tt => $val:expr )* $(,)?) => {{ + MbtilesCopier { + src_file: $src_path, + dst_file: $dst_path + $(, $key : $val)*, + ..Default::default() + }.run().await.unwrap() + }}; +} + +/// Same as the copy! macro, but with the result dumped. +macro_rules! copy_dump { + ($src_path:expr, $dst_path:expr $( , $key:tt => $val:expr )* $(,)?) => {{ + dump(&mut copy!($src_path, $dst_path $(, $key => $val)*)).await.unwrap() + }}; +} + macro_rules! open { ($function:ident, $($arg:tt)*) => { open!(@"", $function, $($arg)*) @@ -132,20 +152,18 @@ macro_rules! new_file { cn_tmp.execute($sql_meta).await.unwrap(); let (dst_mbt, cn_dst) = open!($function, $($arg)*); - let opt = MbtilesCopier { - src_file: path(&tmp_mbt), - dst_file: path(&dst_mbt), - dst_type_cli: Some($dst_type_cli), - skip_agg_tiles_hash: $skip_agg, - ..Default::default() - }; - opt.run().await.unwrap(); + copy! { + path(&tmp_mbt), + path(&dst_mbt), + dst_type_cli => Some($dst_type_cli), + skip_agg_tiles_hash => $skip_agg, + }; (dst_mbt, cn_dst) }}; } -macro_rules! assert_snapshot { +macro_rules! assert_dump { ($actual_value:expr, $($arg:tt)*) => {{ let mut settings = insta::Settings::clone_current(); settings.set_snapshot_suffix(format!($($arg)*)); @@ -155,8 +173,12 @@ macro_rules! assert_snapshot { } #[derive(Default)] +#[allow(clippy::type_complexity)] struct Databases( - HashMap<(&'static str, MbtTypeCli), (Vec, Mbtiles, SqliteConnection)>, + HashMap< + (&'static str, MbtTypeCli), + (Vec, Mbtiles, Option, SqliteConnection), + >, ); impl Databases { @@ -166,9 +188,10 @@ impl Databases { typ: MbtTypeCli, dump: Vec, mbtiles: Mbtiles, + hash: Option, conn: SqliteConnection, ) { - self.0.insert((name, typ), (dump, mbtiles, conn)); + self.0.insert((name, typ), (dump, mbtiles, hash, conn)); } fn dump(&self, name: &'static str, typ: MbtTypeCli) -> &Vec { &self.0.get(&(name, typ)).unwrap().0 @@ -176,6 +199,12 @@ impl Databases { fn mbtiles(&self, name: &'static str, typ: MbtTypeCli) -> &Mbtiles { &self.0.get(&(name, typ)).unwrap().1 } + fn path(&self, name: &'static str, typ: MbtTypeCli) -> PathBuf { + path(self.mbtiles(name, typ)) + } + fn hash(&self, name: &'static str, typ: MbtTypeCli) -> &str { + self.0.get(&(name, typ)).unwrap().2.as_deref().unwrap() + } } /// Generate a set of databases for testing, and validate them against snapshot files. @@ -188,28 +217,32 @@ fn databases() -> Databases { for &mbt_typ in &[Flat, FlatWithHash, Normalized] { let typ = shorten(mbt_typ); + // ----------------- empty_no_hash ----------------- let (raw_empty_mbt, mut raw_empty_cn) = new_file_no_hash!(databases, mbt_typ, "", "", "{typ}__empty-no-hash"); let dmp = dump(&mut raw_empty_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__empty-no-hash"); - result.add("empty_no_hash", mbt_typ, dmp, raw_empty_mbt, raw_empty_cn); + assert_dump!(&dmp, "{typ}__empty-no-hash"); + result.add( + "empty_no_hash", + mbt_typ, + dmp, + raw_empty_mbt, + None, + raw_empty_cn, + ); + // ----------------- empty ----------------- let (empty_mbt, mut empty_cn) = open!(databases, "{typ}__empty"); - let raw_empty_mbt = result.mbtiles("empty_no_hash", mbt_typ); - let opt = MbtilesCopier { - src_file: path(raw_empty_mbt), - dst_file: path(&empty_mbt), - ..Default::default() - }; - opt.run().await.unwrap(); + copy!(result.path("empty_no_hash", mbt_typ), path(&empty_mbt)); let dmp = dump(&mut empty_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__empty"); + assert_dump!(&dmp, "{typ}__empty"); let hash = empty_mbt.validate(Off, Verify).await.unwrap(); allow_duplicates! { - assert_display_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); + assert_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); } - result.add("empty", mbt_typ, dmp, empty_mbt, empty_cn); + result.add("empty", mbt_typ, dmp, empty_mbt, Some(hash), empty_cn); + // ----------------- v1_no_hash ----------------- let (raw_mbt, mut raw_cn) = new_file_no_hash!( databases, mbt_typ, @@ -218,52 +251,83 @@ fn databases() -> Databases { "{typ}__v1-no-hash" ); let dmp = dump(&mut raw_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__v1-no-hash"); - result.add("v1_no_hash", mbt_typ, dmp, raw_mbt, raw_cn); + assert_dump!(&dmp, "{typ}__v1-no-hash"); + result.add("v1_no_hash", mbt_typ, dmp, raw_mbt, None, raw_cn); + // ----------------- v1 ----------------- let (v1_mbt, mut v1_cn) = open!(databases, "{typ}__v1"); - let raw_mbt = result.mbtiles("v1_no_hash", mbt_typ); - let opt = MbtilesCopier { - src_file: path(raw_mbt), - dst_file: path(&v1_mbt), - ..Default::default() - }; - opt.run().await.unwrap(); + copy!(result.path("v1_no_hash", mbt_typ), path(&v1_mbt)); let dmp = dump(&mut v1_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__v1"); + assert_dump!(&dmp, "{typ}__v1"); let hash = v1_mbt.validate(Off, Verify).await.unwrap(); allow_duplicates! { - assert_display_snapshot!(hash, @"9ED9178D7025276336C783C2B54D6258"); + assert_snapshot!(hash, @"9ED9178D7025276336C783C2B54D6258"); } - result.add("v1", mbt_typ, dmp, v1_mbt, v1_cn); + result.add("v1", mbt_typ, dmp, v1_mbt, Some(hash), v1_cn); + // ----------------- v2 ----------------- let (v2_mbt, mut v2_cn) = new_file!(databases, mbt_typ, METADATA_V2, TILES_V2, "{typ}__v2"); let dmp = dump(&mut v2_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__v2"); + assert_dump!(&dmp, "{typ}__v2"); let hash = v2_mbt.validate(Off, Verify).await.unwrap(); allow_duplicates! { - assert_display_snapshot!(hash, @"3BCDEE3F52407FF1315629298CB99133"); + assert_snapshot!(hash, @"3BCDEE3F52407FF1315629298CB99133"); } - result.add("v2", mbt_typ, dmp, v2_mbt, v2_cn); + result.add("v2", mbt_typ, dmp, v2_mbt, Some(hash), v2_cn); + // ----------------- dif (v1 -> v2) ----------------- let (dif_mbt, mut dif_cn) = open!(databases, "{typ}__dif"); - let v1_mbt = result.mbtiles("v1", mbt_typ); - let v2_mbt = result.mbtiles("v2", mbt_typ); - let opt = MbtilesCopier { - src_file: path(v1_mbt), - dst_file: path(&dif_mbt), - diff_with_file: Some(path(v2_mbt)), - ..Default::default() + copy! { + result.path("v1", mbt_typ), + path(&dif_mbt), + diff_with_file => Some(result.path("v2", mbt_typ)), }; - opt.run().await.unwrap(); let dmp = dump(&mut dif_cn).await.unwrap(); - assert_snapshot!(&dmp, "{typ}__dif"); + assert_dump!(&dmp, "{typ}__dif"); let hash = dif_mbt.validate(Off, Verify).await.unwrap(); allow_duplicates! { - assert_display_snapshot!(hash, @"B86122579EDCDD4C51F3910894FCC1A1"); + assert_snapshot!(hash, @"B86122579EDCDD4C51F3910894FCC1A1"); + } + result.add("dif", mbt_typ, dmp, dif_mbt, Some(hash), dif_cn); + + // ----------------- v1_clone ----------------- + let (v1_clone_mbt, v1_clone_cn) = open!(databases, "{typ}__v1-clone"); + let dmp = copy_dump!(result.path("v1", mbt_typ), path(&v1_clone_mbt)); + let hash = v1_clone_mbt.validate(Off, Verify).await.unwrap(); + allow_duplicates! { + assert_snapshot!(hash, @"9ED9178D7025276336C783C2B54D6258"); + } + result.add( + "v1_clone", + mbt_typ, + dmp, + v1_clone_mbt, + Some(hash), + v1_clone_cn, + ); + + // ----------------- dif_empty (v1 -> v1_clone) ----------------- + let (dif_empty_mbt, mut dif_empty_cn) = open!(databases, "{typ}__dif_empty"); + copy! { + result.path("v1", mbt_typ), + path(&dif_empty_mbt), + diff_with_file => Some(result.path("v1_clone", mbt_typ)), + }; + let dmp = dump(&mut dif_empty_cn).await.unwrap(); + assert_dump!(&dmp, "{typ}__dif_empty"); + let hash = dif_empty_mbt.validate(Off, Verify).await.unwrap(); + allow_duplicates! { + assert_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); } - result.add("dif", mbt_typ, dmp, dif_mbt, dif_cn); + result.add( + "dif_empty", + mbt_typ, + dmp, + dif_empty_mbt, + Some(hash), + dif_empty_cn, + ); } result }) @@ -274,7 +338,7 @@ async fn update() -> MbtResult<()> { let (mbt, mut cn) = new_file_no_hash!(databases, Flat, METADATA_V1, TILES_V1, "update"); mbt.update_metadata(&mut cn, UpdateZoomType::Reset).await?; let dmp = dump(&mut cn).await?; - assert_snapshot!(&dmp, "update"); + assert_dump!(&dmp, "update"); Ok(()) } @@ -291,49 +355,43 @@ async fn convert( let mem = Mbtiles::new(":memory:")?; let (frm_mbt, _frm_cn) = new_file!(convert, frm_type, METADATA_V1, TILES_V1, "{frm}-{to}"); - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - dst_type_cli: Some(dst_type), - ..Default::default() - }; - let dmp = dump(&mut opt.run().await?).await?; - pretty_assert_eq!(databases.dump("v1", dst_type), &dmp); - - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - copy: CopyType::Metadata, - dst_type_cli: Some(dst_type), - ..Default::default() + pretty_assert_eq!( + databases.dump("v1", dst_type), + ©_dump! { + path(&frm_mbt), + path(&mem), + dst_type_cli => Some(dst_type), + } + ); + + let dmp = copy_dump! { + path(&frm_mbt), + path(&mem), + copy => CopyType::Metadata, + dst_type_cli => Some(dst_type), }; - let dmp = dump(&mut opt.run().await?).await?; allow_duplicates! { - assert_snapshot!(dmp, "v1__meta__{to}"); - }; + assert_dump!(dmp, "v1__meta__{to}"); + } - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - copy: CopyType::Tiles, - dst_type_cli: Some(dst_type), - ..Default::default() + let dmp = copy_dump! { + path(&frm_mbt), + path(&mem), + copy => CopyType::Tiles, + dst_type_cli => Some(dst_type), }; - let dmp = dump(&mut opt.run().await?).await?; allow_duplicates! { - assert_snapshot!(dmp, "v1__tiles__{to}"); + assert_dump!(dmp, "v1__tiles__{to}"); } - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - dst_type_cli: Some(dst_type), - zoom_levels: vec![6], - ..Default::default() + let z6only = copy_dump! { + path(&frm_mbt), + path(&mem), + dst_type_cli => Some(dst_type), + zoom_levels => vec![6], }; - let z6only = dump(&mut opt.run().await?).await?; allow_duplicates! { - assert_snapshot!(z6only, "v1__z6__{to}"); + assert_dump!(z6only, "v1__z6__{to}"); } // Filter (0, 0, 2, 2) in mbtiles coordinates, which is (0, 2^5-1-2, 2, 2^5-1-0) = (0, 29, 2, 31) in XYZ coordinates, and slightly decrease it @@ -343,36 +401,36 @@ async fn convert( bbox[1] += adjust; bbox[2] -= adjust; bbox[3] -= adjust; - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - dst_type_cli: Some(dst_type), - bbox: vec![bbox.into()], - ..Default::default() + let dmp = copy_dump! { + path(&frm_mbt), + path(&mem), + dst_type_cli => Some(dst_type), + bbox => vec![bbox.into()], }; - let dmp = dump(&mut opt.run().await?).await?; allow_duplicates! { - assert_snapshot!(dmp, "v1__bbox__{to}"); + assert_dump!(dmp, "v1__bbox__{to}"); } - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - dst_type_cli: Some(dst_type), - min_zoom: Some(6), - ..Default::default() - }; - pretty_assert_eq!(&z6only, &dump(&mut opt.run().await?).await?); - - let opt = MbtilesCopier { - src_file: path(&frm_mbt), - dst_file: path(&mem), - dst_type_cli: Some(dst_type), - min_zoom: Some(6), - max_zoom: Some(6), - ..Default::default() - }; - pretty_assert_eq!(&z6only, &dump(&mut opt.run().await?).await?); + pretty_assert_eq!( + &z6only, + ©_dump! { + path(&frm_mbt), + path(&mem), + dst_type_cli => Some(dst_type), + min_zoom => Some(6), + } + ); + + pretty_assert_eq!( + &z6only, + ©_dump! { + path(&frm_mbt), + path(&mem), + dst_type_cli => Some(dst_type), + min_zoom => Some(6), + max_zoom => Some(6), + } + ); Ok(()) } @@ -381,66 +439,58 @@ async fn convert( #[trace] #[actix_rt::test] async fn diff_and_patch( - #[values(Flat, FlatWithHash, Normalized)] v1_type: MbtTypeCli, - #[values(Flat, FlatWithHash, Normalized)] v2_type: MbtTypeCli, + #[values(Flat, FlatWithHash, Normalized)] a_type: MbtTypeCli, + #[values(Flat, FlatWithHash, Normalized)] b_type: MbtTypeCli, #[values(None, Some(Flat), Some(FlatWithHash), Some(Normalized))] dif_type: Option, + #[values(&[Flat, FlatWithHash, Normalized])] destination_types: &[MbtTypeCli], + #[values( + ("v1", "v2", "dif"), + ("v1", "v1_clone", "dif_empty"))] + tilesets: (&'static str, &'static str, &'static str), #[notrace] databases: &Databases, ) -> MbtResult<()> { - let (v1, v2) = (shorten(v1_type), shorten(v2_type)); + let (a_db, b_db, dif_db) = tilesets; let dif = dif_type.map_or("dflt", shorten); - let prefix = format!("{v2}-{v1}={dif}"); - - let v1_mbt = databases.mbtiles("v1", v1_type); - let v2_mbt = databases.mbtiles("v2", v2_type); - let (dif_mbt, mut dif_cn) = open!(diff_and_patchdiff_and_patch, "{prefix}__dif"); + let prefix = format!( + "{a_db}_{}--{b_db}_{}={dif}", + shorten(b_type), + shorten(a_type) + ); - info!("TEST: Compare v1 with v2, and copy anything that's different (i.e. mathematically: v2-v1=diff)"); - let mut opt = MbtilesCopier { - src_file: path(v1_mbt), - dst_file: path(&dif_mbt), - diff_with_file: Some(path(v2_mbt)), - ..Default::default() + eprintln!("TEST: Compare {a_db} with {b_db}, and copy anything that's different (i.e. mathematically: {b_db} - {a_db} = {dif_db})"); + let (dif_mbt, mut dif_cn) = open!(diff_and_patch, "{prefix}__{dif_db}"); + copy! { + databases.path(a_db, a_type), + path(&dif_mbt), + diff_with_file => Some(databases.path(b_db, b_type)), + dst_type_cli => dif_type, }; - if let Some(dif_type) = dif_type { - opt.dst_type_cli = Some(dif_type); - } - opt.run().await?; pretty_assert_eq!( &dump(&mut dif_cn).await?, - databases.dump("dif", dif_type.unwrap_or(v1_type)) + databases.dump(dif_db, dif_type.unwrap_or(a_type)) ); - for target_type in &[Flat, FlatWithHash, Normalized] { - let trg = shorten(*target_type); - let prefix = format!("{prefix}__to__{trg}"); - let expected_v2 = databases.dump("v2", *target_type); - - info!("TEST: Applying the difference (v2-v1=diff) to v1, should get v2"); - let (tar1_mbt, mut tar1_cn) = new_file!( - diff_and_patch, - *target_type, - METADATA_V1, - TILES_V1, - "{prefix}__v1" - ); - apply_patch(path(&tar1_mbt), path(&dif_mbt)).await?; - let hash_v1 = tar1_mbt.validate(Off, Verify).await?; - allow_duplicates! { - assert_display_snapshot!(hash_v1, @"3BCDEE3F52407FF1315629298CB99133"); - } - let dmp = dump(&mut tar1_cn).await?; - pretty_assert_eq!(&dmp, expected_v2); - - info!("TEST: Applying the difference (v2-v1=diff) to v2, should not modify it"); - let (tar2_mbt, mut tar2_cn) = - new_file! {diff_and_patch, *target_type, METADATA_V2, TILES_V2, "{prefix}__v2"}; - apply_patch(path(&tar2_mbt), path(&dif_mbt)).await?; - let hash_v2 = tar2_mbt.validate(Off, Verify).await?; - allow_duplicates! { - assert_display_snapshot!(hash_v2, @"3BCDEE3F52407FF1315629298CB99133"); - } - let dmp = dump(&mut tar2_cn).await?; - pretty_assert_eq!(&dmp, expected_v2); + for dst_type in destination_types { + let prefix = format!("{prefix}__to__{}", shorten(*dst_type)); + let expected_b = databases.dump(b_db, *dst_type); + + eprintln!("TEST: Applying the difference ({b_db} - {a_db} = {dif_db}) to {a_db}, should get {b_db}"); + let (clone_mbt, mut clone_cn) = open!(diff_and_patch, "{prefix}__1"); + copy!(databases.path(a_db, *dst_type), path(&clone_mbt)); + apply_patch(path(&clone_mbt), path(&dif_mbt)).await?; + let hash = clone_mbt.validate(Off, Verify).await?; + assert_eq!(hash, databases.hash(b_db, *dst_type)); + let dmp = dump(&mut clone_cn).await?; + pretty_assert_eq!(&dmp, expected_b); + + eprintln!("TEST: Applying the difference ({b_db} - {a_db} = {dif_db}) to {b_db}, should not modify it"); + let (clone_mbt, mut clone_cn) = open!(diff_and_patch, "{prefix}__2"); + copy!(databases.path(b_db, *dst_type), path(&clone_mbt)); + apply_patch(path(&clone_mbt), path(&dif_mbt)).await?; + let hash = clone_mbt.validate(Off, Verify).await?; + assert_eq!(hash, databases.hash(b_db, *dst_type)); + let dmp = dump(&mut clone_cn).await?; + pretty_assert_eq!(&dmp, expected_b); } Ok(()) @@ -459,21 +509,14 @@ async fn patch_on_copy( let v2 = v2_type.map_or("dflt", shorten); let prefix = format!("{v1}+{dif}={v2}"); - let v1_mbt = databases.mbtiles("v1", v1_type); - let dif_mbt = databases.mbtiles("dif", dif_type); - let (v2_mbt, mut v2_cn) = open!(patch_on_copy, "{prefix}__v2"); - info!("TEST: Compare v1 with v2, and copy anything that's different (i.e. mathematically: v2-v1=diff)"); - let mut opt = MbtilesCopier { - src_file: path(v1_mbt), - dst_file: path(&v2_mbt), - apply_patch: Some(path(dif_mbt)), - ..Default::default() + let (v2_mbt, mut v2_cn) = open!(patch_on_copy, "{prefix}__v2"); + copy! { + databases.path("v1", v1_type), + path(&v2_mbt), + apply_patch => Some(databases.path("dif", dif_type)), + dst_type_cli => v2_type, }; - if let Some(v2_type) = v2_type { - opt.dst_type_cli = Some(v2_type); - } - opt.run().await?; pretty_assert_eq!( &dump(&mut v2_cn).await?, databases.dump("v2", v2_type.unwrap_or(v1_type)) @@ -486,7 +529,9 @@ async fn patch_on_copy( #[actix_rt::test] #[ignore] async fn test_one() { - let db = Databases::default(); + // This will cause an error if ran together with other tests + let db = databases(); + // let db = Databases::default(); // Test convert convert(Flat, Flat, &db).await.unwrap(); @@ -497,9 +542,17 @@ async fn test_one() { // let dst_type = Some(FlatWithHash); let dst_type = None; - diff_and_patch(src_type, dif_type, dst_type, &db) - .await - .unwrap(); + diff_and_patch( + src_type, + dif_type, + dst_type, + &[Flat], + ("v1", "v2", "dif"), + &db, + ) + .await + .unwrap(); + patch_on_copy(src_type, dif_type, dst_type, &db) .await .unwrap(); @@ -600,14 +653,10 @@ async fn dump(conn: &mut SqliteConnection) -> MbtResult> { } #[allow(dead_code)] -async fn save_to_file(source_mbt: &Mbtiles, path_mbt: &str) -> MbtResult<()> { - let dst = &Mbtiles::new(path_mbt)?; - let opt = MbtilesCopier { - src_file: path(source_mbt), - dst_file: path(dst), - skip_agg_tiles_hash: true, - ..Default::default() - }; - opt.run().await?; - Ok(()) +async fn save_to_file(source_mbt: &Mbtiles, path_mbt: &str) { + copy!( + path(source_mbt), + path(&Mbtiles::new(path_mbt).unwrap()), + skip_agg_tiles_hash => true, + ); } diff --git a/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap new file mode 100644 index 000000000..3e8eb17a9 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap @@ -0,0 +1,32 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'table' +tbl_name = 'tiles' +sql = ''' +CREATE TABLE tiles ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles' diff --git a/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap new file mode 100644 index 000000000..f23bd8a89 --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap @@ -0,0 +1,40 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'table' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE TABLE tiles_with_hash ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_data blob, + tile_hash text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'index' +tbl_name = 'tiles_with_hash' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT zoom_level, tile_column, tile_row, tile_data FROM tiles_with_hash''' diff --git a/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap new file mode 100644 index 000000000..0170e862f --- /dev/null +++ b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap @@ -0,0 +1,71 @@ +--- +source: mbtiles/tests/copy.rs +expression: actual_value +--- +[[]] +type = 'table' +tbl_name = 'images' +sql = ''' +CREATE TABLE images ( + tile_id text NOT NULL PRIMARY KEY, + tile_data blob)''' +values = [] + +[[]] +type = 'table' +tbl_name = 'map' +sql = ''' +CREATE TABLE map ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + tile_id text, + PRIMARY KEY(zoom_level, tile_column, tile_row))''' +values = [] + +[[]] +type = 'table' +tbl_name = 'metadata' +sql = ''' +CREATE TABLE metadata ( + name text NOT NULL PRIMARY KEY, + value text)''' +values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] + +[[]] +type = 'index' +tbl_name = 'images' + +[[]] +type = 'index' +tbl_name = 'map' + +[[]] +type = 'index' +tbl_name = 'metadata' + +[[]] +type = 'view' +tbl_name = 'tiles' +sql = ''' +CREATE VIEW tiles AS + SELECT map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data + FROM map + JOIN images ON images.tile_id = map.tile_id''' + +[[]] +type = 'view' +tbl_name = 'tiles_with_hash' +sql = ''' +CREATE VIEW tiles_with_hash AS + SELECT + map.zoom_level AS zoom_level, + map.tile_column AS tile_column, + map.tile_row AS tile_row, + images.tile_data AS tile_data, + images.tile_id AS tile_hash + FROM map + JOIN images ON images.tile_id = map.tile_id''' diff --git a/tests/expected/configured/spr_cmp.png b/tests/expected/configured/spr_cmp.png index 197c70d09170009358a804c09136a9b17b727ff5..ffb3546925d2136c95e615982d07ad025b0077b1 100644 GIT binary patch delta 700 zcmV;t0z>_i29XAkBmvlwB_RQ_kw+wdA$tj;mqa`i57K%pD9?H2?XnJrWtmqJ!4E!m zXXbs$`)1zEtkw>oX`_NA!KNS(>(m!-r+agEeCWmG>D8yH0jOjWjraKr``X3g7{*|1 zIg|K~T8#r_z;KfHA;uW89!-3$K7nsbW%yJn!a~NZ7RNDU>N?!nW4i!m*=jz@u=;P370vIP|27L zoaMz^=O|%+F3(K?Y95d4tEwiFf}lvlsrzS_Pp$YG@DNvRe&ToowJIh;f@=&$ni`=n z7|CIRftZM-RaYacYC>L>hly~1Er4(TGhe zqGNKiBS$vxhn45Euxm$;YoxFDfP3>}493n3hxe-*vA8$8Q(o`#SKM2F`}5*F+)RzZ zgR7UY?Gi6eJgzxz^d#%?ODH8{A(7-4O1Ldw-#P!0^Fy)4V4|f-$eWRgrQ+m9I};xs zWqx28avCu>SA#ZuNf3~wv7_*6`V4+VBJthX8%Qjz6sMV-(nn+0fXw{!CZsa+-7^$p zXu;5;BY2J4TdyTUmUPd5*wkkP{PULl^Gezd!4gb*+DS?#q@?Wt48c0RUl&{#tO=%h zv|FEim1eI_&$6IRvzetnpg4m^%Wq- i&{OvtSJM7R7veWEY1+w8yORk30000E7HOA9^u)di7~$0BX5Z^L_EcKEGHT!x)UM z=2G8LtEm7PU{3M@#26;((ZtvK6Zp1Ng-^9IEaZ%O$>>Xzjp(srDxO5*JNDs!7{*{M zY8Ix3*HxLQa6(Al*F3=4#l(pg<+&+9&Es)>Rn|nB6C}x;x_@^0)JmWM4{_DzCyqB!D`O(Uxu(EKOCyv9 zV+Bkw6jQOR>}up?O^B=VFcocogfT%hWsS5H8Zkv91M%H(wtp{(iTCc={#P3{vPM85 zE&Qf8!5b$JAw?r-uB(keh|=nQBUta=ByW$NfSo$dQfvVdeQO?Ap=e8tLmj;NJWggRwKi(fzVUOx2s+DX(|MEAFj-{dsX7Zf3^d z!PQIHc8M1!9@i>v^t96BmrzM3B0R}2l&~*f-#P!$(Wo%fR$!v72`Cz|iKX)7x}S*; zk8(e;3{@IoDp!Lxe8t(wm9eAnYWfWRiA3VNvp0}fS{apQ3Q~U>y9Q+Dzc(S2S>T?b z7^a0on~vZ$YHz-l44J}zJ!4ZJ3;E-1@$*vJ4#DJ1I}LgV&WMz@17MsMyz;UBPOBc4=fep)WlT?r zv}im_{Z7ISIjwqt=iT;fRuG;M;Y0#Ct$NtvQaiI2G%lxA4@M;|k)(E#+IrBqlvXjs kSps_MLE}=|Ep#FN05WOX$sKl12mk;807*qoM6N<$f`JKHIsgCw diff --git a/tests/expected/configured/spr_cmp_2x.png b/tests/expected/configured/spr_cmp_2x.png index c8343819da06ff76bc66ddfd2f51609dcc7ef924..e1ce6514bfef7520f22e378a4d87aece82c7f688 100644 GIT binary patch delta 902 zcmV;119|+R44(|JcLINtNklsK2^7zXf1c1u#I#dyhLqm)u(ZEOoFB(^~$ z5|m0Y5u(-VHdw1ssiA5?2|A)v>-|!F|6q3}n-Z4n&fA;rwrJS8SHh_Rr7e!;~5CRS@HN=~zz-Ap=kZl%D#L#A5)N3zmHyXp(rx{TyGpen*)vOuIH+F4jf5c5mZXTcd?Tu10{dBN=?A*oD4N-LD^nY z>-bFUbItXvF-pc|gh?n%8(znT=wRI|*_dZ^M9S!+y1ibli;im5_3ejXkdy{`_lGZu z5Z{PP!!WQ)(x7DNIkAeAX$F~fN7!Z{PDABxphl49XDPrmXTJ;4@AOuljtU|+yeDmiy4NAERDM)m1+KjsE(2 z)m5&jvt=^CzO4ZL%U`(rh?n|cv?v)Cp$%=i`z-gvEW^CjYmdC`2E2X{X8ebi_Tanj z9&hx4WrDvDJo?JkC+@Dx*TmU=a9AtSV8w#gcSd+N>mOWpJ@3`lw>b9{{$C>9@uIk6 zOY9o$#RW&ppeM41AA3(&*@zAcy)t3AR=ts2>3FV^=qOK~0&usf)nPFi3!Tl7f-cfn zW>L0T%)~l>$2>G5W*RgwlAV*Dx$MY5=y#J41r&dli5x@Py%|aYND*D2oFVOAit@ly zL{G&^`;%iz`BFr=1Z+p0(_$P* zkjFtHN8}h%HoHuzRvE?hd^Alt{X*G}PQlfDi{8`=bhJ6g^#@{x($Oin3X}j~t4(!i zM!kO50do2S5>$vz!9}F2^rlkTpB*~i%%an~EGeo@1<~%@%%W3p6)6E3>w2Bj)%_*OqE)o^fc5pVN c_xvCI3tS4geFRkVJOBUy07*qoM6N<$f_FlsK2^7zXf1c1zMwi}Au@qm)u(ZEOoFB(|wY zBq)_)B1EgzZLn6OQbW~(5_CkT*88RU{=x1{HYF_CotK;(k01K`z~SXN$&=Zc?1J55 zk4>JNky6e~9!ntL)FshaJcNKliw*JSDX>|`=4G4t6EU=z6ZJ6K>dnS5c6q#UbG23% zbL@(e3>vr4a#~z-JvSN$(B?qnhU>W|o&(2_t_Ug(!FQ>XB?BdYx=KyJ?3@fWX+haq zRqOan>~UR{tO^*7%LtQD7T3Lwb|il%Jv^Wi?e7A^h@k(BhEZMs&`STay z+rD#Wn^#hjEHkPkgtZgZ}r+EZ@U4nAA}kIp`|_e zuDi<{ePEg3F9eUiviXU-p!J;*o{jnkS5(7$wY5$2J%#@-k>By6 zxNB4F812P>10vaE>kz6~=6H%9kpWuS}Hz zAX)Y&$CUD=h;m8Tjyk8sIFKZdgJe$qG^AX1nNqDXitG7knsWLNWji_rSMw!$Q!mod z<{Z~=h-pekr{F43QmsdAszcN2wGNQeZ;+%ybP6saU8Ogb%Kq%og=Q9=?z5y=jO*Wb z=4KXKor0@KN%)df49?N%J~n;|zC5Lab94$WyFw{wV^pz&b94$ehiK|Ba5zuo1ZPvq u=Tu0mIKkPR^4aMkQ88@?XG40=|Ixo(3b=jzso?Mc0000vDv diff --git a/tests/expected/configured/spr_mysrc.png b/tests/expected/configured/spr_mysrc.png index 076b4c2c412cc822263904304717a9fedc844536..db2640780735fc4dec9a06f6443d03133329341e 100644 GIT binary patch delta 161 zcmV;S0AByU0lfi`B!7fSL_t(|+O5$+5yCJSMBz_Dr63^=h=fY01CUY&;GlKTI3NyE z2R}0%E}d|LcYC{gTYser?R#7SLCwtBz zaWGV+xTKaF{L9qu>0A3NRcPPi3J7{;BN&B2N4DW+x0=q6Mc9OgVsID2B15*z#|=+| ztf_;O>x|B zQv!%Y;Y%B-BB@~)O0QCQz!wDcn8fFv-xhZitzkgHQzqW~G#iP1xy8tWmV76?aZ#l* zoQ@Sl9oUQpl&UClH<8CCYxGzY(A!aM0bo%O#iN zM&WyV{Q&a%(&VM!4|t3yvL+nHL&fFDNu!HXy#J)(u$agwxVcDE6Z@@i1pRLDra11m zDam`H@THAZk<_pYrB^9D;0pqJOyYCTXNxvp3HIc_AYjj%_(DQAADP|OBGgVkAY+zGnWf+@{%7$4 X@xtlDO$A=t00000NkvXXu0mjfNwtGI diff --git a/tests/expected/configured/spr_src1.png b/tests/expected/configured/spr_src1.png index 8aeb48a2d6a1c03a554d99b0fa006b8d71dc7775..b3c301e8271c15e67ee8cc03248ad96fd6c5fe1e 100644 GIT binary patch delta 723 zcmV;^0xbRZ1@;AyFMrce9LICjsq~-+PyS=jb_f-A@nk_S&O?K1*qFk~M8;5Q1sMeA ztcVJNSTU`R9TH>+BHA*&OvLt}ld(f`8KRd)JPZ%Ac^oJ|-!J@LiCIF7P1?(T@FjWg z{oZ?@{NC^VB6t}H!YGr<)MNsZPJJ1#d2jEI551f`z4|Oa0Dm<(yYfM~u+PgE$Iu6T zt8(@S&UFJ3IfReUM|93dm~Zu`@O`lgpKBGEm!*1H>PuCm_%S7$%%Jcc`)~|>&==>- zPYrK4VN@mvsQZG=@N01c)Vq5Zp)4hTD}!-x)1#rozm{gNwfu2zyD(fOfvhG=EBMt5 zx6aYV{#u%y0)L$IWIVmfVRB5+rbM0>&o7@^_Jgnsqc}Hl+{!nEi7~B(0Mr!7%7cj# zZWKt_M1e=A$QKPON)NN~Mi3a1#(|n40%=a5f#hyD+rM`cK<}RIf3T zVwtd4=v=7Ro=nZ9Vr;Xow6Uk&+&TZr?T2cH0AmUcQ>4ViVr6o}3+Cfv`6nK)8;}@g zbSSY^o`10F*im>reFlHFD17I+gTf=ryFr!O`niT~1l4UAkK^;tDe@78U}nJtM3n46aGqG?PyTRTTUF`-K)GU@bwooSt^!Bn8WjzQEZ5;{GrOa?`!NPR$l zV$?9}^yF<|su7GxU?x+V`_p?QrrQ=z(T&n<$4u6w@dEX8=thKmzstcMIXOG_0RDpHC{B1j=v zYeZBK#E40>^pHi0AfgG?OGQi%S}8qbFGci{6%WOORF4JaId6Fr#_cZawv*)24?cEh z=grP<-@KXCyabvy%w6Vga09tc&k|na-rgM@csYK0_k{|4u9jdntJjKpPpqVej}?;91RC%08TMfe#^RXS ziNQ4|Oqm-3`o1O!zZNGzzq@x4ihA@Wsi$-(e`0c5ByYO!qZ3s;(_@Rzw6xS1Y-2Ujm)Ti8B8 z@tBZL=#vVse`zQB2cSdWM2%<)rsMEE=ZBk}(+(52T ze9Ocr3rw_W;wr%~0<*Z|BA)JBqPq0*80{!ST1>VE^=IfgLE|#2mvaZ1QbB`!rEFR4 z*m!`_+rlG9{>;pmyB1zl9QC40MhA_HXGw^%vE?pi9)1;OYPX002ovPDHLk FV1ffWTs{B* From db094400bb9581d787fafb50850cce7973a30aff Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 11 Mar 2024 02:52:26 -0400 Subject: [PATCH 047/164] bug: ensure agg_tiles_hash_after_apply is added even on empty mbtiles (#1242) If a diff between two mbtiles is empty, `agg_tiles_hash_after_apply` must still be generated. It was not before because two identical tilesets would have the same `agg_tiles_hash`, thus skipping the generation of `agg_tiles_hash_after_apply` --- mbtiles/src/copier.rs | 3 ++- mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap | 5 ++++- mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap | 5 ++++- mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index 69e842ad9..af6a10021 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -235,6 +235,7 @@ impl MbtileCopierInt { // Also insert all names from sourceDb.metadata that do not exist in diffDb.metadata, with their value set to NULL. // Rename agg_tiles_hash to agg_tiles_hash_in_diff because agg_tiles_hash will be auto-added later if self.options.diff_with_file.is_some() { + // Include agg_tiles_hash value even if it is the same because we will still need it when applying the diff sql = format!( " INSERT {on_dupl} INTO metadata (name, value) @@ -245,7 +246,7 @@ impl MbtileCopierInt { , difMD.value as value FROM sourceDb.metadata AS srcMD FULL JOIN diffDb.metadata AS difMD ON srcMD.name = difMD.name - WHERE srcMD.value != difMD.value OR srcMD.value ISNULL OR difMD.value ISNULL + WHERE srcMD.value != difMD.value OR srcMD.value ISNULL OR difMD.value ISNULL OR srcMD.name = '{AGG_TILES_HASH}' ) joinedMD WHERE name != '{AGG_TILES_HASH_IN_DIFF}'" ); diff --git a/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap index 3e8eb17a9..b88309497 100644 --- a/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap @@ -9,7 +9,10 @@ sql = ''' CREATE TABLE metadata ( name text NOT NULL PRIMARY KEY, value text)''' -values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] +values = [ + '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', + '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', +] [[]] type = 'table' diff --git a/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap index f23bd8a89..7dc8868c9 100644 --- a/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap @@ -9,7 +9,10 @@ sql = ''' CREATE TABLE metadata ( name text NOT NULL PRIMARY KEY, value text)''' -values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] +values = [ + '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', + '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', +] [[]] type = 'table' diff --git a/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap index 0170e862f..d84884200 100644 --- a/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap @@ -30,7 +30,10 @@ sql = ''' CREATE TABLE metadata ( name text NOT NULL PRIMARY KEY, value text)''' -values = ['( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )'] +values = [ + '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', + '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', +] [[]] type = 'index' From 60ae6cf16885d5c19757c95d1b5fca0bcda1e346 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 11 Mar 2024 04:29:50 -0400 Subject: [PATCH 048/164] chore: rename agg_tiles_hash_in_diff to agg_tiles_hash_after_apply (#1243) This is just a documentation change - the actual value stored in the mbtiles was always `agg_tiles_hash_after_apply`, but accidentally the constant in the code was not renamed, nor were the docs updated. --- docs/src/mbtiles-diff.md | 27 ++++++++++++++++++++++----- mbtiles/src/copier.rs | 10 +++++----- mbtiles/src/lib.rs | 2 +- mbtiles/src/patcher.rs | 4 ++-- mbtiles/src/validation.rs | 2 +- 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/docs/src/mbtiles-diff.md b/docs/src/mbtiles-diff.md index 8adb65804..607b8df0d 100644 --- a/docs/src/mbtiles-diff.md +++ b/docs/src/mbtiles-diff.md @@ -2,9 +2,16 @@ ## `mbtiles diff` -Copy command can also be used to compare two mbtiles files and generate a delta (diff) file. The diff file can be [applied](#mbtiles-apply-patch) to the `src_file.mbtiles` elsewhere, to avoid copying/transmitting the entire modified dataset. The delta file will contain all tiles that are different between the two files (modifications, insertions, and deletions as `NULL` values), for both the tile and metadata tables. +Copy command can also be used to compare two mbtiles files and generate a delta (diff) file. The diff file can +be [applied](#mbtiles-apply-patch) to the `src_file.mbtiles` elsewhere, to avoid copying/transmitting the entire +modified dataset. The delta file will contain all tiles that are different between the two files (modifications, +insertions, and deletions as `NULL` values), for both the tile and metadata tables. -There is one exception: `agg_tiles_hash` metadata value will be renamed to `agg_tiles_hash_in_diff`, and a new `agg_tiles_hash` will be generated for the diff file itself. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-diff` command will automatically rename the `agg_tiles_hash_in_diff` value back to `agg_tiles_hash` when applying the diff. +There is one exception: `agg_tiles_hash` metadata value will be renamed to `agg_tiles_hash_after_apply`, and a +new `agg_tiles_hash` will be generated for the diff file itself. This is done to avoid confusion when applying the diff +file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-diff` +command will automatically rename the `agg_tiles_hash_after_apply` value back to `agg_tiles_hash` when applying the +diff. ```shell # This command will compare `file1.mbtiles` and `file2.mbtiles`, and generate a new diff file `diff.mbtiles`. @@ -24,9 +31,15 @@ mbtiles validate file2a.mbtiles ## `mbtiles apply-patch` -Apply the diff file generated with the `mbtiles diff` command above to an MBTiles file. The diff file can be applied to the `src_file.mbtiles` that has been previously downloaded to avoid copying/transmitting the entire modified dataset again. The `src_file.mbtiles` will modified in-place. It is also possible to apply the diff file while copying the source file to a new destination file, by using the [`mbtiles copy --apply-patch`](mbtiles-copy.md#mbtiles-copy---apply-patch) command. +Apply the diff file generated with the `mbtiles diff` command above to an MBTiles file. The diff file can be applied to +the `src_file.mbtiles` that has been previously downloaded to avoid copying/transmitting the entire modified dataset +again. The `src_file.mbtiles` will modified in-place. It is also possible to apply the diff file while copying the +source file to a new destination file, by using +the [`mbtiles copy --apply-patch`](mbtiles-copy.md#mbtiles-copy---apply-patch) command. -Note that the `agg_tiles_hash_in_diff` metadata value will be renamed to `agg_tiles_hash` when applying the diff. This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. +Note that the `agg_tiles_hash_after_apply` metadata value will be renamed to `agg_tiles_hash` when applying the diff. +This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be +different after the diff is applied. ```shell mbtiles apply-patch src_file.mbtiles diff_file.mbtiles @@ -34,7 +47,11 @@ mbtiles apply-patch src_file.mbtiles diff_file.mbtiles #### Applying diff with SQLite -Another way to apply the diff is to use the `sqlite3` command line tool directly. This SQL will delete all tiles from `src_file.mbtiles` that are set to `NULL` in `diff_file.mbtiles`, and then insert or update all new tiles from `diff_file.mbtiles` into `src_file.mbtiles`, where both files are of `flat` type. The name of the diff file is passed as a query parameter to the sqlite3 command line tool, and then used in the SQL statements. Note that this does not update the `agg_tiles_hash` metadata value, so it will be incorrect after the diff is applied. +Another way to apply the diff is to use the `sqlite3` command line tool directly. This SQL will delete all tiles +from `src_file.mbtiles` that are set to `NULL` in `diff_file.mbtiles`, and then insert or update all new tiles +from `diff_file.mbtiles` into `src_file.mbtiles`, where both files are of `flat` type. The name of the diff file is +passed as a query parameter to the sqlite3 command line tool, and then used in the SQL statements. Note that this does +not update the `agg_tiles_hash` metadata value, so it will be incorrect after the diff is applied. ```shell sqlite3 src_file.mbtiles \ diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index af6a10021..ebe8b76c2 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -17,7 +17,7 @@ use crate::queries::{ use crate::MbtType::{Flat, FlatWithHash, Normalized}; use crate::{ invert_y_value, reset_db_settings, CopyType, MbtError, MbtType, MbtTypeCli, Mbtiles, - AGG_TILES_HASH, AGG_TILES_HASH_IN_DIFF, + AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumDisplay)] @@ -233,13 +233,13 @@ impl MbtileCopierInt { if dif.is_some() { // Insert all rows from diffDb.metadata if they do not exist or are different in sourceDb.metadata. // Also insert all names from sourceDb.metadata that do not exist in diffDb.metadata, with their value set to NULL. - // Rename agg_tiles_hash to agg_tiles_hash_in_diff because agg_tiles_hash will be auto-added later + // Rename agg_tiles_hash to agg_tiles_hash_after_apply because agg_tiles_hash will be auto-added later if self.options.diff_with_file.is_some() { // Include agg_tiles_hash value even if it is the same because we will still need it when applying the diff sql = format!( " INSERT {on_dupl} INTO metadata (name, value) - SELECT IIF(name = '{AGG_TILES_HASH}','{AGG_TILES_HASH_IN_DIFF}', name) as name + SELECT IIF(name = '{AGG_TILES_HASH}','{AGG_TILES_HASH_AFTER_APPLY}', name) as name , value FROM ( SELECT COALESCE(difMD.name, srcMD.name) as name @@ -248,14 +248,14 @@ impl MbtileCopierInt { ON srcMD.name = difMD.name WHERE srcMD.value != difMD.value OR srcMD.value ISNULL OR difMD.value ISNULL OR srcMD.name = '{AGG_TILES_HASH}' ) joinedMD - WHERE name != '{AGG_TILES_HASH_IN_DIFF}'" + WHERE name != '{AGG_TILES_HASH_AFTER_APPLY}'" ); debug!("Copying metadata, taking into account diff file with {sql}"); } else { sql = format!( " INSERT {on_dupl} INTO metadata (name, value) - SELECT IIF(name = '{AGG_TILES_HASH_IN_DIFF}','{AGG_TILES_HASH}', name) as name + SELECT IIF(name = '{AGG_TILES_HASH_AFTER_APPLY}','{AGG_TILES_HASH}', name) as name , value FROM ( SELECT COALESCE(srcMD.name, difMD.name) as name diff --git a/mbtiles/src/lib.rs b/mbtiles/src/lib.rs index 056044f44..272915f8b 100644 --- a/mbtiles/src/lib.rs +++ b/mbtiles/src/lib.rs @@ -32,7 +32,7 @@ pub use update::UpdateZoomType; mod validation; pub use validation::{ calc_agg_tiles_hash, AggHashType, IntegrityCheckType, MbtType, AGG_TILES_HASH, - AGG_TILES_HASH_IN_DIFF, + AGG_TILES_HASH_AFTER_APPLY, }; /// `MBTiles` uses a TMS (Tile Map Service) scheme for its tile coordinates (inverted along the Y axis). diff --git a/mbtiles/src/patcher.rs b/mbtiles/src/patcher.rs index 1e1777fa9..3ae43163a 100644 --- a/mbtiles/src/patcher.rs +++ b/mbtiles/src/patcher.rs @@ -5,7 +5,7 @@ use sqlx::query; use crate::queries::detach_db; use crate::MbtType::{Flat, FlatWithHash, Normalized}; -use crate::{MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_IN_DIFF}; +use crate::{MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY}; pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<()> { let base_mbt = Mbtiles::new(base_file)?; @@ -53,7 +53,7 @@ pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<( query(&format!( " INSERT OR REPLACE INTO metadata (name, value) - SELECT IIF(name = '{AGG_TILES_HASH_IN_DIFF}', '{AGG_TILES_HASH}', name) as name, + SELECT IIF(name = '{AGG_TILES_HASH_AFTER_APPLY}', '{AGG_TILES_HASH}', name) as name, value FROM patchDb.metadata WHERE name NOTNULL AND name != '{AGG_TILES_HASH}';" diff --git a/mbtiles/src/validation.rs b/mbtiles/src/validation.rs index 50509a815..d583af078 100644 --- a/mbtiles/src/validation.rs +++ b/mbtiles/src/validation.rs @@ -26,7 +26,7 @@ pub const AGG_TILES_HASH: &str = "agg_tiles_hash"; /// Metadata key for a diff file, /// describing the eventual [`AGG_TILES_HASH`] value once the diff is applied -pub const AGG_TILES_HASH_IN_DIFF: &str = "agg_tiles_hash_after_apply"; +pub const AGG_TILES_HASH_AFTER_APPLY: &str = "agg_tiles_hash_after_apply"; #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, EnumDisplay, Serialize)] #[enum_display(case = "Kebab")] From 7fafe5690a22fbb116ff5878bac004d1348d5436 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:48:17 +0000 Subject: [PATCH 049/164] chore(deps): Bump thiserror from 1.0.57 to 1.0.58 (#1249) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.57 to 1.0.58.
Release notes

Sourced from thiserror's releases.

1.0.58

  • Make backtrace support available when using -Dwarnings (#292)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=thiserror&package-manager=cargo&previous-version=1.0.57&new-version=1.0.58)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0744241fe..f6fcb56ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4187,18 +4187,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", From 9f4273954eead4d395f79697c881a5a9775583ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:50:29 +0000 Subject: [PATCH 050/164] chore(deps): Bump sqlx from 0.7.3 to 0.7.4 (#1250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sqlx](https://github.com/launchbadge/sqlx) from 0.7.3 to 0.7.4.
Changelog

Sourced from sqlx's changelog.

0.7.4 - 2024-03-11

38 pull requests were merged this release cycle.

This is officially the last release of the 0.7.x release cycle.

As of this release, development of 0.8.0 has begun on main and only high-priority bugfixes may be backported.

Added

  • [#2891]: feat: expose getters for connect options fields [[@​saiintbrisson]]
  • [#2902]: feat: add to_url_lossy to connect options [[@​lily-mosquitoes]]
  • [#2927]: Support query! for cargo-free systems [[@​kshramt]]
  • [#2997]: doc(FAQ): add entry explaining prepared statements [[@​abonander]]
  • [#3001]: Update README to clarify MariaDB support [[@​iangilfillan]]
  • [#3004]: feat(logging): Add numeric elapsed time field elapsed_secs [[@​iamjpotts]]
  • [#3007]: feat: add raw_sql API [[@​abonander]]
    • This hopefully makes it easier to find how to execute statements which are not supported by the default prepared statement interfaces query*() and query!().
    • Improved documentation across the board for the query*() functions.
    • Deprecated: execute_many() and fetch_many() on interfaces that use prepared statements.
      • Multiple SQL statements in one query string were only supported by SQLite because its prepared statement interface is the only way to execute SQL. All other database flavors forbid multiple statements in one prepared statement string as an extra defense against SQL injection.
      • The new raw_sql API retains this functionality because it explicitly does not use prepared statements. Raw or text-mode query interfaces generally allow multiple statements in one query string, and this is supported by all current databases. Due to their nature, however, one cannot use bind parameters with them.
      • If this change affects you, an issue is open for discussion: launchbadge/sqlx#3108
  • [#3011]: Added support to IpAddr with MySQL/MariaDB. [[@​Icerath]]
  • [#3013]: Add default implementation for PgInterval [[@​pawurb]]
  • [#3018]: Add default implementation for PgMoney [[@​pawurb]]
  • [#3026]: Update docs to reflect support for MariaDB data types [[@​iangilfillan]]
  • [#3037]: feat(mysql): allow to connect with mysql driver without default behavor [[@​darkecho731]]

Changed

... (truncated)

Commits
  • 635dba5 fix: deprecation in postgres::types::chrono
  • a2b89d7 fix: deprecation warnings in sqlite::types::chrono, document DATETIME beh...
  • 248d617 chore: prepare 0.7.4 release
  • d005111 fix: better I/O errors when migrate!() cannot read a file
  • 24be262 fix: restore Migrator to the public API
  • bbfd0d7 fix: AnyRow not support PgType::Varchar (#2976)
  • b29eab0 feat: add to_url_lossy to connect options (#2902)
  • 34860b7 fix(ci): just cfg-out the whole tests/sqlite/sqlcipher.rs
  • 791a7f5 doc(pg): document behavior of bigdecimal and rust_decimal with out-of-ran...
  • e5c18b3 fix: gate sqlcipher testing behind cfg to make development less annoying
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sqlx&package-manager=cargo&previous-version=0.7.3&new-version=0.7.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 61 ++++++++++++++---------------------------------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6fcb56ea..8a4b314ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,16 +429,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atomic-write-file" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8204db279bf648d64fe845bd8840f78b39c8132ed4d6a4194c3b10d4b4cfb0b" -dependencies = [ - "nix 0.28.0", - "rand", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -658,12 +648,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "chrono" version = "0.4.35" @@ -2317,18 +2301,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -2810,7 +2782,7 @@ dependencies = [ "inferno", "libc", "log", - "nix 0.26.4", + "nix", "once_cell", "parking_lot", "smallvec", @@ -3800,9 +3772,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", @@ -3813,9 +3785,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ "ahash", "atoi", @@ -3823,7 +3795,6 @@ dependencies = [ "bytes", "crc", "crossbeam-queue", - "dotenvy", "either", "event-listener", "futures-channel", @@ -3853,9 +3824,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" dependencies = [ "proc-macro2", "quote", @@ -3866,11 +3837,10 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ - "atomic-write-file", "dotenvy", "either", "heck", @@ -3892,9 +3862,9 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", @@ -3934,9 +3904,9 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", @@ -3961,7 +3931,6 @@ dependencies = [ "rand", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", @@ -3973,9 +3942,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", "flume", From 9113746396933adc9f9be8557c75ae3b494df03a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 02:53:49 +0000 Subject: [PATCH 051/164] chore(deps): Bump anyhow from 1.0.80 to 1.0.81 (#1251) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.80 to 1.0.81.
Release notes

Sourced from anyhow's releases.

1.0.81

  • Make backtrace support available when using -Dwarnings (#354)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.80&new-version=1.0.81)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a4b314ea..a55c37ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "approx" From 7d1763f827071a4b084b8b86045c362e74ae0b47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:24:36 -0400 Subject: [PATCH 052/164] chore(deps): Bump serde_with from 3.6.1 to 3.7.0 (#1247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.6.1 to 3.7.0.
Release notes

Sourced from serde_with's releases.

serde_with v3.7.0

Added

Fixed

  • Detect conflicting schema_with attributes on fields with schemars annotations by @​swlynch99 (#715) This extends the existing avoidance mechanism to a new variant fixing #712.
Commits
  • bcda3fa Bump version to 3.7.0 (#720)
  • a446da1 Bump version to 3.7.0
  • 7e9772f Implement JsonSchemaAs for OneOrMany (#719)
  • 5e36083 Add impls and tests for OneOrMany
  • c5c35db Implement JsonSchemaAs for KeyValueMap (#713)
  • 046f820 Bump the github-actions group with 1 update (#718)
  • 7e87fe5 Bump the github-actions group with 1 update
  • ffade77 Add JsonSchemaAs impl for IfIsHumanReadable (#717)
  • bb2ab60 Add JsonSchemaAs impl for IfIsHumanReadable
  • a804257 Implement JsonSchemaAs for KeyValueMap
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_with&package-manager=cargo&previous-version=3.6.1&new-version=3.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a55c37ae9..58291164f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3537,9 +3537,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" dependencies = [ "base64 0.21.7", "chrono", @@ -3555,9 +3555,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" dependencies = [ "darling", "proc-macro2", From 9505a2107eb7c763ec1c7330c76d75ff6d1fa3d2 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 16 Mar 2024 04:23:35 -0400 Subject: [PATCH 053/164] chore: increase complexity of the SQL table test (#1256) a few more characters that have to be properly escaped --- martin/tests/pg_server_test.rs | 2 +- martin/tests/pg_table_source_test.rs | 2 +- tests/expected/auto/catalog_auto.json | 2 +- tests/expected/auto/save_config.yaml | 8 ++--- .../martin-cp/flat-with-hash_save_config.yaml | 8 ++--- .../expected/martin-cp/flat_save_config.yaml | 8 ++--- .../martin-cp/normalized_save_config.yaml | 8 ++--- tests/fixtures/tables/SpacesAndQuotes.sql | 29 +++++-------------- 8 files changed, 27 insertions(+), 40 deletions(-) diff --git a/martin/tests/pg_server_test.rs b/martin/tests/pg_server_test.rs index e1a65780a..600e774ab 100644 --- a/martin/tests/pg_server_test.rs +++ b/martin/tests/pg_server_test.rs @@ -60,7 +60,7 @@ postgres: "-function.withweired---_-characters": content_type: application/x-protobuf description: a function source with special characters - ".-Points---quote": + ".-Points-----------quote": content_type: application/x-protobuf description: Escaping test table MixPoints: diff --git a/martin/tests/pg_table_source_test.rs b/martin/tests/pg_table_source_test.rs index 29f93936a..d4179167f 100644 --- a/martin/tests/pg_table_source_test.rs +++ b/martin/tests/pg_table_source_test.rs @@ -21,7 +21,7 @@ async fn table_source() { "-function.withweired---_-characters": content_type: application/x-protobuf description: a function source with special characters - ".-Points---quote": + ".-Points-----------quote": content_type: application/x-protobuf description: Escaping test table MixPoints: diff --git a/tests/expected/auto/catalog_auto.json b/tests/expected/auto/catalog_auto.json index d3b77b680..e3d4a3531 100644 --- a/tests/expected/auto/catalog_auto.json +++ b/tests/expected/auto/catalog_auto.json @@ -4,7 +4,7 @@ "content_type": "application/x-protobuf", "description": "a function source with special characters" }, - ".-Points---quote": { + ".-Points-----------quote": { "content_type": "application/x-protobuf", "description": "Escaping test table" }, diff --git a/tests/expected/auto/save_config.yaml b/tests/expected/auto/save_config.yaml index a46b295f4..3b1105cae 100644 --- a/tests/expected/auto/save_config.yaml +++ b/tests/expected/auto/save_config.yaml @@ -4,11 +4,11 @@ postgres: auto_bounds: calc auto_publish: true tables: - .-Points---quote: - schema: '"Quotes'' and Space.Dot.' - table: . Points" 'quote + .-Points-----------quote: + schema: '"Quotes'' \ \'' \" and Space.Dot.' + table: . Points" \ \' \" 'quote srid: 4326 - geometry_column: . "Geom" + geometry_column: . ' \ \' \" "Geom" bounds: - -170.94984639004662 - -84.20025580733805 diff --git a/tests/expected/martin-cp/flat-with-hash_save_config.yaml b/tests/expected/martin-cp/flat-with-hash_save_config.yaml index bdbe22a96..4e811e610 100644 --- a/tests/expected/martin-cp/flat-with-hash_save_config.yaml +++ b/tests/expected/martin-cp/flat-with-hash_save_config.yaml @@ -3,11 +3,11 @@ postgres: auto_bounds: calc auto_publish: true tables: - .-Points---quote: - schema: '"Quotes'' and Space.Dot.' - table: . Points" 'quote + .-Points-----------quote: + schema: '"Quotes'' \ \'' \" and Space.Dot.' + table: . Points" \ \' \" 'quote srid: 4326 - geometry_column: . "Geom" + geometry_column: . ' \ \' \" "Geom" bounds: - -170.94984639004662 - -84.20025580733805 diff --git a/tests/expected/martin-cp/flat_save_config.yaml b/tests/expected/martin-cp/flat_save_config.yaml index bdbe22a96..4e811e610 100644 --- a/tests/expected/martin-cp/flat_save_config.yaml +++ b/tests/expected/martin-cp/flat_save_config.yaml @@ -3,11 +3,11 @@ postgres: auto_bounds: calc auto_publish: true tables: - .-Points---quote: - schema: '"Quotes'' and Space.Dot.' - table: . Points" 'quote + .-Points-----------quote: + schema: '"Quotes'' \ \'' \" and Space.Dot.' + table: . Points" \ \' \" 'quote srid: 4326 - geometry_column: . "Geom" + geometry_column: . ' \ \' \" "Geom" bounds: - -170.94984639004662 - -84.20025580733805 diff --git a/tests/expected/martin-cp/normalized_save_config.yaml b/tests/expected/martin-cp/normalized_save_config.yaml index bdbe22a96..4e811e610 100644 --- a/tests/expected/martin-cp/normalized_save_config.yaml +++ b/tests/expected/martin-cp/normalized_save_config.yaml @@ -3,11 +3,11 @@ postgres: auto_bounds: calc auto_publish: true tables: - .-Points---quote: - schema: '"Quotes'' and Space.Dot.' - table: . Points" 'quote + .-Points-----------quote: + schema: '"Quotes'' \ \'' \" and Space.Dot.' + table: . Points" \ \' \" 'quote srid: 4326 - geometry_column: . "Geom" + geometry_column: . ' \ \' \" "Geom" bounds: - -170.94984639004662 - -84.20025580733805 diff --git a/tests/fixtures/tables/SpacesAndQuotes.sql b/tests/fixtures/tables/SpacesAndQuotes.sql index a8f83637f..d942461b3 100644 --- a/tests/fixtures/tables/SpacesAndQuotes.sql +++ b/tests/fixtures/tables/SpacesAndQuotes.sql @@ -1,27 +1,14 @@ DROP SCHEMA IF EXISTS """Quotes' and Space.Dot." CASCADE; -CREATE SCHEMA """Quotes' and Space.Dot."; +CREATE SCHEMA """Quotes' \ \' \"" and Space.Dot."; -CREATE TABLE """Quotes' and Space.Dot.".". Points"" 'quote" +CREATE TABLE """Quotes' \ \' \"" and Space.Dot.".". Points"" \ \' \"" 'quote" ( - "' id '" SERIAL PRIMARY KEY, - ".namE " TEXT, - ". ""Geom""" GEOMETRY(POINT, 4326) + "' id '" SERIAL PRIMARY KEY, + ".namE " TEXT, + ". ' \ \' \"" ""Geom""" GEOMETRY(POINT, 4326) ); --- INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" --- SELECT generate_series(1, 3), --- md5(random()::text), --- (ST_DUMP(ST_GENERATEPOINTS(st_transform(st_tileenvelope(18, 235085, 122323), 4326), 3))).Geom; --- INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" --- SELECT generate_series(4, 30), --- md5(random()::text), --- (ST_DUMP(ST_GENERATEPOINTS(st_transform(st_tileenvelope(0, 0, 0), 4326), 27))).Geom; --- --- To dump the data above, uncomment code the above, comment the INSERT code bellow, and run: --- just restart --- just pg_dump --data-only --inserts --rows-per-insert=100 --table="""Quotes' and Space.Dot.".". Points"" 'quote" - -INSERT INTO """Quotes' and Space.Dot.".". Points"" 'quote" +INSERT INTO """Quotes' \ \' \"" and Space.Dot.".". Points"" \ \' \"" 'quote" values (1, '02daedc70702ec68753fde38351f5d9d', '0101000020E610000050C4D38CE9DA61401EFC0EC7C3DA2740'), (2, '7418427ba8a960c3661235f47cc13d46', '0101000020E6100000CC2F4170E9DA6140DEDB02B581DA2740'), (3, 'd5a11dee7203a09442168eec74c7bea8', '0101000020E6100000008E66E9E6DA614059944356B4DA2740'), @@ -53,10 +40,10 @@ values (1, '02daedc70702ec68753fde38351f5d9d', '0101000020E610000050C4D38CE9DA61 (29, 'fd0775c59700ac8c1982aa3efe6cb0c7', '0101000020E6100000D6CF48A3E1A9464077D6BBFDD00C55C0'), (30, '404175d17b08782edc9d316c378adc86', '0101000020E6100000F9B5A5ADB7265BC0EE07F81F2F284840'); -CREATE INDEX ON """Quotes' and Space.Dot.".". Points"" 'quote" USING GIST (". ""Geom"""); +CREATE INDEX ON """Quotes' \ \' \"" and Space.Dot.".". Points"" \ \' \"" 'quote" USING GIST (". ' \ \' \"" ""Geom"""); DO $do$ BEGIN - EXECUTE 'COMMENT ON TABLE """Quotes'' and Space.Dot.".". Points"" ''quote" IS $tj$' || $$ + EXECUTE 'COMMENT ON TABLE """Quotes'' \ \'' \"" and Space.Dot.".". Points"" \ \'' \"" ''quote" IS $tj$' || $$ { "description": "Escaping test table" } From 51d52ba23615726ffaf69c8aae7f39d5c17c1e11 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 16 Mar 2024 18:32:20 -0400 Subject: [PATCH 054/164] fix broken links, reformat markdown (#1257) Fixes #1252 --- docs/src/using-with-mapbox.md | 29 +++++++----- docs/src/using-with-maplibre.md | 81 +++++++++++++++++---------------- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/docs/src/using-with-mapbox.md b/docs/src/using-with-mapbox.md index 87a860ad7..3bef04a1b 100644 --- a/docs/src/using-with-mapbox.md +++ b/docs/src/using-with-mapbox.md @@ -1,20 +1,25 @@ ## Using with Mapbox -[Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) is a JavaScript library for interactive, customizable vector maps on the web. Mapbox GL JS v1.x was open source, and it was forked as MapLibre, so using Martin with Mapbox is similar to MapLibre described [here](using-with-maplibre.md). Mapbox GL JS can accept [MVT vector tiles](https://github.com/mapbox/vector-tile-spec) generated by Martin, and applies [a style](https://docs.mapbox.com/mapbox-gl-js/style-spec/) to them to draw a map using Web GL. +[Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) is a JavaScript library for interactive, customizable vector maps +on the web. Mapbox GL JS v1.x was open source, and it was forked as MapLibre, so using Martin with Mapbox is similar to +MapLibre described [here](using-with-maplibre.md). Mapbox GL JS can +accept [MVT vector tiles](https://github.com/mapbox/vector-tile-spec) generated by Martin, and +applies [a style](https://maplibre.org/maplibre-style-spec/) to them to draw a map using Web GL. -You can add a layer to the map and specify Martin TileJSON endpoint as a vector source URL. You should also specify a `source-layer` property. For [Table Sources](sources-pg-tables.md) it is `{table_name}` by default. +You can add a layer to the map and specify Martin TileJSON endpoint as a vector source URL. You should also specify +a `source-layer` property. For [Table Sources](sources-pg-tables.md) it is `{table_name}` by default. ```js map.addLayer({ - id: 'points', - type: 'circle', - source: { - type: 'vector', - url: 'http://localhost:3000/points' - }, - 'source-layer': 'points', - paint: { - 'circle-color': 'red' - } + id: 'points', + type: 'circle', + source: { + type: 'vector', + url: 'http://localhost:3000/points' + }, + 'source-layer': 'points', + paint: { + 'circle-color': 'red' + } }); ``` diff --git a/docs/src/using-with-maplibre.md b/docs/src/using-with-maplibre.md index a007ddf40..f8e5c94fc 100644 --- a/docs/src/using-with-maplibre.md +++ b/docs/src/using-with-maplibre.md @@ -1,65 +1,70 @@ ## Using with MapLibre -[MapLibre](https://maplibre.org/projects/maplibre-gl-js/) is an Open-source JavaScript library for showing maps on a website. MapLibre can accept [MVT vector tiles](https://github.com/mapbox/vector-tile-spec) generated by Martin, and applies [a style](https://maplibre.org/maplibre-gl-js-docs/style-spec/) to them to draw a map using Web GL. +[MapLibre](https://maplibre.org/maplibre-gl-js/docs/) is an Open-source JavaScript library for showing maps on a +website. MapLibre can accept [MVT vector tiles](https://github.com/mapbox/vector-tile-spec) generated by Martin, and +applies [a style](https://maplibre.org/maplibre-style-spec/) to them to draw a map using Web GL. -You can add a layer to the map and specify Martin [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint as a vector source URL. You should also specify a `source-layer` property. For [Table Sources](sources-pg-tables.md) it is `{table_name}` by default. +You can add a layer to the map and specify Martin [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint as a +vector source URL. You should also specify a `source-layer` property. For [Table Sources](sources-pg-tables.md) it +is `{table_name}` by default. ```js map.addLayer({ - id: 'points', - type: 'circle', - source: { - type: 'vector', - url: 'http://localhost:3000/points' - }, - 'source-layer': 'points', - paint: { - 'circle-color': 'red' - }, + id: 'points', + type: 'circle', + source: { + type: 'vector', + url: 'http://localhost:3000/points' + }, + 'source-layer': 'points', + paint: { + 'circle-color': 'red' + }, }); ``` ```js map.addSource('rpc', { - type: 'vector', - url: `http://localhost:3000/function_zxy_query` + type: 'vector', + url: `http://localhost:3000/function_zxy_query` }); map.addLayer({ - id: 'points', - type: 'circle', - source: 'rpc', - 'source-layer': 'function_zxy_query', - paint: { - 'circle-color': 'blue' - }, + id: 'points', + type: 'circle', + source: 'rpc', + 'source-layer': 'function_zxy_query', + paint: { + 'circle-color': 'blue' + }, }); ``` -You can also combine multiple sources into one source with [Composite Sources](sources-composite.md). Each source in a composite source can be accessed with its `{source_name}` as a `source-layer` property. +You can also combine multiple sources into one source with [Composite Sources](sources-composite.md). Each source in a +composite source can be accessed with its `{source_name}` as a `source-layer` property. ```js map.addSource('points', { - type: 'vector', - url: `http://0.0.0.0:3000/points1,points2` + type: 'vector', + url: `http://0.0.0.0:3000/points1,points2` }); map.addLayer({ - id: 'red_points', - type: 'circle', - source: 'points', - 'source-layer': 'points1', - paint: { - 'circle-color': 'red' - } + id: 'red_points', + type: 'circle', + source: 'points', + 'source-layer': 'points1', + paint: { + 'circle-color': 'red' + } }); map.addLayer({ - id: 'blue_points', - type: 'circle', - source: 'points', - 'source-layer': 'points2', - paint: { - 'circle-color': 'blue' - } + id: 'blue_points', + type: 'circle', + source: 'points', + 'source-layer': 'points2', + paint: { + 'circle-color': 'blue' + } }); ``` From 3a530552d91e13428a09d5579ef88e5449c75a15 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 16 Mar 2024 18:43:04 -0400 Subject: [PATCH 055/164] Bump cargo lock --- Cargo.lock | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58291164f..476cd8c30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,9 +564,9 @@ checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", "clap_derive", @@ -712,11 +712,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.52", @@ -1562,9 +1562,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -1623,6 +1623,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -2809,9 +2815,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -3084,9 +3090,9 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.11.25" +version = "0.11.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" +checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" dependencies = [ "base64 0.21.7", "bytes", @@ -3843,7 +3849,7 @@ checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ "dotenvy", "either", - "heck", + "heck 0.4.1", "hex", "once_cell", "proc-macro2", @@ -4111,20 +4117,20 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "system-configuration" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.2", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", @@ -4362,9 +4368,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4820,9 +4826,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ "redox_syscall", "wasite", From b28dae446617e49a745f3c4e0dc57a3b00dea5d6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 16 Mar 2024 22:45:43 -0400 Subject: [PATCH 056/164] chore: add empty pg table test (#1259) --- tests/expected/auto/catalog_auto.json | 4 ++++ tests/expected/auto/save_config.yaml | 8 ++++++++ .../martin-cp/flat-with-hash_save_config.yaml | 8 ++++++++ .../expected/martin-cp/flat_save_config.yaml | 8 ++++++++ .../martin-cp/normalized_save_config.yaml | 8 ++++++++ tests/fixtures/sprites/expected/all_1.png | Bin 787 -> 785 bytes tests/fixtures/sprites/expected/all_2.png | Bin 1569 -> 1567 bytes tests/fixtures/sprites/expected/src1_1.png | Bin 758 -> 758 bytes tests/fixtures/sprites/expected/src2_1.png | Bin 191 -> 189 bytes tests/fixtures/sprites/expected/src2_2.png | Bin 344 -> 344 bytes tests/fixtures/tables/points_empty.sql | 9 +++++++++ 11 files changed, 45 insertions(+) create mode 100644 tests/fixtures/tables/points_empty.sql diff --git a/tests/expected/auto/catalog_auto.json b/tests/expected/auto/catalog_auto.json index e3d4a3531..5a59f1a5d 100644 --- a/tests/expected/auto/catalog_auto.json +++ b/tests/expected/auto/catalog_auto.json @@ -116,6 +116,10 @@ "content_type": "application/x-protobuf", "description": "public.points3857.geom" }, + "points_empty": { + "content_type": "application/x-protobuf", + "description": "public.points_empty.geom" + }, "points_empty_srid": { "content_type": "application/x-protobuf", "description": "public.points_empty_srid.geom" diff --git a/tests/expected/auto/save_config.yaml b/tests/expected/auto/save_config.yaml index 3b1105cae..a6fc8d64c 100644 --- a/tests/expected/auto/save_config.yaml +++ b/tests/expected/auto/save_config.yaml @@ -112,6 +112,14 @@ postgres: geometry_type: POINT properties: gid: int4 + points_empty: + schema: public + table: points_empty + srid: 900913 + geometry_column: geom + geometry_type: GEOMETRY + properties: + gid: int4 points_empty_srid: schema: public table: points_empty_srid diff --git a/tests/expected/martin-cp/flat-with-hash_save_config.yaml b/tests/expected/martin-cp/flat-with-hash_save_config.yaml index 4e811e610..e3b1109ea 100644 --- a/tests/expected/martin-cp/flat-with-hash_save_config.yaml +++ b/tests/expected/martin-cp/flat-with-hash_save_config.yaml @@ -111,6 +111,14 @@ postgres: geometry_type: POINT properties: gid: int4 + points_empty: + schema: public + table: points_empty + srid: 900913 + geometry_column: geom + geometry_type: GEOMETRY + properties: + gid: int4 points_empty_srid: schema: public table: points_empty_srid diff --git a/tests/expected/martin-cp/flat_save_config.yaml b/tests/expected/martin-cp/flat_save_config.yaml index 4e811e610..e3b1109ea 100644 --- a/tests/expected/martin-cp/flat_save_config.yaml +++ b/tests/expected/martin-cp/flat_save_config.yaml @@ -111,6 +111,14 @@ postgres: geometry_type: POINT properties: gid: int4 + points_empty: + schema: public + table: points_empty + srid: 900913 + geometry_column: geom + geometry_type: GEOMETRY + properties: + gid: int4 points_empty_srid: schema: public table: points_empty_srid diff --git a/tests/expected/martin-cp/normalized_save_config.yaml b/tests/expected/martin-cp/normalized_save_config.yaml index 4e811e610..e3b1109ea 100644 --- a/tests/expected/martin-cp/normalized_save_config.yaml +++ b/tests/expected/martin-cp/normalized_save_config.yaml @@ -111,6 +111,14 @@ postgres: geometry_type: POINT properties: gid: int4 + points_empty: + schema: public + table: points_empty + srid: 900913 + geometry_column: geom + geometry_type: GEOMETRY + properties: + gid: int4 points_empty_srid: schema: public table: points_empty_srid diff --git a/tests/fixtures/sprites/expected/all_1.png b/tests/fixtures/sprites/expected/all_1.png index 197c70d09170009358a804c09136a9b17b727ff5..ffb3546925d2136c95e615982d07ad025b0077b1 100644 GIT binary patch delta 700 zcmV;t0z>_i29XAkBmvlwB_RQ_kw+wdA$tj;mqa`i57K%pD9?H2?XnJrWtmqJ!4E!m zXXbs$`)1zEtkw>oX`_NA!KNS(>(m!-r+agEeCWmG>D8yH0jOjWjraKr``X3g7{*|1 zIg|K~T8#r_z;KfHA;uW89!-3$K7nsbW%yJn!a~NZ7RNDU>N?!nW4i!m*=jz@u=;P370vIP|27L zoaMz^=O|%+F3(K?Y95d4tEwiFf}lvlsrzS_Pp$YG@DNvRe&ToowJIh;f@=&$ni`=n z7|CIRftZM-RaYacYC>L>hly~1Er4(TGhe zqGNKiBS$vxhn45Euxm$;YoxFDfP3>}493n3hxe-*vA8$8Q(o`#SKM2F`}5*F+)RzZ zgR7UY?Gi6eJgzxz^d#%?ODH8{A(7-4O1Ldw-#P!0^Fy)4V4|f-$eWRgrQ+m9I};xs zWqx28avCu>SA#ZuNf3~wv7_*6`V4+VBJthX8%Qjz6sMV-(nn+0fXw{!CZsa+-7^$p zXu;5;BY2J4TdyTUmUPd5*wkkP{PULl^Gezd!4gb*+DS?#q@?Wt48c0RUl&{#tO=%h zv|FEim1eI_&$6IRvzetnpg4m^%Wq- i&{OvtSJM7R7veWEY1+w8yORk30000E7HOA9^u)di7~$0BX5Z^L_EcKEGHT!x)UM z=2G8LtEm7PU{3M@#26;((ZtvK6Zp1Ng-^9IEaZ%O$>>Xzjp(srDxO5*JNDs!7{*{M zY8Ix3*HxLQa6(Al*F3=4#l(pg<+&+9&Es)>Rn|nB6C}x;x_@^0)JmWM4{_DzCyqB!D`O(Uxu(EKOCyv9 zV+Bkw6jQOR>}up?O^B=VFcocogfT%hWsS5H8Zkv91M%H(wtp{(iTCc={#P3{vPM85 zE&Qf8!5b$JAw?r-uB(keh|=nQBUta=ByW$NfSo$dQfvVdeQO?Ap=e8tLmj;NJWggRwKi(fzVUOx2s+DX(|MEAFj-{dsX7Zf3^d z!PQIHc8M1!9@i>v^t96BmrzM3B0R}2l&~*f-#P!$(Wo%fR$!v72`Cz|iKX)7x}S*; zk8(e;3{@IoDp!Lxe8t(wm9eAnYWfWRiA3VNvp0}fS{apQ3Q~U>y9Q+Dzc(S2S>T?b z7^a0on~vZ$YHz-l44J}zJ!4ZJ3;E-1@$*vJ4#DJ1I}LgV&WMz@17MsMyz;UBPOBc4=fep)WlT?r zv}im_{Z7ISIjwqt=iT;fRuG;M;Y0#Ct$NtvQaiI2G%lxA4@M;|k)(E#+IrBqlvXjs kSps_MLE}=|Ep#FN05WOX$sKl12mk;807*qoM6N<$f`JKHIsgCw diff --git a/tests/fixtures/sprites/expected/all_2.png b/tests/fixtures/sprites/expected/all_2.png index c8343819da06ff76bc66ddfd2f51609dcc7ef924..e1ce6514bfef7520f22e378a4d87aece82c7f688 100644 GIT binary patch delta 902 zcmV;119|+R44(|JcLINtNklsK2^7zXf1c1u#I#dyhLqm)u(ZEOoFB(^~$ z5|m0Y5u(-VHdw1ssiA5?2|A)v>-|!F|6q3}n-Z4n&fA;rwrJS8SHh_Rr7e!;~5CRS@HN=~zz-Ap=kZl%D#L#A5)N3zmHyXp(rx{TyGpen*)vOuIH+F4jf5c5mZXTcd?Tu10{dBN=?A*oD4N-LD^nY z>-bFUbItXvF-pc|gh?n%8(znT=wRI|*_dZ^M9S!+y1ibli;im5_3ejXkdy{`_lGZu z5Z{PP!!WQ)(x7DNIkAeAX$F~fN7!Z{PDABxphl49XDPrmXTJ;4@AOuljtU|+yeDmiy4NAERDM)m1+KjsE(2 z)m5&jvt=^CzO4ZL%U`(rh?n|cv?v)Cp$%=i`z-gvEW^CjYmdC`2E2X{X8ebi_Tanj z9&hx4WrDvDJo?JkC+@Dx*TmU=a9AtSV8w#gcSd+N>mOWpJ@3`lw>b9{{$C>9@uIk6 zOY9o$#RW&ppeM41AA3(&*@zAcy)t3AR=ts2>3FV^=qOK~0&usf)nPFi3!Tl7f-cfn zW>L0T%)~l>$2>G5W*RgwlAV*Dx$MY5=y#J41r&dli5x@Py%|aYND*D2oFVOAit@ly zL{G&^`;%iz`BFr=1Z+p0(_$P* zkjFtHN8}h%HoHuzRvE?hd^Alt{X*G}PQlfDi{8`=bhJ6g^#@{x($Oin3X}j~t4(!i zM!kO50do2S5>$vz!9}F2^rlkTpB*~i%%an~EGeo@1<~%@%%W3p6)6E3>w2Bj)%_*OqE)o^fc5pVN c_xvCI3tS4geFRkVJOBUy07*qoM6N<$f_FlsK2^7zXf1c1zMwi}Au@qm)u(ZEOoFB(|wY zBq)_)B1EgzZLn6OQbW~(5_CkT*88RU{=x1{HYF_CotK;(k01K`z~SXN$&=Zc?1J55 zk4>JNky6e~9!ntL)FshaJcNKliw*JSDX>|`=4G4t6EU=z6ZJ6K>dnS5c6q#UbG23% zbL@(e3>vr4a#~z-JvSN$(B?qnhU>W|o&(2_t_Ug(!FQ>XB?BdYx=KyJ?3@fWX+haq zRqOan>~UR{tO^*7%LtQD7T3Lwb|il%Jv^Wi?e7A^h@k(BhEZMs&`STay z+rD#Wn^#hjEHkPkgtZgZ}r+EZ@U4nAA}kIp`|_e zuDi<{ePEg3F9eUiviXU-p!J;*o{jnkS5(7$wY5$2J%#@-k>By6 zxNB4F812P>10vaE>kz6~=6H%9kpWuS}Hz zAX)Y&$CUD=h;m8Tjyk8sIFKZdgJe$qG^AX1nNqDXitG7knsWLNWji_rSMw!$Q!mod z<{Z~=h-pekr{F43QmsdAszcN2wGNQeZ;+%ybP6saU8Ogb%Kq%og=Q9=?z5y=jO*Wb z=4KXKor0@KN%)df49?N%J~n;|zC5Lab94$WyFw{wV^pz&b94$ehiK|Ba5zuo1ZPvq u=Tu0mIKkPR^4aMkQ88@?XG40=|Ixo(3b=jzso?Mc0000vDv diff --git a/tests/fixtures/sprites/expected/src1_1.png b/tests/fixtures/sprites/expected/src1_1.png index 8aeb48a2d6a1c03a554d99b0fa006b8d71dc7775..b3c301e8271c15e67ee8cc03248ad96fd6c5fe1e 100644 GIT binary patch delta 723 zcmV;^0xbRZ1@;AyFMrce9LICjsq~-+PyS=jb_f-A@nk_S&O?K1*qFk~M8;5Q1sMeA ztcVJNSTU`R9TH>+BHA*&OvLt}ld(f`8KRd)JPZ%Ac^oJ|-!J@LiCIF7P1?(T@FjWg z{oZ?@{NC^VB6t}H!YGr<)MNsZPJJ1#d2jEI551f`z4|Oa0Dm<(yYfM~u+PgE$Iu6T zt8(@S&UFJ3IfReUM|93dm~Zu`@O`lgpKBGEm!*1H>PuCm_%S7$%%Jcc`)~|>&==>- zPYrK4VN@mvsQZG=@N01c)Vq5Zp)4hTD}!-x)1#rozm{gNwfu2zyD(fOfvhG=EBMt5 zx6aYV{#u%y0)L$IWIVmfVRB5+rbM0>&o7@^_Jgnsqc}Hl+{!nEi7~B(0Mr!7%7cj# zZWKt_M1e=A$QKPON)NN~Mi3a1#(|n40%=a5f#hyD+rM`cK<}RIf3T zVwtd4=v=7Ro=nZ9Vr;Xow6Uk&+&TZr?T2cH0AmUcQ>4ViVr6o}3+Cfv`6nK)8;}@g zbSSY^o`10F*im>reFlHFD17I+gTf=ryFr!O`niT~1l4UAkK^;tDe@78U}nJtM3n46aGqG?PyTRTTUF`-K)GU@bwooSt^!Bn8WjzQEZ5;{GrOa?`!NPR$l zV$?9}^yF<|su7GxU?x+V`_p?QrrQ=z(T&n<$4u6w@dEX8=thKmzstcMIXOG_0RDpHC{B1j=v zYeZBK#E40>^pHi0AfgG?OGQi%S}8qbFGci{6%WOORF4JaId6Fr#_cZawv*)24?cEh z=grP<-@KXCyabvy%w6Vga09tc&k|na-rgM@csYK0_k{|4u9jdntJjKpPpqVej}?;91RC%08TMfe#^RXS ziNQ4|Oqm-3`o1O!zZNGzzq@x4ihA@Wsi$-(e`0c5ByYO!qZ3s;(_@Rzw6xS1Y-2Ujm)Ti8B8 z@tBZL=#vVse`zQB2cSdWM2%<)rsMEE=ZBk}(+(52T ze9Ocr3rw_W;wr%~0<*Z|BA)JBqPq0*80{!ST1>VE^=IfgLE|#2mvaZ1QbB`!rEFR4 z*m!`_+rlG9{>;pmyB1zl9QC40MhA_HXGw^%vE?pi9)1;OYPX002ovPDHLk FV1ffWTs{B* diff --git a/tests/fixtures/sprites/expected/src2_1.png b/tests/fixtures/sprites/expected/src2_1.png index 076b4c2c412cc822263904304717a9fedc844536..db2640780735fc4dec9a06f6443d03133329341e 100644 GIT binary patch delta 161 zcmV;S0AByU0lfi`B!7fSL_t(|+O5$+5yCJSMBz_Dr63^=h=fY01CUY&;GlKTI3NyE z2R}0%E}d|LcYC{gTYser?R#7SLCwtBz zaWGV+xTKaF{L9qu>0A3NRcPPi3J7{;BN&B2N4DW+x0=q6Mc9OgVsID2B15*z#|=+| ztf_;O>x|B zQv!%Y;Y%B-BB@~)O0QCQz!wDcn8fFv-xhZitzkgHQzqW~G#iP1xy8tWmV76?aZ#l* zoQ@Sl9oUQpl&UClH<8CCYxGzY(A!aM0bo%O#iN zM&WyV{Q&a%(&VM!4|t3yvL+nHL&fFDNu!HXy#J)(u$agwxVcDE6Z@@i1pRLDra11m zDam`H@THAZk<_pYrB^9D;0pqJOyYCTXNxvp3HIc_AYjj%_(DQAADP|OBGgVkAY+zGnWf+@{%7$4 X@xtlDO$A=t00000NkvXXu0mjfNwtGI diff --git a/tests/fixtures/tables/points_empty.sql b/tests/fixtures/tables/points_empty.sql new file mode 100644 index 000000000..5e3c6b3d1 --- /dev/null +++ b/tests/fixtures/tables/points_empty.sql @@ -0,0 +1,9 @@ +-- This table is intentionally left empty +CREATE TABLE points_empty +( + gid SERIAL PRIMARY KEY, + geom GEOMETRY +); + +CREATE INDEX ON points_empty USING GIST (geom); +CLUSTER points_empty_geom_idx ON points_empty; From 69149c6571503ec63fdc08fa8cd0b44961322253 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:58:23 -0400 Subject: [PATCH 057/164] chore(deps): Bump follow-redirects from 1.15.4 to 1.15.6 in /demo/frontend (#1258) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
Commits
  • 35a517c Release version 1.15.6 of the npm package.
  • c4f847f Drop Proxy-Authorization across hosts.
  • 8526b4a Use GitHub for disclosure.
  • b1677ce Release version 1.15.5 of the npm package.
  • d8914f7 Preserve fragment in responseUrl.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.4&new-version=1.15.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- demo/frontend/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/frontend/yarn.lock b/demo/frontend/yarn.lock index 806a98b28..e61e13993 100644 --- a/demo/frontend/yarn.lock +++ b/demo/frontend/yarn.lock @@ -2796,9 +2796,9 @@ flatted@^3.2.9: integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== follow-redirects@^1.15.0: - version "1.15.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" - integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== for-each@^0.3.3: version "0.3.3" From 7107db5887f6233f3066077513978cbfe2757c46 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 17 Mar 2024 21:17:30 -0400 Subject: [PATCH 058/164] Fix apply-patch documentation (#1261) --- docs/src/mbtiles-diff.md | 4 ++-- mbtiles/src/bin/mbtiles.rs | 7 ++++--- mbtiles/src/copier.rs | 29 +++++++++++++-------------- mbtiles/src/patcher.rs | 41 ++++++++++++++++---------------------- mbtiles/src/validation.rs | 5 ++--- mbtiles/tests/copy.rs | 6 ++---- 6 files changed, 41 insertions(+), 51 deletions(-) diff --git a/docs/src/mbtiles-diff.md b/docs/src/mbtiles-diff.md index 607b8df0d..b2d627b2d 100644 --- a/docs/src/mbtiles-diff.md +++ b/docs/src/mbtiles-diff.md @@ -9,7 +9,7 @@ insertions, and deletions as `NULL` values), for both the tile and metadata tabl There is one exception: `agg_tiles_hash` metadata value will be renamed to `agg_tiles_hash_after_apply`, and a new `agg_tiles_hash` will be generated for the diff file itself. This is done to avoid confusion when applying the diff -file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-diff` +file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. The `apply-patch` command will automatically rename the `agg_tiles_hash_after_apply` value back to `agg_tiles_hash` when applying the diff. @@ -18,7 +18,7 @@ diff. mbtiles diff file1.mbtiles file2.mbtiles diff.mbtiles # If diff.mbtiles is applied to file1.mbtiles, it will produce file2.mbtiles -mbtiles apply-diff file1.mbtiles diff.mbtiles file2a.mbtiles +mbtiles apply-patch file1.mbtiles diff.mbtiles file2a.mbtiles # file2.mbtiles and file2a.mbtiles should now be the same # Validate both files and see that their hash values are identical diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index fc3d7228f..6776bcbe0 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -102,11 +102,12 @@ pub struct CopyArgs { pub options: SharedCopyOpts, /// Compare source file with this file, and only copy non-identical tiles to destination. /// Use `mbtiles diff` as a more convenient way to generate this file. - /// It should be later possible to run `mbtiles apply-diff` to merge it in. + /// Use `mbtiles apply-patch` or `mbtiles copy --apply-patch` to apply the diff file. #[arg(long, conflicts_with("apply_patch"))] diff_with_file: Option, - /// Compare source file with this file, and only copy non-identical tiles to destination. - /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. + /// Apply a patch file while copying src to dst. + /// Use `mbtiles diff` or `mbtiles copy --diff-with-file` to generate the patch file. + /// Use `mbtiles apply-patch` to apply the patch file in-place, without making a copy of the original. #[arg(long, conflicts_with("diff_with_file"))] apply_patch: Option, } diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index ebe8b76c2..c3b450fb3 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -63,11 +63,8 @@ pub struct MbtilesCopier { /// Bounding box to copy, in the format `min_lon,min_lat,max_lon,max_lat`. Can be used multiple times. pub bbox: Vec, /// Compare source file with this file, and only copy non-identical tiles to destination. - /// Use `mbtiles diff` as a more convenient way to generate this file. - /// It should be later possible to run `mbtiles apply-diff` to merge it in. pub diff_with_file: Option, - /// Compare source file with this file, and only copy non-identical tiles to destination. - /// It should be later possible to run `mbtiles apply-diff SRC_FILE DST_FILE` to get the same DIFF file. + /// Apply a patch file while copying src to dst. pub apply_patch: Option, /// Skip generating a global hash for mbtiles validation. By default, `mbtiles` will compute `agg_tiles_hash` metadata value. pub skip_agg_tiles_hash: bool, @@ -128,7 +125,7 @@ impl MbtileCopierInt { (Some(dif_file), None) | (None, Some(dif_file)) => { let dif_mbt = Mbtiles::new(dif_file)?; let dif_type = dif_mbt.open_and_detect_type().await?; - Some((dif_mbt, dif_type, dif_type)) + Some((dif_mbt, dif_type)) } (Some(_), Some(_)) => unreachable!(), // validated in the Self::new _ => None, @@ -157,7 +154,7 @@ impl MbtileCopierInt { CopyType::Metadata => "metadata ", }; let dst_type: MbtType; - if let Some((dif_mbt, dif_type, _)) = &dif { + if let Some((dif_mbt, dif_type)) = &dif { if !is_empty_db { return Err(MbtError::NonEmptyTargetFile(self.options.dst_file)); } @@ -183,9 +180,9 @@ impl MbtileCopierInt { self.init_new_schema(&mut conn, src_type, dst_type).await?; } + // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn + // Make sure not to execute any other queries while the handle is locked { - // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn - // Make sure not to execute any other queries while the handle is locked let mut handle_lock = conn.lock_handle().await?; let handle = handle_lock.as_raw_handle().as_ptr(); @@ -205,7 +202,7 @@ impl MbtileCopierInt { } if self.options.copy.copy_metadata() { - self.copy_metadata(&rusqlite_conn, dif.as_ref(), on_duplicate)?; + self.copy_metadata(&rusqlite_conn, dif.is_some(), on_duplicate)?; } else { debug!("Skipping copying metadata"); } @@ -215,9 +212,11 @@ impl MbtileCopierInt { dst_mbt.update_agg_tiles_hash(&mut conn).await?; } + if dif.is_some() { + detach_db(&mut conn, "diffDb").await?; + } + detach_db(&mut conn, "sourceDb").await?; - // Ignore error because we might not have attached diffDb - let _ = detach_db(&mut conn, "diffDb").await; Ok(conn) } @@ -225,12 +224,12 @@ impl MbtileCopierInt { fn copy_metadata( &self, rusqlite_conn: &Connection, - dif: Option<&(Mbtiles, MbtType, MbtType)>, + is_diff: bool, on_duplicate: CopyDuplicateMode, ) -> Result<(), MbtError> { let on_dupl = on_duplicate.to_sql(); let sql; - if dif.is_some() { + if is_diff { // Insert all rows from diffDb.metadata if they do not exist or are different in sourceDb.metadata. // Also insert all names from sourceDb.metadata that do not exist in diffDb.metadata, with their value set to NULL. // Rename agg_tiles_hash to agg_tiles_hash_after_apply because agg_tiles_hash will be auto-added later @@ -282,14 +281,14 @@ impl MbtileCopierInt { fn copy_tiles( &self, rusqlite_conn: &Connection, - dif: Option<&(Mbtiles, MbtType, MbtType)>, + dif: Option<&(Mbtiles, MbtType)>, src_type: MbtType, dst_type: MbtType, on_duplicate: CopyDuplicateMode, ) -> Result<(), MbtError> { let on_dupl = on_duplicate.to_sql(); - let select_from = if let Some((_, dif_type, _)) = &dif { + let select_from = if let Some((_, dif_type)) = &dif { if self.options.diff_with_file.is_some() { Self::get_select_from_with_diff(*dif_type, dst_type) } else { diff --git a/mbtiles/src/patcher.rs b/mbtiles/src/patcher.rs index 3ae43163a..6e983ffec 100644 --- a/mbtiles/src/patcher.rs +++ b/mbtiles/src/patcher.rs @@ -14,60 +14,53 @@ pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<( let mut conn = base_mbt.open().await?; let base_type = base_mbt.detect_type(&mut conn).await?; - patch_mbt.attach_to(&mut conn, "patchDb").await?; info!("Applying patch file {patch_mbt} ({patch_type}) to {base_mbt} ({base_type})"); + + patch_mbt.attach_to(&mut conn, "patchDb").await?; let select_from = get_select_from(base_type, patch_type); let (main_table, insert1, insert2) = get_insert_sql(base_type, select_from); - query(&format!("{insert1} WHERE tile_data NOTNULL")) - .execute(&mut conn) - .await?; + let sql = format!("{insert1} WHERE tile_data NOTNULL"); + query(&sql).execute(&mut conn).await?; if let Some(insert2) = insert2 { - query(&format!("{insert2} WHERE tile_data NOTNULL")) - .execute(&mut conn) - .await?; + let sql = format!("{insert2} WHERE tile_data NOTNULL"); + query(&sql).execute(&mut conn).await?; } - query(&format!( + let sql = format!( " DELETE FROM {main_table} WHERE (zoom_level, tile_column, tile_row) IN ( SELECT zoom_level, tile_column, tile_row FROM ({select_from} WHERE tile_data ISNULL) )" - )) - .execute(&mut conn) - .await?; + ); + query(&sql).execute(&mut conn).await?; if base_type.is_normalized() { debug!("Removing unused tiles from the images table (normalized schema)"); - query("DELETE FROM images WHERE tile_id NOT IN (SELECT tile_id FROM map)") - .execute(&mut conn) - .await?; + let sql = "DELETE FROM images WHERE tile_id NOT IN (SELECT tile_id FROM map)"; + query(sql).execute(&mut conn).await?; } // Copy metadata from patchDb to the destination file, replacing existing values // Convert 'agg_tiles_hash_in_patch' into 'agg_tiles_hash' // Delete metadata entries if the value is NULL in patchDb - query(&format!( + let sql = format!( " INSERT OR REPLACE INTO metadata (name, value) SELECT IIF(name = '{AGG_TILES_HASH_AFTER_APPLY}', '{AGG_TILES_HASH}', name) as name, value FROM patchDb.metadata WHERE name NOTNULL AND name != '{AGG_TILES_HASH}';" - )) - .execute(&mut conn) - .await?; + ); + query(&sql).execute(&mut conn).await?; - query( - " + let sql = " DELETE FROM metadata - WHERE name IN (SELECT name FROM patchDb.metadata WHERE value ISNULL);", - ) - .execute(&mut conn) - .await?; + WHERE name IN (SELECT name FROM patchDb.metadata WHERE value ISNULL);"; + query(sql).execute(&mut conn).await?; detach_db(&mut conn, "patchDb").await } diff --git a/mbtiles/src/validation.rs b/mbtiles/src/validation.rs index d583af078..1ac919f2c 100644 --- a/mbtiles/src/validation.rs +++ b/mbtiles/src/validation.rs @@ -24,8 +24,7 @@ use crate::{invert_y_value, Mbtiles}; /// Metadata key for the aggregate tiles hash value pub const AGG_TILES_HASH: &str = "agg_tiles_hash"; -/// Metadata key for a diff file, -/// describing the eventual [`AGG_TILES_HASH`] value once the diff is applied +/// Metadata key for a diff file, describing the eventual [`AGG_TILES_HASH`] value of the resulting tileset once the diff is applied pub const AGG_TILES_HASH_AFTER_APPLY: &str = "agg_tiles_hash_after_apply"; #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, EnumDisplay, Serialize)] @@ -116,7 +115,7 @@ impl Mbtiles { tested_zoom = r.zoom_level.unwrap_or(-1); } - // Afterwards, iterate over tiles in all allowed zooms and check for consistency + // Afterward, iterate over tiles in all allowed zooms and check for consistency for z in tilejson.minzoom.unwrap_or(0)..=tilejson.maxzoom.unwrap_or(18) { if i64::from(z) == tested_zoom { continue; diff --git a/mbtiles/tests/copy.rs b/mbtiles/tests/copy.rs index f81438d85..97efcc64e 100644 --- a/mbtiles/tests/copy.rs +++ b/mbtiles/tests/copy.rs @@ -5,7 +5,6 @@ use std::str::from_utf8; use ctor::ctor; use insta::{allow_duplicates, assert_snapshot}; use itertools::Itertools as _; -use log::info; use martin_tile_utils::xyz_to_bbox; use mbtiles::AggHashType::Verify; use mbtiles::IntegrityCheckType::Off; @@ -105,14 +104,14 @@ async fn open(file: &str) -> MbtResult<(Mbtiles, SqliteConnection)> { /// Run [`MbtilesCopier`], the first two params are source and destination [`Mbtiles`] refs, the rest are optional (key => val)* params. macro_rules! copy { - ($src_path:expr, $dst_path:expr $( , $key:tt => $val:expr )* $(,)?) => {{ + ($src_path:expr, $dst_path:expr $( , $key:tt => $val:expr )* $(,)?) => { MbtilesCopier { src_file: $src_path, dst_file: $dst_path $(, $key : $val)*, ..Default::default() }.run().await.unwrap() - }}; + }; } /// Same as the copy! macro, but with the result dumped. @@ -509,7 +508,6 @@ async fn patch_on_copy( let v2 = v2_type.map_or("dflt", shorten); let prefix = format!("{v1}+{dif}={v2}"); - info!("TEST: Compare v1 with v2, and copy anything that's different (i.e. mathematically: v2-v1=diff)"); let (v2_mbt, mut v2_cn) = open!(patch_on_copy, "{prefix}__v2"); copy! { databases.path("v1", v1_type), From 23505da318ffb506d16f15c4c63dd12eea44cd2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:29:23 +0000 Subject: [PATCH 059/164] chore(deps): Bump serde_yaml from 0.9.32 to 0.9.33 (#1264) Bumps [serde_yaml](https://github.com/dtolnay/serde-yaml) from 0.9.32 to 0.9.33.
Release notes

Sourced from serde_yaml's releases.

0.9.33

Commits
  • f4c9ed9 Release 0.9.33
  • b4edaee Pull in yaml_parser_fetch_more_tokens fix from libyaml
  • 8a5542c Resolve non_local_definitions warning in test
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_yaml&package-manager=cargo&previous-version=0.9.32&new-version=0.9.33)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 476cd8c30..378cd1710 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3573,9 +3573,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ "indexmap 2.2.5", "itoa", @@ -4578,9 +4578,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "untrusted" From 8c13a20849367f31dbe19d6387a67e2d56224b38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:29:32 +0000 Subject: [PATCH 060/164] chore(deps): Bump async-trait from 0.1.77 to 0.1.78 (#1263) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.77 to 0.1.78.
Release notes

Sourced from async-trait's releases.

0.1.78

  • Prevent unused_qualifications lint being triggered in generated code in nightly-2024-03-05 and up (#260)
Commits
  • c73061d Release 0.1.78
  • b6314bc Refactor inferred bound filtering
  • 8d51928 Merge pull request #262 from dtolnay/asyncspan
  • c98a408 Minimize use of async token's span in expanded code
  • 2f5343c Merge pull request #261 from dtolnay/inferredbound
  • 1a01bb4 Skip needlessly generating inferred bounds during ?Send
  • e68d68c Merge pull request #260 from dtolnay/qualifications
  • 75879e8 Ignore intentional unused_qualifications in a regression test
  • 4cf4ff6 Ignore unused_qualifications rustc lint in generated code
  • 2002954 Reproduce unused_qualifications lint in tests
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=async-trait&package-manager=cargo&previous-version=0.1.77&new-version=0.1.78)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 378cd1710..0e8989bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,9 +411,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", From a486857e7c324873c810669d6a9d9fecaf58a9c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:23:47 -0400 Subject: [PATCH 061/164] chore(deps): Bump brotli from 3.4.0 to 3.5.0 (#1262) Bumps [brotli](https://github.com/dropbox/rust-brotli) from 3.4.0 to 3.5.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=brotli&package-manager=cargo&previous-version=3.4.0&new-version=3.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e8989bd7..9d70196b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,9 +531,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", From f454113a501f08cecd3b57f7b56316bd9c1eb88a Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 19 Mar 2024 02:56:18 -0400 Subject: [PATCH 062/164] noop: refactor mbtiles copy to support new cases (#1265) There should be no functionality change - this will just allow for more changes later. --- mbtiles/src/copier.rs | 466 ++++++++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 216 deletions(-) diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index c3b450fb3..0224b7b9a 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -121,106 +121,158 @@ impl MbtileCopierInt { } pub async fn run(self) -> MbtResult { - let dif = match (&self.options.diff_with_file, &self.options.apply_patch) { - (Some(dif_file), None) | (None, Some(dif_file)) => { - let dif_mbt = Mbtiles::new(dif_file)?; - let dif_type = dif_mbt.open_and_detect_type().await?; - Some((dif_mbt, dif_type)) - } - (Some(_), Some(_)) => unreachable!(), // validated in the Self::new - _ => None, - }; - - // src and diff file connections are not needed later, as they will be attached to the dst file - let src_mbt = &self.src_mbtiles; - let dst_mbt = &self.dst_mbtiles; + if self.options.diff_with_file.is_none() && self.options.apply_patch.is_none() { + self.run_simple().await + } else { + self.run_with_diff_or_patch().await + } + } - let src_type = src_mbt.open_and_detect_type().await?; - let mut conn = dst_mbt.open_or_new().await?; + pub async fn run_simple(self) -> MbtResult { + let src_type = self.src_mbtiles.open_and_detect_type().await?; + let mut conn = self.dst_mbtiles.open_or_new().await?; let is_empty_db = is_empty_database(&mut conn).await?; + let on_duplicate = if let Some(on_duplicate) = self.options.on_duplicate { on_duplicate - } else if !is_empty_database(&mut conn).await? { - return Err(MbtError::DestinationFileExists(self.options.dst_file)); - } else { + } else if is_empty_db { CopyDuplicateMode::Override + } else { + return Err(MbtError::DestinationFileExists(self.options.dst_file)); }; - src_mbt.attach_to(&mut conn, "sourceDb").await?; + self.src_mbtiles.attach_to(&mut conn, "sourceDb").await?; - let what = match self.options.copy { - CopyType::All => "", - CopyType::Tiles => "tiles data ", - CopyType::Metadata => "metadata ", - }; - let dst_type: MbtType; - if let Some((dif_mbt, dif_type)) = &dif { - if !is_empty_db { - return Err(MbtError::NonEmptyTargetFile(self.options.dst_file)); - } - dst_type = self.options.dst_type().unwrap_or(src_type); - dif_mbt.attach_to(&mut conn, "diffDb").await?; - let dif_path = dif_mbt.filepath(); - if self.options.diff_with_file.is_some() { - info!("Comparing {src_mbt} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_mbt} ({dst_type})"); - } else { - info!("Applying patch from {dif_path} ({dif_type}) to {src_mbt} ({src_type}) {what}into a new file {dst_mbt} ({dst_type})"); - } - } else if is_empty_db { - dst_type = self.options.dst_type().unwrap_or(src_type); - info!("Copying {src_mbt} ({src_type}) {what}to a new file {dst_mbt} ({dst_type})"); + let dst_type = if is_empty_db { + self.options.dst_type().unwrap_or(src_type) } else { - dst_type = self.validate_dst_type(dst_mbt.detect_type(&mut conn).await?)?; - info!( - "Copying {src_mbt} ({src_type}) {what}to an existing file {dst_mbt} ({dst_type})" - ); - } + self.validate_dst_type(self.dst_mbtiles.detect_type(&mut conn).await?)? + }; + + info!( + "Copying {src_mbt} ({src_type}) {what}to a {is_new} file {dst_mbt} ({dst_type})", + src_mbt = self.src_mbtiles, + what = self.copy_text(), + is_new = if is_empty_db { "new" } else { "existing" }, + dst_mbt = self.dst_mbtiles, + ); if is_empty_db { self.init_new_schema(&mut conn, src_type, dst_type).await?; } - // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn - // Make sure not to execute any other queries while the handle is locked - { - let mut handle_lock = conn.lock_handle().await?; - let handle = handle_lock.as_raw_handle().as_ptr(); - - // SAFETY: this is safe as long as handle_lock is valid. We will drop the lock. - let rusqlite_conn = unsafe { Connection::from_handle(handle) }?; - - if self.options.copy.copy_tiles() { - self.copy_tiles( - &rusqlite_conn, - dif.as_ref(), - src_type, - dst_type, - on_duplicate, - )?; - } else { - debug!("Skipping copying tiles"); - } + self.copy_with_rusqlite( + &mut conn, + on_duplicate, + dst_type, + get_select_from(src_type, dst_type), + false, + ) + .await?; - if self.options.copy.copy_metadata() { - self.copy_metadata(&rusqlite_conn, dif.is_some(), on_duplicate)?; - } else { - debug!("Skipping copying metadata"); - } + if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { + self.dst_mbtiles.update_agg_tiles_hash(&mut conn).await?; } - if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { - dst_mbt.update_agg_tiles_hash(&mut conn).await?; + detach_db(&mut conn, "sourceDb").await?; + + Ok(conn) + } + + pub async fn run_with_diff_or_patch(self) -> MbtResult { + let ((Some(dif_file), None) | (None, Some(dif_file))) = + (&self.options.diff_with_file, &self.options.apply_patch) + else { + unreachable!() + }; + let dif_mbt = Mbtiles::new(dif_file)?; + let dif_type = dif_mbt.open_and_detect_type().await?; + let is_creating_diff = self.options.diff_with_file.is_some(); + + let src_type = self.src_mbtiles.open_and_detect_type().await?; + + let mut conn = self.dst_mbtiles.open_or_new().await?; + if !is_empty_database(&mut conn).await? { + return Err(MbtError::NonEmptyTargetFile(self.options.dst_file)); } - if dif.is_some() { - detach_db(&mut conn, "diffDb").await?; + self.src_mbtiles.attach_to(&mut conn, "sourceDb").await?; + dif_mbt.attach_to(&mut conn, "diffDb").await?; + + let what = self.copy_text(); + let src_path = &self.src_mbtiles.filepath(); + let dst_path = &self.dst_mbtiles.filepath(); + let dif_path = dif_mbt.filepath(); + let dst_type = self.options.dst_type().unwrap_or(src_type); + if is_creating_diff { + info!("Comparing {src_path} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_path} ({dst_type})"); + } else { + info!("Applying patch from {dif_path} ({dif_type}) to {src_path} ({src_type}) {what}into a new file {dst_path} ({dst_type})"); + } + + self.init_new_schema(&mut conn, src_type, dst_type).await?; + + self.copy_with_rusqlite( + &mut conn, + CopyDuplicateMode::Override, + dst_type, + &(if is_creating_diff { + get_select_from_with_diff(dif_type, dst_type) + } else { + get_select_from_apply_patch(src_type, dif_type, dst_type) + }), + true, + ) + .await?; + + if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { + self.dst_mbtiles.update_agg_tiles_hash(&mut conn).await?; } + detach_db(&mut conn, "diffDb").await?; detach_db(&mut conn, "sourceDb").await?; Ok(conn) } + fn copy_text(&self) -> &str { + match self.options.copy { + CopyType::All => "", + CopyType::Tiles => "tiles data ", + CopyType::Metadata => "metadata ", + } + } + + async fn copy_with_rusqlite( + &self, + conn: &mut SqliteConnection, + on_duplicate: CopyDuplicateMode, + dst_type: MbtType, + select_from: &str, + is_diff: bool, + ) -> Result<(), MbtError> { + // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn + // Make sure not to execute any other queries while the handle is locked + let mut handle_lock = conn.lock_handle().await?; + let handle = handle_lock.as_raw_handle().as_ptr(); + + // SAFETY: this is safe as long as handle_lock is valid. We will drop the lock. + let rusqlite_conn = unsafe { Connection::from_handle(handle) }?; + + if self.options.copy.copy_tiles() { + self.copy_tiles(&rusqlite_conn, dst_type, on_duplicate, select_from)?; + } else { + debug!("Skipping copying tiles"); + } + + if self.options.copy.copy_metadata() { + self.copy_metadata(&rusqlite_conn, is_diff, on_duplicate) + } else { + debug!("Skipping copying metadata"); + Ok(()) + } + } + fn copy_metadata( &self, rusqlite_conn: &Connection, @@ -281,23 +333,11 @@ impl MbtileCopierInt { fn copy_tiles( &self, rusqlite_conn: &Connection, - dif: Option<&(Mbtiles, MbtType)>, - src_type: MbtType, dst_type: MbtType, on_duplicate: CopyDuplicateMode, + select_from: &str, ) -> Result<(), MbtError> { let on_dupl = on_duplicate.to_sql(); - - let select_from = if let Some((_, dif_type)) = &dif { - if self.options.diff_with_file.is_some() { - Self::get_select_from_with_diff(*dif_type, dst_type) - } else { - Self::get_select_from_apply_patch(src_type, *dif_type, dst_type) - } - } else { - Self::get_select_from(src_type, dst_type).to_string() - }; - let where_clause = self.get_where_clause(); let sql_cond = Self::get_on_duplicate_sql_cond(on_duplicate, dst_type); @@ -429,60 +469,102 @@ impl MbtileCopierInt { } } - fn get_select_from_apply_patch( - src_type: MbtType, - dif_type: MbtType, - dst_type: MbtType, - ) -> String { - fn query_for_dst(frm_db: &'static str, frm_type: MbtType, to_type: MbtType) -> String { - match to_type { - Flat => format!("{frm_db}.tiles"), - FlatWithHash | Normalized { .. } => match frm_type { - Flat => format!( - " + /// Format SQL WHERE clause and return it along with the query arguments. + /// Note that there is no risk of SQL injection here, as the arguments are integers. + fn get_where_clause(&self) -> String { + let mut sql = if !&self.options.zoom_levels.is_empty() { + let zooms = self.options.zoom_levels.iter().join(","); + format!(" AND zoom_level IN ({zooms})") + } else if let Some(min_zoom) = self.options.min_zoom { + if let Some(max_zoom) = self.options.max_zoom { + format!(" AND zoom_level BETWEEN {min_zoom} AND {max_zoom}") + } else { + format!(" AND zoom_level >= {min_zoom}") + } + } else if let Some(max_zoom) = self.options.max_zoom { + format!(" AND zoom_level <= {max_zoom}") + } else { + String::new() + }; + + if !self.options.bbox.is_empty() { + sql.push_str(" AND (\n"); + for (idx, bbox) in self.options.bbox.iter().enumerate() { + // Use maximum zoom value for easy filtering, + // converting it on the fly to the actual zoom level + let (min_x, min_y, max_x, max_y) = + bbox_to_xyz(bbox.left, bbox.bottom, bbox.right, bbox.top, MAX_ZOOM); + trace!("Bounding box {bbox} converted to {min_x},{min_y},{max_x},{max_y} at zoom {MAX_ZOOM}"); + let (min_y, max_y) = ( + invert_y_value(MAX_ZOOM, max_y), + invert_y_value(MAX_ZOOM, min_y), + ); + + if idx > 0 { + sql.push_str(" OR\n"); + } + writeln!( + sql, + "((tile_column * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_x} AND {max_x} AND (tile_row * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_y} AND {max_y})", + ).unwrap(); + } + sql.push(')'); + } + + sql + } +} + +fn get_select_from_apply_patch(src_type: MbtType, dif_type: MbtType, dst_type: MbtType) -> String { + fn query_for_dst(frm_db: &'static str, frm_type: MbtType, to_type: MbtType) -> String { + match to_type { + Flat => format!("{frm_db}.tiles"), + FlatWithHash | Normalized { .. } => match frm_type { + Flat => format!( + " (SELECT zoom_level, tile_column, tile_row, tile_data, md5_hex(tile_data) AS tile_hash FROM {frm_db}.tiles)" - ), - FlatWithHash => format!("{frm_db}.tiles_with_hash"), - Normalized { hash_view } => { - if hash_view { - format!("{frm_db}.tiles_with_hash") - } else { - format!( - " + ), + FlatWithHash => format!("{frm_db}.tiles_with_hash"), + Normalized { hash_view } => { + if hash_view { + format!("{frm_db}.tiles_with_hash") + } else { + format!( + " (SELECT zoom_level, tile_column, tile_row, tile_data, map.tile_id AS tile_hash FROM {frm_db}.map JOIN {frm_db}.images ON map.tile_id = images.tile_id)" - ) - } + ) } - }, - } + } + }, } + } - let tile_hash_expr = if dst_type == Flat { - String::new() - } else { - fn get_tile_hash_expr(tbl: &str, typ: MbtType) -> String { - match typ { - Flat => format!("IIF({tbl}.tile_data ISNULL, NULL, md5_hex({tbl}.tile_data))"), - FlatWithHash | Normalized { .. } => format!("{tbl}.tile_hash"), - } + let tile_hash_expr = if dst_type == Flat { + String::new() + } else { + fn get_tile_hash_expr(tbl: &str, typ: MbtType) -> String { + match typ { + Flat => format!("IIF({tbl}.tile_data ISNULL, NULL, md5_hex({tbl}.tile_data))"), + FlatWithHash | Normalized { .. } => format!("{tbl}.tile_hash"), } + } - format!( - ", COALESCE({}, {}) as tile_hash", - get_tile_hash_expr("difTiles", dif_type), - get_tile_hash_expr("srcTiles", src_type) - ) - }; + format!( + ", COALESCE({}, {}) as tile_hash", + get_tile_hash_expr("difTiles", dif_type), + get_tile_hash_expr("srcTiles", src_type) + ) + }; - let src_tiles = query_for_dst("sourceDb", src_type, dst_type); - let diff_tiles = query_for_dst("diffDb", dif_type, dst_type); + let src_tiles = query_for_dst("sourceDb", src_type, dst_type); + let diff_tiles = query_for_dst("diffDb", dif_type, dst_type); - // Take dif tile_data if it is set, otherwise take the one from src - // Skip tiles if src and dif both have a matching index, but the dif tile_data is NULL - format!( - " + // Take dif tile_data if it is set, otherwise take the one from src + // Skip tiles if src and dif both have a matching index, but the dif tile_data is NULL + format!( + " SELECT COALESCE(srcTiles.zoom_level, difTiles.zoom_level) as zoom_level , COALESCE(srcTiles.tile_column, difTiles.tile_column) as tile_column , COALESCE(srcTiles.tile_row, difTiles.tile_row) as tile_row @@ -493,35 +575,33 @@ impl MbtileCopierInt { AND srcTiles.tile_column = difTiles.tile_column AND srcTiles.tile_row = difTiles.tile_row WHERE (difTiles.zoom_level ISNULL OR difTiles.tile_data NOTNULL)" - ) - } + ) +} - fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String { - let tile_hash_expr; - let diff_tiles; - if dst_type == Flat { - tile_hash_expr = ""; - diff_tiles = "diffDb.tiles"; - } else { - tile_hash_expr = match dif_type { - Flat => ", COALESCE(md5_hex(difTiles.tile_data), '') as tile_hash", - FlatWithHash | Normalized { .. } => { - ", COALESCE(difTiles.tile_hash, '') as tile_hash" - } - }; - diff_tiles = match dif_type { - Flat => "diffDb.tiles", - FlatWithHash => "diffDb.tiles_with_hash", - Normalized { .. } => { - " +fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String { + let tile_hash_expr; + let diff_tiles; + if dst_type == Flat { + tile_hash_expr = ""; + diff_tiles = "diffDb.tiles"; + } else { + tile_hash_expr = match dif_type { + Flat => ", COALESCE(md5_hex(difTiles.tile_data), '') as tile_hash", + FlatWithHash | Normalized { .. } => ", COALESCE(difTiles.tile_hash, '') as tile_hash", + }; + diff_tiles = match dif_type { + Flat => "diffDb.tiles", + FlatWithHash => "diffDb.tiles_with_hash", + Normalized { .. } => { + " (SELECT zoom_level, tile_column, tile_row, tile_data, map.tile_id AS tile_hash FROM diffDb.map JOIN diffDb.images ON diffDb.map.tile_id = diffDb.images.tile_id)" - } - }; - } + } + }; + } - format!( - " + format!( + " SELECT COALESCE(srcTiles.zoom_level, difTiles.zoom_level) as zoom_level , COALESCE(srcTiles.tile_column, difTiles.tile_column) as tile_column , COALESCE(srcTiles.tile_row, difTiles.tile_row) as tile_row @@ -534,81 +614,35 @@ impl MbtileCopierInt { WHERE (srcTiles.tile_data != difTiles.tile_data OR srcTiles.tile_data ISNULL OR difTiles.tile_data ISNULL)" - ) - } + ) +} - fn get_select_from(src_type: MbtType, dst_type: MbtType) -> &'static str { - if dst_type == Flat { - "SELECT zoom_level, tile_column, tile_row, tile_data FROM sourceDb.tiles WHERE TRUE" - } else { - match src_type { - Flat => { - " +fn get_select_from(src_type: MbtType, dst_type: MbtType) -> &'static str { + if dst_type == Flat { + "SELECT zoom_level, tile_column, tile_row, tile_data FROM sourceDb.tiles WHERE TRUE" + } else { + match src_type { + Flat => { + " SELECT zoom_level, tile_column, tile_row, tile_data, md5_hex(tile_data) as tile_hash FROM sourceDb.tiles WHERE TRUE" - } - FlatWithHash => { - " + } + FlatWithHash => { + " SELECT zoom_level, tile_column, tile_row, tile_data, tile_hash FROM sourceDb.tiles_with_hash WHERE TRUE" - } - Normalized { .. } => { - " + } + Normalized { .. } => { + " SELECT zoom_level, tile_column, tile_row, tile_data, map.tile_id AS tile_hash FROM sourceDb.map JOIN sourceDb.images ON sourceDb.map.tile_id = sourceDb.images.tile_id WHERE TRUE" - } } } } - - /// Format SQL WHERE clause and return it along with the query arguments. - /// Note that there is no risk of SQL injection here, as the arguments are integers. - fn get_where_clause(&self) -> String { - let mut sql = if !&self.options.zoom_levels.is_empty() { - let zooms = self.options.zoom_levels.iter().join(","); - format!(" AND zoom_level IN ({zooms})") - } else if let Some(min_zoom) = self.options.min_zoom { - if let Some(max_zoom) = self.options.max_zoom { - format!(" AND zoom_level BETWEEN {min_zoom} AND {max_zoom}") - } else { - format!(" AND zoom_level >= {min_zoom}") - } - } else if let Some(max_zoom) = self.options.max_zoom { - format!(" AND zoom_level <= {max_zoom}") - } else { - String::new() - }; - - if !self.options.bbox.is_empty() { - sql.push_str(" AND (\n"); - for (idx, bbox) in self.options.bbox.iter().enumerate() { - // Use maximum zoom value for easy filtering, - // converting it on the fly to the actual zoom level - let (min_x, min_y, max_x, max_y) = - bbox_to_xyz(bbox.left, bbox.bottom, bbox.right, bbox.top, MAX_ZOOM); - trace!("Bounding box {bbox} converted to {min_x},{min_y},{max_x},{max_y} at zoom {MAX_ZOOM}"); - let (min_y, max_y) = ( - invert_y_value(MAX_ZOOM, max_y), - invert_y_value(MAX_ZOOM, min_y), - ); - - if idx > 0 { - sql.push_str(" OR\n"); - } - writeln!( - sql, - "((tile_column * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_x} AND {max_x} AND (tile_row * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_y} AND {max_y})", - ).unwrap(); - } - sql.push(')'); - } - - sql - } } #[cfg(test)] From b92a4077c674443397afb387a93c1d76553cd298 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 21 Mar 2024 18:22:12 -0400 Subject: [PATCH 063/164] Update lock --- Cargo.lock | 100 ++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d70196b4..cee1587fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bytes", "futures-core", "futures-sink", @@ -46,7 +46,7 @@ dependencies = [ "actix-utils", "ahash", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "brotli", "bytes", "bytestring", @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -378,13 +378,13 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -406,7 +406,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -417,7 +417,7 @@ checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -501,9 +501,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -719,7 +719,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -952,7 +952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -976,7 +976,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -987,7 +987,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1149,7 +1149,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1368,7 +1368,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1fad2be0bf06af23adddcf6cd143c94ff0ba3b329691f92d1a38dae5c5aeebf" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "freetype-sys", "libc", ] @@ -1469,7 +1469,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2516,7 +2516,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2607,7 +2607,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2929,7 +2929,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "memchr", "unicase", ] @@ -3009,7 +3009,7 @@ version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", ] [[package]] @@ -3090,9 +3090,9 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.11.26" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -3230,7 +3230,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.52", + "syn 2.0.53", "unicode-ident", ] @@ -3240,7 +3240,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "fallible-iterator 0.3.0", "fallible-streaming-iterator", "hashlink", @@ -3271,11 +3271,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -3494,7 +3494,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3568,7 +3568,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3697,9 +3697,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -3874,7 +3874,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "bytes", "crc", @@ -3916,7 +3916,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "crc", "dotenvy", @@ -4022,7 +4022,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4033,7 +4033,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4100,9 +4100,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -4177,7 +4177,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4301,7 +4301,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4447,7 +4447,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4674,9 +4674,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", ] @@ -4751,7 +4751,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-shared", ] @@ -4785,7 +4785,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5089,7 +5089,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5109,7 +5109,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] From 6d6f83378624a0383f312be7ca16cac006f8e38f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:59:11 +0000 Subject: [PATCH 064/164] chore(deps): Bump dependabot/fetch-metadata from 1.6.0 to 2.0.0 (#1267) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.6.0 to 2.0.0.
Release notes

Sourced from dependabot/fetch-metadata's releases.

v2.0.0 - Switch to node20

What's Changed

Full Changelog: https://github.com/dependabot/fetch-metadata/compare/v1.7.0...v2.0.0

v1.7.0

What's Changed

New Contributors

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dependabot/fetch-metadata&package-manager=github_actions&previous-version=1.6.0&new-version=2.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 2a6b0bc5d..4549aac67 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v1.6.0 + uses: dependabot/fetch-metadata@v2.0.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Approve Dependabot PRs From 115c976c92792a983d59dab44891dae423658214 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 22 Mar 2024 17:04:16 -0400 Subject: [PATCH 065/164] Update sqlite-hashes dependency (#1268) Minor internal breaking changes --- Cargo.lock | 12 ++++++------ Cargo.toml | 3 ++- mbtiles/src/mbtiles.rs | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cee1587fe..287099b02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,9 +437,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "95d8e92cac0961e91dbd517496b00f7e9b92363dbe6d42c3198268323798860c" dependencies = [ "addr2line", "cc", @@ -606,9 +606,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" [[package]] name = "cargo-platform" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -3766,9 +3766,9 @@ dependencies = [ [[package]] name = "sqlite-hashes" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832470995a0edea4cfc1524c02060e1e1fcbe3230f2bc7be7e8eaa5ad60cfec5" +checksum = "b4faff0b1f487d94938f61fe78989b8e1e9524cf16a0b63174129c6a427057e2" dependencies = [ "digest", "hex", diff --git a/Cargo.toml b/Cargo.toml index eb672a33f..bee3e2b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ insta = "1" itertools = "0.12" json-patch = "1.2" lambda-web = { version = "0.2.1", features = ["actix4"] } +libsqlite3-sys = { version = ">=0.27", features = ["bundled"] } log = "0.4" martin-tile-utils = { path = "./martin-tile-utils", version = "0.4.0" } mbtiles = { path = "./mbtiles", version = "0.9.0" } @@ -72,7 +73,7 @@ serde_with = "3" serde_yaml = "0.9" size_format = "1.0.2" spreet = { version = "0.11", default-features = false } -sqlite-hashes = { version = "0.6", default-features = false, features = ["md5", "window", "hex"] } # window forces libsqlite3-sys to bundle sqlite3. We require v3.44.0 or newer. +sqlite-hashes = { version = "0.7.1", default-features = false, features = ["md5", "aggregate", "hex"] } sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] } subst = { version = "0.3", features = ["yaml"] } thiserror = "1" diff --git a/mbtiles/src/mbtiles.rs b/mbtiles/src/mbtiles.rs index fe62c7e6b..9808fb194 100644 --- a/mbtiles/src/mbtiles.rs +++ b/mbtiles/src/mbtiles.rs @@ -5,7 +5,7 @@ use std::path::Path; use enum_display::EnumDisplay; use log::debug; use serde::{Deserialize, Serialize}; -use sqlite_hashes::register_md5_function; +use sqlite_hashes::register_md5_functions; use sqlx::sqlite::SqliteConnectOptions; use sqlx::{query, Connection as _, Executor, SqliteConnection, SqliteExecutor, Statement}; @@ -225,7 +225,7 @@ pub async fn attach_hash_fn(conn: &mut SqliteConnection) -> MbtResult<()> { // Safety: we know that the handle is a SQLite connection is locked and is not used anywhere else. // The registered functions will be dropped when SQLX drops DB connection. let rc = unsafe { sqlite_hashes::rusqlite::Connection::from_handle(handle) }?; - register_md5_function(&rc)?; + register_md5_functions(&rc)?; Ok(()) } From 4a85e3e3517945bcaa88faf969a66c663d848619 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 02:19:51 +0000 Subject: [PATCH 066/164] chore(deps): Bump async-trait from 0.1.78 to 0.1.79 (#1269) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.78 to 0.1.79.
Release notes

Sourced from async-trait's releases.

0.1.79

  • Clean up some dead code
Commits
  • 1eb21ed Release 0.1.79
  • 82cb95c Resolve unused field of ReplaceSelf syntax tree visitor
  • cd8286b Update ui test suite to nightly-2024-03-22
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=async-trait&package-manager=cargo&previous-version=0.1.78&new-version=0.1.79)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 287099b02..d16bc63d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,9 +411,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", From 09d5313bdf02c8f97e6b7593a36a093d068770e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 02:22:58 +0000 Subject: [PATCH 067/164] chore(deps): Bump indoc from 2.0.4 to 2.0.5 (#1272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [indoc](https://github.com/dtolnay/indoc) from 2.0.4 to 2.0.5.
Release notes

Sourced from indoc's releases.

2.0.5

Commits
  • 4bfa29f Release 2.0.5
  • 8d38299 Merge pull request #62 from ilyagr/docstring
  • 735ddcc Update docstring for indoc!
  • 60b5fa2 Remove 'remember to update' reminder from Cargo.toml
  • 15abc17 Test docs.rs documentation build in CI
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=indoc&package-manager=cargo&previous-version=2.0.4&new-version=2.0.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d16bc63d4..c8ee1482d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1822,9 +1822,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "inferno" From d69bbba20083c1362851d64395ad0de728715d39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 02:23:04 +0000 Subject: [PATCH 068/164] chore(deps): Bump regex from 1.10.3 to 1.10.4 (#1271) Bumps [regex](https://github.com/rust-lang/regex) from 1.10.3 to 1.10.4.
Commits
  • aa2d8bd 1.10.4
  • 088d7f3 api: add Cow guarantee to replace API
  • a5ae351 regex-automata-0.4.6
  • 9cf4a42 automata: fix bug where reverse NFA lacked an unanchored prefix
  • 10fe722 style: clean up some recent lint violations
  • d7f9347 regex-automata-0.4.5
  • 07ef7f1 automata: make additional prefileter metadata public
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=regex&package-manager=cargo&previous-version=1.10.3&new-version=1.10.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8ee1482d..1389fa976 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3049,9 +3049,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", From 61acbe042969c340bd1ed0a08811362cf7e5cf6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 02:24:31 +0000 Subject: [PATCH 069/164] chore(deps): Bump serde_yaml from 0.9.33 to 0.9.34+deprecated (#1270) Bumps [serde_yaml](https://github.com/dtolnay/serde-yaml) from 0.9.33 to 0.9.34+deprecated.
Release notes

Sourced from serde_yaml's releases.

0.9.34

As of this release, I am not planning to publish further versions of serde_yaml as none of my projects have been using YAML for a long time, so I have archived the GitHub repo and marked the crate deprecated in the version number. An official replacement isn't designated for those who still need to work with YAML, but https://crates.io/search?q=yaml&sort=relevance and https://crates.io/keywords/yaml has a number of reasonable-looking options available.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_yaml&package-manager=cargo&previous-version=0.9.33&new-version=0.9.34+deprecated)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1389fa976..f1abab610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3573,9 +3573,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.33" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap 2.2.5", "itoa", From 42fbf5486c10c1e42649b136291df77c704df93e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 02:32:01 +0000 Subject: [PATCH 070/164] chore(deps): Bump clap from 4.5.3 to 4.5.4 (#1275) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.3 to 4.5.4.
Release notes

Sourced from clap's releases.

v4.5.4

[4.5.4] - 2024-03-25

Fixes

  • (derive) Allow non-literal #[arg(id)] attributes again
Changelog

Sourced from clap's changelog.

[4.5.4] - 2024-03-25

Fixes

  • (derive) Allow non-literal #[arg(id)] attributes again
Commits
  • 5e4facf chore: Release
  • 8880b0a docs: Update changelog
  • 132b5dd Merge pull request #5425 from epage/lit
  • df915fe fix(derive): Re-allow expressions for id's
  • 8eab48f refactor(derive): Make it easier to work with 'Name'
  • be73195 refactor(derive): Clarify tests
  • 024089b Merge pull request #5415 from Pi-Cla/patch-1
  • 3b35dba docs: Add mention of nushell to clap_complete README
  • 58469d1 Merge pull request #5405 from epage/docs
  • 655d829 docs(derive): Fix ToC links within tutorial chapters
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.3&new-version=4.5.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1abab610..5ecf80d53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -712,9 +712,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck 0.5.0", "proc-macro2", From 2d82202fee1d3be086413752954358ffad557aaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 02:35:07 +0000 Subject: [PATCH 071/164] chore(deps): Bump rustls from 0.22.2 to 0.22.3 (#1274) Bumps [rustls](https://github.com/rustls/rustls) from 0.22.2 to 0.22.3.
Commits
  • a1e28cd Prepare 0.22.3
  • 114c476 suites.rs: fix nonsensical duplicated feature gate
  • ffd933a Fix new clippy::use_self warnings
  • fb6e70a dangerous_extract_secrets(): test ConnectionTrafficSecrets variant
  • 2d5c80e Return correct ConnectionTrafficSecrets variant when AES-256-GCM is negotia...
  • 77ffe49 tests: fix implied_bounds_in_impls clippy warn
  • 65dfd9c Avoid clippy::std_instead_of_core false positive
  • b4adf89 Address clippy::multiple_bound_locations
  • 1104a47 Address clippy::mixed_attributes_style
  • 5a5f638 Address clippy::assigning_clones
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.22.2&new-version=0.22.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ecf80d53..3b953296d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2132,7 +2132,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.22.2", + "rustls 0.22.3", "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.1", "semver", @@ -3296,9 +3296,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" dependencies = [ "log", "ring", @@ -4338,7 +4338,7 @@ checksum = "0ea13f22eda7127c827983bdaf0d7fff9df21c8817bab02815ac277a21143677" dependencies = [ "futures", "ring", - "rustls 0.22.2", + "rustls 0.22.3", "tokio", "tokio-postgres", "tokio-rustls 0.25.0", @@ -4361,7 +4361,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.2", + "rustls 0.22.3", "rustls-pki-types", "tokio", ] From bad56b913f8b39e11b7e9c8b2a122ec89a63d9ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 03:06:59 +0000 Subject: [PATCH 072/164] chore(deps): Bump serde_json from 1.0.114 to 1.0.115 (#1278) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.114 to 1.0.115.
Release notes

Sourced from serde_json's releases.

v1.0.115

  • Documentation improvements
Commits
  • b1ebf38 Release 1.0.115
  • c3dc153 Merge pull request #1119 from titaniumtraveler/pr
  • 218770b Explicitly install a Rust toolchain for cargo-outdated job
  • 840da8e Fix missing backticks in doc comments
  • 3a3f61b Temporarily disable miri on doctests
  • 4a0be88 Format regression tests with rustfmt
  • d2dbbf7 Ignore dead code lint in tests
  • 8e7b37b Merge pull request #1118 from serde-rs/transparent
  • a25f6c6 Remove conditional on repr(transparent)
  • fedf834 Ignore non_local_definitions false positive in test
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.114&new-version=1.0.115)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b953296d..d6f1a898c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3499,9 +3499,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", From a9d8edc76d76811f22d8b13668f2bc6552dd6b1e Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Sat, 30 Mar 2024 18:11:47 +0100 Subject: [PATCH 073/164] Update documentation for running with Docker Compose (#1283) Some small changes to make the Docker compose documentation up to date: - Update dependency versions of PostGIS and Martin - Use the bundled `docker compose` extension, not `docker-compose`. (see https://docs.docker.com/compose/migrate/#docker-compose-vs-docker-compose) - Remove `version` from the Docker Compose file (see https://docs.docker.com/compose/compose-file/04-version-and-name/) --- docker-compose.yml | 2 -- docs/src/run-with-docker-compose.md | 10 ++++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a29dd5c2c..aeaa433ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: fileserver: image: nginx:alpine diff --git a/docs/src/run-with-docker-compose.md b/docs/src/run-with-docker-compose.md index 98e79d0c2..005f0187e 100644 --- a/docs/src/run-with-docker-compose.md +++ b/docs/src/run-with-docker-compose.md @@ -3,11 +3,9 @@ You can use example [`docker-compose.yml`](https://raw.githubusercontent.com/maplibre/martin/main/docker-compose.yml) file as a reference ```yml -version: '3' - services: martin: - image: ghcr.io/maplibre/martin:v0.11.2 + image: ghcr.io/maplibre/martin:v0.13.0 restart: unless-stopped ports: - "3000:3000" @@ -17,7 +15,7 @@ services: - db db: - image: postgis/postgis:14-3.3-alpine + image: postgis/postgis:16-3.4-alpine restart: unless-stopped environment: - POSTGRES_DB=db @@ -31,13 +29,13 @@ services: First, you need to start `db` service ```shell -docker-compose up -d db +docker compose up -d db ``` Then, after `db` service is ready to accept connections, you can start `martin` ```shell -docker-compose up -d martin +docker compose up -d martin ``` By default, Martin will be available at [localhost:3000](http://localhost:3000/) From a2532ccabca5846bcb5dff3666b01e01506d03b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:51:35 +0000 Subject: [PATCH 074/164] chore(deps): Bump h2 from 0.3.25 to 0.3.26 (#1286) Bumps [h2](https://github.com/hyperium/h2) from 0.3.25 to 0.3.26.
Release notes

Sourced from h2's releases.

v0.3.26

What's Changed

  • Limit number of CONTINUATION frames for misbehaving connections.

See https://seanmonstar.com/blog/hyper-http2-continuation-flood/ for more info.

Changelog

Sourced from h2's changelog.

0.3.26 (April 3, 2024)

  • Limit number of CONTINUATION frames for misbehaving connections.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=h2&package-manager=cargo&previous-version=0.3.25&new-version=0.3.26)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6f1a898c..1a0f92b43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1562,9 +1562,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", From 59040a8686fbaa0390d6f0e8903774dab75fc320 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 02:34:58 +0000 Subject: [PATCH 075/164] chore(deps): Bump rustls-pemfile from 2.1.1 to 2.1.2 (#1288) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [rustls-pemfile](https://github.com/rustls/pemfile) from 2.1.1 to 2.1.2.
Release notes

Sourced from rustls-pemfile's releases.

2.1.2

Dependency updates.

What's Changed

New Contributors

Full Changelog: https://github.com/rustls/pemfile/compare/v/2.1.1...v/2.1.2

Commits
  • 7ba4ab7 Delete obsolete release history section
  • 07686b2 Cargo: version 2.1.1 -> 2.1.2
  • 48ab234 Fixed warnings from rust nightly
  • d7b1215 Bump base64 from 0.21.5 to 0.22.0
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls-pemfile&package-manager=cargo&previous-version=2.1.1&new-version=2.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a0f92b43..fa08d842b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,6 +462,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "base64ct" version = "1.6.0" @@ -2134,7 +2140,7 @@ dependencies = [ "regex", "rustls 0.22.3", "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "semver", "serde", "serde_json", @@ -3327,7 +3333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "rustls-pki-types", "schannel", "security-framework", @@ -3344,11 +3350,11 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "rustls-pki-types", ] From 1ee28202a96c84e2c9ff78bae5f5c454c9099041 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:59:24 -0400 Subject: [PATCH 076/164] chore(deps): Bump peaceiris/actions-gh-pages from 3 to 4 (#1292) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [peaceiris/actions-gh-pages](https://github.com/peaceiris/actions-gh-pages) from 3 to 4.
Release notes

Sourced from peaceiris/actions-gh-pages's releases.

actions-github-pages v4.0.0

See CHANGELOG.md for more details.

actions-github-pages v3.9.3

See CHANGELOG.md for more details.

actions-github-pages v3.9.2

See CHANGELOG.md for more details.

actions-github-pages v3.9.1

  • update deps

See CHANGELOG.md for more details.

actions-github-pages v3.9.0

  • deps: bump node12 to node16
  • deps: bump @​actions/core from 1.6.0 to 1.10.0

See CHANGELOG.md for more details.

actions-github-pages v3.8.0

See CHANGELOG.md for more details.

actions-github-pages v3.7.3

See CHANGELOG.md for more details.

actions-github-pages v3.7.2

See CHANGELOG.md for more details.

actions-github-pages v3.7.1

See CHANGELOG.md for more details.

actions-github-pages v3.7.0

See CHANGELOG.md for more details.

Overviews:

  • Add .nojekyll file by default for all branches (#438) (079d483), closes #438
  • Add destination_dir option (#403) (f30118c), closes #403 #324 #390
  • Add exclude_assets option (#416) (0f5c65e), closes #416 #163
  • exclude_assets supports glob patterns (#417) (6f45501), closes #417 #163

actions-github-pages v3.6.4

See CHANGELOG.md for more details.

actions-github-pages v3.6.3

See CHANGELOG.md for more details.

actions-github-pages v3.6.2

See CHANGELOG.md for more details.

... (truncated)

Changelog

Sourced from peaceiris/actions-gh-pages's changelog.

3.9.3 (2023-03-30)

docs

fix

3.9.2 (2023-01-17)

chore

ci

deps

3.9.1 (2023-01-05)

chore

ci

  • add Renovate config (#802) (072d16c), closes #802
  • bump actions/dependency-review-action from 2 to 3 (#799) (e3b45f2), closes #799
  • bump peaceiris/actions-github-app-token from 1.1.4 to 1.1.5 (#798) (a5f971f), closes #798
  • bump peaceiris/actions-mdbook from 1.1.14 to 1.2.0 (#793) (9af6a68), closes #793
  • bump peaceiris/workflows from 0.17.1 to 0.17.2 (#794) (087a759), closes #794

... (truncated)

Commits
  • 4f9cc66 chore(release): 4.0.0
  • 9c75028 chore(release): Add build assets
  • 5049354 build: node 20.11.1
  • 4eb285e chore: bump node16 to node20 (#1067)
  • cdc09a3 chore(deps): update dependency @​types/node to v16.18.77 (#1065)
  • d830378 chore(deps): update dependency @​types/node to v16.18.76 (#1063)
  • 80daa1d chore(deps): update dependency @​types/node to v16.18.75 (#1061)
  • 108285e chore(deps): update dependency ts-jest to v29.1.2 (#1060)
  • 99c95ff chore(deps): update dependency @​types/node to v16.18.74 (#1058)
  • 1f46537 chore(deps): update dependency @​types/node to v16.18.73 (#1057)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peaceiris/actions-gh-pages&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml index 4b8b4f505..af457a703 100644 --- a/.github/workflows/build-deploy-docs.yml +++ b/.github/workflows/build-deploy-docs.yml @@ -37,7 +37,7 @@ jobs: - run: mdbook build docs - name: Deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 if: github.ref == 'refs/heads/main' with: github_token: ${{ secrets.GITHUB_TOKEN }} From b79bfdb75a23bc7dc6fae548e87ca23d1a9fb883 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:59:38 -0400 Subject: [PATCH 077/164] chore(deps): Bump DavidAnson/markdownlint-cli2-action from 15 to 16 (#1291) Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 15 to 16.
Release notes

Sourced from DavidAnson/markdownlint-cli2-action's releases.

Update markdownlint version (markdownlint-cli2 v0.13.0, markdownlint v0.34.0).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.12.1, markdownlint v0.33.0).

Update markdownlint version (markdownlint-cli2 v0.11.0, markdownlint v0.32.1), remove deprecated "command" input.

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.10.0, markdownlint v0.31.1).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.9.2, markdownlint v0.30.0).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.8.1, markdownlint v0.29.0), add "config" and "fix" inputs, deprecate "command" input.

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.7.1, markdownlint v0.28.2).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.7.0, markdownlint v0.28.1), include link to rule information in title of annotations (clickable in GitHub).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.6.0, markdownlint v0.27.0).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.5.1, markdownlint v0.26.2).

No release notes provided.

Update markdownlint version (markdownlint-cli2 v0.4.0, markdownlint v0.25.1)

No release notes provided.

Commits
  • b4c9fea Update to version 16.0.0.
  • 349248f Update CONTRIBUTING.md to link to a more relevant (my own) blog post about ve...
  • b22040a Freshen generated index.js file.
  • d73fc7d Bump markdownlint-cli2 from 0.12.1 to 0.13.0
  • 4a035c1 Bump eslint-plugin-unicorn from 51.0.1 to 52.0.0
  • 3eeb58c Freshen generated index.js file.
  • 73e365c Bump tj-actions/changed-files from 43 to 44
  • 60d6e1a Bump tj-actions/changed-files from 42 to 43
  • 58bc1d1 Freshen generated index.js file.
  • 1341c61 Bump eslint from 8.56.0 to 8.57.0
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=DavidAnson/markdownlint-cli2-action&package-manager=github_actions&previous-version=15&new-version=16)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml index af457a703..67f23b09e 100644 --- a/.github/workflows/build-deploy-docs.yml +++ b/.github/workflows/build-deploy-docs.yml @@ -16,7 +16,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: 'Validate .md files (use "just fmt-md" to fix)' - uses: DavidAnson/markdownlint-cli2-action@v15 + uses: DavidAnson/markdownlint-cli2-action@v16 with: config: '.github/files/config.markdownlint-cli2.jsonc' From e4a2fa5cb89288f23c55282942e3fea742f82f2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:59:56 -0400 Subject: [PATCH 078/164] chore(deps): Bump peaceiris/actions-mdbook from 1 to 2 (#1290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [peaceiris/actions-mdbook](https://github.com/peaceiris/actions-mdbook) from 1 to 2.
Release notes

Sourced from peaceiris/actions-mdbook's releases.

actions-mdbook v2.0.0

See CHANGELOG.md for more details.

actions-mdbook v1.2.0

  • deps: bump node12 to node16
  • deps: bump @​actions/core from 1.6.0 to 1.10.0

See CHANGELOG.md for more details.

actions-mdbook v1.1.14

See CHANGELOG.md for more details.

actions-mdbook v1.1.13

See CHANGELOG.md for more details.

actions-mdbook v1.1.12

See CHANGELOG.md for more details.

actions-mdbook v1.1.11

See CHANGELOG.md for more details.

actions-mdbook v1.1.10

See CHANGELOG.md for more details.

This action was featured at GitHub Action Hero: Shohei Ueda - The GitHub Blog. Thanks all.

actions-mdbook v1.1.9

See CHANGELOG.md for more details.

actions-mdbook v1.1.8

See CHANGELOG.md for more details.

actions-mdbook v1.1.7

See CHANGELOG.md for more details.

actions-mdbook v1.1.6

See CHANGELOG.md for more details.

actions-mdbook v1.1.5

See CHANGELOG.md for more details.

Release v1.1.4

See CHANGELOG.md for more details.

Release v1.1.3

See CHANGELOG.md for more details.

Release v1.1.2

See CHANGELOG.md for more details.

... (truncated)

Changelog

Sourced from peaceiris/actions-mdbook's changelog.

2.0.0 (2024-04-08)

build

chore

ci

feat

Commits
  • ee69d23 chore(release): 2.0.0
  • 2d79d45 chore(release): Add build assets
  • c95f05c chore: revert build
  • cb4d902 build: bump node to 20.12.1 (#504)
  • 46c97c2 feat: bump to node20 runtime (#500)
  • 7b0c98f ci: bump codecov/codecov-action from 3 to 4 (#490)
  • 60cc2ff ci: bump actions/dependency-review-action from 3.0.8 to 3.1.0 (#488)
  • c0c1ffe ci: bump actions/checkout from 3 to 4 (#487)
  • c6c9e0f ci: bump actions/setup-node from 3.8.0 to 3.8.1 (#486)
  • 162a198 ci: bump actions/dependency-review-action from 3.0.7 to 3.0.8 (#485)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peaceiris/actions-mdbook&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml index 67f23b09e..025016a63 100644 --- a/.github/workflows/build-deploy-docs.yml +++ b/.github/workflows/build-deploy-docs.yml @@ -30,7 +30,7 @@ jobs: config-file: '.github/files/markdown.links.config.json' - name: Setup mdBook - uses: peaceiris/actions-mdbook@v1 + uses: peaceiris/actions-mdbook@v2 with: mdbook-version: 'latest' From 7ec8c19f72257b1bd308bc95ef92247786ec1301 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:00:36 -0400 Subject: [PATCH 079/164] chore(deps-dev): Bump vite from 4.5.2 to 4.5.3 in /demo/frontend (#1285) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.2 to 4.5.3.
Changelog

Sourced from vite's changelog.

4.5.3 (2024-03-24)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=4.5.2&new-version=4.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- demo/frontend/package.json | 2 +- demo/frontend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/frontend/package.json b/demo/frontend/package.json index b39d85517..89992df7c 100644 --- a/demo/frontend/package.json +++ b/demo/frontend/package.json @@ -33,7 +33,7 @@ "eslint-config-airbnb-base": "15.0.0", "eslint-config-react-app": "7.0.1", "typescript": "^5.2.2", - "vite": "^4.5.2", + "vite": "^4.5.3", "vite-plugin-mkcert": "^1.16.0", "vite-tsconfig-paths": "^4.2.1" }, diff --git a/demo/frontend/yarn.lock b/demo/frontend/yarn.lock index e61e13993..1cae63c00 100644 --- a/demo/frontend/yarn.lock +++ b/demo/frontend/yarn.lock @@ -4410,10 +4410,10 @@ vite-tsconfig-paths@^4.2.1: globrex "^0.1.2" tsconfck "^2.1.0" -vite@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.2.tgz#d6ea8610e099851dad8c7371599969e0f8b97e82" - integrity sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w== +vite@^4.5.3: + version "4.5.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" + integrity sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg== dependencies: esbuild "^0.18.10" postcss "^8.4.27" From 823955c59a39347fcae53ac5b29f764961d0a2d5 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 9 Apr 2024 16:04:40 -0400 Subject: [PATCH 080/164] bump locks --- Cargo.lock | 251 ++++++++++++++++++++++++++++------------------------- 1 file changed, 131 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa08d842b..00f958f8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,7 +47,7 @@ dependencies = [ "ahash", "base64 0.21.7", "bitflags 2.5.0", - "brotli", + "brotli 3.5.0", "bytes", "bytestring", "derive_more", @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -353,11 +353,11 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" dependencies = [ - "brotli", + "brotli 4.0.0", "flate2", "futures-core", "memchr", @@ -384,7 +384,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -406,7 +406,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -417,7 +417,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -431,15 +431,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.70" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d8e92cac0961e91dbd517496b00f7e9b92363dbe6d42c3198268323798860c" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -543,7 +543,18 @@ checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor", + "brotli-decompressor 2.5.1", +] + +[[package]] +name = "brotli" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor 3.0.0", ] [[package]] @@ -556,11 +567,21 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "brotli-decompressor" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecount" @@ -582,9 +603,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytestring" @@ -640,9 +661,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" dependencies = [ "jobserver", "libc", @@ -656,9 +677,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -713,7 +734,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] @@ -725,7 +746,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -826,9 +847,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -958,7 +979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -982,7 +1003,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -993,7 +1014,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1046,9 +1067,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1148,14 +1169,14 @@ dependencies = [ [[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1243,9 +1264,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fdeflate" @@ -1381,9 +1402,9 @@ dependencies = [ [[package]] name = "freetype-sys" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4dbbf4b8447b92e62282bf26760e7221f4f7ac15b9b10b3c99e4033379dbe0" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" dependencies = [ "cc", "libc", @@ -1475,7 +1496,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1535,9 +1556,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -1578,7 +1599,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1587,9 +1608,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", @@ -1816,9 +1837,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1839,7 +1860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "indexmap 2.2.5", + "indexmap 2.2.6", "is-terminal", "itoa", "log", @@ -1852,9 +1873,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.36.1" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +checksum = "3eab73f58e59ca6526037208f0e98851159ec1633cf17b6cd2e1f2c3fd5d53cc" dependencies = [ "console", "lazy_static", @@ -1862,7 +1883,6 @@ dependencies = [ "serde", "similar", "toml", - "yaml-rust", ] [[package]] @@ -1902,9 +1922,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -1961,7 +1981,7 @@ dependencies = [ "actix-service", "actix-web", "base64 0.13.1", - "brotli", + "brotli 3.5.0", "lambda_runtime", "percent-encoding", "serde", @@ -2023,18 +2043,18 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libdeflate-sys" -version = "1.19.3" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9caa76c8cc6ee8c4efcf8f4514a812ebcad3aa7d3b548efe4d26da1203f177" +checksum = "669ea17f9257bcb48c09c7ee4bef3957777504acffac557263e20c11001977bc" dependencies = [ "cc", ] [[package]] name = "libdeflater" -version = "1.19.3" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265a985bd31e5f22e2b2ac107cbed44c6ccf40ae236e46963cd00dd213e4bd03" +checksum = "8dfd6424f7010ee0a3416f1d796d0450e3ad3ac237a237644f728277c4ded016" dependencies = [ "libdeflate-sys", ] @@ -2111,7 +2131,7 @@ dependencies = [ "actix-web", "async-trait", "bit-set", - "brotli", + "brotli 3.5.0", "cargo-husky", "clap", "criterion", @@ -2204,9 +2224,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -2466,7 +2486,7 @@ dependencies = [ "bitvec", "crossbeam-channel", "filetime", - "indexmap 2.2.5", + "indexmap 2.2.6", "libdeflater", "log", "rayon", @@ -2522,7 +2542,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -2549,11 +2569,11 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "serde", ] @@ -2613,14 +2633,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2942,9 +2962,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca0b7bac0b97248c40bb77288fc52029cf1459c0461ea1b05ee32ccf011de2c" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" dependencies = [ "crossbeam-utils", "libc", @@ -3020,9 +3040,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3062,7 +3082,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -3073,7 +3093,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -3084,9 +3104,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "relative-path" @@ -3236,7 +3256,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.53", + "syn 2.0.58", "unicode-ident", ] @@ -3360,9 +3380,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" [[package]] name = "rustls-webpki" @@ -3453,9 +3473,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -3466,9 +3486,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -3500,7 +3520,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -3557,7 +3577,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -3574,7 +3594,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -3583,7 +3603,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -3639,9 +3659,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "similar" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" [[package]] name = "simplecss" @@ -3816,7 +3836,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.5", + "indexmap 2.2.6", "log", "memchr", "once_cell", @@ -4015,9 +4035,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structmeta" @@ -4028,7 +4048,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -4039,7 +4059,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -4106,9 +4126,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.53" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -4183,7 +4203,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -4282,9 +4302,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -4307,7 +4327,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -4453,7 +4473,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -4757,7 +4777,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -4791,7 +4811,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5063,15 +5083,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "yansi" version = "0.5.1" @@ -5095,7 +5106,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -5115,7 +5126,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -5132,27 +5143,27 @@ dependencies = [ [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.10+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" dependencies = [ "cc", "pkg-config", From 566f91d4cdf011e593d0d2c81d2c9022088d62ef Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 9 Apr 2024 19:36:40 -0400 Subject: [PATCH 081/164] upgrade dependencies, Nasm on Windows (#1295) * Install `nasm` when running CI on Windows (required by rustls new faster crypto-provider) * In integration testing, wrap connection in mutex due to `rstest` now requiring `once` fixtures to be `Sync` * Upgrade to Brotli v4, and disable FFI due to compilation conflict --- .github/workflows/ci.yml | 3 + Cargo.lock | 163 +++++++++++++++++++++++++++++++++++---- Cargo.toml | 10 ++- martin/src/pg/tls.rs | 3 +- mbtiles/tests/copy.rs | 11 ++- 5 files changed, 166 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1ad98875..4fb703485 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -264,6 +264,9 @@ jobs: run: rustc --version && cargo --version - uses: Swatinem/rust-cache@v2 if: github.event_name != 'release' && github.event_name != 'workflow_dispatch' + - name: Install NASM for rustls/aws-lc-rs on Windows + if: runner.os == 'Windows' + uses: ilammy/setup-nasm@v1 - name: Build (.deb) if: matrix.target == 'debian-x86_64' run: | diff --git a/Cargo.lock b/Cargo.lock index 00f958f8d..1e985073f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,32 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +[[package]] +name = "aws-lc-rs" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f379c4e505c0692333bd90a334baa234990faa06bdabefd3261f765946aa920" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68aa3d613f42dbf301dbbcaf3dc260805fd33ffd95f6d290ad7231a9e5d877a7" +dependencies = [ + "bindgen", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -484,6 +510,29 @@ dependencies = [ "smallvec", ] +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools 0.10.5", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.58", + "which", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -669,6 +718,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -715,6 +773,17 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.4" @@ -755,6 +824,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1123,6 +1201,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "either" version = "1.10.0" @@ -1423,6 +1507,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -2035,6 +2125,12 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.153" @@ -2059,6 +2155,16 @@ dependencies = [ "libdeflate-sys", ] +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.48.5", +] + [[package]] name = "libm" version = "0.2.8" @@ -2131,7 +2237,7 @@ dependencies = [ "actix-web", "async-trait", "bit-set", - "brotli 3.5.0", + "brotli 4.0.0", "cargo-husky", "clap", "criterion", @@ -2158,7 +2264,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.22.3", + "rustls 0.23.4", "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.2", "semver", @@ -2289,6 +2395,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "moka" version = "0.12.5" @@ -2839,6 +2951,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +dependencies = [ + "proc-macro2", + "syn 2.0.58", +] + [[package]] name = "proc-macro2" version = "1.0.79" @@ -3233,9 +3355,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" dependencies = [ "futures", "futures-timer", @@ -3245,9 +3367,9 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" dependencies = [ "cfg-if", "glob", @@ -3322,12 +3444,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +checksum = "8c4d6d8ad9f2492485e13453acbb291dd08f64441b6609c491f1c2cd2c6b4fe1" dependencies = [ + "aws-lc-rs", "log", - "ring", + "once_cell", "rustls-pki-types", "rustls-webpki 0.102.2", "subtle", @@ -3400,6 +3523,7 @@ version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -3632,6 +3756,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -4358,16 +4488,15 @@ dependencies = [ [[package]] name = "tokio-postgres-rustls" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea13f22eda7127c827983bdaf0d7fff9df21c8817bab02815ac277a21143677" +checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ - "futures", "ring", - "rustls 0.22.3", + "rustls 0.23.4", "tokio", "tokio-postgres", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "x509-certificate", ] @@ -4383,11 +4512,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.22.3", + "rustls 0.23.4", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index bee3e2b90..08edd32a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ anyhow = "1.0" approx = "0.5.1" async-trait = "0.1" bit-set = "0.5.3" -brotli = "3" +brotli = { version = "4", default-features = false, features = ["std"] } cargo-husky = { version = "1", features = ["user-hooks"], default-features = false } clap = { version = "4", features = ["derive"] } criterion = { version = "0.5", features = ["async_futures", "async_tokio", "html_reports"] } @@ -62,8 +62,10 @@ postgres-protocol = "0.6" pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" -rstest = "0.18" -rustls = "0.22" +rstest = "0.19" +rustls = "0.23.4" +# ring feature does not require NASM windows executable, but works slower +#rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" rustls-pemfile = "2" semver = "1" @@ -80,7 +82,7 @@ thiserror = "1" tile-grid = "0.5" tilejson = "0.4" tokio = { version = "1", features = ["macros"] } -tokio-postgres-rustls = "0.11" +tokio-postgres-rustls = "0.12" url = "2.5" [profile.dev.package] diff --git a/martin/src/pg/tls.rs b/martin/src/pg/tls.rs index 9f28fc664..f397393ba 100644 --- a/martin/src/pg/tls.rs +++ b/martin/src/pg/tls.rs @@ -9,7 +9,8 @@ use deadpool_postgres::tokio_postgres::Config; use log::{info, warn}; use regex::Regex; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; -use rustls::crypto::ring::default_provider; +// use rustls::crypto::ring::default_provider; +use rustls::crypto::aws_lc_rs::default_provider; use rustls::crypto::{verify_tls12_signature, verify_tls13_signature}; use rustls::pki_types::{CertificateDer, ServerName, UnixTime}; use rustls::{DigitallySignedStruct, Error, SignatureScheme}; diff --git a/mbtiles/tests/copy.rs b/mbtiles/tests/copy.rs index 97efcc64e..e0525cd31 100644 --- a/mbtiles/tests/copy.rs +++ b/mbtiles/tests/copy.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::path::PathBuf; use std::str::from_utf8; +use std::sync::Mutex; use ctor::ctor; use insta::{allow_duplicates, assert_snapshot}; @@ -176,7 +177,12 @@ macro_rules! assert_dump { struct Databases( HashMap< (&'static str, MbtTypeCli), - (Vec, Mbtiles, Option, SqliteConnection), + ( + Vec, + Mbtiles, + Option, + Mutex, + ), >, ); @@ -190,7 +196,8 @@ impl Databases { hash: Option, conn: SqliteConnection, ) { - self.0.insert((name, typ), (dump, mbtiles, hash, conn)); + self.0 + .insert((name, typ), (dump, mbtiles, hash, Mutex::new(conn))); } fn dump(&self, name: &'static str, typ: MbtTypeCli) -> &Vec { &self.0.get(&(name, typ)).unwrap().0 From e980f03d13972f8e1434c22b43d78838136927f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 03:15:05 +0000 Subject: [PATCH 082/164] chore(deps): Bump anyhow from 1.0.81 to 1.0.82 (#1298) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.82.
Release notes

Sourced from anyhow's releases.

1.0.82

  • Documentation improvements
Commits
  • 074bdea Release 1.0.82
  • 47a4fbf Merge pull request #360 from dtolnay/docensure
  • c5af1db Make ensure's doc comment apply to the cfg(not(doc)) macro too
  • bebc7a2 Revert "Temporarily disable miri on doctests"
  • f2c4db9 Update ui test suite to nightly-2024-03-31
  • 028cbee Explicitly install a Rust toolchain for cargo-outdated job
  • 7a4cac5 Merge pull request #358 from dtolnay/workspacewrapper
  • 939db01 Apply RUSTC_WORKSPACE_WRAPPER
  • 9f84a37 Temporarily disable miri on doctests
  • 45e5a58 Ignore dead code lint in test
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.81&new-version=1.0.82)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e985073f..4406ed294 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "approx" From e89e90f163c6b928dec1191ff0f5db37f44b70d3 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 10 Apr 2024 23:55:27 -0400 Subject: [PATCH 083/164] Migrate to newer pmtiles dependency (#1299) also minor code cleanup --- Cargo.lock | 251 ++++++++++++++++++++------------------ Cargo.toml | 2 +- martin/src/pmtiles/mod.rs | 2 +- martin/src/utils/error.rs | 21 ++-- 4 files changed, 144 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4406ed294..0e79a609d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,7 +55,7 @@ dependencies = [ "flate2", "futures-core", "h2", - "http", + "http 0.2.12", "httparse", "httpdate", "itoa", @@ -90,7 +90,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" dependencies = [ "bytestring", - "http", + "http 0.2.12", "regex", "serde", "tracing", @@ -519,7 +519,7 @@ dependencies = [ "bitflags 2.5.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -1224,9 +1224,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1688,7 +1688,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -1802,6 +1802,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1809,7 +1820,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -1841,9 +1875,8 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1855,18 +1888,60 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http", - "hyper", - "rustls 0.21.10", + "http 1.1.0", + "hyper 1.2.0", + "hyper-util", + "rustls 0.22.3", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -2087,8 +2162,8 @@ dependencies = [ "async-stream", "bytes", "futures", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "lambda_runtime_api_client", "serde", "serde_json", @@ -2104,8 +2179,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7210012be904051520f0dc502140ba599bae3042b65b3737b87727f1aa88a7d6" dependencies = [ - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "tokio", "tower-service", ] @@ -2162,7 +2237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] @@ -2265,8 +2340,8 @@ dependencies = [ "pprof", "regex", "rustls 0.23.4", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.2", + "rustls-native-certs", + "rustls-pemfile", "semver", "serde", "serde_json", @@ -2817,9 +2892,9 @@ dependencies = [ [[package]] name = "pmtiles" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92175e077dcbf7a8b9b0269f69b6d62b887b6b1ce57163d040cbda93c879957c" +checksum = "5382dab62c7151c9fb050626ad18560b4900e133257033782abb3b7ae23f2234" dependencies = [ "async-compression", "async-recursion", @@ -3108,9 +3183,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -3238,20 +3313,20 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", "hyper-rustls", + "hyper-util", "ipnet", "js-sys", "log", @@ -3259,16 +3334,16 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", - "rustls-native-certs 0.6.3", - "rustls-pemfile 1.0.4", + "rustls 0.22.3", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls 0.25.0", "tower-service", "url", "wasm-bindgen", @@ -3432,14 +3507,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" dependencies = [ "log", "ring", - "rustls-webpki 0.101.7", - "sct", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] @@ -3452,23 +3529,11 @@ dependencies = [ "log", "once_cell", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -3476,21 +3541,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3507,16 +3563,6 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.102.2" @@ -3575,16 +3621,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sdf_glyph_renderer" version = "1.0.1" @@ -4271,27 +4307,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tagptr" version = "0.2.0" @@ -4350,9 +4365,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -4371,9 +4386,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -4502,11 +4517,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.21.10", + "rustls 0.22.3", + "rustls-pki-types", "tokio", ] @@ -4565,6 +4581,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", + "tokio", "tower-layer", "tower-service", "tracing", @@ -5164,9 +5181,9 @@ checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winreg" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", diff --git a/Cargo.toml b/Cargo.toml index 08edd32a2..7c6c15d37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ mbtiles = { path = "./mbtiles", version = "0.9.0" } moka = { version = "0.12", features = ["future"] } num_cpus = "1" pbf_font_tools = { version = "2.5.1", features = ["freetype"] } -pmtiles = { version = "0.7", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } +pmtiles = { version = "0.8", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } postgis = "0.9" postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] } postgres-protocol = "0.6" diff --git a/martin/src/pmtiles/mod.rs b/martin/src/pmtiles/mod.rs index 9605e73b2..4a972ff0f 100644 --- a/martin/src/pmtiles/mod.rs +++ b/martin/src/pmtiles/mod.rs @@ -264,7 +264,7 @@ macro_rules! impl_pmtiles_source { if let Some(t) = self .pmtiles .get_tile(xyz.z, u64::from(xyz.x), u64::from(xyz.y)) - .await + .await? { Ok(t.to_vec()) } else { diff --git a/martin/src/utils/error.rs b/martin/src/utils/error.rs index 0687356c8..d59eef77c 100644 --- a/martin/src/utils/error.rs +++ b/martin/src/utils/error.rs @@ -3,15 +3,6 @@ use std::fmt::Write as _; use std::io; use std::path::PathBuf; -#[cfg(feature = "mbtiles")] -use mbtiles::MbtError; - -use crate::file_config::FileError; -#[cfg(feature = "fonts")] -use crate::fonts::FontError; -#[cfg(feature = "sprites")] -use crate::sprites::SpriteError; - /// A convenience [`Result`] for Martin crate. pub type MartinResult = Result; @@ -65,20 +56,24 @@ pub enum MartinError { #[error(transparent)] PostgresError(#[from] crate::pg::PgError), + #[cfg(feature = "pmtiles")] + #[error(transparent)] + PmtilesError(#[from] pmtiles::PmtError), + #[cfg(feature = "mbtiles")] #[error(transparent)] - MbtilesError(#[from] MbtError), + MbtilesError(#[from] mbtiles::MbtError), #[error(transparent)] - FileError(#[from] FileError), + FileError(#[from] crate::file_config::FileError), #[cfg(feature = "sprites")] #[error(transparent)] - SpriteError(#[from] SpriteError), + SpriteError(#[from] crate::sprites::SpriteError), #[cfg(feature = "fonts")] #[error(transparent)] - FontError(#[from] FontError), + FontError(#[from] crate::fonts::FontError), #[error(transparent)] WebError(#[from] actix_web::Error), From 99db6d771d7ccb21089e06742e53922f6bcc52d2 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 11 Apr 2024 03:36:19 -0400 Subject: [PATCH 084/164] Upgrade to pmtiles, rm async-trait in a trait (#1300) * Bump to pmtiles that doesn't use `async_trait` crate * `trait SourceConfigExtras` no longer needs `#[async_trait]` --- Cargo.lock | 5 ++--- Cargo.toml | 2 +- martin/src/file_config.rs | 15 +++++++++++---- martin/src/mbtiles/mod.rs | 4 +++- martin/src/pmtiles/mod.rs | 3 +-- martin/src/sprites/mod.rs | 2 -- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e79a609d..b2e9c7bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2892,13 +2892,12 @@ dependencies = [ [[package]] name = "pmtiles" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5382dab62c7151c9fb050626ad18560b4900e133257033782abb3b7ae23f2234" +checksum = "a1336029dbfe273811a751f91e85a6011bcfe399c9b8d1ad9662e96df2a2d74e" dependencies = [ "async-compression", "async-recursion", - "async-trait", "bytes", "fmmap", "hilbert_2d", diff --git a/Cargo.toml b/Cargo.toml index 7c6c15d37..1a96e23f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ mbtiles = { path = "./mbtiles", version = "0.9.0" } moka = { version = "0.12", features = ["future"] } num_cpus = "1" pbf_font_tools = { version = "2.5.1", features = ["freetype"] } -pmtiles = { version = "0.8", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } +pmtiles = { version = "0.9", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } postgis = "0.9" postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] } postgres-protocol = "0.6" diff --git a/martin/src/file_config.rs b/martin/src/file_config.rs index d79c008dc..695ef9d01 100644 --- a/martin/src/file_config.rs +++ b/martin/src/file_config.rs @@ -3,7 +3,6 @@ use std::fmt::Debug; use std::mem; use std::path::{Path, PathBuf}; -use async_trait::async_trait; use futures::TryFutureExt; use log::{info, warn}; use serde::{Deserialize, Serialize}; @@ -61,15 +60,23 @@ pub trait ConfigExtras: Clone + Debug + Default + PartialEq + Send { fn get_unrecognized(&self) -> &UnrecognizedValues; } -#[async_trait] pub trait SourceConfigExtras: ConfigExtras { #[must_use] fn parse_urls() -> bool { false } - async fn new_sources(&self, id: String, path: PathBuf) -> FileResult>; - async fn new_sources_url(&self, id: String, url: Url) -> FileResult>; + fn new_sources( + &self, + id: String, + path: PathBuf, + ) -> impl std::future::Future>> + Send; + + fn new_sources_url( + &self, + id: String, + url: Url, + ) -> impl std::future::Future>> + Send; } #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] diff --git a/martin/src/mbtiles/mod.rs b/martin/src/mbtiles/mod.rs index d9ea2dfcd..b9e446f24 100644 --- a/martin/src/mbtiles/mod.rs +++ b/martin/src/mbtiles/mod.rs @@ -29,12 +29,14 @@ impl ConfigExtras for MbtConfig { } } -#[async_trait] impl SourceConfigExtras for MbtConfig { async fn new_sources(&self, id: String, path: PathBuf) -> FileResult> { Ok(Box::new(MbtSource::new(id, path).await?)) } + // TODO: Remove #[allow] after switching to Rust/Clippy v1.78+ in CI + // See https://github.com/rust-lang/rust-clippy/pull/12323 + #[allow(clippy::no_effect_underscore_binding)] async fn new_sources_url(&self, _id: String, _url: Url) -> FileResult> { unreachable!() } diff --git a/martin/src/pmtiles/mod.rs b/martin/src/pmtiles/mod.rs index 4a972ff0f..3b0c134f9 100644 --- a/martin/src/pmtiles/mod.rs +++ b/martin/src/pmtiles/mod.rs @@ -39,7 +39,6 @@ impl PmtCache { } } -#[async_trait] impl DirectoryCache for PmtCache { async fn get_dir_entry(&self, offset: usize, tile_id: u64) -> DirCacheResult { if let Some(dir) = get_cached_value!(&self.cache, CacheValue::PmtDirectory, { @@ -129,7 +128,7 @@ impl ConfigExtras for PmtConfig { &self.unrecognized } } -#[async_trait] + impl SourceConfigExtras for PmtConfig { fn parse_urls() -> bool { true diff --git a/martin/src/sprites/mod.rs b/martin/src/sprites/mod.rs index 7dce53c82..07e1c769a 100644 --- a/martin/src/sprites/mod.rs +++ b/martin/src/sprites/mod.rs @@ -3,7 +3,6 @@ use std::collections::{BTreeMap, HashMap}; use std::fmt::Debug; use std::path::PathBuf; -use async_trait::async_trait; use futures::future::try_join_all; use log::{info, warn}; use serde::{Deserialize, Serialize}; @@ -65,7 +64,6 @@ pub struct SpriteConfig { pub unrecognized: UnrecognizedValues, } -#[async_trait] impl ConfigExtras for SpriteConfig { fn get_unrecognized(&self) -> &UnrecognizedValues { &self.unrecognized From b3455edee0b775ba0387e0d1799493fc7637a64e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 02:48:14 +0000 Subject: [PATCH 085/164] chore(deps): Bump moka from 0.12.5 to 0.12.6 (#1305) Bumps [moka](https://github.com/moka-rs/moka) from 0.12.5 to 0.12.6.
Changelog

Sourced from moka's changelog.

Version 0.12.6

Fixed

  • Fixed a bug in future::Cache that pending run_pending_tasks calls may cause infinite busy loop in an internal schedule_write_op method (#412[gh-issue-0412]):
    • This bug was introduced in v0.12.0 when the background threads were removed from future::Cache.
    • This bug can occur when run_pending_task method is called by user code while cache is receiving a very high number of concurrent cache write operations. (e.g. insert, get_with, invalidate etc.)
    • When it occurs, the schedule_write_op method will be spinning in a busy loop forever, causing high CPU usage and all other async tasks to be starved.

Changed

  • Upgraded async-lock crate used by future::Cache from v2.4 to the latest v3.3.
Commits
  • 1d2af53 Merge pull request #416 from moka-rs/fix-stacked-borrow-violation
  • 7879dde Fix Miri error (Stacked Borrow violation) in the test code of the timer wheel
  • 2f23e5c Merge pull request #415 from moka-rs/avoid-async-scheduler-busy-loop
  • c50d186 Update the changelog
  • 6c4f0ac Bump the version to v0.12.6
  • 8805940 Prevent the busy loop of async schedulers
  • dc960af Fix typos in comments
  • 5996c87 Prevent the busy loop of async schedulers
  • 6ba5445 Merge pull request #413 from moka-rs/fix-ci-2024-04-10/v0.12
  • 4042c4a Fix Clippy warnings
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=moka&package-manager=cargo&previous-version=0.12.5&new-version=0.12.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 147 ++++++++++++++++++++--------------------------------- 1 file changed, 56 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2e9c7bd7..72c9f5520 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -369,11 +369,13 @@ dependencies = [ [[package]] name = "async-lock" -version = "2.8.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener", + "event-listener 4.0.3", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -632,12 +634,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "bytecount" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" - [[package]] name = "bytemuck" version = "1.15.0" @@ -665,43 +661,12 @@ dependencies = [ "bytes", ] -[[package]] -name = "camino" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] - [[package]] name = "cargo-husky" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - [[package]] name = "cast" version = "0.3.0" @@ -845,6 +810,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console" version = "0.15.8" @@ -1302,15 +1276,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check", -] - [[package]] name = "etcetera" version = "0.8.0" @@ -1328,6 +1293,38 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -2478,21 +2475,21 @@ checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] name = "moka" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1911e88d5831f748a4097a43862d129e3c6fca831eecac9b8db6d01d93c9de2" +checksum = "87bfd249f570638bfb0b4f9d258e6b8cddd2a5a7d0ed47e8bb8b176bfc0e7a17" dependencies = [ "async-lock", "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", + "event-listener 5.3.0", "futures-util", "once_cell", "parking_lot", "quanta", "rustc_version", - "skeptic", "smallvec", "tagptr", "thiserror", @@ -2683,6 +2680,12 @@ dependencies = [ "zopfli", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.1" @@ -3145,17 +3148,6 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9653c3ed92974e34c5a6e0a510864dab979760481714c172e0a34e437cb98804" -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags 2.5.0", - "memchr", - "unicase", -] - [[package]] name = "quanta" version = "0.12.3" @@ -3658,9 +3650,6 @@ name = "semver" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" -dependencies = [ - "serde", -] [[package]] name = "serde" @@ -3853,21 +3842,6 @@ dependencies = [ "num", ] -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - [[package]] name = "slab" version = "0.4.9" @@ -3993,7 +3967,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener", + "event-listener 2.5.3", "futures-channel", "futures-core", "futures-intrusive", @@ -4669,15 +4643,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.15" From e18628a830547bac9440e303649f81c5e45d9938 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 02:49:04 +0000 Subject: [PATCH 086/164] chore(deps): Bump async-trait from 0.1.79 to 0.1.80 (#1306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [//]: # (dependabot-start) ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- [//]: # (dependabot-end) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.79 to 0.1.80.
Release notes

Sourced from async-trait's releases.

0.1.80

  • Fix unreachable code warning for async functions that return ! (#265, thanks @​de-vri-es)
Commits
  • d528b5a Release 0.1.80
  • 10b5c99 Drop support for compilers older than 1.47
  • 83a5422 Drop support for compilers older than 1.45
  • 22d017e Build script no longer looks at $DOCS_RS
  • b64d041 Move never_type test under issue266
  • b683da8 Merge pull request #265 from de-vri-es/fix-unreachable-code-warning
  • c8d958d Fix unreachable code warning for functions that return !
  • 4f0b72e Explicitly install a Rust toolchain for cargo-outdated job
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=async-trait&package-manager=cargo&previous-version=0.1.79&new-version=0.1.80)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72c9f5520..7e6c9707e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -413,9 +413,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", From ce182d2a9e6abdc7eeb242354c29d8f0e1a93497 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 14 Apr 2024 22:59:02 -0400 Subject: [PATCH 087/164] Bump dependencies --- Cargo.lock | 166 +++++++++++++++++++++++++++++++---------------------- Cargo.toml | 2 +- 2 files changed, 98 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e6c9707e..6bb09e629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -251,9 +251,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -386,7 +386,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -408,7 +408,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -419,7 +419,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -531,7 +531,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.58", + "syn 2.0.59", "which", ] @@ -608,6 +608,17 @@ dependencies = [ "brotli-decompressor 3.0.0", ] +[[package]] +name = "brotli" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19483b140a7ac7174d34b5a581b406c64f84da5409d3e09cf4fff604f9270e67" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor 4.0.0", +] + [[package]] name = "brotli-decompressor" version = "2.5.1" @@ -628,6 +639,16 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "brotli-decompressor" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6221fe77a248b9117d431ad93761222e1cf8ff282d9d1d5d9f53d6299a1cf76" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -675,9 +696,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" dependencies = [ "jobserver", "libc", @@ -708,7 +729,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -780,7 +801,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -1031,7 +1052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -1055,7 +1076,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -1066,7 +1087,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -1183,9 +1204,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" dependencies = [ "serde", ] @@ -1234,7 +1255,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -1583,7 +1604,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -2090,9 +2111,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" dependencies = [ "libc", ] @@ -2234,7 +2255,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -2309,7 +2330,7 @@ dependencies = [ "actix-web", "async-trait", "bit-set", - "brotli 4.0.0", + "brotli 5.0.0", "cargo-husky", "clap", "criterion", @@ -2732,7 +2753,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -2823,7 +2844,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -3030,19 +3051,19 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" dependencies = [ "proc-macro2", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" dependencies = [ "unicode-ident", ] @@ -3444,7 +3465,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.58", + "syn 2.0.59", "unicode-ident", ] @@ -3668,7 +3689,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -3742,7 +3763,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4187,7 +4208,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4198,7 +4219,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4265,9 +4286,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" dependencies = [ "proc-macro2", "quote", @@ -4321,7 +4342,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4445,7 +4466,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4592,7 +4613,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -4887,7 +4908,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", "wasm-bindgen-shared", ] @@ -4921,7 +4942,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5008,7 +5029,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5026,7 +5047,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5046,17 +5067,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -5067,9 +5089,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -5079,9 +5101,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -5091,9 +5113,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -5103,9 +5131,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -5115,9 +5143,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -5127,9 +5155,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -5139,9 +5167,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" @@ -5216,7 +5244,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] @@ -5236,7 +5264,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.59", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1a96e23f3..ed0e2d706 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ anyhow = "1.0" approx = "0.5.1" async-trait = "0.1" bit-set = "0.5.3" -brotli = { version = "4", default-features = false, features = ["std"] } +brotli = "5.0.0" cargo-husky = { version = "1", features = ["user-hooks"], default-features = false } clap = { version = "4", features = ["derive"] } criterion = { version = "0.5", features = ["async_futures", "async_tokio", "html_reports"] } From e6c58fdfde75369be8dda5bca986b4f4591199ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 02:46:23 +0000 Subject: [PATCH 088/164] chore(deps): Bump serde from 1.0.197 to 1.0.198 (#1309) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.198.
Release notes

Sourced from serde's releases.

v1.0.198

Commits
  • c4fb923 Release 1.0.198
  • 65b7eea Merge pull request #2729 from dtolnay/saturating
  • 01cd696 Integrate Saturating<T> deserialization into impl_deserialize_num macro
  • c13b3f7 Format PR 2709
  • a6571ee Merge pull request #2709 from jbethune/master
  • 6e38aff Revert "Temporarily disable miri on doctests"
  • 3d1b19e Implement Ser+De for Saturating\<T>
  • 5b24f88 Resolve legacy_numeric_constants clippy lints
  • 74d0670 Explicitly install a Rust toolchain for cargo-outdated job
  • 3bfab6e Temporarily disable miri on doctests
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.197&new-version=1.0.198)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bb09e629..4f8c08c46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3674,18 +3674,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", From 44c0b90777584b6b607a7c0b5e2d4dc78a357054 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 02:46:54 +0000 Subject: [PATCH 089/164] chore(deps): Bump serde_json from 1.0.115 to 1.0.116 (#1308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.116.
Release notes

Sourced from serde_json's releases.

v1.0.116

Commits
  • a3f62bb Release 1.0.116
  • 12c8ee0 Hide "non-exhaustive patterns" errors when crate fails to compile
  • 051ce97 Merge pull request 1124 from mleonhard/master
  • 25dc750 Replace features_check mod with a call to std::compile_error!. Fixes htt...
  • 2e15e3d Revert "Temporarily disable miri on doctests"
  • 0baba28 Resolve legacy_numeric_constants clippy lints
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.115&new-version=1.0.116)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f8c08c46..c822291a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3694,9 +3694,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", From 352e6162badd0263ef7ab83138c35afa5b14674c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 02:48:14 +0000 Subject: [PATCH 090/164] chore(deps): Bump ctor from 0.2.7 to 0.2.8 (#1310) Bumps [ctor](https://github.com/mmastrac/rust-ctor) from 0.2.7 to 0.2.8.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ctor&package-manager=cargo&previous-version=0.2.7&new-version=0.2.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c822291a5..e66ff61ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1047,9 +1047,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", "syn 2.0.59", From f670f9e88bf316171cf6cf3fc4c95586146173fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 02:58:32 +0000 Subject: [PATCH 091/164] chore(deps): Bump moka from 0.12.6 to 0.12.7 (#1311) Bumps [moka](https://github.com/moka-rs/moka) from 0.12.6 to 0.12.7.
Changelog

Sourced from moka's changelog.

Version 0.12.7

Changed

  • Ensure a single call to run_pending_tasks to evict as many entries as possible from the cache (#417[gh-pull-0417]).
Commits
  • c56d646 Merge pull request #417 from moka-rs/evict-more-entries-at-once
  • ccb285b Tweak some source code comments
  • dfbbe3f Make a single call to run_pending_tasks to evict as many entries as
  • c6a4d4b Make a single call to run_pending_tasks to evict as many entries as
  • 91c8497 Update the change log
  • b59b938 Update the change log
  • b9923f8 Bump the version to v0.12.7
  • 364567e Make run_pending_tasks to evict more entries from the cache at once
  • 3b9adc3 Make run_pending_tasks to evict more entries from the cache at once
  • c7f67cd Make run_pending_tasks to evict more entries from the cache at once
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=moka&package-manager=cargo&previous-version=0.12.6&new-version=0.12.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e66ff61ba..2f2a7fc8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2496,9 +2496,9 @@ checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] name = "moka" -version = "0.12.6" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87bfd249f570638bfb0b4f9d258e6b8cddd2a5a7d0ed47e8bb8b176bfc0e7a17" +checksum = "9e0d88686dc561d743b40de8269b26eaf0dc58781bde087b0984646602021d08" dependencies = [ "async-lock", "async-trait", From 4ac4ff2b20c4fb04fa14b205088251df3ae271c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 20:20:11 +0000 Subject: [PATCH 092/164] chore(deps): Bump rustls from 0.23.4 to 0.23.5 (#1312) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.4 to 0.23.5.
Commits
  • 14cb5d2 Prepare 0.23.5
  • 6e938bc complete_io: bail out if progress is impossible
  • 2123576 Regression test for complete_io infinite loop bug
  • f45664f Don't specially handle unauthenticated close_notify alerts
  • 1f5146c docs: update SECURITY example
  • 5ea02ed Return Option from handshake_kind()
  • d2e1e66 bogo: verify expected handshake kind
  • d8a2ae0 Add API exposing shape of the performed handshake
  • 740ca41 tests/api.rs: reformat
  • 5ed2c97 deps: update cargo semver compatible deps
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.23.4&new-version=0.23.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f2a7fc8b..ef3786de1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2357,7 +2357,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.23.4", + "rustls 0.23.5", "rustls-native-certs", "rustls-pemfile", "semver", @@ -3533,9 +3533,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.4" +version = "0.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4d6d8ad9f2492485e13453acbb291dd08f64441b6609c491f1c2cd2c6b4fe1" +checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" dependencies = [ "aws-lc-rs", "log", @@ -4502,7 +4502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.4", + "rustls 0.23.5", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4526,7 +4526,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.4", + "rustls 0.23.5", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index ed0e2d706..6a6c4ea4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" rstest = "0.19" -rustls = "0.23.4" +rustls = "0.23.5" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" From 184789b56d85d19d9d3fffb07e125c176dec4492 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 19 Apr 2024 16:34:20 -0400 Subject: [PATCH 093/164] bump lock --- Cargo.lock | 99 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef3786de1..68473f3a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -386,7 +386,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -408,7 +408,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -419,7 +419,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -439,9 +439,9 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-lc-rs" -version = "1.6.4" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f379c4e505c0692333bd90a334baa234990faa06bdabefd3261f765946aa920" +checksum = "5509d663b2c00ee421bda8d6a24d6c42e15970957de1701b8df9f6fbe5707df1" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -451,11 +451,12 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68aa3d613f42dbf301dbbcaf3dc260805fd33ffd95f6d290ad7231a9e5d877a7" +checksum = "8d5d317212c2a78d86ba6622e969413c38847b62f48111f8b763af3dac2f9840" dependencies = [ "bindgen", + "cc", "cmake", "dunce", "fs_extra", @@ -531,7 +532,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.59", + "syn 2.0.60", "which", ] @@ -721,9 +722,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -801,7 +802,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1052,7 +1053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1076,7 +1077,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1087,7 +1088,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1255,7 +1256,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1604,7 +1605,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -1908,9 +1909,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -1933,9 +1934,9 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", - "rustls 0.22.3", + "rustls 0.22.4", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -1953,7 +1954,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -2753,7 +2754,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -2844,7 +2845,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -3056,14 +3057,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" dependencies = [ "proc-macro2", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] name = "proc-macro2" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -3325,9 +3326,9 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64 0.22.0", "bytes", @@ -3336,7 +3337,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-rustls", "hyper-util", "ipnet", @@ -3346,7 +3347,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.3", + "rustls 0.22.4", "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", @@ -3465,7 +3466,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.59", + "syn 2.0.60", "unicode-ident", ] @@ -3519,9 +3520,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring", @@ -3689,7 +3690,7 @@ checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -3763,7 +3764,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4208,7 +4209,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4219,7 +4220,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4286,9 +4287,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.59" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -4342,7 +4343,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4466,7 +4467,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4515,7 +4516,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.3", + "rustls 0.22.4", "rustls-pki-types", "tokio", ] @@ -4613,7 +4614,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -4908,7 +4909,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -4942,7 +4943,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5244,7 +5245,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] @@ -5264,7 +5265,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.59", + "syn 2.0.60", ] [[package]] From c54ac4049a4923be05796fba5f955d2e06ee3351 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:38:29 +0000 Subject: [PATCH 094/164] chore(deps): Bump thiserror from 1.0.58 to 1.0.59 (#1313) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.58 to 1.0.59.
Release notes

Sourced from thiserror's releases.

1.0.59

  • Unblock testing of rustc debug-fmt-detail option (#297)
Commits
  • e7ad85e Release 1.0.59
  • af477ec Merge pull request #297 from dtolnay/traitident
  • f3fbd99 Implement ToTokens without reliance on {:?}
  • 508ece8 Revert "Temporarily disable miri on doctests"
  • c8c804c Explicitly install a Rust toolchain for cargo-outdated job
  • 6969595 Merge pull request #293 from dtolnay/workspacewrapper
  • 488d52f Apply RUSTC_WORKSPACE_WRAPPER
  • ba33438 Temporarily disable miri on doctests
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=thiserror&package-manager=cargo&previous-version=1.0.58&new-version=1.0.59)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68473f3a0..9e2134996 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4328,18 +4328,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", From 89464a134e3691a113b4492bce0ab7a4b7ebcd6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 03:19:22 +0000 Subject: [PATCH 095/164] chore(deps): Bump serde from 1.0.198 to 1.0.199 (#1318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde](https://github.com/serde-rs/serde) from 1.0.198 to 1.0.199.
Release notes

Sourced from serde's releases.

v1.0.199

  • Fix ambiguous associated item when forward_to_deserialize_any! is used on an enum with Error variant (#2732, thanks @​aatifsyed)
Commits
  • 1477028 Release 1.0.199
  • 789740b Merge pull request #2732 from aatifsyed/master
  • 8fe7539 fix: ambiguous associated type in forward_to_deserialize_any!
  • f6623a3 Ignore cast_precision_loss pedantic clippy lint
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.198&new-version=1.0.199)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e2134996..bff82b3eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3675,18 +3675,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", From e7af716ccfb822e954bb70af564188b4fcad4bcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 03:19:35 +0000 Subject: [PATCH 096/164] chore(deps): Bump flate2 from 1.0.28 to 1.0.29 (#1320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.28 to 1.0.29.
Release notes

Sourced from flate2's releases.

1.0.29 - with new zlib-rs feature (~zlib-ng in Rust)

With the new zlib-rs feature, a new backend is enabled that brings in a SIMD-accelerated Rust implementation.

What's Changed

New Contributors

Full Changelog: https://github.com/rust-lang/flate2-rs/compare/1.0.28...1.0.29

Commits
  • 9a25bc0 Merge pull request #403 from folkertdev/bump-version-zlib-rs
  • e9c87c0 zlib-rs support version bump
  • 8a502a7 Merge pull request #402 from jongiddy/bufread-tests
  • 320e7c7 Merge pull request #400 from folkertdev/zlib-rs-c-api
  • 6a26c0c Test that BufRead and Write can be used after decoding
  • 7e6429a add zlib-rs support via the libz-rs-sys C api for zlib-rs
  • ae78497 Merge pull request #398 from rust-lang/fix-imports
  • 20bbd74 Avoid redudant imports
  • 0a584f4 Merge pull request #394 from icmccorm/main
  • 8386651 Switched to storing mz_stream as a raw pointer to fix tree borrows violation.
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flate2&package-manager=cargo&previous-version=1.0.28&new-version=1.0.29)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bff82b3eb..9a8ab2d9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1412,9 +1412,9 @@ checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "4556222738635b7a3417ae6130d8f52201e45a0c4d1a907f0826383adb5f85e7" dependencies = [ "crc32fast", "miniz_oxide", From 15496df706e04540fb1e7eaf7d555882bd87f44d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 02:29:23 +0000 Subject: [PATCH 097/164] chore(deps): Bump flate2 from 1.0.29 to 1.0.30 (#1321) Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.29 to 1.0.30.
Commits
  • d3bea90 Merge pull request #405 from Byron/fix-CI
  • 5048843 Merge pull request #407 from striezel-stash/actions-checkout-v4
  • 42c86ce Merge pull request #406 from striezel-stash/fix-some-typos
  • f7b99e9 Update actions/checkout in GitHub Actions workflows to v4
  • 563f1c4 Fix typos
  • 1126a4a prepare bugfix release to make docs work again
  • bc1b3e9 CI verifies that docs can be built (#404)
  • 5ce4154 fix CI by assuring builds work with --all-features enabled (#404)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flate2&package-manager=cargo&previous-version=1.0.29&new-version=1.0.30)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a8ab2d9b..ffb8142a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1412,9 +1412,9 @@ checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" [[package]] name = "flate2" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4556222738635b7a3417ae6130d8f52201e45a0c4d1a907f0826383adb5f85e7" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", From 5742bb38ef50275d2ab20a358da148feb47ad80b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 02:47:09 +0000 Subject: [PATCH 098/164] chore(deps): Bump serde from 1.0.199 to 1.0.200 (#1323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde](https://github.com/serde-rs/serde) from 1.0.199 to 1.0.200.
Release notes

Sourced from serde's releases.

v1.0.200

  • Fix formatting of "invalid type" and "invalid value" deserialization error messages containing NaN or infinite floats (#2733, thanks @​jamessan)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.199&new-version=1.0.200)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffb8142a6..2dd2453d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3675,18 +3675,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", From 792f24bbd91028c57e87012ea6c58f1d2a3fce24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 02:58:27 +0000 Subject: [PATCH 099/164] chore(deps): Bump anyhow from 1.0.82 to 1.0.83 (#1331) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.83.
Release notes

Sourced from anyhow's releases.

1.0.83

  • Integrate compile-time checking of cfgs (#363)
Commits
  • 96f0392 Release 1.0.83
  • 17bbd1e Merge pull request #363 from dtolnay/checkcfg
  • 3ab3c3b Resolve unexpected_cfgs warning
  • 8e62244 Discard CI coverage of backtrace feature on toolchains older than 1.63
  • e77374f Mirror PR 343 changes from readme to rustdoc
  • cb47d7c Reword no-std documentation change from PR 343
  • 6b5bdb1 Wrap PR 343 to 80 columns
  • f01080b Merge pull request #343 from Arthur-Milchior/readme1
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.82&new-version=1.0.83)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2dd2453d1..472405c30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "approx" From 7dee6c1b738207045416514983b22bebdff3be38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 02:58:53 +0000 Subject: [PATCH 100/164] chore(deps): Bump thiserror from 1.0.59 to 1.0.60 (#1329) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.59 to 1.0.60.
Release notes

Sourced from thiserror's releases.

1.0.60

  • Resolve unexpected_cfgs warning (#298)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=thiserror&package-manager=cargo&previous-version=1.0.59&new-version=1.0.60)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 472405c30..82c6821fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4328,18 +4328,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", From 12bebb5a6e932a2a8331c7d766eb60bc61af7a7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 02:59:15 +0000 Subject: [PATCH 101/164] chore(deps): Bump semver from 1.0.22 to 1.0.23 (#1328) Bumps [semver](https://github.com/dtolnay/semver) from 1.0.22 to 1.0.23.
Release notes

Sourced from semver's releases.

1.0.23

  • Resolve unexpected_cfgs warning (#318)
Commits
  • 69efd3c Release 1.0.23
  • 451b419 Merge pull request #318 from dtolnay/checkcfg
  • 5b71485 Resolve unexpected_cfgs warning
  • c520af7 Revert "Temporarily disable miri on doctests"
  • 73b5d9e Merge pull request #313 from Saecki/patch-1
  • e8d61de chore: fix typo in safety comment
  • d282d48 Explicitly install a Rust toolchain for cargo-outdated job
  • 6e6ba22 Temporarily disable miri on doctests
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=semver&package-manager=cargo&previous-version=1.0.22&new-version=1.0.23)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82c6821fc..9825459a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3669,9 +3669,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" From ededde4d6057bb753520cca4fc29b5974b39a0a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 03:05:41 +0000 Subject: [PATCH 102/164] chore(deps): Bump serde_json from 1.0.116 to 1.0.117 (#1333) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.116 to 1.0.117.
Release notes

Sourced from serde_json's releases.

v1.0.117

  • Resolve unexpected_cfgs warning (#1130)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.116&new-version=1.0.117)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9825459a2..40a92a759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3695,9 +3695,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", From 01c165c368841403a75fd885a8a010130d6456ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 03:18:46 +0000 Subject: [PATCH 103/164] chore(deps): Bump serde from 1.0.200 to 1.0.201 (#1334) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.201.
Release notes

Sourced from serde's releases.

v1.0.201

  • Resolve unexpected_cfgs warning (#2737)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.200&new-version=1.0.201)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40a92a759..8017dab54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3675,18 +3675,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", From 45ae20b2fdc225374a5b1be73595c708a8b32ea6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 03:13:21 +0000 Subject: [PATCH 104/164] chore(deps): Bump serde from 1.0.201 to 1.0.202 (#1338) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.202.
Release notes

Sourced from serde's releases.

v1.0.202

  • Provide public access to RenameAllRules in serde_derive_internals (#2743)
Commits
  • 9e32a40 Release 1.0.202
  • 87f635e Release serde_derive_internals 0.29.1
  • d4b2dfb Merge pull request #2743 from dtolnay/renameallrules
  • f6ab0bc Provide public access to RenameAllRules in serde_derive_internals
  • 48cc2a6 Replace use of a syn From impl
  • 3202a68 Skip rerunning build script on library code changes
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.201&new-version=1.0.202)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8017dab54..07f8b4cd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3675,18 +3675,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", From 3031e104f9f8054bf9dd671c67d5cfb5b8fe4c03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 02:50:02 +0000 Subject: [PATCH 105/164] chore(deps): Bump rustls from 0.23.5 to 0.23.6 (#1340) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.5 to 0.23.6.
Commits
  • 06dc1d5 deps: update cargo semver compatible deps
  • 252b5d3 Prepare 0.23.6
  • 55890f0 Test for junk in unbuffered input after close_notify
  • 972da7f Test app data after close_notify is ignored
  • 424bb31 Test for junk in deframer buffer after close_notify
  • 749121a Ignore data appearing after close_notify
  • ef02434 Deduplicate Reader state checks
  • ccb352c Linearize Reader::read() and read_buf()
  • 27d81e0 Warn on lints, don't deny
  • f214df9 bogo: fix config rewriting when cpp is clang
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.23.5&new-version=0.23.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07f8b4cd6..cfb8c22db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2358,7 +2358,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.23.5", + "rustls 0.23.6", "rustls-native-certs", "rustls-pemfile", "semver", @@ -3534,9 +3534,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.5" +version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" +checksum = "94cf0812de1f0cee6b163ce35c2f57b90e1ef5a2bed57bcf07c16475bac8c852" dependencies = [ "aws-lc-rs", "log", @@ -4503,7 +4503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.5", + "rustls 0.23.6", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4527,7 +4527,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.5", + "rustls 0.23.6", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 6a6c4ea4f..528167d9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" rstest = "0.19" -rustls = "0.23.5" +rustls = "0.23.6" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" From df8880fe4cf6d4d920ef3e4825b0b3941dadd87c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 17 May 2024 01:05:19 -0400 Subject: [PATCH 106/164] Fix a few CI issues and bump deps (#1341) --- .github/workflows/build-deploy-docs.yml | 2 +- Cargo.lock | 428 ++++++++++++------------ Cargo.toml | 8 +- martin/src/args/pg.rs | 2 +- martin/src/args/srv.rs | 1 + martin/src/utils/cache.rs | 6 +- martin/src/utils/id_resolver.rs | 2 + mbtiles/src/bin/mbtiles.rs | 4 + mbtiles/src/copier.rs | 4 +- 9 files changed, 238 insertions(+), 219 deletions(-) diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml index 025016a63..3bd642b34 100644 --- a/.github/workflows/build-deploy-docs.yml +++ b/.github/workflows/build-deploy-docs.yml @@ -32,7 +32,7 @@ jobs: - name: Setup mdBook uses: peaceiris/actions-mdbook@v2 with: - mdbook-version: 'latest' + mdbook-version: '0.4.40' - run: mdbook build docs diff --git a/Cargo.lock b/Cargo.lock index cfb8c22db..7bcc5dacc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -194,7 +194,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -278,47 +278,48 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -353,18 +354,15 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" +checksum = "9c90a406b4495d129f00461241616194cb8a032c8d1c53c657f0961d5f8e0498" dependencies = [ - "brotli 4.0.0", "flate2", "futures-core", "memchr", "pin-project-lite", "tokio", - "zstd", - "zstd-safe", ] [[package]] @@ -378,17 +376,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-recursion" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - [[package]] name = "async-stream" version = "0.3.5" @@ -408,7 +395,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -419,7 +406,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -433,15 +420,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5509d663b2c00ee421bda8d6a24d6c42e15970957de1701b8df9f6fbe5707df1" +checksum = "8487b59d62764df8231cb371c459314df895b41756df457a1fb1243d65c89195" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -451,9 +438,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5d317212c2a78d86ba6622e969413c38847b62f48111f8b763af3dac2f9840" +checksum = "c15eb61145320320eb919d9bab524617a7aa4216c78d342fae3a758bc33073e4" dependencies = [ "bindgen", "cc", @@ -493,9 +480,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -532,7 +519,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.60", + "syn 2.0.64", "which", ] @@ -600,20 +587,9 @@ dependencies = [ [[package]] name = "brotli" -version = "4.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor 3.0.0", -] - -[[package]] -name = "brotli" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19483b140a7ac7174d34b5a581b406c64f84da5409d3e09cf4fff604f9270e67" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -630,16 +606,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "brotli-decompressor" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "brotli-decompressor" version = "4.0.0" @@ -658,9 +624,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" [[package]] name = "byteorder" @@ -697,12 +663,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.94" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -790,7 +757,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -802,7 +769,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -811,6 +778,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "clap_mangen" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1dd95b5ebb5c1c54581dd6346f3ed6a79a3eef95dd372fc2ac13d535535300e" +dependencies = [ + "clap", + "roff", +] + [[package]] name = "cmake" version = "0.1.50" @@ -828,15 +805,15 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1053,14 +1030,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -1068,27 +1045,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.60", + "strsim", + "syn 2.0.64", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1123,9 +1100,9 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ "tokio", ] @@ -1205,9 +1182,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" dependencies = [ "serde", ] @@ -1256,7 +1233,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1290,9 +1267,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1367,9 +1344,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fdeflate" @@ -1388,7 +1365,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "windows-sys 0.52.0", ] @@ -1426,6 +1403,15 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "flume" version = "0.11.0" @@ -1605,7 +1591,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1733,9 +1719,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1747,7 +1733,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -2026,7 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "rayon", "serde", ] @@ -2057,9 +2043,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.38.0" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eab73f58e59ca6526037208f0e98851159ec1633cf17b6cd2e1f2c3fd5d53cc" +checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" dependencies = [ "console", "lazy_static", @@ -2086,6 +2072,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -2104,6 +2096,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2112,9 +2113,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -2136,14 +2137,25 @@ dependencies = [ [[package]] name = "json-patch" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" dependencies = [ + "jsonptr", "serde", "serde_json", "thiserror", - "treediff", +] + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", ] [[package]] @@ -2284,9 +2296,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "local-channel" @@ -2307,9 +2319,9 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2331,7 +2343,7 @@ dependencies = [ "actix-web", "async-trait", "bit-set", - "brotli 5.0.0", + "brotli 6.0.0", "cargo-husky", "clap", "criterion", @@ -2343,7 +2355,7 @@ dependencies = [ "futures", "indoc", "insta", - "itertools 0.12.1", + "itertools 0.13.0", "json-patch", "lambda-web", "log", @@ -2395,7 +2407,7 @@ dependencies = [ "env_logger", "futures", "insta", - "itertools 0.12.1", + "itertools 0.13.0", "log", "martin-tile-utils", "pretty_assertions", @@ -2616,9 +2628,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2638,9 +2650,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2685,11 +2697,13 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "oxipng" -version = "9.0.0" +version = "9.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e5c341ef78a228e47a551bfd15ff885d8c501af49f953358763a538c01f14d" +checksum = "3f398c53eb34e0cf71d9e0bc676cfa7c611e3844dd14ab05e92fb7b423c98ecf" dependencies = [ "bitvec", + "clap", + "clap_mangen", "crossbeam-channel", "filetime", "indexmap 2.2.6", @@ -2710,9 +2724,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -2720,15 +2734,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -2754,14 +2768,14 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbf_font_tools" @@ -2785,7 +2799,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "serde", ] @@ -2845,7 +2859,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -2917,12 +2931,11 @@ dependencies = [ [[package]] name = "pmtiles" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1336029dbfe273811a751f91e85a6011bcfe399c9b8d1ad9662e96df2a2d74e" +checksum = "8e39d63d8051c398a45214a806202db469fc1089d9f8de6c5cfc2bcebbdffb13" dependencies = [ "async-compression", - "async-recursion", "bytes", "fmmap", "hilbert_2d", @@ -3052,19 +3065,19 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -3241,9 +3254,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ "bitflags 2.5.0", ] @@ -3283,6 +3296,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "regex" version = "1.10.4" @@ -3320,9 +3342,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "relative-path" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" @@ -3330,7 +3352,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "bytes", "futures-core", "futures-util", @@ -3406,6 +3428,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "roff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" + [[package]] name = "roxmltree" version = "0.18.1" @@ -3466,7 +3494,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.60", + "syn 2.0.64", "unicode-ident", ] @@ -3486,9 +3514,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3507,9 +3535,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -3566,21 +3594,21 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "aws-lc-rs", "ring", @@ -3606,9 +3634,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3646,11 +3674,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -3659,9 +3687,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -3690,7 +3718,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -3739,11 +3767,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -3757,14 +3785,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -3810,9 +3838,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3890,9 +3918,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4188,12 +4216,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -4209,7 +4231,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -4220,7 +4242,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -4287,9 +4309,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", @@ -4343,7 +4365,7 @@ checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -4467,7 +4489,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -4545,16 +4567,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -4614,7 +4635,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -4626,15 +4647,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "treediff" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" -dependencies = [ - "serde_json", -] - [[package]] name = "triomphe" version = "0.1.11" @@ -4724,9 +4736,9 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode_categories" @@ -4909,7 +4921,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", "wasm-bindgen-shared", ] @@ -4943,7 +4955,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4988,7 +5000,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall", + "redox_syscall 0.4.1", "wasite", "web-sys", ] @@ -5011,11 +5023,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -5230,22 +5242,22 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -5265,7 +5277,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 528167d9d..425500dcd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ anyhow = "1.0" approx = "0.5.1" async-trait = "0.1" bit-set = "0.5.3" -brotli = "5.0.0" +brotli = ">=5, <7" cargo-husky = { version = "1", features = ["user-hooks"], default-features = false } clap = { version = "4", features = ["derive"] } criterion = { version = "0.5", features = ["async_futures", "async_tokio", "html_reports"] } @@ -45,8 +45,8 @@ flate2 = "1" futures = "0.3" indoc = "2" insta = "1" -itertools = "0.12" -json-patch = "1.2" +itertools = "0.13" +json-patch = "2.0" lambda-web = { version = "0.2.1", features = ["actix4"] } libsqlite3-sys = { version = ">=0.27", features = ["bundled"] } log = "0.4" @@ -55,7 +55,7 @@ mbtiles = { path = "./mbtiles", version = "0.9.0" } moka = { version = "0.12", features = ["future"] } num_cpus = "1" pbf_font_tools = { version = "2.5.1", features = ["freetype"] } -pmtiles = { version = "0.9", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } +pmtiles = { version = "0.10", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots"] } postgis = "0.9" postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] } postgres-protocol = "0.6" diff --git a/martin/src/args/pg.rs b/martin/src/args/pg.rs index d3224672d..304b47c65 100644 --- a/martin/src/args/pg.rs +++ b/martin/src/args/pg.rs @@ -119,7 +119,7 @@ impl PgArgs { info!("Overriding root certificate file to {} on all Postgres connections because of a CLI parameter", value.display()); pg_config.iter_mut().for_each(|c| { - c.ssl_certificates.ssl_root_cert = ca_root_file.clone(); + c.ssl_certificates.ssl_root_cert.clone_from(&ca_root_file); }); } diff --git a/martin/src/args/srv.rs b/martin/src/args/srv.rs index ac07e755a..73c38c3f2 100644 --- a/martin/src/args/srv.rs +++ b/martin/src/args/srv.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::srv::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; +#[allow(clippy::doc_markdown)] #[derive(clap::Args, Debug, PartialEq, Default)] #[command(about, version)] pub struct SrvArgs { diff --git a/martin/src/utils/cache.rs b/martin/src/utils/cache.rs index d6b5cff24..f1b948744 100755 --- a/martin/src/utils/cache.rs +++ b/martin/src/utils/cache.rs @@ -8,11 +8,11 @@ pub const NO_MAIN_CACHE: OptMainCache = None; #[derive(Debug, Hash, PartialEq, Eq)] pub enum CacheKey { - /// (pmtiles_id, offset) + /// (`pmtiles_id`, `offset`) PmtDirectory(usize, usize), - /// (source_id, xyz) + /// (`source_id`, `xyz`) Tile(String, TileCoord), - /// (source_id, xyz, url_query) + /// (`source_id`, `xyz`, `url_query`) TileWithQuery(String, TileCoord, String), } diff --git a/martin/src/utils/id_resolver.rs b/martin/src/utils/id_resolver.rs index 3942717e2..cfec73d8f 100644 --- a/martin/src/utils/id_resolver.rs +++ b/martin/src/utils/id_resolver.rs @@ -58,6 +58,8 @@ impl IdResolver { e.insert(unique_name); return id; } + // Rust v1.78 - possibly due to bug fixed in https://github.com/rust-lang/rust-clippy/pull/12756 + #[allow(unknown_lints, clippy::assigning_clones)] Entry::Occupied(e) => { name = e.key().clone(); if e.get() == &unique_name { diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index 6776bcbe0..7bf406851 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -23,6 +23,7 @@ pub struct Args { command: Commands, } +#[allow(clippy::doc_markdown)] #[derive(Subcommand, PartialEq, Debug)] enum Commands { /// Show MBTiles file summary statistics @@ -92,6 +93,7 @@ enum Commands { }, } +#[allow(clippy::doc_markdown)] #[derive(Clone, Default, PartialEq, Debug, clap::Args)] pub struct CopyArgs { /// MBTiles file to read from @@ -112,6 +114,7 @@ pub struct CopyArgs { apply_patch: Option, } +#[allow(clippy::doc_markdown)] #[derive(Clone, Default, PartialEq, Debug, clap::Args)] pub struct DiffArgs { /// First MBTiles file to compare @@ -125,6 +128,7 @@ pub struct DiffArgs { pub options: SharedCopyOpts, } +#[allow(clippy::doc_markdown)] #[derive(Clone, Default, PartialEq, Debug, clap::Args)] pub struct SharedCopyOpts { /// Limit what gets copied. diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index 0224b7b9a..c152205b4 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -42,9 +42,9 @@ impl CopyDuplicateMode { #[derive(Clone, Default, PartialEq, Debug)] pub struct MbtilesCopier { - /// MBTiles file to read from + /// `MBTiles` file to read from pub src_file: PathBuf, - /// MBTiles file to write to + /// `MBTiles` file to write to pub dst_file: PathBuf, /// Limit what gets copied pub copy: CopyType, From 054c803eb9592bb76bd2619de62885ee7ed197af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 02:38:37 +0000 Subject: [PATCH 107/164] chore(deps): Bump rustls from 0.23.6 to 0.23.7 (#1344) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.6 to 0.23.7.
Commits
  • e45fec4 Prepare 0.23.7
  • 2c72fb0 Test for more close_notify conditions
  • 7d4e809 Ignore duplicative send_close_notify calls
  • ced64bc read_tls refuse to read further data after close_notify alert
  • 386b6fd Correctly discard data after close_notify alert
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.23.6&new-version=0.23.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bcc5dacc..a6e271bcc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2370,7 +2370,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.23.6", + "rustls 0.23.7", "rustls-native-certs", "rustls-pemfile", "semver", @@ -3562,9 +3562,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.6" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94cf0812de1f0cee6b163ce35c2f57b90e1ef5a2bed57bcf07c16475bac8c852" +checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" dependencies = [ "aws-lc-rs", "log", @@ -4525,7 +4525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.6", + "rustls 0.23.7", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4549,7 +4549,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.6", + "rustls 0.23.7", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 425500dcd..10785ea1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" rstest = "0.19" -rustls = "0.23.6" +rustls = "0.23.7" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" From 5886748f1205ac1f233744eaeb7f89084fbbd344 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 02:39:50 +0000 Subject: [PATCH 108/164] chore(deps): Bump anyhow from 1.0.83 to 1.0.86 (#1348) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.83 to 1.0.86.
Release notes

Sourced from anyhow's releases.

1.0.86

  • Fix parse error in ensure! with non-literal after minus sign (#373)

1.0.85

  • Improve ensure! macro's rules to unblock some rustc pretty-printer improvements (#368, #371)

1.0.84

  • Disallow calling ensure! through a Not impl for a type that is not bool (#367)
Commits
  • 8ea1819 Release 1.0.86
  • 0a1b405 Merge pull request #373 from dtolnay/minusneg
  • e0c74f2 Ensure $:literal never matches negative literal
  • 013c66e Fix parse error with non-literal after minus sign
  • ca7aff7 Add binary operator ensure tests
  • 2737bbe Release 1.0.85
  • 82b8b34 Merge pull request #371 from dtolnay/split
  • ad78d70 Preserve more token spans in expression parser
  • 5cce406 Parse comparison operators before other binary operators
  • 7205394 Merge pull request #369 from dtolnay/tokensplit
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.83&new-version=1.0.86)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6e271bcc..4013da94e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,9 +327,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "approx" From ff16f9a82090f711ac4d03831f39d4f14580b6e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 02:40:41 +0000 Subject: [PATCH 109/164] chore(deps): Bump thiserror from 1.0.60 to 1.0.61 (#1346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.60 to 1.0.61.
Release notes

Sourced from thiserror's releases.

1.0.61

  • Use core::fmt and core::panic to facilitate error_in_core support (#299, thanks @​jordens)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=thiserror&package-manager=cargo&previous-version=1.0.60&new-version=1.0.61)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4013da94e..01d74ce60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4350,18 +4350,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", From f9f6777812536cb2bfc5e55cebdebc80d2718335 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 03:13:35 +0000 Subject: [PATCH 110/164] chore(deps): Bump rustls from 0.23.7 to 0.23.8 (#1350) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.7 to 0.23.8.
Commits
  • 99abca5 Prepare 0.23.8
  • 06c777b Hide internals from documentation
  • 091587b Derive Clone for ServerConfig & ClientConfig
  • 9664833 Refactor construction of CertificatePayloadTls13
  • 45c8a54 Remove PayloadU24::new
  • 04ef27c api.rs: format imports
  • 572f970 Add test for CRL expiration
  • 8da3530 Add support for enforcing CRL expiration
  • c570793 Cover HandshakeMessagePayload::into_owned()
  • 125d641 Test theoretical support for OCSP pinning
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.23.7&new-version=0.23.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01d74ce60..f5f07b4b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2370,7 +2370,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", - "rustls 0.23.7", + "rustls 0.23.8", "rustls-native-certs", "rustls-pemfile", "semver", @@ -3562,9 +3562,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.7" +version = "0.23.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +checksum = "79adb16721f56eb2d843e67676896a61ce7a0fa622dc18d3e372477a029d2740" dependencies = [ "aws-lc-rs", "log", @@ -4525,7 +4525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.7", + "rustls 0.23.8", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4549,7 +4549,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.7", + "rustls 0.23.8", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 10785ea1f..e16757999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" rstest = "0.19" -rustls = "0.23.7" +rustls = "0.23.8" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" From d77533f627927001b890de777672da4941da8ecd Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 24 May 2024 22:41:26 -0400 Subject: [PATCH 111/164] Fix CI: use new nginx and postgis actions (#1351) I recently released a new nginx github action that should work on all OS and in all runners. Also, postgis action has been updated. --- .github/workflows/ci.yml | 130 +++++++----------------------------- .github/workflows/grcov.yml | 2 +- tests/fixtures/initdb.sh | 4 +- 3 files changed, 26 insertions(+), 110 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4fb703485..291a1ddfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -162,14 +162,12 @@ jobs: mv target_releases/aarch64-unknown-linux-musl/* target_releases/linux/arm64/ mkdir -p target_releases/linux/amd64 mv target_releases/x86_64-unknown-linux-musl/* target_releases/linux/amd64/ - - - name: Start HTTP Server - run: | - docker run --rm -d \ - --name fileserver \ - -p 5412:80 \ - -v ${{ github.workspace }}/tests/fixtures/pmtiles2:/usr/share/nginx/html \ - nginx:alpine + - name: Start NGINX + uses: nyurik/action-setup-nginx@v1.1 + id: nginx + with: { port: '5412', output-unix-paths: 'yes' } + - name: Copy static files + run: cp -r tests/fixtures/pmtiles2/* ${{ steps.nginx.outputs.html-dir }} - name: Build linux/arm64 Docker image uses: docker/build-push-action@v5 # https://github.com/docker/build-push-action @@ -328,108 +326,27 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 - # - name: Install Docker (MacOS) - # if: runner.os == 'macos' - # run: brew install docker && colima start - - name: Start HTTP Server (with Docker) - if: matrix.os == 'ubuntu-latest' - run: | - docker run --rm -d \ - --name fileserver \ - -p 5412:80 \ - -v ${{ github.workspace }}/tests/fixtures/pmtiles2:/usr/share/nginx/html \ - nginx:alpine - - name: Start HTTP Server (MacOS, no Docker) - if: runner.os == 'macos' - run: | - mkdir -p /usr/local/etc/nginx - cat << EOF > /usr/local/etc/nginx/nginx.conf - worker_processes 1; - events { - worker_connections 1024; - } - http { - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - server { - listen 5412; - server_name localhost; - location / { - root $PWD/tests/fixtures/pmtiles2; - index index.html index.htm; - } - } - } - EOF - - brew services info nginx - brew services start nginx - sleep 2 - curl -I http://localhost:5412/ - curl -I http://localhost:5412/webp2.pmtiles - - - name: Start HTTP Server (Windows, no Docker) - if: runner.os == 'windows' - shell: pwsh - run: | - $nginxConf = @" - worker_processes 1; - events { - worker_connections 1024; - } - http { - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - server { - listen 5412; - server_name localhost; - location / { - root $($PWD.Path)/tests/fixtures/pmtiles2; - index index.html index.htm; - } - } - } - "@ - - # Replace the default Nginx configuration file - echo "$nginxConf" - Set-Content -Path "C:\tools\nginx-1.25.4\conf\nginx.conf" -Value $nginxConf - Get-Content -Path "C:\tools\nginx-1.25.4\conf\nginx.conf" - - # Start Nginx - #Get-Service -ErrorAction SilentlyContinue - #Get-CimInstance -ClassName Win32_Service - Set-Service nginx -StartupType manual - Start-Service nginx - #Start-Process -FilePath "C:\tools\nginx-1.25.4\nginx.exe" - dir C:\tools\nginx-1.25.4\logs\ - Start-Sleep -Seconds 5 - netstat -a - - # Print Nginx Error Logs (on Windows systems) - #nginx -t - Get-Content -Path "C:\tools\nginx-1.25.4\logs\error.log" - dir D:\a\martin\martin\ - - name: Start postgres - uses: nyurik/action-setup-postgis@v1.1 + - name: Start NGINX + uses: nyurik/action-setup-nginx@v1.1 + id: nginx + with: { port: '5412', output-unix-paths: 'yes' } + - name: Copy static files + run: cp -r tests/fixtures/pmtiles2/* ${{ steps.nginx.outputs.html-dir }} + - name: Install and run Postgis + uses: nyurik/action-setup-postgis@v2 id: pg with: username: test password: test database: test - rights: --superuser - name: Init database run: | - echo "DATABASE_URL=$DATABASE_URL" + echo "DATABASE_URL=${{ steps.pg.outputs.connection-uri }}" echo "Print the same in base64 to bypass Github's obfuscation (uses hardcoded password):" - echo "$DATABASE_URL" | base64 + echo "${{ steps.pg.outputs.connection-uri }}" | base64 tests/fixtures/initdb.sh env: - DATABASE_URL: ${{ steps.pg.outputs.connection-uri }} + PGSERVICE: ${{ steps.pg.outputs.service-name }} - name: Download build artifact build-${{ matrix.target }} uses: actions/download-artifact@v3 with: @@ -534,13 +451,12 @@ jobs: uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 if: github.event_name != 'release' && github.event_name != 'workflow_dispatch' - - name: Start HTTP Server - run: | - docker run --rm -d \ - --name fileserver \ - -p 5412:80 \ - -v ${{ github.workspace }}/tests/fixtures/pmtiles2:/usr/share/nginx/html \ - nginx:alpine + - name: Run NGINX + uses: nyurik/action-setup-nginx@v1.1 + id: nginx + with: { port: '5412', output-unix-paths: 'yes' } + - name: Copy static files + run: cp -r tests/fixtures/pmtiles2/* ${{ steps.nginx.outputs.html-dir }} - name: Init database run: tests/fixtures/initdb.sh env: diff --git a/.github/workflows/grcov.yml b/.github/workflows/grcov.yml index 9d0326b8c..d50fecb55 100644 --- a/.github/workflows/grcov.yml +++ b/.github/workflows/grcov.yml @@ -51,7 +51,7 @@ jobs: - name: Install nightly toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2023-11-03 + toolchain: nightly-2024-05-24 override: true - name: Cleanup GCDA files diff --git a/tests/fixtures/initdb.sh b/tests/fixtures/initdb.sh index 74121058c..a9bfd2f4c 100755 --- a/tests/fixtures/initdb.sh +++ b/tests/fixtures/initdb.sh @@ -4,7 +4,7 @@ set -euo pipefail FIXTURES_DIR="$(dirname "$0")" echo -e "\n\n\n" echo "################################################################################################" -echo "Loading Martin test fixtures into '$PGDATABASE' as user '$PGUSER'" +echo "Loading Martin test fixtures into '${DATABASE_URL:-${PGDATABASE:-(local db)}}'" echo "################################################################################################" @@ -16,7 +16,7 @@ psql -P pager=off -v ON_ERROR_STOP=1 -t -c "select PostGIS_Full_Version();" # On error, make sure do delete all the tables we created # TODO: see if we can have a fail-early service test to detect errors -trap 'echo -e "\n\n\n!!!!!!!!!!!!!!!!!!!!!!!!\n\nDELETING DB $PGDATABASE DUE TO AN ERROR!\n\n\n" && psql -c "DROP SCHEMA IF EXISTS "MixedCase" CASCADE; DROP SCHEMA IF EXISTS autodetect CASCADE;"' ERR +trap 'echo -e "\n\n\n!!!!!!!!!!!!!!!!!!!!!!!!\n\nDropping schemas DUE TO AN ERROR!\n\n\n" && psql -c "DROP SCHEMA IF EXISTS "MixedCase" CASCADE; DROP SCHEMA IF EXISTS autodetect CASCADE;"' ERR echo -e "\n\n\n" echo "################################################################################################" From a98bc81086207490cc6ecc433d832d7a51a473d0 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 25 May 2024 01:17:26 -0400 Subject: [PATCH 112/164] Bump all dependencies, fix CI (#1353) --- .github/workflows/ci.yml | 9 +-- Cargo.lock | 161 +++++++++++++++++++++------------------ Cargo.toml | 2 +- 3 files changed, 90 insertions(+), 82 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 291a1ddfa..444a6f8dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -249,7 +249,7 @@ jobs: - target: debian-x86_64 os: ubuntu-latest - target: x86_64-apple-darwin - os: macos-12 # x64 CPU + os: macos-13 # x64 CPU - target: x86_64-pc-windows-msvc os: windows-latest ext: '.exe' @@ -317,7 +317,7 @@ jobs: matrix: include: - target: x86_64-apple-darwin - os: macOS-latest + os: macos-13 - target: x86_64-pc-windows-msvc os: windows-latest ext: '.exe' @@ -335,10 +335,7 @@ jobs: - name: Install and run Postgis uses: nyurik/action-setup-postgis@v2 id: pg - with: - username: test - password: test - database: test + with: { username: 'test', password: 'test', database: 'test' } - name: Init database run: | echo "DATABASE_URL=${{ steps.pg.outputs.connection-uri }}" diff --git a/Cargo.lock b/Cargo.lock index f5f07b4b1..a8fb4ff55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,18 +36,18 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743" +checksum = "4eb9843d84c775696c37d9a418bbb01b932629d01870722c0f13eb3f95e2536d" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "ahash", - "base64 0.21.7", + "base64 0.22.1", "bitflags 2.5.0", - "brotli 3.5.0", + "brotli 6.0.0", "bytes", "bytestring", "derive_more", @@ -80,18 +80,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] name = "actix-router" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", + "cfg-if", "http 0.2.12", "regex", + "regex-lite", "serde", "tracing", ] @@ -147,9 +149,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.5.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984" +checksum = "b1cf67dadb19d7c95e5a299e2dda24193b89d5d4f33a3b9800888ede9e19aa32" dependencies = [ "actix-codec", "actix-http", @@ -176,6 +178,7 @@ dependencies = [ "once_cell", "pin-project-lite", "regex", + "regex-lite", "serde", "serde_json", "serde_urlencoded", @@ -194,7 +197,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -395,7 +398,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -406,7 +409,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -426,9 +429,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8487b59d62764df8231cb371c459314df895b41756df457a1fb1243d65c89195" +checksum = "474d7cec9d0a1126fad1b224b767fcbf351c23b0309bb21ec210bcfd379926a5" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -438,9 +441,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15eb61145320320eb919d9bab524617a7aa4216c78d342fae3a758bc33073e4" +checksum = "7505fc3cb7acbf42699a43a79dd9caa4ed9e99861dfbb837c5c0fb5a0a8d2980" dependencies = [ "bindgen", "cc", @@ -519,7 +522,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.64", + "syn 2.0.66", "which", ] @@ -663,9 +666,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" dependencies = [ "jobserver", "libc", @@ -769,7 +772,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -913,9 +916,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -960,9 +963,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -997,9 +1000,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunch" @@ -1030,7 +1033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1054,7 +1057,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1065,7 +1068,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1233,7 +1236,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1591,7 +1594,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -1651,9 +1654,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1931,9 +1934,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" dependencies = [ "bytes", "futures-channel", @@ -2239,9 +2242,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libdeflate-sys" @@ -2327,6 +2330,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "log" version = "0.4.21" @@ -2481,9 +2490,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", "simd-adler32", @@ -2724,9 +2733,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2768,7 +2777,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2859,7 +2868,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -2903,9 +2912,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -2916,15 +2925,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -3070,14 +3079,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -3328,6 +3337,12 @@ dependencies = [ "regex-syntax 0.8.3", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.7.5" @@ -3494,7 +3509,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.64", + "syn 2.0.66", "unicode-ident", ] @@ -3718,7 +3733,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -3792,7 +3807,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4231,7 +4246,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4242,7 +4257,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4309,9 +4324,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.64" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -4365,7 +4380,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4489,7 +4504,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4635,7 +4650,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -4665,12 +4680,6 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - [[package]] name = "typenum" version = "1.17.0" @@ -4921,7 +4930,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -4955,7 +4964,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5257,7 +5266,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -5277,19 +5286,21 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] name = "zopfli" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1f48f3508a3a3f2faee01629564400bc12260f6214a056d06a3aaaa6ef0736" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" dependencies = [ + "bumpalo", "crc32fast", + "lockfree-object-pool", "log", + "once_cell", "simd-adler32", - "typed-arena", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e16757999..4499a9f0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,7 +79,7 @@ sqlite-hashes = { version = "0.7.1", default-features = false, features = ["md5" sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] } subst = { version = "0.3", features = ["yaml"] } thiserror = "1" -tile-grid = "0.5" +tile-grid = "0.6" tilejson = "0.4" tokio = { version = "1", features = ["macros"] } tokio-postgres-rustls = "0.12" From 37609dd30323a535ebee9bf52ed07ba57c912340 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 May 2024 01:24:25 -0400 Subject: [PATCH 113/164] chore(deps): Bump dependabot/fetch-metadata from 2.0.0 to 2.1.0 (#1316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 2.0.0 to 2.1.0.
Release notes

Sourced from dependabot/fetch-metadata's releases.

v2.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/dependabot/fetch-metadata/compare/v2.0.0...v2.1.0

Commits
  • 5e5f996 Merge pull request #518 from dependabot/bump-to-v2.1.0
  • 63415e5 v2.1.0
  • 76b7fe9 Merge pull request #509 from dependabot/switch-to-monthly-release-cadence
  • 7c323d5 Switch to monthly release cadence
  • 5c7b450 Merge pull request #450 from HealthengineAU/handle-branches-with-hyphens
  • a44a9df Handle branch names containing hyphen separators
  • 518993c Relax engine-strict=true (#510)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dependabot/fetch-metadata&package-manager=github_actions&previous-version=2.0.0&new-version=2.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 4549aac67..c4d1d2365 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.0.0 + uses: dependabot/fetch-metadata@v2.1.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Approve Dependabot PRs From 81f4d4cd03b561e331f6fd48fc3c9d2be8974456 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 25 May 2024 01:51:04 -0400 Subject: [PATCH 114/164] Switch default encoding to gzip for now (#1260) GZip is significantly faster, so for now lets use that until brotli project gains some performance, and until we get proper after-compression caching. --- Cargo.lock | 1 + docs/src/config-file.md | 55 ++++++++++++++------------- docs/src/run-with-cli.md | 5 ++- martin/Cargo.toml | 1 + martin/src/args/srv.rs | 5 +-- martin/src/srv/tiles.rs | 80 +++++++++++++++++++--------------------- 6 files changed, 74 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8fb4ff55..37dfa0fac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2379,6 +2379,7 @@ dependencies = [ "postgres-protocol", "pprof", "regex", + "rstest", "rustls 0.23.8", "rustls-native-certs", "rustls-pemfile", diff --git a/docs/src/config-file.md b/docs/src/config-file.md index cc2670ac4..ad930a947 100644 --- a/docs/src/config-file.md +++ b/docs/src/config-file.md @@ -1,12 +1,17 @@ # Configuration File -If you don't want to expose all of your tables and functions, you can list your sources in a configuration file. To start Martin with a configuration file you need to pass a path to a file with a `--config` argument. Config files may contain environment variables, which will be expanded before parsing. For example, to use `MY_DATABASE_URL` in your config file: `connection_string: ${MY_DATABASE_URL}`, or with a default `connection_string: ${MY_DATABASE_URL:-postgresql://postgres@localhost/db}` +If you don't want to expose all of your tables and functions, you can list your sources in a configuration file. To +start Martin with a configuration file you need to pass a path to a file with a `--config` argument. Config files may +contain environment variables, which will be expanded before parsing. For example, to use `MY_DATABASE_URL` in your +config file: `connection_string: ${MY_DATABASE_URL}`, or with a +default `connection_string: ${MY_DATABASE_URL:-postgresql://postgres@localhost/db}` ```shell martin --config config.yaml ``` -You may wish to auto-generate a config file with `--save-config` argument. This will generate a config yaml file with all of your configuration, which you can edit to remove any sources you don't want to expose. +You may wish to auto-generate a config file with `--save-config` argument. This will generate a config yaml file with +all of your configuration, which you can edit to remove any sources you don't want to expose. ```shell martin ... ... ... --save-config config.yaml @@ -31,7 +36,7 @@ worker_processes: 8 # Amount of memory (in MB) to use for caching tiles [default: 512, 0 to disable] cache_size_mb: 1024 -# If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli. +# If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Default could be different depending on Martin version. preferred_encoding: gzip # Database configuration. This can also be a list of PG configs. @@ -92,76 +97,76 @@ postgres: functions: # Optionally set how source ID should be generated based on the function's name and schema source_id_format: '{schema}.{function}' - + # Associative arrays of table sources tables: table_source_id: # ID of the MVT layer (optional, defaults to table name) layer_id: table_source - + # Table schema (required) schema: public - + # Table name (required) table: table_source - + # Geometry SRID (required) srid: 4326 - + # Geometry column name (required) geometry_column: geom - + # Feature id column name id_column: ~ - + # An integer specifying the minimum zoom level minzoom: 0 - + # An integer specifying the maximum zoom level. MUST be >= minzoom maxzoom: 30 - + # The maximum extent of available map tiles. Bounds MUST define an area # covered by all zoom levels. The bounds are represented in WGS:84 # latitude and longitude values, in the order left, bottom, right, top. # Values may be integers or floating point numbers. - bounds: [-180.0, -90.0, 180.0, 90.0] - + bounds: [ -180.0, -90.0, 180.0, 90.0 ] + # Tile extent in tile coordinate space extent: 4096 - + # Buffer distance in tile coordinate space to optionally clip geometries buffer: 64 - + # Boolean to control if geometries should be clipped or encoded as is clip_geom: true - + # Geometry type geometry_type: GEOMETRY - + # List of columns, that should be encoded as tile properties (required) properties: gid: int4 - + # Associative arrays of function sources functions: function_source_id: # Schema name (required) schema: public - + # Function name (required) function: function_zxy_query - + # An integer specifying the minimum zoom level minzoom: 0 - + # An integer specifying the maximum zoom level. MUST be >= minzoom maxzoom: 30 - + # The maximum extent of available map tiles. Bounds MUST define an area # covered by all zoom levels. The bounds are represented in WGS:84 # latitude and longitude values, in the order left, bottom, right, top. # Values may be integers or floating point numbers. - bounds: [-180.0, -90.0, 180.0, 90.0] + bounds: [ -180.0, -90.0, 180.0, 90.0 ] # Publish PMTiles files from local disk or proxy to a web server pmtiles: @@ -177,7 +182,7 @@ pmtiles: pm-src1: /path/to/pmt.pmtiles # A named source to a web server with a PMTiles file that supports range requests pm-web2: https://example.org/path/tiles.pmtiles - + # Publish MBTiles files mbtiles: paths: diff --git a/docs/src/run-with-cli.md b/docs/src/run-with-cli.md index da3241c1c..17b16fbaf 100644 --- a/docs/src/run-with-cli.md +++ b/docs/src/run-with-cli.md @@ -1,6 +1,7 @@ ## Command-line Interface -You can configure Martin using command-line interface. See `martin --help` or `cargo run -- --help` for more information. +You can configure Martin using command-line interface. See `martin --help` or `cargo run -- --help` for more +information. ```shell Usage: martin [OPTIONS] [CONNECTION]... @@ -34,7 +35,7 @@ Options: Number of web server workers --preferred-encoding - Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli + Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Default could be different depending on Martin version [possible values: brotli, gzip] diff --git a/martin/Cargo.toml b/martin/Cargo.toml index 874f95d43..428cf6ae0 100644 --- a/martin/Cargo.toml +++ b/martin/Cargo.toml @@ -120,3 +120,4 @@ ctor.workspace = true indoc.workspace = true insta = { workspace = true, features = ["yaml"] } pprof.workspace = true +rstest.workspace = true diff --git a/martin/src/args/srv.rs b/martin/src/args/srv.rs index 73c38c3f2..8bbd91178 100644 --- a/martin/src/args/srv.rs +++ b/martin/src/args/srv.rs @@ -17,15 +17,14 @@ pub struct SrvArgs { /// Number of web server workers #[arg(short = 'W', long)] pub workers: Option, - /// Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to brotli. + /// Martin server preferred tile encoding. If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching. Defaults to gzip. #[arg(long)] pub preferred_encoding: Option, } -#[derive(PartialEq, Eq, Default, Debug, Clone, Copy, Serialize, Deserialize, ValueEnum)] +#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize, ValueEnum)] #[serde(rename_all = "lowercase")] pub enum PreferredEncoding { - #[default] #[serde(alias = "br")] #[clap(alias("br"))] Brotli, diff --git a/martin/src/srv/tiles.rs b/martin/src/srv/tiles.rs index c5195b87c..a90c2c53f 100755 --- a/martin/src/srv/tiles.rs +++ b/martin/src/srv/tiles.rs @@ -199,8 +199,8 @@ impl<'a> DynTileSource<'a> { if tile.info.encoding == Encoding::Uncompressed { let ordered_encodings = match self.preferred_enc { - Some(PreferredEncoding::Gzip) => PREFER_GZIP_ENC, - Some(PreferredEncoding::Brotli) | None => PREFER_BROTLI_ENC, + Some(PreferredEncoding::Gzip) | None => PREFER_GZIP_ENC, + Some(PreferredEncoding::Brotli) => PREFER_BROTLI_ENC, }; // only apply compression if the content supports it @@ -264,58 +264,52 @@ pub fn to_encoding(val: ContentEncoding) -> Option { #[cfg(test)] mod tests { + use rstest::rstest; use tilejson::tilejson; use super::*; use crate::srv::server::tests::TestSource; + #[rstest] + #[trace] + #[case(&["gzip", "deflate", "br", "zstd"], None, Encoding::Gzip)] + #[case(&["gzip", "deflate", "br", "zstd"], Some(PreferredEncoding::Brotli), Encoding::Brotli)] + #[case(&["gzip", "deflate", "br", "zstd"], Some(PreferredEncoding::Gzip), Encoding::Gzip)] + #[case(&["br;q=1", "gzip;q=1"], Some(PreferredEncoding::Gzip), Encoding::Gzip)] + #[case(&["gzip;q=1", "br;q=1"], Some(PreferredEncoding::Brotli), Encoding::Brotli)] + #[case(&["gzip;q=1", "br;q=0.5"], Some(PreferredEncoding::Brotli), Encoding::Gzip)] #[actix_rt::test] - async fn test_encoding_preference() { - let source = TestSource { + async fn test_enc_preference( + #[case] accept_enc: &[&'static str], + #[case] preferred_enc: Option, + #[case] expected_enc: Encoding, + ) { + let sources = TileSources::new(vec![vec![Box::new(TestSource { id: "test_source", tj: tilejson! { tiles: vec![] }, data: vec![1_u8, 2, 3], - }; - let sources = TileSources::new(vec![vec![Box::new(source)]]); + })]]); - for (accept_encodings, prefered_encoding, result_encoding) in [ - ( - Some(AcceptEncoding(vec![ - "gzip;q=1".parse().unwrap(), - "br;q=1".parse().unwrap(), - ])), - Some(PreferredEncoding::Brotli), - Encoding::Brotli, - ), - ( - Some(AcceptEncoding(vec![ - "gzip;q=1".parse().unwrap(), - "br;q=0.5".parse().unwrap(), - ])), - Some(PreferredEncoding::Brotli), - Encoding::Gzip, - ), - ] { - let src = DynTileSource::new( - &sources, - "test_source", - None, - "", - accept_encodings, - prefered_encoding, - None, - ) - .unwrap(); - let xyz = TileCoord { z: 0, x: 0, y: 0 }; - let data = &src.get_tile_content(xyz).await.unwrap().data; - let decoded = match result_encoding { - Encoding::Gzip => decode_gzip(data), - Encoding::Brotli => decode_brotli(data), - _ => panic!("Unexpected encoding"), - }; - assert_eq!(vec![1_u8, 2, 3], decoded.unwrap()); - } + let accept_enc = Some(AcceptEncoding( + accept_enc.iter().map(|s| s.parse().unwrap()).collect(), + )); + + let src = DynTileSource::new( + &sources, + "test_source", + None, + "", + accept_enc, + preferred_enc, + None, + ) + .unwrap(); + + let xyz = TileCoord { z: 0, x: 0, y: 0 }; + let tile = src.get_tile_content(xyz).await.unwrap(); + assert_eq!(tile.info.encoding, expected_enc); } + #[actix_rt::test] async fn test_tile_content() { let non_empty_source = TestSource { From a9cb0c972f6e9d6581c8dfad2c52b5e13cbe616e Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 26 May 2024 19:06:28 +0800 Subject: [PATCH 115/164] Adjust readme and martin book (#1253) Fixes #1245 Large book and README refactoring, adding quick started section, list of available features to the README, and moving most of the content from README to the book. --------- Co-authored-by: Yuri Astrakhan --- README.md | 131 +++--------------- docs/src/SUMMARY.md | 6 + docs/src/config-file.md | 4 +- docs/src/development.md | 19 +-- docs/src/images/qgis_add_to_layers.png | Bin 0 -> 38200 bytes docs/src/images/qgis_add_vector_tile.png | Bin 0 -> 101384 bytes .../images/qgis_add_vector_tile_options.png | Bin 0 -> 59384 bytes docs/src/images/qgis_shows_in_the_map.png | Bin 0 -> 177144 bytes docs/src/installation.md | 87 ++++++++---- docs/src/martin-as-a-library.md | 9 ++ docs/src/martin-cp.md | 14 +- docs/src/mbtiles-copy.md | 11 +- docs/src/mbtiles-diff.md | 6 +- docs/src/mbtiles-meta.md | 21 +-- docs/src/mbtiles-validation.md | 38 +++-- docs/src/quick-start-linux.md | 24 ++++ docs/src/quick-start-macos.md | 27 ++++ docs/src/quick-start-qgis.md | 17 +++ docs/src/quick-start-windows.md | 24 ++++ docs/src/quick-start.md | 7 + docs/src/recipes.md | 19 ++- docs/src/run-with-cli.md | 2 +- docs/src/run-with-docker-compose.md | 7 +- docs/src/run-with-docker.md | 16 ++- docs/src/run.md | 9 +- docs/src/sources-composite.md | 8 +- docs/src/sources-files.md | 9 +- docs/src/sources-fonts.md | 15 +- docs/src/sources-pg-functions.md | 34 +++-- docs/src/sources-sprites.md | 30 ++-- docs/src/troubleshooting.md | 11 +- docs/src/using.md | 14 +- 32 files changed, 386 insertions(+), 233 deletions(-) create mode 100644 docs/src/images/qgis_add_to_layers.png create mode 100644 docs/src/images/qgis_add_vector_tile.png create mode 100644 docs/src/images/qgis_add_vector_tile_options.png create mode 100644 docs/src/images/qgis_shows_in_the_map.png create mode 100644 docs/src/martin-as-a-library.md create mode 100644 docs/src/quick-start-linux.md create mode 100644 docs/src/quick-start-macos.md create mode 100644 docs/src/quick-start-qgis.md create mode 100644 docs/src/quick-start-windows.md create mode 100644 docs/src/quick-start.md diff --git a/README.md b/README.md index bbcf8a5ff..47338b2f8 100755 --- a/README.md +++ b/README.md @@ -8,116 +8,27 @@ [![Security audit](https://github.com/maplibre/martin/workflows/Security%20audit/badge.svg)](https://github.com/maplibre/martin/security) [![CI build](https://github.com/maplibre/martin/actions/workflows/ci.yml/badge.svg)](https://github.com/maplibre/martin/actions) -Martin is a tile server able to generate and serve [vector tiles](https://github.com/mapbox/vector-tile-spec) on the fly from large [PostGIS](https://github.com/postgis/postgis) databases, [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) (local or remote), and [MBTile](https://github.com/mapbox/mbtiles-spec) files, allowing multiple tile sources to be dynamically combined into one. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). - -Additionally, there are [several tools](https://maplibre.org/martin/tools.html) for generating tiles in bulk from any Martin-supported sources (similar to `tilelive-copy`), copying tiles between MBTiles files, creating deltas (patches) and applying them, and validating MBTiles files. - -See [Martin book](https://maplibre.org/martin/) for complete documentation. - -## Installation - -_See [installation instructions](https://maplibre.org/martin/installation.html) in the Martin book._ - -**Prerequisites:** If using Martin with PostgreSQL database, you must install PostGIS with at least v3.0+, v3.1+ recommended. - -You can download martin from [GitHub releases page](https://github.com/maplibre/martin/releases). - -| Platform | AMD-64 | ARM-64 | -|----------|--------------------------------------------------------------------------------------------------|-------------------------------------| -| Linux | [.tar.gz][rl-linux-x64] (gnu)
[.tar.gz][rl-linux-x64-musl] (musl)
[.deb][rl-linux-x64-deb] | [.tar.gz][rl-linux-a64-musl] (musl) | -| macOS | [.tar.gz][rl-macos-x64] | [.tar.gz][rl-macos-a64] | -| Windows | [.zip][rl-win64-zip] | | - -[rl-linux-x64]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz -[rl-linux-x64-musl]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-musl.tar.gz -[rl-linux-x64-deb]: https://github.com/maplibre/martin/releases/latest/download/martin-Debian-x86_64.deb -[rl-linux-a64-musl]: https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-unknown-linux-musl.tar.gz -[rl-macos-x64]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-apple-darwin.tar.gz -[rl-macos-a64]: https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-apple-darwin.tar.gz -[rl-win64-zip]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip - -If you are using macOS and [Homebrew](https://brew.sh/) you can install `martin` and `mbtiles` using Homebrew tap. - -```shell -brew tap maplibre/martin -brew install martin -``` - -## Running Martin Service - -_See [running instructions](https://maplibre.org/martin/run.html) in the Martin book._ - -Martin supports any number of PostgreSQL/PostGIS database connections with [geospatial-enabled](https://postgis.net/docs/using_postgis_dbmanagement.html#geometry_columns) tables and tile-producing SQL functions, as well as [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) and [MBTile](https://github.com/mapbox/mbtiles-spec) files as tile sources. - -Martin can auto-discover tables and functions using a [connection string](https://maplibre.org/martin/pg-connections.html). A PG connection string can also be passed via the `DATABASE_URL` environment variable. - -Each tile source will have a [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint. - -#### Examples - -```shell -# publish all tables and functions from a single database -export DATABASE_URL="postgresql://user:password@host:port/database" -martin - -# same as above, but passing connection string via CLI, together with a directory of .mbtiles/.pmtiles files -martin postgresql://user:password@host:port/database path/to/dir - -# publish all discovered tables/funcs from two DBs -# and generate config file with all detected sources -martin postgres://... postgres://... --save-config config.yaml - -# use configuration file instead of auto-discovery -martin --config config.yaml -``` - -#### Docker Example - -_See [Docker instructions](https://maplibre.org/martin/run-with-docker.html) in the Martin book._ - -Martin is also available as a [Docker image](https://ghcr.io/maplibre/martin). You could either share a configuration file from the host with the container via the `-v` param, or you can let Martin auto-discover all sources e.g. by passing `DATABASE_URL` or specifying the .mbtiles/.pmtiles files. - -```shell -export PGPASSWORD=postgres # secret! -docker run -p 3000:3000 \ - -e PGPASSWORD \ - -e DATABASE_URL=postgresql://user@host:port/db \ - -v /path/to/config/dir:/config \ - ghcr.io/maplibre/martin --config /config/config.yaml -``` - -## API - -_See [API documentation](https://maplibre.org/martin/using.html) in the Martin book._ - -Martin data is available via the HTTP `GET` endpoints: - -| URL | Description | -|-----------------------------------------|-----------------------------------------------| -| `/` | Status text, that will eventually show web UI | -| `/catalog` | List of all sources | -| `/{sourceID}` | Source TileJSON | -| `/{sourceID}/{z}/{x}/{y}` | Map Tiles | -| `/{source1},…,{sourceN}` | Composite Source TileJSON | -| `/{source1},…,{sourceN}/{z}/{x}/{y}` | Composite Source Tiles | -| `/sprite/{spriteID}[@2x].{json,png}` | Sprites (low and high DPI, index/png) | -| `/font/{font}/{start}-{end}` | Font source | -| `/font/{font1},…,{fontN}/{start}-{end}` | Composite Font source | -| `/health` | Martin server health check: returns 200 `OK` | - -## Re-use Martin as a library - -Martin can be used as a standalone server, or as a library in your own Rust application. When used as a library, you can use the following features: - -* **postgres** - enable PostgreSQL/PostGIS tile sources -* **pmtiles** - enable PMTile tile sources -* **mbtiles** - enable MBTile tile sources -* **fonts** - enable font sources -* **sprites** - enable sprite sources - -## Documentation - -See [Martin book](https://maplibre.org/martin/) for complete documentation. +Martin is a tile server able to generate and serve [vector tiles](https://github.com/mapbox/vector-tile-spec) on the fly +from large [PostGIS](https://github.com/postgis/postgis) +databases, [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) (local or remote), +and [MBTile](https://github.com/mapbox/mbtiles-spec) files, allowing multiple tile sources to be dynamically combined +into one. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). + +### Features + +* Serve vector tiles from PostGIS, PMTile, and MBTile sources +* [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources +* Generate [sprites](https://maplibre.org/martin/sources-sprites.html) and [font glyphs](https://maplibre.org/martin/sources-fonts.html) +* Generate tiles in bulk from any Martin-supported sources into an `.mbtiles` file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool +* Examine, copy, validate, compare, and apply diffs between `.mbtiles` files with [mbtiles](https://maplibre.org/martin/tools.html#mbtiles) tool + +### Documentation + +* [Quick Start](https://maplibre.org/martin/quick-start.html) +* [Installation](https://maplibre.org/martin/installation.html) +* Running with [CLI](https://maplibre.org/martin/run-with-cli.html) + or [configuration file](https://maplibre.org/martin/config-file.html) +* [Usage and API](https://maplibre.org/martin/using.html) ## License diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index ac0d5e000..62b84d8f8 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -1,5 +1,10 @@ [Introduction](introduction.md) +- [Quick Start](quick-start.md) + - [On Linux](quick-start-linux.md) + - [On macOS](quick-start-macos.md) + - [On Windows](quick-start-windows.md) + - [View with QGIS](quick-start-qgis.md) - [Installation](installation.md) - [Running](run.md) - [Command Line Interface](run-with-cli.md) @@ -32,3 +37,4 @@ - [Diffing/Patching MBTiles](mbtiles-diff.md) - [Validating MBTiles](mbtiles-validation.md) - [Development](development.md) + - [Martin as a library](martin-as-a-library.md) diff --git a/docs/src/config-file.md b/docs/src/config-file.md index ad930a947..2468893a4 100644 --- a/docs/src/config-file.md +++ b/docs/src/config-file.md @@ -6,14 +6,14 @@ contain environment variables, which will be expanded before parsing. For exampl config file: `connection_string: ${MY_DATABASE_URL}`, or with a default `connection_string: ${MY_DATABASE_URL:-postgresql://postgres@localhost/db}` -```shell +```bash martin --config config.yaml ``` You may wish to auto-generate a config file with `--save-config` argument. This will generate a config yaml file with all of your configuration, which you can edit to remove any sources you don't want to expose. -```shell +```bash martin ... ... ... --save-config config.yaml ``` diff --git a/docs/src/development.md b/docs/src/development.md index b3bc71147..ad0369cc2 100644 --- a/docs/src/development.md +++ b/docs/src/development.md @@ -1,36 +1,39 @@ # Development -Clone Martin, setting remote name to `upstream`. This way `main` branch will be updated automatically with the latest changes from the upstream repo. +Clone Martin, setting remote name to `upstream`. This way `main` branch will be updated automatically with the latest +changes from the upstream repo. -```shell, ignore +```bash, ignore git clone https://github.com/maplibre/martin.git -o upstream cd martin ``` Fork Martin repo into your own GitHub account, and add your fork as a remote -```shell, ignore +```bash, ignore git remote add origin _URL_OF_YOUR_FORK_ ``` Install [docker](https://docs.docker.com/get-docker/) and [docker-compose](https://docs.docker.com/compose/) -```shell, ignore +```bash, ignore # Ubuntu-based distros have an older version that might also work: sudo apt install -y docker.io docker-compose ``` Install a few required libs and tools: -```shell, ignore +```bash, ignore # For Ubuntu-based distros sudo apt install -y build-essential pkg-config jq file ``` -Install [Just](https://github.com/casey/just#readme) (improved makefile processor). Note that some Linux and Homebrew distros have outdated versions of Just, so you should install it from source: +Install [Just](https://github.com/casey/just#readme) (improved makefile processor). Note that some Linux and Homebrew +distros have outdated versions of Just, so you should install it from source: -```shell, ignore +```bash, ignore cargo install just --locked ``` -When developing MBTiles SQL code, you may need to use `just prepare-sqlite` whenever SQL queries are modified. Run `just` to see all available commands. +When developing MBTiles SQL code, you may need to use `just prepare-sqlite` whenever SQL queries are modified. +Run `just` to see all available commands. diff --git a/docs/src/images/qgis_add_to_layers.png b/docs/src/images/qgis_add_to_layers.png new file mode 100644 index 0000000000000000000000000000000000000000..68d6097a9a2f7a23496a419ed38822e1feaad434 GIT binary patch literal 38200 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 JPDHLkV1n5(W4{0Z literal 0 HcmV?d00001 diff --git a/docs/src/images/qgis_add_vector_tile.png b/docs/src/images/qgis_add_vector_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..de707e506a210fbd9539b26cc0f87f90bf7f5de9 GIT binary patch literal 101384 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Μ9^qD%Qr- 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[.tar.gz][rl-linux-x64-musl] (musl)
[.deb][rl-linux-x64-deb] | [.tar.gz][rl-linux-a64-musl] (musl) | +| macOS | [.tar.gz][rl-macos-x64] | [.tar.gz][rl-macos-a64] | +| Windows | [.zip][rl-win64-zip] | | -[rl-linux-tar]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz -[rl-macos-tar]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-apple-darwin.tar.gz -[rl-win64-zip]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip +[rl-linux-x64]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz -### Building with Cargo +[rl-linux-x64-musl]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-musl.tar.gz -If you [install Rust](https://www.rust-lang.org/tools/install), you can build martin from source with Cargo: +[rl-linux-x64-deb]: https://github.com/maplibre/martin/releases/latest/download/martin-Debian-x86_64.deb -```shell -cargo install martin --locked +[rl-linux-a64-musl]: https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-unknown-linux-musl.tar.gz + +[rl-macos-x64]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-apple-darwin.tar.gz + +[rl-macos-a64]: https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-apple-darwin.tar.gz + +[rl-win64-zip]: https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip + +Rust users can install pre-built martin binary +with [cargo-binstall](https://github.com/cargo-bins/cargo-binstall) and `cargo`. + +```bash +cargo install cargo-binstall +cargo binstall martin martin --help ``` -### Homebrew +### From package + +To install with apt source and others, We need your help +to [improve packaging for various platforms](https://github.com/maplibre/martin/issues/578). + +#### Homebrew If you are using macOS and [Homebrew](https://brew.sh/) you can install martin using Homebrew tap. -```shell +```bash brew tap maplibre/martin brew install martin +martin --help ``` -### Docker +#### Debian Packages(x86_64) manually -Martin is also available as a [Docker image](https://ghcr.io/maplibre/martin). You could either share a configuration file from the host with the container via the `-v` param, or you can let Martin auto-discover all sources e.g. by passing `DATABASE_URL` or specifying the .mbtiles/.pmtiles files or URLs to .pmtiles. +```bash +curl -O https://github.com/maplibre/martin/releases/latest/download/martin-Debian-x86_64.deb +sudo dpkg -i ./martin-Debian-x86_64.deb +martin --help +rm ./martin-Debian-x86_64.deb +``` -```shell -export PGPASSWORD=postgres # secret! -docker run -p 3000:3000 \ - -e PGPASSWORD \ - -e DATABASE_URL=postgresql://user@host:port/db \ - -v /path/to/config/dir:/config \ - ghcr.io/maplibre/martin --config /config/config.yaml +### Building From source + +If you [install Rust](https://www.rust-lang.org/tools/install), you can build martin from source with Cargo: + +```bash +cargo install martin --locked +martin --help ``` diff --git a/docs/src/martin-as-a-library.md b/docs/src/martin-as-a-library.md new file mode 100644 index 000000000..680d2435e --- /dev/null +++ b/docs/src/martin-as-a-library.md @@ -0,0 +1,9 @@ +# Martin as a library + +Martin can be used as a standalone server, or as a library in your own Rust application. When used as a library, you can use the following features: + +* **postgres** - enable PostgreSQL/PostGIS tile sources +* **pmtiles** - enable PMTile tile sources +* **mbtiles** - enable MBTile tile sources +* **fonts** - enable font sources +* **sprites** - enable sprite sources diff --git a/docs/src/martin-cp.md b/docs/src/martin-cp.md index 53e06b319..38660598b 100644 --- a/docs/src/martin-cp.md +++ b/docs/src/martin-cp.md @@ -1,14 +1,20 @@ # Generating Tiles in Bulk -`martin-cp` is a tool for generating tiles in bulk, from any source(s) supported by Martin, and save retrieved tiles into a new or an existing MBTiles file. `martin-cp` can be used to generate tiles for a large area or multiple areas (bounding boxes). If multiple areas overlap, it will ensure each tile is generated only once. `martin-cp` supports the same configuration file and CLI arguments as Martin server, so it can support all sources and even combining sources. +`martin-cp` is a tool for generating tiles in bulk, from any source(s) supported by Martin, and save retrieved tiles +into a new or an existing MBTiles file. `martin-cp` can be used to generate tiles for a large area or multiple areas ( +bounding boxes). If multiple areas overlap, it will ensure each tile is generated only once. `martin-cp` supports the +same configuration file and CLI arguments as Martin server, so it can support all sources and even combining sources. -After copying, `martin-cp` will update the `agg_tiles_hash` metadata value unless `--skip-agg-tiles-hash` is specified. This allows the MBTiles file to be [validated](./mbtiles-validation.md#aggregate-content-validation) using `mbtiles validate` command. +After copying, `martin-cp` will update the `agg_tiles_hash` metadata value unless `--skip-agg-tiles-hash` is specified. +This allows the MBTiles file to be [validated](./mbtiles-validation.md#aggregate-content-validation) +using `mbtiles validate` command. ## Usage -This copies tiles from a PostGIS table `my_table` into an MBTiles file `tileset.mbtiles` using [normalized](mbtiles-schema.md) schema, with zoom levels from 0 to 10, and bounds of the whole world. +This copies tiles from a PostGIS table `my_table` into an MBTiles file `tileset.mbtiles` +using [normalized](mbtiles-schema.md) schema, with zoom levels from 0 to 10, and bounds of the whole world. -```shell +```bash martin-cp --output-file tileset.mbtiles \ --mbtiles-type normalized \ "--bbox=-180,-90,180,90" \ diff --git a/docs/src/mbtiles-copy.md b/docs/src/mbtiles-copy.md index 29a3a46a6..7b005b1bc 100644 --- a/docs/src/mbtiles-copy.md +++ b/docs/src/mbtiles-copy.md @@ -4,14 +4,14 @@ Copy command copies an mbtiles file, optionally filtering its content by zoom levels. -```shell +```bash mbtiles copy src_file.mbtiles dst_file.mbtiles \ --min-zoom 0 --max-zoom 10 ``` This command can also be used to generate files of different [supported schema](mbtiles-schema.md). -```shell +```bash mbtiles copy normalized.mbtiles dst.mbtiles \ --dst-mbttype flat-with-hash ``` @@ -20,7 +20,7 @@ mbtiles copy normalized.mbtiles dst.mbtiles \ This option is identical to using [`mbtiles diff ...`](mbtiles-diff.md). The following commands two are equivalent: -```shell +```bash mbtiles diff file1.mbtiles file2.mbtiles diff.mbtiles mbtiles copy file1.mbtiles diff.mbtiles \ @@ -29,9 +29,10 @@ mbtiles copy file1.mbtiles diff.mbtiles \ ## `mbtiles copy --apply-patch` -Copy a source file to destination while also applying the diff file generated by `copy --diff-with-file` command above to the destination mbtiles file. This allows safer application of the diff file, as the source file is not modified. +Copy a source file to destination while also applying the diff file generated by `copy --diff-with-file` command above +to the destination mbtiles file. This allows safer application of the diff file, as the source file is not modified. -```shell +```bash mbtiles copy src_file.mbtiles dst_file.mbtiles \ --apply-patch diff.mbtiles ``` diff --git a/docs/src/mbtiles-diff.md b/docs/src/mbtiles-diff.md index b2d627b2d..d5a02e2e8 100644 --- a/docs/src/mbtiles-diff.md +++ b/docs/src/mbtiles-diff.md @@ -13,7 +13,7 @@ file to the original file, as the `agg_tiles_hash` value will be different after command will automatically rename the `agg_tiles_hash_after_apply` value back to `agg_tiles_hash` when applying the diff. -```shell +```bash # This command will compare `file1.mbtiles` and `file2.mbtiles`, and generate a new diff file `diff.mbtiles`. mbtiles diff file1.mbtiles file2.mbtiles diff.mbtiles @@ -41,7 +41,7 @@ Note that the `agg_tiles_hash_after_apply` metadata value will be renamed to `ag This is done to avoid confusion when applying the diff file to the original file, as the `agg_tiles_hash` value will be different after the diff is applied. -```shell +```bash mbtiles apply-patch src_file.mbtiles diff_file.mbtiles ``` @@ -53,7 +53,7 @@ from `diff_file.mbtiles` into `src_file.mbtiles`, where both files are of `flat` passed as a query parameter to the sqlite3 command line tool, and then used in the SQL statements. Note that this does not update the `agg_tiles_hash` metadata value, so it will be incorrect after the diff is applied. -```shell +```bash sqlite3 src_file.mbtiles \ -bail \ -cmd ".parameter set @diffDbFilename diff_file.mbtiles" \ diff --git a/docs/src/mbtiles-meta.md b/docs/src/mbtiles-meta.md index ac1d0fb76..422cf51e8 100644 --- a/docs/src/mbtiles-meta.md +++ b/docs/src/mbtiles-meta.md @@ -2,9 +2,11 @@ ## summary -Use `mbtiles summary` to get a summary of the contents of an MBTiles file. The command will print a table with the number of tiles per zoom level, the size of the smallest and largest tiles, and the average size of tiles at each zoom level. The command will also print the bounding box of the covered area per zoom level. +Use `mbtiles summary` to get a summary of the contents of an MBTiles file. The command will print a table with the +number of tiles per zoom level, the size of the smallest and largest tiles, and the average size of tiles at each zoom +level. The command will also print the bounding box of the covered area per zoom level. -```shell +```bash MBTiles file summary for tests/fixtures/mbtiles/world_cities.mbtiles Schema: flat File size: 48.00KiB @@ -24,24 +26,27 @@ Page count: 12 ## meta-all -Print all metadata values to stdout, as well as the results of tile detection. The format of the values printed is not stable, and should only be used for visual inspection. +Print all metadata values to stdout, as well as the results of tile detection. The format of the values printed is not +stable, and should only be used for visual inspection. -```shell +```bash mbtiles meta-all my_file.mbtiles ``` ## meta-get -Retrieve raw metadata value by its name. The value is printed to stdout without any modifications. For example, to get the `description` value from an mbtiles file: +Retrieve raw metadata value by its name. The value is printed to stdout without any modifications. For example, to get +the `description` value from an mbtiles file: -```shell +```bash mbtiles meta-get my_file.mbtiles description ``` ## meta-set -Set metadata value by its name, or delete the key if no value is supplied. For example, to set the `description` value to `A vector tile dataset`: +Set metadata value by its name, or delete the key if no value is supplied. For example, to set the `description` value +to `A vector tile dataset`: -```shell +```bash mbtiles meta-set my_file.mbtiles description "A vector tile dataset" ``` diff --git a/docs/src/mbtiles-validation.md b/docs/src/mbtiles-validation.md index bd5486c5e..4e95930b5 100644 --- a/docs/src/mbtiles-validation.md +++ b/docs/src/mbtiles-validation.md @@ -1,32 +1,47 @@ # MBTiles Validation -The original [MBTiles specification](https://github.com/mapbox/mbtiles-spec#readme) does not provide any guarantees for the content of the tile data in MBTiles. `mbtiles validate` assumes a few additional conventions and uses them to ensure that the content of the tile data is valid performing several validation steps. If the file is not valid, the command will print an error message and exit with a non-zero exit code. +The original [MBTiles specification](https://github.com/mapbox/mbtiles-spec#readme) does not provide any guarantees for +the content of the tile data in MBTiles. `mbtiles validate` assumes a few additional conventions and uses them to ensure +that the content of the tile data is valid performing several validation steps. If the file is not valid, the command +will print an error message and exit with a non-zero exit code. -```shell +```bash mbtiles validate src_file.mbtiles ``` ## SQLite Integrity check -The `validate` command will run `PRAGMA integrity_check` on the file, and will fail if the result is not `ok`. The `--integrity-check` flag can be used to disable this check, or to make it more thorough with `full` value. Default is `quick`. +The `validate` command will run `PRAGMA integrity_check` on the file, and will fail if the result is not `ok`. +The `--integrity-check` flag can be used to disable this check, or to make it more thorough with `full` value. Default +is `quick`. ## Schema check -The `validate` command will verify that the `tiles` table/view exists, and that it has the expected columns and indexes. It will also verify that the `metadata` table/view exists, and that it has the expected columns and indexes. +The `validate` command will verify that the `tiles` table/view exists, and that it has the expected columns and indexes. +It will also verify that the `metadata` table/view exists, and that it has the expected columns and indexes. ## Per-tile validation -If the `.mbtiles` file uses [flat_with_hash](mbtiles-schema.md#flat-with-hash) or [normalized](mbtiles-schema.md#normalized) schema, the `validate` command will verify that the MD5 hash of the `tile_data` column matches the `tile_hash` or `tile_id` columns (depending on the schema). +If the `.mbtiles` file uses [flat_with_hash](mbtiles-schema.md#flat-with-hash) +or [normalized](mbtiles-schema.md#normalized) schema, the `validate` command will verify that the MD5 hash of +the `tile_data` column matches the `tile_hash` or `tile_id` columns (depending on the schema). -A typical Normalized schema generated by tools like [tilelive-copy](https://github.com/mapbox/TileLive#bintilelive-copy) use MD5 hash in the `tile_id` column. The Martin's `mbtiles` tool can use this hash to verify the content of each tile. We also define a new [flat-with-hash](mbtiles-schema.md#flat-with-hash) schema that stores the hash and tile data in the same table, allowing per-tile validation without the multiple table layout. +A typical Normalized schema generated by tools like [tilelive-copy](https://github.com/mapbox/TileLive#bintilelive-copy) +use MD5 hash in the `tile_id` column. The Martin's `mbtiles` tool can use this hash to verify the content of each tile. +We also define a new [flat-with-hash](mbtiles-schema.md#flat-with-hash) schema that stores the hash and tile data in the +same table, allowing per-tile validation without the multiple table layout. Per-tile validation is not available for the `flat` schema, and will be skipped. ## Aggregate Content Validation -Per-tile validation will catch individual tile corruption, but it will not detect overall datastore corruption such as missing tiles, tiles that should not exist, or tiles with incorrect z/x/y values. For that, the `mbtiles` tool defines a new metadata value called `agg_tiles_hash`. +Per-tile validation will catch individual tile corruption, but it will not detect overall datastore corruption such as +missing tiles, tiles that should not exist, or tiles with incorrect z/x/y values. For that, the `mbtiles` tool defines a +new metadata value called `agg_tiles_hash`. -The value is computed by hashing the combined value for all rows in the `tiles` table/view, ordered by z,x,y. The value is computed using the following SQL expression, which uses a custom `md5_concat_hex` function from [sqlite-hashes crate](https://crates.io/crates/sqlite-hashes): +The value is computed by hashing the combined value for all rows in the `tiles` table/view, ordered by z,x,y. The value +is computed using the following SQL expression, which uses a custom `md5_concat_hex` function +from [sqlite-hashes crate](https://crates.io/crates/sqlite-hashes): ```sql, ignore md5_concat_hex( @@ -36,6 +51,9 @@ md5_concat_hex( tile_data) ``` -In case there are no rows or all are NULL, the hash value of an empty string is used. Note that SQLite allows any value type to be stored as in any column, so if `tile_data` accidentally contains non-blob/text/null value, validation will fail. +In case there are no rows or all are NULL, the hash value of an empty string is used. Note that SQLite allows any value +type to be stored as in any column, so if `tile_data` accidentally contains non-blob/text/null value, validation will +fail. -The `mbtiles` tool will compute `agg_tiles_hash` value when copying or validating mbtiles files. Use `--agg-hash update` to force the value to be updated, even if it is incorrect or does not exist. +The `mbtiles` tool will compute `agg_tiles_hash` value when copying or validating mbtiles files. Use `--agg-hash update` +to force the value to be updated, even if it is incorrect or does not exist. diff --git a/docs/src/quick-start-linux.md b/docs/src/quick-start-linux.md new file mode 100644 index 000000000..093b323b0 --- /dev/null +++ b/docs/src/quick-start-linux.md @@ -0,0 +1,24 @@ +## Quick start on Linux + +```bash +mkdir martin +cd martin + +# Download some sample data +curl -O https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles + +# Download the latest version of Martin binary, extract it, and make it executable +curl -O https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz +tar -xzf martin-x86_64-unknown-linux-gnu.tar.gz +chmod +x ./martin + +# Show Martin help screen +./martin --help + +# Run Martin with the sample data as the only tile source +./martin world_cities.mbtiles +``` + +### View the map + +See [quick start with QGIS](quick-start-qgis.md) for instructions on how to view the map. diff --git a/docs/src/quick-start-macos.md b/docs/src/quick-start-macos.md new file mode 100644 index 000000000..921e8a2f4 --- /dev/null +++ b/docs/src/quick-start-macos.md @@ -0,0 +1,27 @@ +## Quick start on macOS + +1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). + +2. Download the latest version of Martin from + the [release page](https://github.com/maplibre/martin/releases/latest/download). + Use [about this Mac](https://support.apple.com/en-us/116943) to find your processors type. + * Use [martin-x86_64-apple-darwin.tar.gz](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-apple-darwin.tar.gz) for Intel + * Use [martin-aarch64-apple-darwin.tar.gz](https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-apple-darwin.tar.gz) for M1 + +3. Extract content of both files and place them in a same directory. + +4. Open the command prompt and navigate to the directory where `martin` and `world_cities.mbtiles` are located. + +5. Run the following command to start Martin with the demo data: + +```bash +# Show Martin help screen +./martin --help + +# Run Martin with the sample data as the only tile source +./martin world_cities.mbtiles +``` + +### View the map + +See [quick start with QGIS](quick-start-qgis.md) for instructions on how to view the map. diff --git a/docs/src/quick-start-qgis.md b/docs/src/quick-start-qgis.md new file mode 100644 index 000000000..8ad2db54b --- /dev/null +++ b/docs/src/quick-start-qgis.md @@ -0,0 +1,17 @@ +### View map with QGIS + +1. Download, install, and run [QGIS](https://qgis.org/en/site/forusers/download.html) for your platform + +2. Add a new `Vector Tiles` connection + > ![alt text](images/qgis_add_vector_tile.png) + +3. In the `Vector Tile Connection` dialog, give it some name and the URL of the Martin server, + e.g. `http://localhost:3000/martin/{z}/{x}/{y}.pbf` and click `OK`. + > ![alt text](images/qgis_add_vector_tile_options.png) + +4. In the QGIS browser panel (left), double-click the newly added connection, or right-click it and click + on `Add Layer to Project`. + > ![alt text](images/qgis_add_to_layers.png) + +5. The map should now be visible in the QGIS map view. + > ![alt text](images/qgis_shows_in_the_map.png) diff --git a/docs/src/quick-start-windows.md b/docs/src/quick-start-windows.md new file mode 100644 index 000000000..af7fa0f5e --- /dev/null +++ b/docs/src/quick-start-windows.md @@ -0,0 +1,24 @@ +## Quick start on Windows + +1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). + +2. Download the latest Windows version of Martin from + the [release page](https://github.com/maplibre/martin/releases): []([martin-x86_64-pc-windows-msvc.zip](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip) + +3. Extract content of both files and place them in a same directory. + +4. Open the command prompt and navigate to the directory where `martin` and `world_cities.mbtiles` are located. + +5. Run the following command to start Martin with the demo data: + +```bash +# Show Martin help screen +martin --help + +# Run Martin with the sample data as the only tile source +martin world_cities.mbtiles +``` + +### View the map + +See [quick start with QGIS](quick-start-qgis.md) for instructions on how to view the map. diff --git a/docs/src/quick-start.md b/docs/src/quick-start.md new file mode 100644 index 000000000..5e35ee51f --- /dev/null +++ b/docs/src/quick-start.md @@ -0,0 +1,7 @@ +## Martin Quick Start Guide + +Choose your operating system to get started with Martin tile server + +* [Linux](quick-start-linux.md) +* [macOS](quick-start-macos.md) +* [Windows](quick-start-windows.md) diff --git a/docs/src/recipes.md b/docs/src/recipes.md index 2c864efeb..423c64b08 100644 --- a/docs/src/recipes.md +++ b/docs/src/recipes.md @@ -2,11 +2,15 @@ ### Using with DigitalOcean PostgreSQL -You can use Martin with [Managed PostgreSQL from DigitalOcean](https://www.digitalocean.com/products/managed-databases-postgresql/) with PostGIS extension +You can use Martin +with [Managed PostgreSQL from DigitalOcean](https://www.digitalocean.com/products/managed-databases-postgresql/) with +PostGIS extension -First, you need to download the CA certificate and get your cluster connection string from the [dashboard](https://cloud.digitalocean.com/databases). After that, you can use the connection string and the CA certificate to connect to the database +First, you need to download the CA certificate and get your cluster connection string from +the [dashboard](https://cloud.digitalocean.com/databases). After that, you can use the connection string and the CA +certificate to connect to the database -```shell +```bash martin --ca-root-file ./ca-certificate.crt \ postgresql://user:password@host:port/db?sslmode=require ``` @@ -15,13 +19,14 @@ martin --ca-root-file ./ca-certificate.crt \ You can use Martin with [Managed PostgreSQL from Heroku](https://www.heroku.com/postgres) with PostGIS extension -```shell +```bash heroku pg:psql -a APP_NAME -c 'create extension postgis' ``` -Use the same environment variables as Heroku [suggests for psql](https://devcenter.heroku.com/articles/heroku-postgres-via-mtls#step-2-configure-environment-variables). +Use the same environment variables as +Heroku [suggests for psql](https://devcenter.heroku.com/articles/heroku-postgres-via-mtls#step-2-configure-environment-variables). -```shell +```bash export DATABASE_URL=$(heroku config:get DATABASE_URL -a APP_NAME) export PGSSLCERT=DIRECTORY/PREFIXpostgresql.crt export PGSSLKEY=DIRECTORY/PREFIXpostgresql.key @@ -32,6 +37,6 @@ martin You may also be able to validate SSL certificate with an explicit sslmode, e.g. -```shell +```bash export DATABASE_URL="$(heroku config:get DATABASE_URL -a APP_NAME)?sslmode=verify-ca" ``` diff --git a/docs/src/run-with-cli.md b/docs/src/run-with-cli.md index 17b16fbaf..fe6ddaf14 100644 --- a/docs/src/run-with-cli.md +++ b/docs/src/run-with-cli.md @@ -3,7 +3,7 @@ You can configure Martin using command-line interface. See `martin --help` or `cargo run -- --help` for more information. -```shell +```text Usage: martin [OPTIONS] [CONNECTION]... Arguments: diff --git a/docs/src/run-with-docker-compose.md b/docs/src/run-with-docker-compose.md index 005f0187e..31a6cd2a6 100644 --- a/docs/src/run-with-docker-compose.md +++ b/docs/src/run-with-docker-compose.md @@ -1,6 +1,7 @@ ## Running with Docker Compose -You can use example [`docker-compose.yml`](https://raw.githubusercontent.com/maplibre/martin/main/docker-compose.yml) file as a reference +You can use example [`docker-compose.yml`](https://raw.githubusercontent.com/maplibre/martin/main/docker-compose.yml) +file as a reference ```yml services: @@ -28,13 +29,13 @@ services: First, you need to start `db` service -```shell +```bash docker compose up -d db ``` Then, after `db` service is ready to accept connections, you can start `martin` -```shell +```bash docker compose up -d martin ``` diff --git a/docs/src/run-with-docker.md b/docs/src/run-with-docker.md index 75ae7e488..ebb5b5421 100644 --- a/docs/src/run-with-docker.md +++ b/docs/src/run-with-docker.md @@ -4,7 +4,7 @@ You can use official Docker image [`ghcr.io/maplibre/martin`](https://ghcr.io/ma ### Using Non-Local PostgreSQL -```shell +```bash docker run \ -p 3000:3000 \ -e DATABASE_URL=postgresql://postgres@postgres.example.org/db \ @@ -15,7 +15,7 @@ docker run \ You can expose local files to the Docker container using the `-v` flag. -```shell +```bash docker run \ -p 3000:3000 \ -v /path/to/local/files:/files \ @@ -24,11 +24,13 @@ docker run \ ### Accessing Local PostgreSQL on Linux -If you are running PostgreSQL instance on `localhost`, you have to change network settings to allow the Docker container to access the `localhost` network. +If you are running PostgreSQL instance on `localhost`, you have to change network settings to allow the Docker container +to access the `localhost` network. -For Linux, add the `--net=host` flag to access the `localhost` PostgreSQL service. You would not need to export ports with `-p` because the container is already using the host network. +For Linux, add the `--net=host` flag to access the `localhost` PostgreSQL service. You would not need to export ports +with `-p` because the container is already using the host network. -```shell +```bash docker run \ --net=host \ -e DATABASE_URL=postgresql://postgres@localhost/db \ @@ -39,7 +41,7 @@ docker run \ For macOS, use `host.docker.internal` as hostname to access the `localhost` PostgreSQL service. -```shell +```bash docker run \ -p 3000:3000 \ -e DATABASE_URL=postgresql://postgres@host.docker.internal/db \ @@ -50,7 +52,7 @@ docker run \ For Windows, use `docker.for.win.localhost` as hostname to access the `localhost` PostgreSQL service. -```shell +```bash docker run \ -p 3000:3000 \ -e DATABASE_URL=postgresql://postgres@docker.for.win.localhost/db \ diff --git a/docs/src/run.md b/docs/src/run.md index 4007b4cd0..829fa1323 100644 --- a/docs/src/run.md +++ b/docs/src/run.md @@ -1,9 +1,12 @@ # Usage -Martin requires at least one PostgreSQL [connection string](pg-connections.md) or a [tile source file](sources-files.md) as a command-line argument. A PG connection string can also be passed via the `DATABASE_URL` environment variable. +Martin requires at least one PostgreSQL [connection string](pg-connections.md) or a [tile source file](sources-files.md) +as a command-line argument. A PG connection string can also be passed via the `DATABASE_URL` environment variable. -```shell +```bash martin postgresql://postgres@localhost/db ``` -Martin provides [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint for each [geospatial-enabled](https://postgis.net/docs/using_postgis_dbmanagement.html#geometry_columns) table in your database. +Martin provides [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint for +each [geospatial-enabled](https://postgis.net/docs/using_postgis_dbmanagement.html#geometry_columns) table in your +database. diff --git a/docs/src/sources-composite.md b/docs/src/sources-composite.md index 255b5caf0..68769b470 100644 --- a/docs/src/sources-composite.md +++ b/docs/src/sources-composite.md @@ -1,14 +1,16 @@ ## Composite Sources -Composite Sources allows combining multiple sources into one. Composite Source consists of multiple sources separated by comma `{source1},...,{sourceN}` +Composite Sources allows combining multiple sources into one. Composite Source consists of multiple sources separated by +comma `{source1},...,{sourceN}` Each source in a composite source can be accessed with its `{source_name}` as a `source-layer` property. -Composite source [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint is available at `/{source1},...,{sourceN}`, and tiles are available at `/{source1},...,{sourceN}/{z}/{x}/{y}`. +Composite source [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint is available +at `/{source1},...,{sourceN}`, and tiles are available at `/{source1},...,{sourceN}/{z}/{x}/{y}`. For example, composite source combining `points` and `lines` sources will be available at `/points,lines/{z}/{x}/{y}` -```shell +```bash # TileJSON curl localhost:3000/points,lines diff --git a/docs/src/sources-files.md b/docs/src/sources-files.md index 658453c2e..c755794f5 100644 --- a/docs/src/sources-files.md +++ b/docs/src/sources-files.md @@ -1,9 +1,12 @@ ## MBTiles and PMTiles File Sources -Martin can serve any type of tiles from [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) and [MBTile](https://github.com/mapbox/mbtiles-spec) files. To serve a file from CLI, simply put the path to the file or the directory with `*.mbtiles` or `*.pmtiles` files. A path to PMTiles file may be a URL. For example: +Martin can serve any type of tiles from [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) +and [MBTile](https://github.com/mapbox/mbtiles-spec) files. To serve a file from CLI, simply put the path to the file or +the directory with `*.mbtiles` or `*.pmtiles` files. A path to PMTiles file may be a URL. For example: -```shell +```bash martin /path/to/mbtiles/file.mbtiles /path/to/directory https://example.org/path/tiles.pmtiles ``` -You may also want to generate a [config file](config-file.md) using the `--save-config my-config.yaml`, and later edit it and use it with `--config my-config.yaml` option. +You may also want to generate a [config file](config-file.md) using the `--save-config my-config.yaml`, and later edit +it and use it with `--config my-config.yaml` option. diff --git a/docs/src/sources-fonts.md b/docs/src/sources-fonts.md index 21095ca8e..a223eb06e 100644 --- a/docs/src/sources-fonts.md +++ b/docs/src/sources-fonts.md @@ -1,11 +1,14 @@ ## Font Sources -Martin can serve glyph ranges from `otf`, `ttf`, and `ttc` fonts as needed by MapLibre text rendering. Martin will generate them dynamically on the fly. +Martin can serve glyph ranges from `otf`, `ttf`, and `ttc` fonts as needed by MapLibre text rendering. Martin will +generate them dynamically on the fly. The glyph range generation is not yet cached, and may require external reverse proxy or CDN for faster operation. ## API -Fonts ranges are available either for a single font, or a combination of multiple fonts. The font names are case-sensitive and should match the font name in the font file as published in the catalog. Make sure to URL-escape font names as they usually contain spaces. +Fonts ranges are available either for a single font, or a combination of multiple fonts. The font names are +case-sensitive and should match the font name in the font file as published in the catalog. Make sure to URL-escape font +names as they usually contain spaces. | | Font Request | |---------|--------------------------------------| @@ -14,7 +17,9 @@ Fonts ranges are available either for a single font, or a combination of multipl ### Composite Font Request -When combining multiple fonts, the glyph range will contain glyphs from the first listed font if available, and fallback to the next font if the glyph is not available in the first font, etc. The glyph range will be empty if none of the fonts contain the glyph. +When combining multiple fonts, the glyph range will contain glyphs from the first listed font if available, and fallback +to the next font if the glyph is not available in the first font, etc. The glyph range will be empty if none of the +fonts contain the glyph. | | Composite Font Request with fallbacks | |---------|--------------------------------------------------------------| @@ -25,7 +30,7 @@ When combining multiple fonts, the glyph range will contain glyphs from the firs Martin will show all available fonts at the `/catalog` endpoint. -```shell +```bash curl http://127.0.0.1:3000/catalog { "fonts": { @@ -58,7 +63,7 @@ curl http://127.0.0.1:3000/catalog A font file or directory can be configured from the [CLI](run-with-cli.md) with one or more `--font` parameters. -```shell +```bash martin --font /path/to/font/file.ttf --font /path/to/font_dir ``` diff --git a/docs/src/sources-pg-functions.md b/docs/src/sources-pg-functions.md index 1dfa95536..3578c6ebb 100644 --- a/docs/src/sources-pg-functions.md +++ b/docs/src/sources-pg-functions.md @@ -1,6 +1,11 @@ ## PostgreSQL Function Sources -Function Source is a database function which can be used to query [vector tiles](https://github.com/mapbox/vector-tile-spec). When started, Martin will look for the functions with a suitable signature. A function that takes `z integer` (or `zoom integer`), `x integer`, `y integer`, and an optional `query json` and returns `bytea`, can be used as a Function Source. Alternatively the function could return a record with a single `bytea` field, or a record with two fields of types `bytea` and `text`, where the `text` field is an etag key (i.e. md5 hash). +Function Source is a database function which can be used to +query [vector tiles](https://github.com/mapbox/vector-tile-spec). When started, Martin will look for the functions with +a suitable signature. A function that takes `z integer` (or `zoom integer`), `x integer`, `y integer`, and an +optional `query json` and returns `bytea`, can be used as a Function Source. Alternatively the function could return a +record with a single `bytea` field, or a record with two fields of types `bytea` and `text`, where the `text` field is +an etag key (i.e. md5 hash). | Argument | Type | Description | |----------------------------|---------|-------------------------| @@ -11,7 +16,8 @@ Function Source is a database function which can be used to query [vector tiles] ### Simple Function -For example, if you have a table `table_source` in WGS84 (`4326` SRID), then you can use this function as a Function Source: +For example, if you have a table `table_source` in WGS84 (`4326` SRID), then you can use this function as a Function +Source: ```sql, ignore CREATE OR REPLACE @@ -63,15 +69,18 @@ END $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; ``` -The `query_params` argument is a JSON representation of the tile request query params. Query params could be passed as simple query values, e.g. +The `query_params` argument is a JSON representation of the tile request query params. Query params could be passed as +simple query values, e.g. -```shell +```bash curl localhost:3000/function_zxy_query/0/0/0?token=martin ``` -You can also use [urlencoded](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) params to encode complex values: +You can also +use [urlencoded](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) +params to encode complex values: -```shell +```bash curl \ --data-urlencode 'arrayParam=[1, 2, 3]' \ --data-urlencode 'numberParam=42' \ @@ -101,7 +110,11 @@ You can access this params using [json operators](https://www.postgresql.org/doc ### Modifying TileJSON -Martin will automatically generate a basic [TileJSON](https://github.com/mapbox/tilejson-spec) manifest for each function source that will contain the name and description of the function, plus optionally `minzoom`, `maxzoom`, and `bounds` (if they were specified via one of the configuration methods). For example, if there is a function `public.function_zxy_query_jsonb`, the default `TileJSON` might look like this (note that URL will be automatically adjusted to match the request host): +Martin will automatically generate a basic [TileJSON](https://github.com/mapbox/tilejson-spec) manifest for each +function source that will contain the name and description of the function, plus optionally `minzoom`, `maxzoom`, +and `bounds` (if they were specified via one of the configuration methods). For example, if there is a +function `public.function_zxy_query_jsonb`, the default `TileJSON` might look like this (note that URL will be +automatically adjusted to match the request host): ```json { @@ -116,9 +129,12 @@ Martin will automatically generate a basic [TileJSON](https://github.com/mapbox/ #### TileJSON in SQL Comments -To modify automatically generated `TileJSON`, you can add a valid JSON as an SQL comment on the function. Martin will merge function comment into the generated `TileJSON` using [JSON Merge patch](https://www.rfc-editor.org/rfc/rfc7386). The following example adds `attribution` and `version` fields to the `TileJSON`. +To modify automatically generated `TileJSON`, you can add a valid JSON as an SQL comment on the function. Martin will +merge function comment into the generated `TileJSON` using [JSON Merge patch](https://www.rfc-editor.org/rfc/rfc7386). +The following example adds `attribution` and `version` fields to the `TileJSON`. -**Note:** This example uses `EXECUTE` to ensure that the comment is a valid JSON (or else PostgreSQL will throw an error). You can use other methods of creating SQL comments. +**Note:** This example uses `EXECUTE` to ensure that the comment is a valid JSON (or else PostgreSQL will throw an +error). You can use other methods of creating SQL comments. ```sql DO $do$ BEGIN diff --git a/docs/src/sources-sprites.md b/docs/src/sources-sprites.md index 809e87092..298b011ea 100644 --- a/docs/src/sources-sprites.md +++ b/docs/src/sources-sprites.md @@ -1,20 +1,28 @@ ## Sprite Sources -Given a directory with SVG images, Martin will generate a sprite -- a JSON index and a PNG image, for both low and high resolution displays. The SVG filenames without extension will be used as the sprite image IDs. The images are searched recursively in the given directory, so subdirectory names will be used as prefixes for the image IDs, e.g. `icons/bicycle.svg` will be available as `icons/bicycle` sprite image. The sprite generation is not yet cached, and may require external reverse proxy or CDN for faster operation. +Given a directory with SVG images, Martin will generate a sprite -- a JSON index and a PNG image, for both low and high +resolution displays. The SVG filenames without extension will be used as the sprite image IDs. The images are searched +recursively in the given directory, so subdirectory names will be used as prefixes for the image IDs, +e.g. `icons/bicycle.svg` will be available as `icons/bicycle` sprite image. The sprite generation is not yet cached, and +may require external reverse proxy or CDN for faster operation. ### API -Martin uses [MapLibre sprites API](https://maplibre.org/maplibre-style-spec/sprite/) specification to serve sprites via several endpoints. The sprite image and index are generated on the fly, so if the sprite directory is updated, the changes will be reflected immediately. +Martin uses [MapLibre sprites API](https://maplibre.org/maplibre-style-spec/sprite/) specification to serve sprites via +several endpoints. The sprite image and index are generated on the fly, so if the sprite directory is updated, the +changes will be reflected immediately. ##### Sprite PNG ![sprite](sources-sprites.png) -`GET /sprite/.png` endpoint contains a single PNG sprite image that combines all sources images. Additionally, there is a high DPI version available at `GET /sprite/@2x.png`. +`GET /sprite/.png` endpoint contains a single PNG sprite image that combines all sources images. +Additionally, there is a high DPI version available at `GET /sprite/@2x.png`. ##### Sprite index -`/sprite/.json` metadata index describing the position and size of each image inside the sprite. Just like the PNG, there is a high DPI version available at `/sprite/@2x.json`. +`/sprite/.json` metadata index describing the position and size of each image inside the sprite. Just like +the PNG, there is a high DPI version available at `/sprite/@2x.json`. ```json { @@ -31,19 +39,25 @@ Martin uses [MapLibre sprites API](https://maplibre.org/maplibre-style-spec/spri #### Combining Multiple Sprites -Multiple sprite_id values can be combined into one sprite with the same pattern as for tile joining: `/sprite/,,...,`. No ID renaming is done, so identical sprite names will override one another. +Multiple sprite_id values can be combined into one sprite with the same pattern as for tile +joining: `/sprite/,,...,`. No ID renaming is done, so identical sprite names will +override one another. ### Configuring from CLI -A sprite directory can be configured from the CLI with the `--sprite` flag. The flag can be used multiple times to configure multiple sprite directories. The name of the sprite will be the name of the directory -- in the example below, the sprites will be available at `/sprite/sprite_a` and `/sprite/sprite_b`. Use `--save-config` to save the configuration to the config file. +A sprite directory can be configured from the CLI with the `--sprite` flag. The flag can be used multiple times to +configure multiple sprite directories. The name of the sprite will be the name of the directory -- in the example below, +the sprites will be available at `/sprite/sprite_a` and `/sprite/sprite_b`. Use `--save-config` to save the +configuration to the config file. -```shell +```bash martin --sprite /path/to/sprite_a --sprite /path/to/other/sprite_b ``` ### Configuring with Config File -A sprite directory can be configured from the config file with the `sprite` key, similar to how [MBTiles and PMTiles](config-file.md) are configured. +A sprite directory can be configured from the config file with the `sprite` key, similar to +how [MBTiles and PMTiles](config-file.md) are configured. ```yaml # Sprite configuration diff --git a/docs/src/troubleshooting.md b/docs/src/troubleshooting.md index 0c46f4478..9800c2df8 100644 --- a/docs/src/troubleshooting.md +++ b/docs/src/troubleshooting.md @@ -1,17 +1,20 @@ ## Troubleshooting -Log levels are controlled on a per-module basis, and by default all logging is disabled except for errors. Logging is controlled via the `RUST_LOG` environment variable. The value of this environment variable is a comma-separated list of logging directives. +Log levels are controlled on a per-module basis, and by default all logging is disabled except for errors. Logging is +controlled via the `RUST_LOG` environment variable. The value of this environment variable is a comma-separated list of +logging directives. This will enable debug logging for all modules: -```shell +```bash export RUST_LOG=debug martin postgresql://postgres@localhost/db ``` -While this will only enable verbose logging for the `actix_web` module and enable debug logging for the `martin` and `tokio_postgres` modules: +While this will only enable verbose logging for the `actix_web` module and enable debug logging for the `martin` +and `tokio_postgres` modules: -```shell +```bash export RUST_LOG=actix_web=info,martin=debug,tokio_postgres=debug martin postgresql://postgres@localhost/db ``` diff --git a/docs/src/using.md b/docs/src/using.md index 2d854b23f..2d8c3c537 100644 --- a/docs/src/using.md +++ b/docs/src/using.md @@ -17,11 +17,14 @@ Martin data is available via the HTTP `GET` endpoints: ### Duplicate Source ID -In case there is more than one source that has the same name, e.g. a PG function is available in two schemas/connections, or a table has more than one geometry columns, sources will be assigned unique IDs such as `/points`, `/points.1`, etc. +In case there is more than one source that has the same name, e.g. a PG function is available in two +schemas/connections, or a table has more than one geometry columns, sources will be assigned unique IDs such +as `/points`, `/points.1`, etc. ### Reserved Source IDs -Some source IDs are reserved for internal use. If you try to use them, they will be automatically renamed to a unique ID the same way as duplicate source IDs are handled, e.g. a `catalog` source will become `catalog.1`. +Some source IDs are reserved for internal use. If you try to use them, they will be automatically renamed to a unique ID +the same way as duplicate source IDs are handled, e.g. a `catalog` source will become `catalog.1`. Some of the reserved IDs: `_`, `catalog`, `config`, `font`, `health`, `help`, `index`, `manifest`, `metrics`, `refresh`, `reload`, `sprite`, `status`. @@ -30,7 +33,7 @@ Some of the reserved IDs: `_`, `catalog`, `config`, `font`, `health`, `help`, `i A list of all available sources is available via catalogue endpoint: -```shell +```bash curl localhost:3000/catalog | jq ``` @@ -73,9 +76,10 @@ curl localhost:3000/catalog | jq All tile sources have a [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint available at the `/{SourceID}`. -For example, a `points` function or a table will be available as `/points`. Composite source combining `points` and `lines` sources will be available at `/points,lines` endpoint. +For example, a `points` function or a table will be available as `/points`. Composite source combining `points` +and `lines` sources will be available at `/points,lines` endpoint. -```shell +```bash curl localhost:3000/points | jq curl localhost:3000/points,lines | jq ``` From 030beb8b1c2f98cb0cbaf85c50298badf45ca42d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 07:30:47 -0400 Subject: [PATCH 116/164] temporary remove link to the book to pass CI --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 47338b2f8..c01c365f6 100755 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ into one. Martin optimizes for speed and heavy traffic, and is written in [Rust] ### Documentation -* [Quick Start](https://maplibre.org/martin/quick-start.html) * [Installation](https://maplibre.org/martin/installation.html) * Running with [CLI](https://maplibre.org/martin/run-with-cli.html) or [configuration file](https://maplibre.org/martin/config-file.html) From 15a5402e552a8c0da55577c5999aa0e8bc824940 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 07:40:52 -0400 Subject: [PATCH 117/164] fix docs download link --- docs/src/quick-start-windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/quick-start-windows.md b/docs/src/quick-start-windows.md index af7fa0f5e..e66fafbf3 100644 --- a/docs/src/quick-start-windows.md +++ b/docs/src/quick-start-windows.md @@ -3,7 +3,7 @@ 1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). 2. Download the latest Windows version of Martin from - the [release page](https://github.com/maplibre/martin/releases): []([martin-x86_64-pc-windows-msvc.zip](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip) + the [release page](https://github.com/maplibre/martin/releases): [martin-x86_64-pc-windows-msvc.zip](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip) 3. Extract content of both files and place them in a same directory. From fbb1a86b24331cfc5514302df779f7b9b777c6ec Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 07:43:36 -0400 Subject: [PATCH 118/164] fix docs download link2 --- docs/src/quick-start-macos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/quick-start-macos.md b/docs/src/quick-start-macos.md index 921e8a2f4..5da4c70a2 100644 --- a/docs/src/quick-start-macos.md +++ b/docs/src/quick-start-macos.md @@ -3,7 +3,7 @@ 1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). 2. Download the latest version of Martin from - the [release page](https://github.com/maplibre/martin/releases/latest/download). + the [release page](https://github.com/maplibre/martin/releases/latest). Use [about this Mac](https://support.apple.com/en-us/116943) to find your processors type. * Use [martin-x86_64-apple-darwin.tar.gz](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-apple-darwin.tar.gz) for Intel * Use [martin-aarch64-apple-darwin.tar.gz](https://github.com/maplibre/martin/releases/latest/download/martin-aarch64-apple-darwin.tar.gz) for M1 From c33c7e1faa3a620947147f43e03ad1bf302a445e Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 07:46:51 -0400 Subject: [PATCH 119/164] re-add quick start to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c01c365f6..47338b2f8 100755 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ into one. Martin optimizes for speed and heavy traffic, and is written in [Rust] ### Documentation +* [Quick Start](https://maplibre.org/martin/quick-start.html) * [Installation](https://maplibre.org/martin/installation.html) * Running with [CLI](https://maplibre.org/martin/run-with-cli.html) or [configuration file](https://maplibre.org/martin/config-file.html) From 8c82423fc36c60df26b58b692752a8a3670f8a8f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 08:06:15 -0400 Subject: [PATCH 120/164] Minor readme improvements --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 47338b2f8..78d788682 100755 --- a/README.md +++ b/README.md @@ -8,21 +8,21 @@ [![Security audit](https://github.com/maplibre/martin/workflows/Security%20audit/badge.svg)](https://github.com/maplibre/martin/security) [![CI build](https://github.com/maplibre/martin/actions/workflows/ci.yml/badge.svg)](https://github.com/maplibre/martin/actions) -Martin is a tile server able to generate and serve [vector tiles](https://github.com/mapbox/vector-tile-spec) on the fly -from large [PostGIS](https://github.com/postgis/postgis) -databases, [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new) (local or remote), -and [MBTile](https://github.com/mapbox/mbtiles-spec) files, allowing multiple tile sources to be dynamically combined -into one. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). +Martin is a tile server and a set of tools able to generate vector tiles on the fly +from large PostgreSQL databases, and serve tiles from PMTiles and MBTiles files. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). -### Features +## Features -* Serve vector tiles from PostGIS, PMTile, and MBTile sources -* [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources +* Serve [vector tiles](https://github.com/mapbox/vector-tile-spec) from + * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions + * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP + * [MBTile](https://github.com/mapbox/mbtiles-spec) files +* [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources into one * Generate [sprites](https://maplibre.org/martin/sources-sprites.html) and [font glyphs](https://maplibre.org/martin/sources-fonts.html) -* Generate tiles in bulk from any Martin-supported sources into an `.mbtiles` file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool -* Examine, copy, validate, compare, and apply diffs between `.mbtiles` files with [mbtiles](https://maplibre.org/martin/tools.html#mbtiles) tool +* Generate tiles in bulk from any Martin-supported sources into an MBTiles file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool +* Examine, copy, validate, compare, and apply diffs between MBTiles files with [mbtiles](https://maplibre.org/martin/tools.html#mbtiles) tool -### Documentation +## Documentation * [Quick Start](https://maplibre.org/martin/quick-start.html) * [Installation](https://maplibre.org/martin/installation.html) From c49648ca18e98ff1ffd860502659777aadbd33b8 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 12:27:47 -0400 Subject: [PATCH 121/164] add application_name to PG connection (#1325) --- martin/src/pg/tls.rs | 6 +++++- martin/src/srv/server.rs | 2 +- martin/src/srv/tiles.rs | 4 ++-- martin/src/srv/tiles_info.rs | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/martin/src/pg/tls.rs b/martin/src/pg/tls.rs index f397393ba..894373c06 100644 --- a/martin/src/pg/tls.rs +++ b/martin/src/pg/tls.rs @@ -50,10 +50,14 @@ pub fn parse_conn_str(conn_str: &str) -> PgResult<(Config, SslModeOverride)> { } else { Config::from_str(conn_str) }; - let pg_cfg = pg_cfg.map_err(|e| BadConnectionString(e, conn_str.to_string()))?; + let mut pg_cfg = pg_cfg.map_err(|e| BadConnectionString(e, conn_str.to_string()))?; if let SslModeOverride::Unmodified(_) = mode { mode = SslModeOverride::Unmodified(pg_cfg.get_ssl_mode()); } + let crate_ver = env!("CARGO_PKG_VERSION"); + if pg_cfg.get_application_name().is_none() { + pg_cfg.application_name(&format!("Martin v{crate_ver} - pid={}", std::process::id())); + } Ok((pg_cfg, mode)) } diff --git a/martin/src/srv/server.rs b/martin/src/srv/server.rs index c187662e7..80f11bf24 100755 --- a/martin/src/srv/server.rs +++ b/martin/src/srv/server.rs @@ -113,7 +113,7 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server let listen_addresses = config .listen_addresses .clone() - .unwrap_or_else(|| LISTEN_ADDRESSES_DEFAULT.to_owned()); + .unwrap_or_else(|| LISTEN_ADDRESSES_DEFAULT.to_string()); let factory = move || { let cors_middleware = Cors::default() diff --git a/martin/src/srv/tiles.rs b/martin/src/srv/tiles.rs index a90c2c53f..d79cdc467 100755 --- a/martin/src/srv/tiles.rs +++ b/martin/src/srv/tiles.rs @@ -133,9 +133,9 @@ impl<'a> DynTileSource<'a> { CacheValue::Tile, s.get_tile(xyz, self.query_obj.as_ref()), { - let id = s.get_id().to_owned(); + let id = s.get_id().to_string(); if let Some(query_str) = self.query_str { - CacheKey::TileWithQuery(id, xyz, query_str.to_owned()) + CacheKey::TileWithQuery(id, xyz, query_str.to_string()) } else { CacheKey::Tile(id, xyz) } diff --git a/martin/src/srv/tiles_info.rs b/martin/src/srv/tiles_info.rs index 049a27c44..a93313808 100755 --- a/martin/src/srv/tiles_info.rs +++ b/martin/src/srv/tiles_info.rs @@ -38,7 +38,7 @@ async fn get_source_info( .get("x-rewrite-url") .and_then(|v| v.to_str().ok()) .and_then(|v| v.parse::().ok()) - .map_or_else(|| req.path().to_owned(), |v| v.path().to_owned()) + .map_or_else(|| req.path().to_string(), |v| v.path().to_string()) }; let query_string = req.query_string(); From bb8db5dfcc0d1b8c51875469d2f28004e8121d92 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 26 May 2024 12:33:22 -0400 Subject: [PATCH 122/164] format README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 78d788682..f984a79c1 100755 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ from large PostgreSQL databases, and serve tiles from PMTiles and MBTiles files. ## Features * Serve [vector tiles](https://github.com/mapbox/vector-tile-spec) from - * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions - * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP - * [MBTile](https://github.com/mapbox/mbtiles-spec) files + * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions + * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP + * [MBTile](https://github.com/mapbox/mbtiles-spec) files * [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources into one * Generate [sprites](https://maplibre.org/martin/sources-sprites.html) and [font glyphs](https://maplibre.org/martin/sources-fonts.html) * Generate tiles in bulk from any Martin-supported sources into an MBTiles file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool From 73909f2e201824d730aa088e7e96820f6e951f0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 02:16:08 +0000 Subject: [PATCH 123/164] chore(deps): Bump serde from 1.0.202 to 1.0.203 (#1354) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.202 to 1.0.203.
Release notes

Sourced from serde's releases.

v1.0.203

  • Documentation improvements (#2747)
Commits
  • d5bc546 Release 1.0.203
  • 45ae217 Merge pull request #2747 from dtolnay/variadic
  • b7b97dd Unindent implementation inside tuple_impl_body macro
  • 5d3c563 Document tuple impls as fake variadic
  • 3761854 Merge pull request #2745 from dtolnay/docsrs
  • a8f1484 Rely on docs.rs to define --cfg=docsrs by default
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.202&new-version=1.0.203)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37dfa0fac..adee409be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3719,18 +3719,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", From e4228fb77c644d4d24f36a3af1748440840c8571 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 28 May 2024 22:13:51 -0400 Subject: [PATCH 124/164] Fix preferred encoding computation (#1355) * Decides which encoding to use depending on both `Accept-Encode` and the preferred encoding (chooses the preferred one in case brotli and gzip have the same q value) * Uses `gzip` by default This will fix #1315 --- martin/src/srv/tiles.rs | 69 ++++++++++++++++++++++++++-------- martin/tests/mb_server_test.rs | 10 ++--- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/martin/src/srv/tiles.rs b/martin/src/srv/tiles.rs index d79cdc467..fe592180a 100755 --- a/martin/src/srv/tiles.rs +++ b/martin/src/srv/tiles.rs @@ -1,5 +1,6 @@ +use actix_http::header::Quality; use actix_http::ContentEncoding; -use actix_web::error::{ErrorBadRequest, ErrorNotFound}; +use actix_web::error::{ErrorBadRequest, ErrorNotAcceptable, ErrorNotFound}; use actix_web::http::header::{ AcceptEncoding, Encoding as HeaderEnc, Preference, CONTENT_ENCODING, }; @@ -21,13 +22,7 @@ use crate::utils::{ }; use crate::{Tile, TileCoord, TileData}; -static PREFER_BROTLI_ENC: &[HeaderEnc] = &[ - HeaderEnc::brotli(), - HeaderEnc::gzip(), - HeaderEnc::identity(), -]; - -static PREFER_GZIP_ENC: &[HeaderEnc] = &[ +static SUPPORTED_ENC: &[HeaderEnc] = &[ HeaderEnc::gzip(), HeaderEnc::brotli(), HeaderEnc::identity(), @@ -180,6 +175,49 @@ impl<'a> DynTileSource<'a> { self.recompress(data) } + /// Decide which encoding to use for the uncompressed tile data, based on the client's Accept-Encoding header + fn decide_encoding(&self, accept_enc: &AcceptEncoding) -> ActixResult> { + let mut q_gzip = None; + let mut q_brotli = None; + for enc in accept_enc.iter() { + if let Preference::Specific(HeaderEnc::Known(e)) = enc.item { + match e { + ContentEncoding::Gzip => q_gzip = Some(enc.quality), + ContentEncoding::Brotli => q_brotli = Some(enc.quality), + _ => {} + } + } else if let Preference::Any = enc.item { + q_gzip.get_or_insert(enc.quality); + q_brotli.get_or_insert(enc.quality); + } + } + Ok(match (q_gzip, q_brotli) { + (Some(q_gzip), Some(q_brotli)) if q_gzip == q_brotli => { + if q_gzip > Quality::ZERO { + Some(self.get_preferred_enc()) + } else { + None + } + } + (Some(q_gzip), Some(q_brotli)) if q_brotli > q_gzip => Some(ContentEncoding::Brotli), + (Some(_), Some(_)) => Some(ContentEncoding::Gzip), + _ => { + if let Some(HeaderEnc::Known(enc)) = accept_enc.negotiate(SUPPORTED_ENC.iter()) { + Some(enc) + } else { + return Err(ErrorNotAcceptable("No supported encoding found")); + } + } + }) + } + + fn get_preferred_enc(&self) -> ContentEncoding { + match self.preferred_enc { + None | Some(PreferredEncoding::Gzip) => ContentEncoding::Gzip, + Some(PreferredEncoding::Brotli) => ContentEncoding::Brotli, + } + } + fn recompress(&self, tile: TileData) -> ActixResult { let mut tile = Tile::new(tile, self.info); if let Some(accept_enc) = &self.accept_enc { @@ -198,18 +236,12 @@ impl<'a> DynTileSource<'a> { } if tile.info.encoding == Encoding::Uncompressed { - let ordered_encodings = match self.preferred_enc { - Some(PreferredEncoding::Gzip) | None => PREFER_GZIP_ENC, - Some(PreferredEncoding::Brotli) => PREFER_BROTLI_ENC, - }; - - // only apply compression if the content supports it - if let Some(HeaderEnc::Known(enc)) = accept_enc.negotiate(ordered_encodings.iter()) - { + if let Some(enc) = self.decide_encoding(accept_enc)? { // (re-)compress the tile into the preferred encoding tile = encode(tile, enc)?; } } + Ok(tile) } else { // no accepted-encoding header, decode the tile if compressed @@ -270,6 +302,11 @@ mod tests { use super::*; use crate::srv::server::tests::TestSource; + #[actix_rt::test] + async fn test_deleteme() { + test_enc_preference(&["gzip", "deflate", "br", "zstd"], None, Encoding::Gzip).await; + } + #[rstest] #[trace] #[case(&["gzip", "deflate", "br", "zstd"], None, Encoding::Gzip)] diff --git a/martin/tests/mb_server_test.rs b/martin/tests/mb_server_test.rs index 9af72bc9a..95bb70746 100644 --- a/martin/tests/mb_server_test.rs +++ b/martin/tests/mb_server_test.rs @@ -3,8 +3,8 @@ use actix_web::test::{call_service, read_body, read_body_json, TestRequest}; use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; -use martin::decode_gzip; use martin::srv::SrvConfig; +use martin::{decode_brotli, decode_gzip}; use tilejson::TileJSON; pub mod utils; @@ -211,7 +211,7 @@ async fn mbt_get_mvt_brotli() { assert_eq!(response.headers().get(CONTENT_ENCODING).unwrap(), "br"); let body = read_body(response).await; assert_eq!(body.len(), 871); // this number could change if compression gets more optimized - let body = martin::decode_brotli(&body).unwrap(); + let body = decode_brotli(&body).unwrap(); assert_eq!(body.len(), 1828); } @@ -267,10 +267,10 @@ async fn mbt_get_raw_mvt_gzip_br() { response.headers().get(CONTENT_TYPE).unwrap(), "application/x-protobuf" ); - assert_eq!(response.headers().get(CONTENT_ENCODING).unwrap(), "br"); + assert_eq!(response.headers().get(CONTENT_ENCODING).unwrap(), "gzip"); let body = read_body(response).await; - assert_eq!(body.len(), 871); // this number could change if compression gets more optimized - let body = martin::decode_brotli(&body).unwrap(); + assert_eq!(body.len(), 1107); // this number could change if compression gets more optimized + let body = decode_gzip(&body).unwrap(); assert_eq!(body.len(), 1828); } From f3bc6b7aeb5ef52dc87512116b429d732c27befb Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 29 May 2024 12:19:32 -0400 Subject: [PATCH 125/164] Use actions/upload-artifact@v4 --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 444a6f8dc..a01da0d09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: done - name: Save build artifacts to build-${{ matrix.target }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cross-build path: target_releases/* @@ -287,7 +287,7 @@ jobs: mv target/${{ matrix.target }}/release/martin-cp${{ matrix.ext }} target_releases/ mv target/${{ matrix.target }}/release/mbtiles${{ matrix.ext }} target_releases/ - name: Save build artifacts to build-${{ matrix.target }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-${{ matrix.target }} path: target_releases/* @@ -383,7 +383,7 @@ jobs: DATABASE_URL: ${{ steps.pg.outputs.connection-uri }} - name: Save test output (on error) if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: failed-test-output-${{ runner.os }} path: | @@ -517,7 +517,7 @@ jobs: DATABASE_URL: postgres://${{ env.PGUSER }}:${{ env.PGUSER }}@${{ env.PGHOST }}:${{ job.services.postgres.ports[5432] }}/${{ env.PGDATABASE }}?sslmode=${{ matrix.sslmode }} - name: Save test output (on error) if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output path: | @@ -631,7 +631,7 @@ jobs: EOF - name: Save Homebrew Config - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: homebrew-config path: target/homebrew_config.yaml From d8defffddaefe0d0878ff16dc4b983d09893fa99 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 29 May 2024 12:40:35 -0400 Subject: [PATCH 126/164] Use actions/download-artifact@v4 --- .github/workflows/ci.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a01da0d09..2989b7e90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -300,7 +300,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - name: Download build artifact cross-build - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: cross-build - run: tests/test-aws-lambda.sh @@ -345,7 +345,7 @@ jobs: env: PGSERVICE: ${{ steps.pg.outputs.service-name }} - name: Download build artifact build-${{ matrix.target }} - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-${{ matrix.target }} path: target/ @@ -366,7 +366,7 @@ jobs: run: diff --brief --recursive --new-file tests/output tests/expected - name: Download Debian package (Linux) if: matrix.target == 'x86_64-unknown-linux-gnu' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-debian-x86_64 path: target/ @@ -466,7 +466,7 @@ jobs: docker cp ${{ job.services.postgres.id }}:/etc/ssl/certs/ssl-cert-snakeoil.pem target/certs/server.crt docker cp ${{ job.services.postgres.id }}:/etc/ssl/private/ssl-cert-snakeoil.key target/certs/server.key - name: Download build artifact build-x86_64-unknown-linux-gnu - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-x86_64-unknown-linux-gnu path: target_releases/ @@ -485,7 +485,7 @@ jobs: env: DATABASE_URL: postgres://${{ env.PGUSER }}:${{ env.PGUSER }}@${{ env.PGHOST }}:${{ job.services.postgres.ports[5432] }}/${{ env.PGDATABASE }}?sslmode=${{ matrix.sslmode }} - name: Download Debian package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-debian-x86_64 path: target_releases/ @@ -533,34 +533,34 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - name: Download build artifact build-aarch64-apple-darwin - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-aarch64-apple-darwin path: target/aarch64-apple-darwin - name: Download build artifact build-x86_64-apple-darwin - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-x86_64-apple-darwin path: target/x86_64-apple-darwin - name: Download build artifact build-x86_64-unknown-linux-gnu - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-x86_64-unknown-linux-gnu path: target/x86_64-unknown-linux-gnu - name: Download cross-build artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: cross-build path: target/cross - name: Download build artifact build-x86_64-pc-windows-msvc - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-x86_64-pc-windows-msvc path: target/x86_64-pc-windows-msvc - name: Download build artifact build-debian-x86_64 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-debian-x86_64 path: target/debian-x86_64 From 6320e0fff3ad7e1b262cd7115353c4671b47f0b1 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 30 May 2024 14:28:34 -0400 Subject: [PATCH 127/164] Add `agg_tiles_hash_before_apply`, warnings, and validate on patch (#1266) Implement #1244 --- mbtiles/src/bin/mbtiles.rs | 17 +- mbtiles/src/copier.rs | 248 ++++++++++++------ mbtiles/src/errors.rs | 20 +- mbtiles/src/lib.rs | 2 +- mbtiles/src/mbtiles.rs | 12 +- mbtiles/src/patcher.rs | 54 +++- mbtiles/src/validation.rs | 93 ++++++- mbtiles/tests/copy.rs | 27 +- .../snapshots/copy__databases@flat__dif.snap | 1 + .../copy__databases@flat__dif_empty.snap | 1 + .../snapshots/copy__databases@hash__dif.snap | 1 + .../copy__databases@hash__dif_empty.snap | 1 + .../snapshots/copy__databases@norm__dif.snap | 1 + .../copy__databases@norm__dif_empty.snap | 1 + tests/expected/mbtiles/meta-all.txt | 1 + tests/fixtures/mbtiles/world_cities.mbtiles | Bin 49152 -> 49152 bytes .../mbtiles/world_cities_modified.mbtiles | Bin 49152 -> 49152 bytes 17 files changed, 361 insertions(+), 119 deletions(-) diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index 7bf406851..26992c236 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -66,6 +66,9 @@ enum Commands { base_file: PathBuf, /// Diff file patch_file: PathBuf, + /// Force patching operation, ignoring some warnings that otherwise would prevent the operation. Use with caution. + #[arg(short, long)] + force: bool, }, /// Update metadata to match the content of the file #[command(name = "meta-update", alias = "update-meta")] @@ -156,6 +159,12 @@ pub struct SharedCopyOpts { /// Skip generating a global hash for mbtiles validation. By default, `mbtiles` will compute `agg_tiles_hash` metadata value. #[arg(long)] skip_agg_tiles_hash: bool, + /// Force copy operation, ignoring some warnings that otherwise would prevent the operation. Use with caution. + #[arg(short, long)] + force: bool, + /// Perform agg_hash validation on the original and destination files. + #[arg(long)] + validate: bool, } impl SharedCopyOpts { @@ -181,6 +190,8 @@ impl SharedCopyOpts { zoom_levels: self.zoom_levels, bbox: self.bbox, skip_agg_tiles_hash: self.skip_agg_tiles_hash, + force: self.force, + validate: self.validate, // Constants dst_type: None, // Taken from dst_type_cli } @@ -233,8 +244,9 @@ async fn main_int() -> anyhow::Result<()> { Commands::ApplyPatch { base_file, patch_file, + force, } => { - apply_patch(base_file, patch_file).await?; + apply_patch(base_file, patch_file, force).await?; } Commands::UpdateMetadata { file, update_zoom } => { let mbt = Mbtiles::new(file.as_path())?; @@ -258,7 +270,7 @@ async fn main_int() -> anyhow::Result<()> { } }); let mbt = Mbtiles::new(file.as_path())?; - mbt.validate(integrity_check, agg_hash).await?; + mbt.open_and_validate(integrity_check, agg_hash).await?; } Commands::Summary { file } => { let mbt = Mbtiles::new(file.as_path())?; @@ -597,6 +609,7 @@ mod tests { command: ApplyPatch { base_file: PathBuf::from("src_file"), patch_file: PathBuf::from("diff_file"), + force: false, } } ); diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index c152205b4..a550b8460 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -3,21 +3,24 @@ use std::path::PathBuf; use enum_display::EnumDisplay; use itertools::Itertools as _; -use log::{debug, info, trace}; +use log::{debug, info, trace, warn}; use martin_tile_utils::{bbox_to_xyz, MAX_ZOOM}; use serde::{Deserialize, Serialize}; use sqlite_hashes::rusqlite::Connection; -use sqlx::{query, Executor as _, Row, SqliteConnection}; +use sqlx::{query, Connection as _, Executor as _, Row, SqliteConnection}; use tilejson::Bounds; use crate::errors::MbtResult; +use crate::mbtiles::PatchFileInfo; use crate::queries::{ create_tiles_with_hash_view, detach_db, init_mbtiles_schema, is_empty_database, }; +use crate::AggHashType::Verify; +use crate::IntegrityCheckType::Quick; use crate::MbtType::{Flat, FlatWithHash, Normalized}; use crate::{ invert_y_value, reset_db_settings, CopyType, MbtError, MbtType, MbtTypeCli, Mbtiles, - AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, + AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumDisplay)] @@ -68,12 +71,16 @@ pub struct MbtilesCopier { pub apply_patch: Option, /// Skip generating a global hash for mbtiles validation. By default, `mbtiles` will compute `agg_tiles_hash` metadata value. pub skip_agg_tiles_hash: bool, + /// Ignore some warnings and continue with the copying operation + pub force: bool, + /// Perform `agg_hash` validation on the original and destination files. + pub validate: bool, } #[derive(Clone, Debug)] struct MbtileCopierInt { - src_mbtiles: Mbtiles, - dst_mbtiles: Mbtiles, + src_mbt: Mbtiles, + dst_mbt: Mbtiles, options: MbtilesCopier, } @@ -114,23 +121,30 @@ impl MbtileCopierInt { } Ok(MbtileCopierInt { - src_mbtiles: Mbtiles::new(&options.src_file)?, - dst_mbtiles: Mbtiles::new(&options.dst_file)?, + src_mbt: Mbtiles::new(&options.src_file)?, + dst_mbt: Mbtiles::new(&options.dst_file)?, options, }) } pub async fn run(self) -> MbtResult { - if self.options.diff_with_file.is_none() && self.options.apply_patch.is_none() { - self.run_simple().await + if let Some(diff_file) = &self.options.diff_with_file { + let mbt = Mbtiles::new(diff_file)?; + self.run_with_diff(mbt).await + } else if let Some(patch_file) = &self.options.apply_patch { + let mbt = Mbtiles::new(patch_file)?; + self.run_with_patch(mbt).await } else { - self.run_with_diff_or_patch().await + self.run_simple().await } } - pub async fn run_simple(self) -> MbtResult { - let src_type = self.src_mbtiles.open_and_detect_type().await?; - let mut conn = self.dst_mbtiles.open_or_new().await?; + async fn run_simple(self) -> MbtResult { + let mut conn = self.src_mbt.open_readonly().await?; + let src_type = self.src_mbt.detect_type(&mut conn).await?; + conn.close().await?; + + conn = self.dst_mbt.open_or_new().await?; let is_empty_db = is_empty_database(&mut conn).await?; let on_duplicate = if let Some(on_duplicate) = self.options.on_duplicate { @@ -141,24 +155,24 @@ impl MbtileCopierInt { return Err(MbtError::DestinationFileExists(self.options.dst_file)); }; - self.src_mbtiles.attach_to(&mut conn, "sourceDb").await?; + self.src_mbt.attach_to(&mut conn, "sourceDb").await?; let dst_type = if is_empty_db { self.options.dst_type().unwrap_or(src_type) } else { - self.validate_dst_type(self.dst_mbtiles.detect_type(&mut conn).await?)? + self.validate_dst_type(self.dst_mbt.detect_type(&mut conn).await?)? }; info!( "Copying {src_mbt} ({src_type}) {what}to a {is_new} file {dst_mbt} ({dst_type})", - src_mbt = self.src_mbtiles, + src_mbt = self.src_mbt, what = self.copy_text(), is_new = if is_empty_db { "new" } else { "existing" }, - dst_mbt = self.dst_mbtiles, + dst_mbt = self.dst_mbt, ); if is_empty_db { - self.init_new_schema(&mut conn, src_type, dst_type).await?; + self.init_schema(&mut conn, src_type, dst_type).await?; } self.copy_with_rusqlite( @@ -166,12 +180,11 @@ impl MbtileCopierInt { on_duplicate, dst_type, get_select_from(src_type, dst_type), - false, ) .await?; if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { - self.dst_mbtiles.update_agg_tiles_hash(&mut conn).await?; + self.dst_mbt.update_agg_tiles_hash(&mut conn).await?; } detach_db(&mut conn, "sourceDb").await?; @@ -179,62 +192,149 @@ impl MbtileCopierInt { Ok(conn) } - pub async fn run_with_diff_or_patch(self) -> MbtResult { - let ((Some(dif_file), None) | (None, Some(dif_file))) = - (&self.options.diff_with_file, &self.options.apply_patch) - else { - unreachable!() - }; - let dif_mbt = Mbtiles::new(dif_file)?; - let dif_type = dif_mbt.open_and_detect_type().await?; - let is_creating_diff = self.options.diff_with_file.is_some(); + /// Compare two files, and write their difference to the diff file + async fn run_with_diff(self, dif_mbt: Mbtiles) -> MbtResult { + let mut dif_conn = dif_mbt.open_readonly().await?; + let dif_info = dif_mbt.examine_diff(&mut dif_conn).await?; + dif_mbt.assert_hashes(&dif_info, self.options.force)?; + dif_conn.close().await?; - let src_type = self.src_mbtiles.open_and_detect_type().await?; + let src_info = self.validate_src_file().await?; - let mut conn = self.dst_mbtiles.open_or_new().await?; + let mut conn = self.dst_mbt.open_or_new().await?; if !is_empty_database(&mut conn).await? { return Err(MbtError::NonEmptyTargetFile(self.options.dst_file)); } - self.src_mbtiles.attach_to(&mut conn, "sourceDb").await?; + self.src_mbt.attach_to(&mut conn, "sourceDb").await?; dif_mbt.attach_to(&mut conn, "diffDb").await?; - let what = self.copy_text(); - let src_path = &self.src_mbtiles.filepath(); - let dst_path = &self.dst_mbtiles.filepath(); - let dif_path = dif_mbt.filepath(); - let dst_type = self.options.dst_type().unwrap_or(src_type); - if is_creating_diff { - info!("Comparing {src_path} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_path} ({dst_type})"); - } else { - info!("Applying patch from {dif_path} ({dif_type}) to {src_path} ({src_type}) {what}into a new file {dst_path} ({dst_type})"); + let dst_type = self.options.dst_type().unwrap_or(src_info.mbt_type); + info!( + "Comparing {src_mbt} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_path} ({dst_type})", + src_mbt = self.src_mbt, + src_type = src_info.mbt_type, + dif_path = dif_mbt.filepath(), + dif_type = dif_info.mbt_type, + what = self.copy_text(), + dst_path = self.dst_mbt.filepath() + ); + + self.init_schema(&mut conn, src_info.mbt_type, dst_type) + .await?; + self.copy_with_rusqlite( + &mut conn, + CopyDuplicateMode::Override, + dst_type, + &get_select_from_with_diff(dif_info.mbt_type, dst_type), + ) + .await?; + + if let Some(hash) = src_info.agg_tiles_hash { + self.dst_mbt + .set_metadata_value(&mut conn, AGG_TILES_HASH_BEFORE_APPLY, &hash) + .await?; + } + if let Some(hash) = dif_info.agg_tiles_hash { + self.dst_mbt + .set_metadata_value(&mut conn, AGG_TILES_HASH_AFTER_APPLY, &hash) + .await?; + }; + + // TODO: perhaps disable all except --copy all when using with diffs, or else is not making much sense + if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { + self.dst_mbt.update_agg_tiles_hash(&mut conn).await?; } - self.init_new_schema(&mut conn, src_type, dst_type).await?; + detach_db(&mut conn, "diffDb").await?; + detach_db(&mut conn, "sourceDb").await?; + self.validate(&self.dst_mbt, &mut conn).await?; + + Ok(conn) + } + + /// Apply a patch file to the source file and write the result to the destination file + async fn run_with_patch(self, dif_mbt: Mbtiles) -> MbtResult { + let mut dif_conn = dif_mbt.open_readonly().await?; + let dif_info = dif_mbt.examine_diff(&mut dif_conn).await?; + self.validate(&dif_mbt, &mut dif_conn).await?; + dif_mbt.validate_diff_info(&dif_info, self.options.force)?; + dif_conn.close().await?; + + let src_type = self.validate_src_file().await?.mbt_type; + let mut conn = self.dst_mbt.open_or_new().await?; + if !is_empty_database(&mut conn).await? { + return Err(MbtError::NonEmptyTargetFile(self.options.dst_file)); + } + + self.src_mbt.attach_to(&mut conn, "sourceDb").await?; + dif_mbt.attach_to(&mut conn, "diffDb").await?; + + let dst_type = self.options.dst_type().unwrap_or(src_type); + info!("Applying patch from {dif_path} ({dif_type}) to {src_mbt} ({src_type}) {what}into a new file {dst_path} ({dst_type})", + dif_path = dif_mbt.filepath(), + dif_type = dif_info.mbt_type, + src_mbt = self.src_mbt, + what = self.copy_text(), + dst_path = self.dst_mbt.filepath()); + + self.init_schema(&mut conn, src_type, dst_type).await?; self.copy_with_rusqlite( &mut conn, CopyDuplicateMode::Override, dst_type, - &(if is_creating_diff { - get_select_from_with_diff(dif_type, dst_type) - } else { - get_select_from_apply_patch(src_type, dif_type, dst_type) - }), - true, + &get_select_from_apply_patch(src_type, dif_info.mbt_type, dst_type), ) .await?; + // TODO: perhaps disable all except --copy all when using with diffs, or else is not making much sense if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { - self.dst_mbtiles.update_agg_tiles_hash(&mut conn).await?; + self.dst_mbt.update_agg_tiles_hash(&mut conn).await?; + + let new_hash = self.dst_mbt.get_agg_tiles_hash(&mut conn).await?; + match (dif_info.agg_tiles_hash_after_apply, new_hash) { + (Some(expected), Some(actual)) if expected != actual => { + let err = MbtError::AggHashMismatchAfterApply( + dif_mbt.filepath().to_string(), + expected, + self.dst_mbt.filepath().to_string(), + actual, + ); + if !self.options.force { + return Err(err); + } + warn!("{err}"); + } + _ => {} + } } detach_db(&mut conn, "diffDb").await?; detach_db(&mut conn, "sourceDb").await?; + self.validate(&self.dst_mbt, &mut conn).await?; + Ok(conn) } + async fn validate(&self, mbt: &Mbtiles, conn: &mut SqliteConnection) -> MbtResult<()> { + if self.options.validate { + mbt.validate(conn, Quick, Verify).await?; + } + Ok(()) + } + + async fn validate_src_file(&self) -> MbtResult { + let mut src_conn = self.src_mbt.open_readonly().await?; + let src_info = self.src_mbt.examine_diff(&mut src_conn).await?; + self.validate(&self.src_mbt, &mut src_conn).await?; + self.src_mbt.assert_hashes(&src_info, self.options.force)?; + src_conn.close().await?; + + Ok(src_info) + } + fn copy_text(&self) -> &str { match self.options.copy { CopyType::All => "", @@ -249,7 +349,6 @@ impl MbtileCopierInt { on_duplicate: CopyDuplicateMode, dst_type: MbtType, select_from: &str, - is_diff: bool, ) -> Result<(), MbtError> { // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn // Make sure not to execute any other queries while the handle is locked @@ -266,7 +365,7 @@ impl MbtileCopierInt { } if self.options.copy.copy_metadata() { - self.copy_metadata(&rusqlite_conn, is_diff, on_duplicate) + self.copy_metadata(&rusqlite_conn, on_duplicate) } else { debug!("Skipping copying metadata"); Ok(()) @@ -276,38 +375,35 @@ impl MbtileCopierInt { fn copy_metadata( &self, rusqlite_conn: &Connection, - is_diff: bool, on_duplicate: CopyDuplicateMode, ) -> Result<(), MbtError> { let on_dupl = on_duplicate.to_sql(); let sql; - if is_diff { - // Insert all rows from diffDb.metadata if they do not exist or are different in sourceDb.metadata. - // Also insert all names from sourceDb.metadata that do not exist in diffDb.metadata, with their value set to NULL. - // Rename agg_tiles_hash to agg_tiles_hash_after_apply because agg_tiles_hash will be auto-added later - if self.options.diff_with_file.is_some() { - // Include agg_tiles_hash value even if it is the same because we will still need it when applying the diff - sql = format!( - " + + // Insert all rows from diffDb.metadata if they do not exist or are different in sourceDb.metadata. + // Also insert all names from sourceDb.metadata that do not exist in diffDb.metadata, with their value set to NULL. + // Skip agg_tiles_hash because that requires special handling + if self.options.diff_with_file.is_some() { + // Include agg_tiles_hash value even if it is the same because we will still need it when applying the diff + sql = format!( + " INSERT {on_dupl} INTO metadata (name, value) - SELECT IIF(name = '{AGG_TILES_HASH}','{AGG_TILES_HASH_AFTER_APPLY}', name) as name - , value + SELECT name, value FROM ( SELECT COALESCE(difMD.name, srcMD.name) as name , difMD.value as value FROM sourceDb.metadata AS srcMD FULL JOIN diffDb.metadata AS difMD ON srcMD.name = difMD.name - WHERE srcMD.value != difMD.value OR srcMD.value ISNULL OR difMD.value ISNULL OR srcMD.name = '{AGG_TILES_HASH}' + WHERE srcMD.value != difMD.value OR srcMD.value ISNULL OR difMD.value ISNULL ) joinedMD - WHERE name != '{AGG_TILES_HASH_AFTER_APPLY}'" - ); - debug!("Copying metadata, taking into account diff file with {sql}"); - } else { - sql = format!( - " + WHERE name NOT IN ('{AGG_TILES_HASH}', '{AGG_TILES_HASH_BEFORE_APPLY}', '{AGG_TILES_HASH_AFTER_APPLY}')" + ); + debug!("Copying metadata, taking into account diff file with {sql}"); + } else if self.options.apply_patch.is_some() { + sql = format!( + " INSERT {on_dupl} INTO metadata (name, value) - SELECT IIF(name = '{AGG_TILES_HASH_AFTER_APPLY}','{AGG_TILES_HASH}', name) as name - , value + SELECT name, value FROM ( SELECT COALESCE(srcMD.name, difMD.name) as name , COALESCE(difMD.value, srcMD.value) as value @@ -315,10 +411,9 @@ impl MbtileCopierInt { ON srcMD.name = difMD.name WHERE difMD.name ISNULL OR difMD.value NOTNULL ) joinedMD - WHERE name != '{AGG_TILES_HASH}'" - ); - debug!("Copying metadata, and applying the diff file with {sql}"); - } + WHERE name NOT IN ('{AGG_TILES_HASH}', '{AGG_TILES_HASH_BEFORE_APPLY}', '{AGG_TILES_HASH_AFTER_APPLY}')" + ); + debug!("Copying metadata, and applying the diff file with {sql}"); } else { sql = format!( " @@ -404,7 +499,7 @@ impl MbtileCopierInt { Ok(dst_type) } - async fn init_new_schema( + async fn init_schema( &self, conn: &mut SqliteConnection, src: MbtType, @@ -826,6 +921,7 @@ mod tests { src_file: src.clone(), dst_file: dst.clone(), diff_with_file: Some(diff_file.clone()), + force: true, ..Default::default() }; let mut dst_conn = opt.run().await?; diff --git a/mbtiles/src/errors.rs b/mbtiles/src/errors.rs index b68137fbd..2f4e60924 100644 --- a/mbtiles/src/errors.rs +++ b/mbtiles/src/errors.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use martin_tile_utils::{TileInfo, MAX_ZOOM}; use sqlite_hashes::rusqlite; -use crate::MbtType; +use crate::{MbtType, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY}; #[derive(thiserror::Error, Debug)] pub enum MbtError { @@ -77,6 +77,24 @@ pub enum MbtError { #[error("Invalid zoom value {0}={1}, expecting an integer between 0..{MAX_ZOOM}")] InvalidZoomValue(&'static str, String), + + #[error("A file {0} does not have an {AGG_TILES_HASH} metadata entry, probably because it was not created by this tool. Use `--force` to ignore this warning, or run this to update hash value: `mbtiles validate --agg-hash update {0}`")] + CannotDiffFileWithoutHash(String), + + #[error("File {0} has {AGG_TILES_HASH_BEFORE_APPLY} or {AGG_TILES_HASH_AFTER_APPLY} metadata entry, indicating it is a patch file which should not be diffed with another file. Use `--force` to ignore this warning.")] + DiffingDiffFile(String), + + #[error("A file {0} does not seem to be a patch diff file because it has no {AGG_TILES_HASH_BEFORE_APPLY} and {AGG_TILES_HASH_AFTER_APPLY} metadata entries. These entries are automatically created when using `mbtiles diff` and `mbitiles copy --diff-with-file`. Use `--force` to ignore this warning.")] + PatchFileHasNoHashes(String), + + #[error("A file {0} does not have {AGG_TILES_HASH_BEFORE_APPLY} metadata, probably because it was created by an older version of the `mbtiles` tool. Use `--force` to ignore this warning, but ensure you are applying the patch to the right file.")] + PatchFileHasNoBeforeHash(String), + + #[error("The {AGG_TILES_HASH_BEFORE_APPLY}='{1}' in patch file {0} does not match {AGG_TILES_HASH}='{3}' in the file {2}")] + AggHashMismatchWithDiff(String, String, String, String), + + #[error("The {AGG_TILES_HASH_AFTER_APPLY}='{1}' in patch file {0} does not match {AGG_TILES_HASH}='{3}' in the file {2} after the patch was applied")] + AggHashMismatchAfterApply(String, String, String, String), } pub type MbtResult = Result; diff --git a/mbtiles/src/lib.rs b/mbtiles/src/lib.rs index 272915f8b..1f54ebb66 100644 --- a/mbtiles/src/lib.rs +++ b/mbtiles/src/lib.rs @@ -32,7 +32,7 @@ pub use update::UpdateZoomType; mod validation; pub use validation::{ calc_agg_tiles_hash, AggHashType, IntegrityCheckType, MbtType, AGG_TILES_HASH, - AGG_TILES_HASH_AFTER_APPLY, + AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY, }; /// `MBTiles` uses a TMS (Tile Map Service) scheme for its tile coordinates (inverted along the Y axis). diff --git a/mbtiles/src/mbtiles.rs b/mbtiles/src/mbtiles.rs index 9808fb194..ebd2e5c2d 100644 --- a/mbtiles/src/mbtiles.rs +++ b/mbtiles/src/mbtiles.rs @@ -42,6 +42,13 @@ impl CopyType { } } +pub struct PatchFileInfo { + pub mbt_type: MbtType, + pub agg_tiles_hash: Option, + pub agg_tiles_hash_before_apply: Option, + pub agg_tiles_hash_after_apply: Option, +} + #[derive(Clone, Debug)] pub struct Mbtiles { filepath: String, @@ -212,11 +219,6 @@ impl Mbtiles { ), } } - - pub async fn open_and_detect_type(&self) -> MbtResult { - let mut conn = self.open_readonly().await?; - self.detect_type(&mut conn).await - } } pub async fn attach_hash_fn(conn: &mut SqliteConnection) -> MbtResult<()> { diff --git a/mbtiles/src/patcher.rs b/mbtiles/src/patcher.rs index 6e983ffec..6650021cf 100644 --- a/mbtiles/src/patcher.rs +++ b/mbtiles/src/patcher.rs @@ -1,25 +1,53 @@ use std::path::PathBuf; -use log::{debug, info}; -use sqlx::query; +use log::{debug, info, warn}; +use sqlx::{query, Connection as _}; use crate::queries::detach_db; use crate::MbtType::{Flat, FlatWithHash, Normalized}; -use crate::{MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY}; +use crate::{ + MbtError, MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, + AGG_TILES_HASH_BEFORE_APPLY, +}; -pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<()> { +pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf, force: bool) -> MbtResult<()> { let base_mbt = Mbtiles::new(base_file)?; let patch_mbt = Mbtiles::new(patch_file)?; - let patch_type = patch_mbt.open_and_detect_type().await?; + + let mut conn = patch_mbt.open_readonly().await?; + let patch_info = patch_mbt.examine_diff(&mut conn).await?; + patch_mbt.validate_diff_info(&patch_info, force)?; + let patch_type = patch_info.mbt_type; + conn.close().await?; let mut conn = base_mbt.open().await?; - let base_type = base_mbt.detect_type(&mut conn).await?; + let base_info = base_mbt.examine_diff(&mut conn).await?; + let base_hash = base_mbt.get_agg_tiles_hash(&mut conn).await?; + base_mbt.assert_hashes(&base_info, force)?; + + match (force, base_hash, patch_info.agg_tiles_hash_before_apply) { + (false, Some(base_hash), Some(expected_hash)) if base_hash != expected_hash => { + return Err(MbtError::AggHashMismatchWithDiff( + patch_mbt.filepath().to_string(), + expected_hash, + base_mbt.filepath().to_string(), + base_hash, + )); + } + (true, Some(base_hash), Some(expected_hash)) if base_hash != expected_hash => { + warn!("Aggregate tiles hash mismatch: Patch file expected {expected_hash} but found {base_hash} in {base_mbt} (force mode)"); + } + _ => {} + } - info!("Applying patch file {patch_mbt} ({patch_type}) to {base_mbt} ({base_type})"); + info!( + "Applying patch file {patch_mbt} ({patch_type}) to {base_mbt} ({base_type})", + base_type = base_info.mbt_type + ); patch_mbt.attach_to(&mut conn, "patchDb").await?; - let select_from = get_select_from(base_type, patch_type); - let (main_table, insert1, insert2) = get_insert_sql(base_type, select_from); + let select_from = get_select_from(base_info.mbt_type, patch_type); + let (main_table, insert1, insert2) = get_insert_sql(base_info.mbt_type, select_from); let sql = format!("{insert1} WHERE tile_data NOTNULL"); query(&sql).execute(&mut conn).await?; @@ -38,7 +66,7 @@ pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<( ); query(&sql).execute(&mut conn).await?; - if base_type.is_normalized() { + if base_info.mbt_type.is_normalized() { debug!("Removing unused tiles from the images table (normalized schema)"); let sql = "DELETE FROM images WHERE tile_id NOT IN (SELECT tile_id FROM map)"; query(sql).execute(&mut conn).await?; @@ -53,7 +81,7 @@ pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf) -> MbtResult<( SELECT IIF(name = '{AGG_TILES_HASH_AFTER_APPLY}', '{AGG_TILES_HASH}', name) as name, value FROM patchDb.metadata - WHERE name NOTNULL AND name != '{AGG_TILES_HASH}';" + WHERE name NOTNULL AND name NOT IN ('{AGG_TILES_HASH}', '{AGG_TILES_HASH_BEFORE_APPLY}');" ); query(&sql).execute(&mut conn).await?; @@ -151,7 +179,7 @@ mod tests { // Apply patch to the src data in in-memory DB let patch_file = PathBuf::from("../tests/fixtures/mbtiles/world_cities_diff.mbtiles"); - apply_patch(src, patch_file).await?; + apply_patch(src, patch_file, true).await?; // Verify the data is the same as the file the patch was generated from Mbtiles::new("../tests/fixtures/mbtiles/world_cities_modified.mbtiles")? @@ -183,7 +211,7 @@ mod tests { // Apply patch to the src data in in-memory DB let patch_file = PathBuf::from("../tests/fixtures/mbtiles/geography-class-jpg-diff.mbtiles"); - apply_patch(src, patch_file).await?; + apply_patch(src, patch_file, true).await?; // Verify the data is the same as the file the patch was generated from Mbtiles::new("../tests/fixtures/mbtiles/geography-class-jpg-modified.mbtiles")? diff --git a/mbtiles/src/validation.rs b/mbtiles/src/validation.rs index 1ac919f2c..8db5cac10 100644 --- a/mbtiles/src/validation.rs +++ b/mbtiles/src/validation.rs @@ -7,10 +7,11 @@ use martin_tile_utils::{Format, TileInfo, MAX_ZOOM}; use serde::Serialize; use serde_json::Value; use sqlx::sqlite::SqliteRow; -use sqlx::{query, Row, SqliteExecutor}; +use sqlx::{query, Row, SqliteConnection, SqliteExecutor}; use tilejson::TileJSON; use crate::errors::{MbtError, MbtResult}; +use crate::mbtiles::PatchFileInfo; use crate::queries::{ has_tiles_with_hash, is_flat_tables_type, is_flat_with_hash_tables_type, is_normalized_tables_type, @@ -27,6 +28,9 @@ pub const AGG_TILES_HASH: &str = "agg_tiles_hash"; /// Metadata key for a diff file, describing the eventual [`AGG_TILES_HASH`] value of the resulting tileset once the diff is applied pub const AGG_TILES_HASH_AFTER_APPLY: &str = "agg_tiles_hash_after_apply"; +/// Metadata key for a diff file, describing the expected [`AGG_TILES_HASH`] value of the tileset to which the diff will be applied. +pub const AGG_TILES_HASH_BEFORE_APPLY: &str = "agg_tiles_hash_before_apply"; + #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, EnumDisplay, Serialize)] #[enum_display(case = "Kebab")] pub enum MbtType { @@ -71,7 +75,7 @@ pub enum AggHashType { } impl Mbtiles { - pub async fn validate( + pub async fn open_and_validate( &self, check_type: IntegrityCheckType, agg_hash: AggHashType, @@ -81,12 +85,24 @@ impl Mbtiles { } else { self.open_readonly().await? }; - self.check_integrity(&mut conn, check_type).await?; - self.check_tiles_type_validity(&mut conn).await?; - self.check_each_tile_hash(&mut conn).await?; + self.validate(&mut conn, check_type, agg_hash).await + } + + pub async fn validate( + &self, + conn: &mut T, + check_type: IntegrityCheckType, + agg_hash: AggHashType, + ) -> MbtResult + where + for<'e> &'e mut T: SqliteExecutor<'e>, + { + self.check_integrity(&mut *conn, check_type).await?; + self.check_tiles_type_validity(&mut *conn).await?; + self.check_each_tile_hash(&mut *conn).await?; match agg_hash { - AggHashType::Verify => self.check_agg_tiles_hashes(&mut conn).await, - AggHashType::Update => self.update_agg_tiles_hash(&mut conn).await, + AggHashType::Verify => self.check_agg_tiles_hashes(conn).await, + AggHashType::Update => self.update_agg_tiles_hash(conn).await, AggHashType::Off => Ok(String::new()), } } @@ -453,6 +469,69 @@ LIMIT 1;" info!("All tile hashes are valid for {self}"); Ok(()) } + + pub async fn examine_diff(&self, conn: &mut SqliteConnection) -> MbtResult { + let info = PatchFileInfo { + mbt_type: self.detect_type(&mut *conn).await?, + agg_tiles_hash: self.get_agg_tiles_hash(&mut *conn).await?, + agg_tiles_hash_before_apply: self + .get_metadata_value(&mut *conn, AGG_TILES_HASH_BEFORE_APPLY) + .await?, + agg_tiles_hash_after_apply: self + .get_metadata_value(&mut *conn, AGG_TILES_HASH_AFTER_APPLY) + .await?, + }; + + Ok(info) + } + + pub fn assert_hashes(&self, info: &PatchFileInfo, force: bool) -> MbtResult<()> { + if info.agg_tiles_hash.is_none() { + if !force { + return Err(MbtError::CannotDiffFileWithoutHash( + self.filepath().to_string(), + )); + } + warn!("File {self} has no {AGG_TILES_HASH} metadata field, probably because it was created by an older version of the `mbtiles` tool. Use this command to update the value:\nmbtiles validate --agg-hash update {self}"); + } else if info.agg_tiles_hash_before_apply.is_some() + || info.agg_tiles_hash_after_apply.is_some() + { + if !force { + return Err(MbtError::DiffingDiffFile(self.filepath().to_string())); + } + warn!("File {self} has {AGG_TILES_HASH_BEFORE_APPLY} or {AGG_TILES_HASH_AFTER_APPLY} metadata field, indicating it is a patch file which should not be diffed with another file."); + } + Ok(()) + } + + pub fn validate_diff_info(&self, info: &PatchFileInfo, force: bool) -> MbtResult<()> { + match ( + &info.agg_tiles_hash_before_apply, + &info.agg_tiles_hash_after_apply, + ) { + (Some(before), Some(after)) => { + info!( + "The patch file {self} expects to be applied to a tileset with {AGG_TILES_HASH}={before}, and should result in hash {after} after applying", + ); + } + (None, Some(_)) => { + if !force { + return Err(MbtError::PatchFileHasNoBeforeHash( + self.filepath().to_string(), + )); + } + warn!( + "The patch file {self} has no {AGG_TILES_HASH_BEFORE_APPLY} metadata field, probably because it was created by an older version of the `mbtiles` tool."); + } + _ => { + if !force { + return Err(MbtError::PatchFileHasNoHashes(self.filepath().to_string())); + } + warn!("The patch file {self} has no {AGG_TILES_HASH_AFTER_APPLY} metadata field, probably because it was not properly created by the `mbtiles` tool."); + } + } + Ok(()) + } } /// Compute the hash of the combined tiles in the mbtiles file tiles table/view. diff --git a/mbtiles/tests/copy.rs b/mbtiles/tests/copy.rs index e0525cd31..5d1347b94 100644 --- a/mbtiles/tests/copy.rs +++ b/mbtiles/tests/copy.rs @@ -242,7 +242,7 @@ fn databases() -> Databases { copy!(result.path("empty_no_hash", mbt_typ), path(&empty_mbt)); let dmp = dump(&mut empty_cn).await.unwrap(); assert_dump!(&dmp, "{typ}__empty"); - let hash = empty_mbt.validate(Off, Verify).await.unwrap(); + let hash = empty_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); } @@ -265,7 +265,7 @@ fn databases() -> Databases { copy!(result.path("v1_no_hash", mbt_typ), path(&v1_mbt)); let dmp = dump(&mut v1_cn).await.unwrap(); assert_dump!(&dmp, "{typ}__v1"); - let hash = v1_mbt.validate(Off, Verify).await.unwrap(); + let hash = v1_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"9ED9178D7025276336C783C2B54D6258"); } @@ -276,7 +276,7 @@ fn databases() -> Databases { new_file!(databases, mbt_typ, METADATA_V2, TILES_V2, "{typ}__v2"); let dmp = dump(&mut v2_cn).await.unwrap(); assert_dump!(&dmp, "{typ}__v2"); - let hash = v2_mbt.validate(Off, Verify).await.unwrap(); + let hash = v2_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"3BCDEE3F52407FF1315629298CB99133"); } @@ -291,7 +291,7 @@ fn databases() -> Databases { }; let dmp = dump(&mut dif_cn).await.unwrap(); assert_dump!(&dmp, "{typ}__dif"); - let hash = dif_mbt.validate(Off, Verify).await.unwrap(); + let hash = dif_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"B86122579EDCDD4C51F3910894FCC1A1"); } @@ -300,7 +300,7 @@ fn databases() -> Databases { // ----------------- v1_clone ----------------- let (v1_clone_mbt, v1_clone_cn) = open!(databases, "{typ}__v1-clone"); let dmp = copy_dump!(result.path("v1", mbt_typ), path(&v1_clone_mbt)); - let hash = v1_clone_mbt.validate(Off, Verify).await.unwrap(); + let hash = v1_clone_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"9ED9178D7025276336C783C2B54D6258"); } @@ -322,7 +322,7 @@ fn databases() -> Databases { }; let dmp = dump(&mut dif_empty_cn).await.unwrap(); assert_dump!(&dmp, "{typ}__dif_empty"); - let hash = dif_empty_mbt.validate(Off, Verify).await.unwrap(); + let hash = dif_empty_mbt.open_and_validate(Off, Verify).await.unwrap(); allow_duplicates! { assert_snapshot!(hash, @"D41D8CD98F00B204E9800998ECF8427E"); } @@ -483,8 +483,8 @@ async fn diff_and_patch( eprintln!("TEST: Applying the difference ({b_db} - {a_db} = {dif_db}) to {a_db}, should get {b_db}"); let (clone_mbt, mut clone_cn) = open!(diff_and_patch, "{prefix}__1"); copy!(databases.path(a_db, *dst_type), path(&clone_mbt)); - apply_patch(path(&clone_mbt), path(&dif_mbt)).await?; - let hash = clone_mbt.validate(Off, Verify).await?; + apply_patch(path(&clone_mbt), path(&dif_mbt), false).await?; + let hash = clone_mbt.open_and_validate(Off, Verify).await?; assert_eq!(hash, databases.hash(b_db, *dst_type)); let dmp = dump(&mut clone_cn).await?; pretty_assert_eq!(&dmp, expected_b); @@ -492,8 +492,8 @@ async fn diff_and_patch( eprintln!("TEST: Applying the difference ({b_db} - {a_db} = {dif_db}) to {b_db}, should not modify it"); let (clone_mbt, mut clone_cn) = open!(diff_and_patch, "{prefix}__2"); copy!(databases.path(b_db, *dst_type), path(&clone_mbt)); - apply_patch(path(&clone_mbt), path(&dif_mbt)).await?; - let hash = clone_mbt.validate(Off, Verify).await?; + apply_patch(path(&clone_mbt), path(&dif_mbt), true).await?; + let hash = clone_mbt.open_and_validate(Off, Verify).await?; assert_eq!(hash, databases.hash(b_db, *dst_type)); let dmp = dump(&mut clone_cn).await?; pretty_assert_eq!(&dmp, expected_b); @@ -522,10 +522,9 @@ async fn patch_on_copy( apply_patch => Some(databases.path("dif", dif_type)), dst_type_cli => v2_type, }; - pretty_assert_eq!( - &dump(&mut v2_cn).await?, - databases.dump("v2", v2_type.unwrap_or(v1_type)) - ); + let actual = dump(&mut v2_cn).await?; + let expected = databases.dump("v2", v2_type.unwrap_or(v1_type)); + pretty_assert_eq!(&actual, expected); Ok(()) } diff --git a/mbtiles/tests/snapshots/copy__databases@flat__dif.snap b/mbtiles/tests/snapshots/copy__databases@flat__dif.snap index 36193a4f5..317787984 100644 --- a/mbtiles/tests/snapshots/copy__databases@flat__dif.snap +++ b/mbtiles/tests/snapshots/copy__databases@flat__dif.snap @@ -12,6 +12,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "B86122579EDCDD4C51F3910894FCC1A1" )', '( "agg_tiles_hash_after_apply", "3BCDEE3F52407FF1315629298CB99133" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', '( "md-edit", "value - v2" )', '( "md-new", "value - new" )', '( "md-remove", NULL )', diff --git a/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap index b88309497..e2b5de434 100644 --- a/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@flat__dif_empty.snap @@ -12,6 +12,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', ] [[]] diff --git a/mbtiles/tests/snapshots/copy__databases@hash__dif.snap b/mbtiles/tests/snapshots/copy__databases@hash__dif.snap index ae6e8941c..d9feedca6 100644 --- a/mbtiles/tests/snapshots/copy__databases@hash__dif.snap +++ b/mbtiles/tests/snapshots/copy__databases@hash__dif.snap @@ -12,6 +12,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "B86122579EDCDD4C51F3910894FCC1A1" )', '( "agg_tiles_hash_after_apply", "3BCDEE3F52407FF1315629298CB99133" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', '( "md-edit", "value - v2" )', '( "md-new", "value - new" )', '( "md-remove", NULL )', diff --git a/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap index 7dc8868c9..aedfc8819 100644 --- a/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@hash__dif_empty.snap @@ -12,6 +12,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', ] [[]] diff --git a/mbtiles/tests/snapshots/copy__databases@norm__dif.snap b/mbtiles/tests/snapshots/copy__databases@norm__dif.snap index 3dda51925..0231bb4f6 100644 --- a/mbtiles/tests/snapshots/copy__databases@norm__dif.snap +++ b/mbtiles/tests/snapshots/copy__databases@norm__dif.snap @@ -50,6 +50,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "B86122579EDCDD4C51F3910894FCC1A1" )', '( "agg_tiles_hash_after_apply", "3BCDEE3F52407FF1315629298CB99133" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', '( "md-edit", "value - v2" )', '( "md-new", "value - new" )', '( "md-remove", NULL )', diff --git a/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap index d84884200..e45a492f8 100644 --- a/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap +++ b/mbtiles/tests/snapshots/copy__databases@norm__dif_empty.snap @@ -33,6 +33,7 @@ CREATE TABLE metadata ( values = [ '( "agg_tiles_hash", "D41D8CD98F00B204E9800998ECF8427E" )', '( "agg_tiles_hash_after_apply", "9ED9178D7025276336C783C2B54D6258" )', + '( "agg_tiles_hash_before_apply", "9ED9178D7025276336C783C2B54D6258" )', ] [[]] diff --git a/tests/expected/mbtiles/meta-all.txt b/tests/expected/mbtiles/meta-all.txt index 2949d92f4..42cf8feef 100644 --- a/tests/expected/mbtiles/meta-all.txt +++ b/tests/expected/mbtiles/meta-all.txt @@ -109,4 +109,5 @@ json: count: 68 geometry: Point layer: cities +agg_tiles_hash: 84792BF4EE9AEDDC5B1A60E707011FEE diff --git a/tests/fixtures/mbtiles/world_cities.mbtiles b/tests/fixtures/mbtiles/world_cities.mbtiles index d5fc059555366aaa27317ea8a171ec50701fdabc..92c23a9e95fcbb693466f4f3071e5a18b845526c 100644 GIT binary patch delta 168 zcmZo@U~Xt&o*>Q0Gf~Ewm4`vEXu-ym1^iOnT#Fd^FZ0jmpTytFU%?;FugEXR&&+j| zYthEW7A|8$9%fD7#Psy|lFXdc;`ofj;tUHDb4w#9HxpM^OGj517iUu^Lq{_MS91e% z14BbMSJ%x~rSwImxcLhh_zU>g@$ck+!9R+_Mp|We>B1KYf5T CpB~`= diff --git a/tests/fixtures/mbtiles/world_cities_modified.mbtiles b/tests/fixtures/mbtiles/world_cities_modified.mbtiles index e6d104bf730a9af5db838195f345bae9e6b817e2..85f88c640de135d281edd05e33649fbac8fd91d0 100644 GIT binary patch delta 193 zcmZo@U~Xt&o*>OAGEv5vRfIvWXu-ym1^iOnTwRR(m$|z5C-JxPSMZ1PEAk8SGjm<# zpTDs&hih|}R3r-%1HfFDZ*G&^A0)HWA2ARb3J-$- j53Ucn59kk?4}%ZH56}58Sg6uw@UkgFk(Mq0}l2 From 5c31d2112036a1d3e48ce38831a9bd8eed85a258 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 30 May 2024 14:34:53 -0400 Subject: [PATCH 128/164] Bump deps --- Cargo.lock | 108 ++++++++++++++++++++++++++++++++++------------------- Cargo.toml | 2 +- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adee409be..a759d364b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -357,9 +357,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c90a406b4495d129f00461241616194cb8a032c8d1c53c657f0961d5f8e0498" +checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" dependencies = [ "flate2", "futures-core", @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ "addr2line", "cc", @@ -596,7 +596,7 @@ checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor 4.0.0", + "brotli-decompressor 4.0.1", ] [[package]] @@ -611,9 +611,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6221fe77a248b9117d431ad93761222e1cf8ff282d9d1d5d9f53d6299a1cf76" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -732,9 +732,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "f803f94ecf597339c7a34eed2036ef83f86aaba937f001f7c5b5e251f043f1f9" dependencies = [ "glob", "libc", @@ -1308,9 +1308,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.3.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1384,12 +1384,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "flate2" version = "1.0.30" @@ -1675,9 +1669,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -1934,9 +1928,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -2528,7 +2522,7 @@ dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "event-listener 5.3.0", + "event-listener 5.3.1", "futures-util", "once_cell", "parking_lot", @@ -2680,9 +2674,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", ] @@ -3083,11 +3077,20 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -3487,9 +3490,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" +checksum = "27059f51958c5f8496a6f79511e7c0ac396dd815dc8894e9b6e2efb5779cf6f0" dependencies = [ "futures", "futures-timer", @@ -3499,12 +3502,13 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" +checksum = "e6132d64df104c0b3ea7a6ad7766a43f587bd773a4a9cf4cd59296d426afaf3a" dependencies = [ "cfg-if", "glob", + "proc-macro-crate", "proc-macro2", "quote", "regex", @@ -4223,13 +4227,13 @@ dependencies = [ [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -4603,6 +4607,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -4665,9 +4686,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "1b2cb4fbb9995eeb36ac86fadf24031ccd58f99d6b4b2d7b911db70bddb80d90" [[package]] name = "try-lock" @@ -5194,6 +5215,15 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.52.0" @@ -5272,9 +5302,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 4499a9f0b..0f2ccd9e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ postgres-protocol = "0.6" pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" -rstest = "0.19" +rstest = "0.20" rustls = "0.23.8" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } From a7f0937d9a60e1ad6ee87ff81bdf1bc356d35fbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 02:41:09 +0000 Subject: [PATCH 129/164] chore(deps): Bump sqlite-hashes from 0.7.1 to 0.7.2 (#1361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sqlite-hashes](https://github.com/nyurik/sqlite-hashes) from 0.7.1 to 0.7.2.
Release notes

Sourced from sqlite-hashes's releases.

v0.7.2

What's Changed

Full Changelog: https://github.com/nyurik/sqlite-hashes/compare/v0.7.1...v0.7.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sqlite-hashes&package-manager=cargo&previous-version=0.7.1&new-version=0.7.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a759d364b..24c75be42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4001,9 +4001,9 @@ dependencies = [ [[package]] name = "sqlite-hashes" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4faff0b1f487d94938f61fe78989b8e1e9524cf16a0b63174129c6a427057e2" +checksum = "16e525595f5f7d0b78daecb5d4fbf347d876a1d17d4486e3aba587891bb26333" dependencies = [ "digest", "hex", diff --git a/Cargo.toml b/Cargo.toml index 0f2ccd9e2..f079d2690 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ serde_with = "3" serde_yaml = "0.9" size_format = "1.0.2" spreet = { version = "0.11", default-features = false } -sqlite-hashes = { version = "0.7.1", default-features = false, features = ["md5", "aggregate", "hex"] } +sqlite-hashes = { version = "0.7.2", default-features = false, features = ["md5", "aggregate", "hex"] } sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] } subst = { version = "0.3", features = ["yaml"] } thiserror = "1" From 9c24e3b4fd1b549073f2746f0fc34f39791b9fb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 02:52:36 +0000 Subject: [PATCH 130/164] chore(deps): Bump rustls from 0.23.8 to 0.23.9 (#1360) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.8 to 0.23.9.
Commits
  • e754234 Prepare 0.23.9
  • 590716e Fix unstable fmt job
  • de851b4 unbuffered examples: avoid clippy lint
  • 5faa88c hs.rs: refactor to eliminate conditional allow()
  • 503d42b Tidy away unneeded #[allow()]s
  • 0c85c01 Add issue number for server-side ECH in the roadmap.
  • bacc19c General roadmap updates.
  • 4bd989c handshake_test: reorder items in file
  • 1aba137 handshake_test: clarify cloning tests
  • d202e0d handshake_test: remove get_ function prefices
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustls&package-manager=cargo&previous-version=0.23.8&new-version=0.23.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24c75be42..a98ce2326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2374,7 +2374,7 @@ dependencies = [ "pprof", "regex", "rstest", - "rustls 0.23.8", + "rustls 0.23.9", "rustls-native-certs", "rustls-pemfile", "semver", @@ -3582,9 +3582,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.8" +version = "0.23.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79adb16721f56eb2d843e67676896a61ce7a0fa622dc18d3e372477a029d2740" +checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b" dependencies = [ "aws-lc-rs", "log", @@ -4545,7 +4545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.8", + "rustls 0.23.9", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4569,7 +4569,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.8", + "rustls 0.23.9", "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index f079d2690..30b4b1f7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" rstest = "0.20" -rustls = "0.23.8" +rustls = "0.23.9" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" From 526aa595bef3867c774f528e16dac8bb64671553 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 03:24:42 +0000 Subject: [PATCH 131/164] chore(deps): Bump clap from 4.5.4 to 4.5.6 (#1363) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.4 to 4.5.6.
Release notes

Sourced from clap's releases.

v4.5.6

[4.5.6] - 2024-06-06

Changelog

Sourced from clap's changelog.

[4.5.6] - 2024-06-06

[4.5.5] - 2024-06-06

Fixes

  • Allow exclusive to override required_unless_present, required_unless_present_any, required_unless_present_all
Commits
  • 51de731 chore(ci): Lint clippy::items_after_statements seems too strict
  • 181a2cf chore(ci): Allow prelude wildcard imports
  • 82cf9a6 chore(ci): Reduce noisy lints
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.4&new-version=4.5.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a98ce2326..74f678d45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,9 +743,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" dependencies = [ "clap_builder", "clap_derive", @@ -753,9 +753,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" dependencies = [ "anstream", "anstyle", @@ -765,9 +765,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -2265,7 +2265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] From 1bef526b77356d2d4a3392bbb3737793cdfb9ce7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 03:25:07 +0000 Subject: [PATCH 132/164] chore(deps): Bump regex from 1.10.4 to 1.10.5 (#1366) Bumps [regex](https://github.com/rust-lang/regex) from 1.10.4 to 1.10.5.
Changelog

Sourced from regex's changelog.

1.10.5 (2024-06-09)

This is a new patch release with some minor fixes.

Bug fixes:

Commits
  • 0718fc5 1.10.5
  • 377463b changelog: 1.10.4 and 1.10.5
  • 68c4f0b regex-automata-0.4.7
  • 4757b5f regex-syntax-0.8.4
  • 1430b65 changelog: 1.10.4
  • 1f9f9cc bytes: escape invalid UTF-8 bytes in debug output for Match
  • ab4c8d1 doc: fix duplicate phrasing typo
  • ddeb85e cli/deps: update memmap2 to 0.9
  • 023f1c9 lite: fix attribute warning about rustfmt
  • 9c139f4 syntax: simplify Hir::dot constructors
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=regex&package-manager=cargo&previous-version=1.10.4&new-version=1.10.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74f678d45..9b9582025 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3320,9 +3320,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", From 131e68fd1ea1962c99541999034994ac4aba5b4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 03:28:14 +0000 Subject: [PATCH 133/164] chore(deps): Bump subst from 0.3.0 to 0.3.1 (#1367) Bumps [subst](https://github.com/fizyr/subst) from 0.3.0 to 0.3.1.
Changelog

Sourced from subst's changelog.

Version 0.3.1 - 2024-06-09

  • [fix][minor] Fix recursive substitution in braced default values.
Commits
  • aee45ad Bump version to 0.3.1.
  • 091d597 Update CHANGELOG.
  • 58ef80f Add more tests for recursive substitution in default values.
  • 476997b fix: Allow recursive substitution of braced variables
  • ce74b13 Merge pull request #10 from nyurik/linting
  • 2a100f4 Expand match on YAML value again.
  • 4b75931 Address PR review feedback
  • 9abed1f Some linting and minor upgrades
  • fa37c2e Merge pull request #13 from cre4ture/fix/cargo_fmt
  • 783e5ae cargo fmt with exceptions for relevant tests and yaml.rs parts
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=subst&package-manager=cargo&previous-version=0.3.0&new-version=0.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b9582025..dbcb3148d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4267,9 +4267,9 @@ dependencies = [ [[package]] name = "subst" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca1318e5d6716d6541696727c88d9b8dfc8cfe6afd6908e186546fd4af7f5b98" +checksum = "914a3487c294386d731fd33a8116b3ae4a8f95c0976b1550cc6b59b3db6c1e26" dependencies = [ "memchr", "serde", From 8f5767d8d340786df8b28e4fb5285bb2dda4fbb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 03:17:36 +0000 Subject: [PATCH 134/164] chore(deps): Bump url from 2.5.0 to 2.5.1 (#1370) Bumps [url](https://github.com/servo/rust-url) from 2.5.0 to 2.5.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=url&package-manager=cargo&previous-version=2.5.0&new-version=2.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 255 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbcb3148d..70d2fd2bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1171,6 +1171,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1969,6 +1980,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1977,12 +2106,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -2297,6 +2428,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "local-channel" version = "0.1.5" @@ -4344,6 +4481,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4457,6 +4605,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4791,9 +4949,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", @@ -4867,6 +5025,18 @@ dependencies = [ "tiny-skia-path", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.1" @@ -5234,6 +5404,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -5280,6 +5462,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -5300,6 +5506,27 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -5320,6 +5547,28 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "zopfli" version = "0.8.1" From bb953beb772564552abd7c9ca0580024d0b3c42f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 03:18:45 +0000 Subject: [PATCH 135/164] chore(deps): Bump clap from 4.5.6 to 4.5.7 (#1371) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.6 to 4.5.7.
Release notes

Sourced from clap's releases.

v4.5.7

[4.5.7] - 2024-06-10

Fixes

  • Clean up error message when too few arguments for num_args
Changelog

Sourced from clap's changelog.

[4.5.7] - 2024-06-10

Fixes

  • Clean up error message when too few arguments for num_args
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.6&new-version=4.5.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70d2fd2bd..80e7b8557 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,9 +743,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -753,9 +753,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", From a0dc75eb1c5db17764be907ee99dc744b448f595 Mon Sep 17 00:00:00 2001 From: Joko Priyono Date: Thu, 13 Jun 2024 10:50:31 +0700 Subject: [PATCH 136/164] =?UTF-8?q?fix:=20handle=20if=20selected=20date=20?= =?UTF-8?q?was=20undefined=20while=20double=20click=20on=20a=20sa=E2=80=A6?= =?UTF-8?q?=20(#1373)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle a negative case if the selected date was undefined while double-clicking on the same date in the calendar on the demo website. ![Screenshot 2024-06-12 at 15 45 49](https://github.com/maplibre/martin/assets/18734643/9d5afd46-f7a4-434e-ba44-925613055627) --- demo/frontend/src/Components/Map/Map.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/demo/frontend/src/Components/Map/Map.tsx b/demo/frontend/src/Components/Map/Map.tsx index 8e2435767..494eca248 100644 --- a/demo/frontend/src/Components/Map/Map.tsx +++ b/demo/frontend/src/Components/Map/Map.tsx @@ -62,17 +62,22 @@ class Map extends PureComponent<{}, {visibleLayer: any, range: any, hour: any}> }; changeFilter = (filter: string, value: any) => { - this.setState(state => ({ - ...state, - [filter]: value - })); + if (filter !== undefined && value !== undefined) { + this.setState(state => ({ + ...state, + [filter]: value + })); + } }; getQueryParams = () => { const { range: { from, to }, hour } = this.state; const dateFrom = `${dateConverter(from)}.2017`; - const dateTo = `${dateConverter(to)}.2017`; + let dateTo = `${dateConverter(to)}.2017`; + if (to === undefined) { + dateTo = dateFrom; + } return encodeURI(`date_from=${dateFrom}&date_to=${dateTo}&hour=${hour}`); }; From 683ce627cff55fcf9da9f5e914f4d4a7ec922031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 00:28:38 -0400 Subject: [PATCH 137/164] chore(deps): Bump braces from 3.0.2 to 3.0.3 in /demo/frontend (#1372) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=braces&package-manager=npm_and_yarn&previous-version=3.0.2&new-version=3.0.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/maplibre/martin/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- demo/frontend/yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/demo/frontend/yarn.lock b/demo/frontend/yarn.lock index 1cae63c00..cd949ef39 100644 --- a/demo/frontend/yarn.lock +++ b/demo/frontend/yarn.lock @@ -2045,11 +2045,11 @@ brace-expansion@^1.1.7: concat-map "0.0.1" braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" browserslist@^4.21.9, browserslist@^4.22.1: version "4.22.1" @@ -2766,10 +2766,10 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" From da681ddd94920b8539091a0022cb5152f1f22e81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 00:29:07 -0400 Subject: [PATCH 138/164] chore(deps): Bump actix-web from 4.6.0 to 4.7.0 (#1369) Bumps [actix-web](https://github.com/actix/actix-web) from 4.6.0 to 4.7.0.
Release notes

Sourced from actix-web's releases.

actix-web: v4.7.0

Added

  • Add #[scope] macro.
  • Add middleware::Identity type.
  • Add CustomizeResponder::add_cookie() method.
  • Add guard::GuardContext::app_data() method.
  • Add compat-routing-macros-force-pub crate feature which (on-by-default) which, when disabled, causes handlers to inherit their attached function's visibility.
  • Add compat crate feature group (on-by-default) which, when disabled, helps with transitioning to some planned v5.0 breaking changes, starting only with compat-routing-macros-force-pub.
  • Implement From<Box<dyn ResponseError>> for Error.
Commits
  • a5c7848 chore(actix-web): prepare release 4.7.0
  • 12a0521 chore(actix-multipart): prepare release 0.6.2
  • b4faf88 chore(actix-web-codegen): prepare release 4.3.0
  • d6f8851 chore(actix-test): prepare release 0.1.4
  • ebc43dc feat: forwards-compatibility for handler visibility inheritance fix (#3391)
  • 7c4c26d feat: expose Identity middleware (#3390)
  • 3db7891 Scope macro (#3136)
  • c366649 docs: example of CPU core pinning
  • 534cfe1 feat: add .customize().add_cookie() (#3215)
  • cff958e chore: address clippy lint
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actix-web&package-manager=cargo&previous-version=4.6.0&new-version=4.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80e7b8557..0771e24b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.6.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1cf67dadb19d7c95e5a299e2dda24193b89d5d4f33a3b9800888ede9e19aa32" +checksum = "5d6316df3fa569627c98b12557a8b6ff0674e5be4bb9b5e4ae2550ddb4964ed6" dependencies = [ "actix-codec", "actix-http", @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "4.2.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" dependencies = [ "actix-router", "proc-macro2", @@ -2396,7 +2396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] From bfb27167c9a1a4b2da9c9e4c73da258dd6901f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 00:29:22 -0400 Subject: [PATCH 139/164] chore(deps): Bump actix-rt from 2.9.0 to 2.10.0 (#1368) Bumps [actix-rt](https://github.com/actix/actix-net) from 2.9.0 to 2.10.0.
Release notes

Sourced from actix-rt's releases.

actix-rt: v2.10.0

  • Relax F's bound (Fn => FnOnce) on {Arbiter, System}::with_tokio_rt() functions.
  • Update tokio-uring dependency to 0.5.
  • Minimum supported Rust version (MSRV) is now 1.70.
Commits
  • 0d3d192 fix: relax bounds on with_tokio_rt (#569)
  • 0c26ecf chore(actix-server): prepare release 2.4.0
  • 1bdb15e chore(actix-rt): prepare release 2.10.0
  • a524f15 build(deps): update tokio-uring requirement from 0.4 to 0.5 (#568)
  • 451a44c build(deps): bump taiki-e/install-action from 2.33.34 to 2.34.1 (#567)
  • 18071d1 ci: disable io-uring tests
  • 786014c build(deps): bump taiki-e/install-action from 2.33.26 to 2.33.34 (#566)
  • a7ef438 ci: use mold linker on linux jobs
  • 375c352 --- (#565)
  • 2d1b546 --- (#563)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actix-rt&package-manager=cargo&previous-version=2.9.0&new-version=2.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0771e24b1..74b5c7e29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,9 +100,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ "actix-macros", "futures-core", From 4e482a14f01ec9965cb1b1b0d72e4d660735ce63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 00:29:59 -0400 Subject: [PATCH 140/164] chore(deps): Bump tokio from 1.37.0 to 1.38.0 (#1357) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.37.0 to 1.38.0.
Release notes

Sourced from tokio's releases.

Tokio v1.38.0

This release marks the beginning of stabilization for runtime metrics. It stabilizes RuntimeMetrics::worker_count. Future releases will continue to stabilize more metrics.

Added

  • fs: add File::create_new (#6573)
  • io: add copy_bidirectional_with_sizes (#6500)
  • io: implement AsyncBufRead for Join (#6449)
  • net: add Apple visionOS support (#6465)
  • net: implement Clone for NamedPipeInfo (#6586)
  • net: support QNX OS (#6421)
  • sync: add Notify::notify_last (#6520)
  • sync: add mpsc::Receiver::{capacity,max_capacity} (#6511)
  • sync: add split method to the semaphore permit (#6472, #6478)
  • task: add tokio::task::join_set::Builder::spawn_blocking (#6578)
  • wasm: support rt-multi-thread with wasm32-wasi-preview1-threads (#6510)

Changed

  • macros: make #[tokio::test] append #[test] at the end of the attribute list (#6497)
  • metrics: fix blocking_threads count (#6551)
  • metrics: stabilize RuntimeMetrics::worker_count (#6556)
  • runtime: move task out of the lifo_slot in block_in_place (#6596)
  • runtime: panic if global_queue_interval is zero (#6445)
  • sync: always drop message in destructor for oneshot receiver (#6558)
  • sync: instrument Semaphore for task dumps (#6499)
  • sync: use FIFO ordering when waking batches of wakers (#6521)
  • task: make LocalKey::get work with Clone types (#6433)
  • tests: update nix and mio-aio dev-dependencies (#6552)
  • time: clean up implementation (#6517)
  • time: lazily init timers on first poll (#6512)
  • time: remove the true_when field in TimerShared (#6563)
  • time: use sharding for timer implementation (#6534)

Fixed

  • taskdump: allow building taskdump docs on non-unix machines (#6564)
  • time: check for overflow in Interval::poll_tick (#6487)
  • sync: fix incorrect is_empty on mpsc block boundaries (#6603)

Documented

  • fs: rewrite file system docs (#6467)
  • io: fix stdin documentation (#6581)
  • io: fix obsolete reference in ReadHalf::unsplit() documentation (#6498)
  • macros: render more comprehensible documentation for select! (#6468)
  • net: add missing types to module docs (#6482)
  • net: fix misleading NamedPipeServer example (#6590)

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio&package-manager=cargo&previous-version=1.37.0&new-version=1.38.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74b5c7e29..f6411345a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4642,9 +4642,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -4661,9 +4661,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", From dadb0ff90603418dc5b6760271081de92ab168bb Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 13 Jun 2024 18:24:25 -0400 Subject: [PATCH 141/164] Fix tiny readme markup lints --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f984a79c1..e9eb9fdb6 100755 --- a/README.md +++ b/README.md @@ -9,18 +9,18 @@ [![CI build](https://github.com/maplibre/martin/actions/workflows/ci.yml/badge.svg)](https://github.com/maplibre/martin/actions) Martin is a tile server and a set of tools able to generate vector tiles on the fly -from large PostgreSQL databases, and serve tiles from PMTiles and MBTiles files. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). +from large `PostgreSQL` databases, and serve tiles from `PMTiles` and `MBTiles` files. Martin optimizes for speed and heavy traffic, and is written in [Rust](https://github.com/rust-lang/rust). ## Features * Serve [vector tiles](https://github.com/mapbox/vector-tile-spec) from - * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions - * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP - * [MBTile](https://github.com/mapbox/mbtiles-spec) files + * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions + * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP + * [MBTile](https://github.com/mapbox/mbtiles-spec) files * [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources into one * Generate [sprites](https://maplibre.org/martin/sources-sprites.html) and [font glyphs](https://maplibre.org/martin/sources-fonts.html) -* Generate tiles in bulk from any Martin-supported sources into an MBTiles file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool -* Examine, copy, validate, compare, and apply diffs between MBTiles files with [mbtiles](https://maplibre.org/martin/tools.html#mbtiles) tool +* Generate tiles in bulk from any Martin-supported sources into an `MBTiles` file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool +* Examine, copy, validate, compare, and apply diffs between `MBTiles` files with [mbtiles](https://maplibre.org/martin/tools.html#mbtiles) tool ## Documentation From 68aca37ba216e3b2f98b1a6a57743568ae36378a Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 13 Jun 2024 18:33:29 -0400 Subject: [PATCH 142/164] fix ci, dep bump --- Cargo.lock | 144 ++++++++++++++++++++++++----------------------------- Cargo.toml | 4 +- README.md | 6 +-- 3 files changed, 71 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6411345a..030752f40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,9 +111,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" dependencies = [ "actix-rt", "actix-service", @@ -311,9 +311,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -370,11 +370,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite", ] @@ -429,9 +429,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474d7cec9d0a1126fad1b224b767fcbf351c23b0309bb21ec210bcfd379926a5" +checksum = "bf7d844e282b4b56750b2d4e893b2205581ded8709fddd2b6aa5418c150ca877" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -441,9 +441,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7505fc3cb7acbf42699a43a79dd9caa4ed9e99861dfbb837c5c0fb5a0a8d2980" +checksum = "c3a2c29203f6bf296d01141cc8bb9dbd5ecd4c27843f2ee0767bcd5985a927da" dependencies = [ "bindgen", "cc", @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -666,9 +666,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" dependencies = [ "jobserver", "libc", @@ -732,9 +732,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.8.2" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f803f94ecf597339c7a34eed2036ef83f86aaba937f001f7c5b5e251f043f1f9" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -777,15 +777,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "clap_mangen" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1dd95b5ebb5c1c54581dd6346f3ed6a79a3eef95dd372fc2ac13d535535300e" +checksum = "74b70fc13e60c0e1d490dc50eb73a749be6d81f4ef03783df1d9b7b0c62bc937" dependencies = [ "clap", "roff", @@ -1306,17 +1306,6 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - [[package]] name = "event-listener" version = "5.3.1" @@ -1330,11 +1319,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "pin-project-lite", ] @@ -1849,12 +1838,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -1862,9 +1851,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpdate" @@ -1880,9 +1869,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -2322,7 +2311,7 @@ dependencies = [ "bytes", "futures", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "lambda_runtime_api_client", "serde", "serde_json", @@ -2339,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7210012be904051520f0dc502140ba599bae3042b65b3737b87727f1aa88a7d6" dependencies = [ "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "tokio", "tower-service", ] @@ -2511,7 +2500,7 @@ dependencies = [ "pprof", "regex", "rstest", - "rustls 0.23.9", + "rustls 0.23.10", "rustls-native-certs", "rustls-pemfile", "semver", @@ -2577,9 +2566,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" [[package]] name = "memmap2" @@ -2811,9 +2800,9 @@ dependencies = [ [[package]] name = "object" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -3225,9 +3214,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -3464,25 +3453,25 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] name = "regex-lite" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" @@ -3492,9 +3481,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" @@ -3627,9 +3616,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27059f51958c5f8496a6f79511e7c0ac396dd815dc8894e9b6e2efb5779cf6f0" +checksum = "9afd55a67069d6e434a95161415f5beeada95a01c7b815508a82dcb0e1593682" dependencies = [ "futures", "futures-timer", @@ -3639,9 +3628,9 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6132d64df104c0b3ea7a6ad7766a43f587bd773a4a9cf4cd59296d426afaf3a" +checksum = "4165dfae59a39dd41d8dec720d3cbfbc71f69744efb480a3920f5d4e0cc6798d" dependencies = [ "cfg-if", "glob", @@ -3719,9 +3708,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.9" +version = "0.23.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" dependencies = [ "aws-lc-rs", "log", @@ -4127,11 +4116,10 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools 0.12.1", "nom", "unicode_categories", ] @@ -4432,9 +4420,9 @@ dependencies = [ [[package]] name = "symbolic-common" -version = "12.8.0" +version = "12.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cccfffbc6bb3bb2d3a26cd2077f4d055f6808d266f9d4d158797a4c60510dfe" +checksum = "71297dc3e250f7dbdf8adb99e235da783d690f5819fdeb4cce39d9cfb0aca9f1" dependencies = [ "debugid", "memmap2 0.9.4", @@ -4444,9 +4432,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.8.0" +version = "12.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a99812da4020a67e76c4eb41f08c87364c14170495ff780f30dd519c221a68" +checksum = "424fa2c9bf2c862891b9cfd354a752751a6730fd838a4691e7f6c2c7957b9daf" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -4703,7 +4691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.9", + "rustls 0.23.10", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -4727,7 +4715,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.9", + "rustls 0.23.10", "rustls-pki-types", "tokio", ] @@ -4925,9 +4913,9 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode_categories" @@ -5039,9 +5027,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" diff --git a/Cargo.toml b/Cargo.toml index 30b4b1f7c..d052f521d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,8 +62,8 @@ postgres-protocol = "0.6" pprof = { version = "0.13", features = ["flamegraph", "criterion"] } pretty_assertions = "1" regex = "1" -rstest = "0.20" -rustls = "0.23.9" +rstest = "0.21" +rustls = "0.23.10" # ring feature does not require NASM windows executable, but works slower #rustls = { version = "0.23", default-features = false, features = ["logging", "std", "tls12", "ring"] } rustls-native-certs = "0.7" diff --git a/README.md b/README.md index e9eb9fdb6..7e2b132f5 100755 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ from large `PostgreSQL` databases, and serve tiles from `PMTiles` and `MBTiles` ## Features * Serve [vector tiles](https://github.com/mapbox/vector-tile-spec) from - * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions - * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP - * [MBTile](https://github.com/mapbox/mbtiles-spec) files + * [PostGIS](https://github.com/postgis/postgis) databases, automatically discovering compatible tables and functions + * [PMTile](https://protomaps.com/blog/pmtiles-v3-whats-new), both local files and over HTTP + * [MBTile](https://github.com/mapbox/mbtiles-spec) files * [Combine](https://maplibre.org/martin/sources-composite.html) multiple tile sources into one * Generate [sprites](https://maplibre.org/martin/sources-sprites.html) and [font glyphs](https://maplibre.org/martin/sources-fonts.html) * Generate tiles in bulk from any Martin-supported sources into an `MBTiles` file with [martin-cp](https://maplibre.org/martin/martin-cp.html) tool From bf1553f74911c389760b073250e9a0aad31d2afa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 02:42:27 +0000 Subject: [PATCH 143/164] chore(deps): Bump url from 2.5.1 to 2.5.2 (#1376) Bumps [url](https://github.com/servo/rust-url) from 2.5.1 to 2.5.2.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=url&package-manager=cargo&previous-version=2.5.1&new-version=2.5.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 261 ++--------------------------------------------------- 1 file changed, 6 insertions(+), 255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 030752f40..fcfa95ad3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1171,17 +1171,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "dotenvy" version = "0.15.7" @@ -1969,124 +1958,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2095,14 +1966,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2417,12 +2286,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "local-channel" version = "0.1.5" @@ -4469,17 +4332,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "tagptr" version = "0.2.0" @@ -4593,16 +4445,6 @@ dependencies = [ "strict-num", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -4937,9 +4779,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -5013,18 +4855,6 @@ dependencies = [ "tiny-skia-path", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -5392,18 +5222,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -5450,30 +5268,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -5494,27 +5288,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zeroize" version = "1.8.1" @@ -5535,28 +5308,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerovec" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "zopfli" version = "0.8.1" From 454df5e31a46113ea79299eca2b044b1cb05e9de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:54:00 +0000 Subject: [PATCH 144/164] chore(deps): Bump sqlite-hashes from 0.7.2 to 0.7.3 (#1379) Bumps [sqlite-hashes](https://github.com/nyurik/sqlite-hashes) from 0.7.2 to 0.7.3.
Release notes

Sourced from sqlite-hashes's releases.

v0.7.3

Minor dependency updates and readme fixes

Full Changelog: https://github.com/nyurik/sqlite-hashes/compare/v0.7.2...v0.7.3

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sqlite-hashes&package-manager=cargo&previous-version=0.7.2&new-version=0.7.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fcfa95ad3..02a55382c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3989,9 +3989,9 @@ dependencies = [ [[package]] name = "sqlite-hashes" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e525595f5f7d0b78daecb5d4fbf347d876a1d17d4486e3aba587891bb26333" +checksum = "39e59834cb3c95e0993b5768ca9f408e8aecda5c9489d3f1f4a05fe848c4f77d" dependencies = [ "digest", "hex", diff --git a/Cargo.toml b/Cargo.toml index d052f521d..18d2d9c5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ serde_with = "3" serde_yaml = "0.9" size_format = "1.0.2" spreet = { version = "0.11", default-features = false } -sqlite-hashes = { version = "0.7.2", default-features = false, features = ["md5", "aggregate", "hex"] } +sqlite-hashes = { version = "0.7.3", default-features = false, features = ["md5", "aggregate", "hex"] } sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] } subst = { version = "0.3", features = ["yaml"] } thiserror = "1" From da44d0b762a19f6485b9d5e2995bc47ca0998754 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 02:43:09 -0400 Subject: [PATCH 145/164] chore(deps): Bump docker/build-push-action from 5 to 6 (#1375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
Release notes

Sourced from docker/build-push-action's releases.

v6.0.0

[!NOTE] This major release adds support for generating Build summary and exporting build record for your build. You can disable this feature by setting DOCKER_BUILD_NO_SUMMARY: true environment variable in your workflow.

Full Changelog: https://github.com/docker/build-push-action/compare/v5.4.0...v6.0.0

v5.4.0

Full Changelog: https://github.com/docker/build-push-action/compare/v5.3.0...v5.4.0

v5.3.0

Full Changelog: https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0

v5.2.0

Full Changelog: https://github.com/docker/build-push-action/compare/v5.1.0...v5.2.0

v5.1.0

Full Changelog: https://github.com/docker/build-push-action/compare/v5.0.0...v5.1.0

Commits
  • c382f71 Merge pull request #1120 from crazy-max/build-summary
  • 5a5b70d chore: update generated content
  • dc24cf9 don't generate summary for cloud driver
  • 667cb22 DOCKER_BUILD_NO_SUMMARY env to disable summary
  • d880b19 generate build summary
  • e51051a export build record and upload artifact
  • 86c2bd0 Merge pull request #1137 from docker/dependabot/npm_and_yarn/braces-3.0.3
  • 268d2b1 Merge pull request #1138 from docker/dependabot/npm_and_yarn/docker/actions-t...
  • 2b8dc7f chore: update generated content
  • 840c12b chore(deps): Bump @​docker/actions-toolkit from 0.25.1 to 0.26.0
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2989b7e90..6ed1bb17a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,7 +169,7 @@ jobs: - name: Copy static files run: cp -r tests/fixtures/pmtiles2/* ${{ steps.nginx.outputs.html-dir }} - name: Build linux/arm64 Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 # https://github.com/docker/build-push-action with: context: . @@ -191,7 +191,7 @@ jobs: DATABASE_URL: postgres://${{ env.PGUSER }}:${{ env.PGUSER }}@${{ env.PGHOST }}:${{ job.services.postgres.ports[5432] }}/${{ env.PGDATABASE }}?sslmode=require - name: Build linux/amd64 Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 # https://github.com/docker/build-push-action with: context: . @@ -228,7 +228,7 @@ jobs: images: ghcr.io/${{ github.repository }} - name: Push the Docker image if: github.event_name != 'pull_request' - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . file: .github/files/multi-platform.Dockerfile From 374525f8ef065cef26055b3faac7b1bb235a641c Mon Sep 17 00:00:00 2001 From: Oquile Date: Tue, 25 Jun 2024 07:43:54 +0100 Subject: [PATCH 146/164] Update quick-start-linux.md (#1380) Curl fails to follow redirects by default. Adding `-L` instructs it to follow them and allows Marlin to be downloaded. --- docs/src/quick-start-linux.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/quick-start-linux.md b/docs/src/quick-start-linux.md index 093b323b0..b169c9891 100644 --- a/docs/src/quick-start-linux.md +++ b/docs/src/quick-start-linux.md @@ -5,10 +5,10 @@ mkdir martin cd martin # Download some sample data -curl -O https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles +curl -L -O https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles # Download the latest version of Martin binary, extract it, and make it executable -curl -O https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz +curl -L -O https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz tar -xzf martin-x86_64-unknown-linux-gnu.tar.gz chmod +x ./martin From 656c197eb3a0e821abc793bcef1e6985ac9bbc07 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 25 Jun 2024 11:00:19 -0400 Subject: [PATCH 147/164] Upgrade deps and fix global RusTLS init (#1381) See https://github.com/rustls/rustls/issues/1877 --- Cargo.lock | 277 ++++++++++++++++++---------------- martin/src/config.rs | 3 +- martin/src/utils/utilities.rs | 17 ++- 3 files changed, 166 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02a55382c..ef0cf8978 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "futures-sink", @@ -36,9 +36,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.7.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb9843d84c775696c37d9a418bbb01b932629d01870722c0f13eb3f95e2536d" +checksum = "3ae682f693a9cd7b058f2b0b5d9a6d7728a8555779bedbbc35dd88528611d020" dependencies = [ "actix-codec", "actix-rt", @@ -46,7 +46,7 @@ dependencies = [ "actix-utils", "ahash", "base64 0.22.1", - "bitflags 2.5.0", + "bitflags 2.6.0", "brotli 6.0.0", "bytes", "bytestring", @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.7.0" +version = "4.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6316df3fa569627c98b12557a8b6ff0674e5be4bb9b5e4ae2550ddb4964ed6" +checksum = "1988c02af8d2b718c05bc4aeb6a66395b7cdf32858c2c71131e5637a8c05a9ff" dependencies = [ "actix-codec", "actix-http", @@ -197,7 +197,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -398,7 +398,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -409,7 +409,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -509,7 +509,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -522,7 +522,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", "which", ] @@ -549,9 +549,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -627,9 +627,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -666,9 +666,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" dependencies = [ "jobserver", "libc", @@ -772,7 +772,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1033,7 +1033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1057,7 +1057,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1068,7 +1068,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1142,15 +1142,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.68", ] [[package]] @@ -1236,7 +1236,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1406,7 +1406,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -1470,7 +1470,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1fad2be0bf06af23adddcf6cd143c94ff0ba3b329691f92d1a38dae5c5aeebf" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "freetype-sys", "libc", ] @@ -1577,7 +1577,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1840,9 +1840,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1900,18 +1900,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", "hyper 1.3.1", "hyper-util", - "rustls 0.22.4", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tower-service", ] @@ -2210,11 +2211,11 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -2249,9 +2250,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets 0.52.5", @@ -2363,7 +2364,7 @@ dependencies = [ "pprof", "regex", "rstest", - "rustls 0.23.10", + "rustls", "rustls-native-certs", "rustls-pemfile", "semver", @@ -2429,9 +2430,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -2474,9 +2475,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -2733,7 +2734,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.1", + "redox_syscall 0.5.2", "smallvec", "windows-targets 0.52.5", ] @@ -2761,7 +2762,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2852,7 +2853,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3063,7 +3064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3077,9 +3078,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -3209,6 +3210,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3260,7 +3308,7 @@ version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -3300,11 +3348,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -3356,9 +3404,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -3377,7 +3425,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", + "quinn", + "rustls", "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", @@ -3386,7 +3435,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", @@ -3431,7 +3480,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", "windows-sys 0.52.0", ] @@ -3503,7 +3552,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.66", + "syn 2.0.68", "unicode-ident", ] @@ -3513,7 +3562,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "fallible-iterator 0.3.0", "fallible-streaming-iterator", "hashlink", @@ -3548,27 +3597,13 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.10" @@ -3578,6 +3613,7 @@ dependencies = [ "aws-lc-rs", "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -3687,7 +3723,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -3727,14 +3763,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "itoa", "ryu", @@ -3801,7 +3837,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3935,12 +3971,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -4097,7 +4127,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "bytes", "crc", @@ -4139,7 +4169,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "crc", "dotenvy", @@ -4239,7 +4269,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4250,14 +4280,14 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "subst" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914a3487c294386d731fd33a8116b3ae4a8f95c0976b1550cc6b59b3db6c1e26" +checksum = "b95bc3d9b5ec35dabec6f7ac966e073ef28d4881c6a2009567632ab721df6203" dependencies = [ "memchr", "serde", @@ -4267,9 +4297,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svgtypes" @@ -4317,9 +4347,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -4328,9 +4358,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "tagptr" @@ -4373,7 +4403,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4457,9 +4487,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -4497,7 +4527,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4533,31 +4563,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.10", + "rustls", "tokio", "tokio-postgres", - "tokio-rustls 0.26.0", + "tokio-rustls", "x509-certificate", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.10", + "rustls", "rustls-pki-types", "tokio", ] @@ -4660,7 +4679,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4674,9 +4693,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2cb4fbb9995eeb36ac86fadf24031ccd58f99d6b4b2d7b911db70bddb80d90" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" [[package]] name = "try-lock" @@ -4863,9 +4882,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom", ] @@ -4940,7 +4959,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -4974,7 +4993,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5285,7 +5304,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5305,7 +5324,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5342,9 +5361,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.11+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" dependencies = [ "cc", "pkg-config", diff --git a/martin/src/config.rs b/martin/src/config.rs index 8be723a91..eff279dc8 100644 --- a/martin/src/config.rs +++ b/martin/src/config.rs @@ -19,7 +19,7 @@ use crate::source::{TileInfoSources, TileSources}; #[cfg(feature = "sprites")] use crate::sprites::{SpriteConfig, SpriteSources}; use crate::srv::{SrvConfig, RESERVED_KEYWORDS}; -use crate::utils::{parse_base_path, CacheValue, MainCache, OptMainCache}; +use crate::utils::{init_aws_lc_tls, parse_base_path, CacheValue, MainCache, OptMainCache}; use crate::MartinError::{ConfigLoadError, ConfigParseError, ConfigWriteError, NoSources}; use crate::{IdResolver, MartinResult, OptOneMany}; @@ -117,6 +117,7 @@ impl Config { } pub async fn resolve(&mut self) -> MartinResult { + init_aws_lc_tls()?; let resolver = IdResolver::new(RESERVED_KEYWORDS); let cache_size = self.cache_size_mb.unwrap_or(512) * 1024 * 1024; let cache = if cache_size > 0 { diff --git a/martin/src/utils/utilities.rs b/martin/src/utils/utilities.rs index 7cc1156b1..8ed5af5ec 100644 --- a/martin/src/utils/utilities.rs +++ b/martin/src/utils/utilities.rs @@ -1,11 +1,26 @@ use std::io::{Read as _, Write as _}; +use std::sync::OnceLock; use actix_web::http::Uri; use flate2::read::GzDecoder; use flate2::write::GzEncoder; use crate::MartinError::BasePathError; -use crate::MartinResult; +use crate::{MartinError, MartinResult}; + +pub fn init_aws_lc_tls() -> MartinResult<()> { + // https://github.com/rustls/rustls/issues/1877 + static INIT_TLS: OnceLock> = OnceLock::new(); + // TODO: replace with LazyCell after 1.80 + INIT_TLS + .get_or_init(|| { + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .map_err(|e| format!("Unable to init rustls: {e:?}")) + }) + .clone() + .map_err(|e| MartinError::InternalError(e.into())) +} pub fn decode_gzip(data: &[u8]) -> Result, std::io::Error> { let mut decoder = GzDecoder::new(data); From 9b55f9263477724822f6cf058d40f56610caf01b Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 26 Jun 2024 00:43:44 +0800 Subject: [PATCH 148/164] Update quick-start-qgis.md (#1382) --- docs/src/quick-start-qgis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/quick-start-qgis.md b/docs/src/quick-start-qgis.md index 8ad2db54b..0c7cec1ec 100644 --- a/docs/src/quick-start-qgis.md +++ b/docs/src/quick-start-qgis.md @@ -6,7 +6,7 @@ > ![alt text](images/qgis_add_vector_tile.png) 3. In the `Vector Tile Connection` dialog, give it some name and the URL of the Martin server, - e.g. `http://localhost:3000/martin/{z}/{x}/{y}.pbf` and click `OK`. + e.g. `http://localhost:3000/world_cities/{z}/{x}/{y}` and click `OK`. > ![alt text](images/qgis_add_vector_tile_options.png) 4. In the QGIS browser panel (left), double-click the newly added connection, or right-click it and click From ccd550a2cffbd126b71864d0bdbf8475ac046985 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 25 Jun 2024 15:34:14 -0400 Subject: [PATCH 149/164] Add binary diff for mbtiles (#1358) * `mbtiles diff` now has an additional `--patch-type` param with `whole`, `bin-diff-raw` and `bin-diff-gz` values: * `whole` stores different tiles as before - as whole tiles in the `tiles` table * `bin-diff-raw` computes binary difference between tiles, and stores them as brotli-encoded value in a `bsdiffraw` table, together with a `xxh3_64` hash of the tile as it will be stored after patching * `bin-diff-gz` same as `bin-diff-raw`, but assumes the tiles are gzip-compressed, so it uncompresses them before comparing. The `xxh3_64` stores the hash of the uncompressed tile. The data will be stored in the `bsdiffrawgz` table (identical structure with above) * `mbtiles copy --apply-patch` will automatically detect if `bsdiffrawgz` or `bsdiffraw` tables exist, and will use binary patching. * `mbtiles apply-patch` does not support binary patching yet * `mbtiles copy --diff-with-file ... --patch-type ...` is an alias to `mbtiles diff --patch-type ...` --- .gitignore | 1 + Cargo.lock | 55 ++- Cargo.toml | 10 +- justfile | 3 +- martin-tile-utils/Cargo.toml | 4 +- martin-tile-utils/src/decoders.rs | 30 ++ martin-tile-utils/src/lib.rs | 26 +- martin/Cargo.toml | 3 +- martin/benches/bench.rs | 6 +- martin/src/bin/martin-cp.rs | 6 +- martin/src/lib.rs | 4 +- martin/src/mbtiles/mod.rs | 4 +- martin/src/pg/errors.rs | 2 +- martin/src/pg/pg_source.rs | 4 +- martin/src/pmtiles/mod.rs | 4 +- martin/src/source.rs | 4 +- martin/src/srv/server.rs | 4 +- martin/src/srv/tiles.rs | 11 +- martin/src/utils/cache.rs | 3 +- martin/src/utils/mod.rs | 3 - martin/src/utils/utilities.rs | 29 -- martin/src/utils/xyz.rs | 18 - martin/tests/mb_server_test.rs | 2 +- martin/tests/pg_function_source_test.rs | 2 +- martin/tests/pg_table_source_test.rs | 3 +- martin/tests/pmt_server_test.rs | 2 +- mbtiles/Cargo.toml | 11 +- mbtiles/src/bin/mbtiles.rs | 24 +- mbtiles/src/bindiff.rs | 390 ++++++++++++++++++ mbtiles/src/copier.rs | 224 +++++++--- mbtiles/src/errors.rs | 15 + mbtiles/src/lib.rs | 5 +- mbtiles/src/mbtiles.rs | 10 +- mbtiles/src/patcher.rs | 4 + mbtiles/src/queries.rs | 91 +++- mbtiles/src/validation.rs | 3 +- mbtiles/tests/copy.rs | 377 ++++++++++------- .../snapshots/copy__databases@flat__bdr.snap | 67 +++ .../snapshots/copy__databases@hash__bdr.snap | 75 ++++ tests/expected/auto/catalog_auto.json | 1 + tests/expected/mbtiles/copy_bindiff.txt | 3 + tests/expected/mbtiles/copy_bindiff2.txt | 5 + tests/expected/mbtiles/copy_bindiff3.txt | 2 + tests/expected/mbtiles/copy_bindiff4.txt | 9 + tests/expected/mbtiles/copy_diff.txt | 2 +- .../mbtiles/world_cities_diff.mbtiles | Bin 3584 -> 4096 bytes .../mbtiles/world_cities_modified.mbtiles | Bin 49152 -> 49152 bytes tests/test.sh | 21 + 48 files changed, 1263 insertions(+), 319 deletions(-) create mode 100644 martin-tile-utils/src/decoders.rs delete mode 100644 martin/src/utils/xyz.rs create mode 100644 mbtiles/src/bindiff.rs create mode 100644 mbtiles/tests/snapshots/copy__databases@flat__bdr.snap create mode 100644 mbtiles/tests/snapshots/copy__databases@hash__bdr.snap create mode 100644 tests/expected/mbtiles/copy_bindiff.txt create mode 100644 tests/expected/mbtiles/copy_bindiff2.txt create mode 100644 tests/expected/mbtiles/copy_bindiff3.txt create mode 100644 tests/expected/mbtiles/copy_bindiff4.txt diff --git a/.gitignore b/.gitignore index 6dec1c8b4..d13179339 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,6 @@ test_log* pg_data/ config.yml tests/output/ +tests/mbtiles_temp_files/ tmp/ .aws-sam/ diff --git a/Cargo.lock b/Cargo.lock index ef0cf8978..50ee96887 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -619,6 +619,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bsdiff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7f2e6c4f2a017f63b5a1fd7cc437f061b53a3e890bcca840ef756d72f6b72f2" + [[package]] name = "bumpalo" version = "3.16.0" @@ -1406,6 +1412,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", + "nanorand", "spin", ] @@ -1642,8 +1649,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -2328,7 +2337,7 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "martin" -version = "0.13.0" +version = "0.14.0" dependencies = [ "actix-cors", "actix-http", @@ -2344,7 +2353,6 @@ dependencies = [ "deadpool-postgres", "enum-display", "env_logger", - "flate2", "futures", "indoc", "insta", @@ -2383,15 +2391,17 @@ dependencies = [ [[package]] name = "martin-tile-utils" -version = "0.4.1" +version = "0.5.0" dependencies = [ "approx", + "brotli 6.0.0", + "flate2", "insta", ] [[package]] name = "mbtiles" -version = "0.9.1" +version = "0.10.0" dependencies = [ "actix-rt", "anyhow", @@ -2399,11 +2409,14 @@ dependencies = [ "ctor", "enum-display", "env_logger", + "flume", "futures", "insta", "itertools 0.13.0", "log", "martin-tile-utils", + "md5", + "num_cpus", "pretty_assertions", "rstest", "serde", @@ -2411,11 +2424,13 @@ dependencies = [ "serde_with", "serde_yaml", "size_format", + "sqlite-compressions", "sqlite-hashes", "sqlx", "thiserror", "tilejson", "tokio", + "xxhash-rust", ] [[package]] @@ -2428,6 +2443,12 @@ dependencies = [ "digest", ] +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.7.4" @@ -2534,6 +2555,15 @@ dependencies = [ "serde", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "nix" version = "0.26.4" @@ -4017,6 +4047,17 @@ dependencies = [ "unicode_categories", ] +[[package]] +name = "sqlite-compressions" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d005d84196a3cc75a3113058d333de388cef7eb665dbcee09e31bb8166a1382" +dependencies = [ + "bsdiff", + "flate2", + "rusqlite", +] + [[package]] name = "sqlite-hashes" version = "0.7.3" @@ -5281,6 +5322,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 18d2d9c5b..5500b6e8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ members = ["martin", "martin-tile-utils", "mbtiles"] edition = "2021" license = "MIT OR Apache-2.0" repository = "https://github.com/maplibre/martin" -rust-version = "1.74" +rust-version = "1.76" readme = "README.md" homepage = "https://martin.maplibre.org/" @@ -42,6 +42,7 @@ deadpool-postgres = "0.12" enum-display = "0.1" env_logger = "0.11" flate2 = "1" +flume = "0.11" futures = "0.3" indoc = "2" insta = "1" @@ -50,8 +51,9 @@ json-patch = "2.0" lambda-web = { version = "0.2.1", features = ["actix4"] } libsqlite3-sys = { version = ">=0.27", features = ["bundled"] } log = "0.4" -martin-tile-utils = { path = "./martin-tile-utils", version = "0.4.0" } -mbtiles = { path = "./mbtiles", version = "0.9.0" } +martin-tile-utils = { path = "./martin-tile-utils", version = "0.5.0" } +mbtiles = { path = "./mbtiles", version = "0.10.0" } +md5 = "0.7.0" moka = { version = "0.12", features = ["future"] } num_cpus = "1" pbf_font_tools = { version = "2.5.1", features = ["freetype"] } @@ -75,6 +77,7 @@ serde_with = "3" serde_yaml = "0.9" size_format = "1.0.2" spreet = { version = "0.11", default-features = false } +sqlite-compressions = { version = "0.2.12", default-features = false, features = ["bsdiffraw", "gzip"] } sqlite-hashes = { version = "0.7.3", default-features = false, features = ["md5", "aggregate", "hex"] } sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] } subst = { version = "0.3", features = ["yaml"] } @@ -84,6 +87,7 @@ tilejson = "0.4" tokio = { version = "1", features = ["macros"] } tokio-postgres-rustls = "0.12" url = "2.5" +xxhash-rust = { version = "0.8", features = ["xxh3"] } [profile.dev.package] # See https://github.com/launchbadge/sqlx#compile-time-verification diff --git a/justfile b/justfile index c7c43f175..4fb3341e8 100644 --- a/justfile +++ b/justfile @@ -188,8 +188,7 @@ bless: restart clean-test bless-insta-martin bless-insta-mbtiles bless-tests ble bless-int: rm -rf tests/temp tests/test.sh - rm -rf tests/expected - mv tests/output tests/expected + rm -rf tests/expected && mv tests/output tests/expected # Run test with bless-tests feature bless-tests: diff --git a/martin-tile-utils/Cargo.toml b/martin-tile-utils/Cargo.toml index ee910c2b5..9ee6e5c24 100644 --- a/martin-tile-utils/Cargo.toml +++ b/martin-tile-utils/Cargo.toml @@ -2,7 +2,7 @@ lints.workspace = true [package] name = "martin-tile-utils" -version = "0.4.1" +version = "0.5.0" authors = ["Yuri Astrakhan ", "MapLibre contributors"] description = "Utilities to help with map tile processing, such as type and compression detection. Used by the MapLibre's Martin tile server." keywords = ["maps", "tiles", "mvt", "tileserver"] @@ -17,6 +17,8 @@ repository.workspace = true rust-version.workspace = true [dependencies] +brotli.workspace = true +flate2.workspace = true [dev-dependencies] approx.workspace = true diff --git a/martin-tile-utils/src/decoders.rs b/martin-tile-utils/src/decoders.rs new file mode 100644 index 000000000..1bdb177ba --- /dev/null +++ b/martin-tile-utils/src/decoders.rs @@ -0,0 +1,30 @@ +use std::io::{Read as _, Write as _}; + +use flate2::read::GzDecoder; +use flate2::write::GzEncoder; + +pub fn decode_gzip(data: &[u8]) -> Result, std::io::Error> { + let mut decoder = GzDecoder::new(data); + let mut decompressed = Vec::new(); + decoder.read_to_end(&mut decompressed)?; + Ok(decompressed) +} + +pub fn encode_gzip(data: &[u8]) -> Result, std::io::Error> { + let mut encoder = GzEncoder::new(Vec::new(), flate2::Compression::default()); + encoder.write_all(data)?; + encoder.finish() +} + +pub fn decode_brotli(data: &[u8]) -> Result, std::io::Error> { + let mut decoder = brotli::Decompressor::new(data, 4096); + let mut decompressed = Vec::new(); + decoder.read_to_end(&mut decompressed)?; + Ok(decompressed) +} + +pub fn encode_brotli(data: &[u8]) -> Result, std::io::Error> { + let mut encoder = brotli::CompressorWriter::new(Vec::new(), 4096, 11, 22); + encoder.write_all(data)?; + Ok(encoder.into_inner()) +} diff --git a/martin-tile-utils/src/lib.rs b/martin-tile-utils/src/lib.rs index 43b7705a1..8c89bc2ad 100644 --- a/martin-tile-utils/src/lib.rs +++ b/martin-tile-utils/src/lib.rs @@ -4,13 +4,33 @@ // project originally written by Kaveh Karimi and licensed under MIT/Apache-2.0 use std::f64::consts::PI; -use std::fmt::Display; +use std::fmt::{Display, Formatter, Result}; pub const EARTH_CIRCUMFERENCE: f64 = 40_075_016.685_578_5; pub const EARTH_RADIUS: f64 = EARTH_CIRCUMFERENCE / 2.0 / PI; pub const MAX_ZOOM: u8 = 30; +mod decoders; +pub use decoders::*; + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct TileCoord { + pub z: u8, + pub x: u32, + pub y: u32, +} + +impl Display for TileCoord { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if f.alternate() { + write!(f, "{}/{}/{}", self.z, self.x, self.y) + } else { + write!(f, "{},{},{}", self.z, self.x, self.y) + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Format { Gif, @@ -74,7 +94,7 @@ impl Format { } impl Display for Format { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.write_str(match *self { Self::Gif => "gif", Self::Jpeg => "jpeg", @@ -189,7 +209,7 @@ impl From for TileInfo { } impl Display for TileInfo { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { write!(f, "{}", self.format.content_type())?; if let Some(encoding) = self.encoding.content_encoding() { write!(f, "; encoding={encoding}")?; diff --git a/martin/Cargo.toml b/martin/Cargo.toml index 428cf6ae0..0c3a871a8 100644 --- a/martin/Cargo.toml +++ b/martin/Cargo.toml @@ -3,7 +3,7 @@ lints.workspace = true [package] name = "martin" # Once the release is published with the hash, update https://github.com/maplibre/homebrew-martin -version = "0.13.0" +version = "0.14.0" authors = ["Stepan Kuzmin ", "Yuri Astrakhan ", "MapLibre contributors"] description = "Blazing fast and lightweight tile server with PostGIS, MBTiles, and PMTiles support" keywords = ["maps", "tiles", "mbtiles", "pmtiles", "postgis"] @@ -81,7 +81,6 @@ clap.workspace = true deadpool-postgres = { workspace = true, optional = true } enum-display.workspace = true env_logger.workspace = true -flate2.workspace = true futures.workspace = true itertools.workspace = true json-patch = { workspace = true, optional = true } diff --git a/martin/benches/bench.rs b/martin/benches/bench.rs index ceb4a6946..114e73656 100644 --- a/martin/benches/bench.rs +++ b/martin/benches/bench.rs @@ -2,10 +2,8 @@ use async_trait::async_trait; use criterion::async_executor::FuturesExecutor; use criterion::{criterion_group, criterion_main, Criterion}; use martin::srv::DynTileSource; -use martin::{ - CatalogSourceEntry, MartinResult, Source, TileCoord, TileData, TileSources, UrlQuery, -}; -use martin_tile_utils::{Encoding, Format, TileInfo}; +use martin::{CatalogSourceEntry, MartinResult, Source, TileData, TileSources, UrlQuery}; +use martin_tile_utils::{Encoding, Format, TileCoord, TileInfo}; use pprof::criterion::{Output, PProfProfiler}; use tilejson::{tilejson, TileJSON}; diff --git a/martin/src/bin/martin-cp.rs b/martin/src/bin/martin-cp.rs index ecb3a291f..7fe50d156 100644 --- a/martin/src/bin/martin-cp.rs +++ b/martin/src/bin/martin-cp.rs @@ -14,10 +14,10 @@ use log::{debug, error, info, log_enabled}; use martin::args::{Args, ExtraArgs, MetaArgs, OsEnv, SrvArgs}; use martin::srv::{merge_tilejson, DynTileSource}; use martin::{ - append_rect, read_config, Config, MartinError, MartinResult, ServerState, Source, TileCoord, - TileData, TileRect, + append_rect, read_config, Config, MartinError, MartinResult, ServerState, Source, TileData, + TileRect, }; -use martin_tile_utils::{bbox_to_xyz, TileInfo}; +use martin_tile_utils::{bbox_to_xyz, TileCoord, TileInfo}; use mbtiles::sqlx::SqliteConnection; use mbtiles::UpdateZoomType::GrowOnly; use mbtiles::{ diff --git a/martin/src/lib.rs b/martin/src/lib.rs index ef4aad9f7..59548426a 100644 --- a/martin/src/lib.rs +++ b/martin/src/lib.rs @@ -9,8 +9,8 @@ pub use source::{CatalogSourceEntry, Source, Tile, TileData, TileSources, UrlQue mod utils; pub use utils::{ - append_rect, decode_brotli, decode_gzip, IdResolver, MartinError, MartinResult, OptBoolObj, - OptOneMany, TileCoord, TileRect, NO_MAIN_CACHE, + append_rect, IdResolver, MartinError, MartinResult, OptBoolObj, OptOneMany, TileRect, + NO_MAIN_CACHE, }; pub mod args; diff --git a/martin/src/mbtiles/mod.rs b/martin/src/mbtiles/mod.rs index b9e446f24..2488098a0 100644 --- a/martin/src/mbtiles/mod.rs +++ b/martin/src/mbtiles/mod.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use async_trait::async_trait; use log::trace; -use martin_tile_utils::TileInfo; +use martin_tile_utils::{TileCoord, TileInfo}; use mbtiles::MbtilesPool; use serde::{Deserialize, Serialize}; use tilejson::TileJSON; @@ -15,7 +15,7 @@ use crate::config::UnrecognizedValues; use crate::file_config::FileError::{AcquireConnError, InvalidMetadata, IoError}; use crate::file_config::{ConfigExtras, FileResult, SourceConfigExtras}; use crate::source::{TileData, UrlQuery}; -use crate::{MartinResult, Source, TileCoord}; +use crate::{MartinResult, Source}; #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] pub struct MbtConfig { diff --git a/martin/src/pg/errors.rs b/martin/src/pg/errors.rs index 2b49bc7ef..37cd6e7c0 100644 --- a/martin/src/pg/errors.rs +++ b/martin/src/pg/errors.rs @@ -3,11 +3,11 @@ use std::path::PathBuf; use deadpool_postgres::tokio_postgres::Error as TokioPgError; use deadpool_postgres::{BuildError, PoolError}; +use martin_tile_utils::TileCoord; use semver::Version; use crate::pg::utils::query_to_json; use crate::source::UrlQuery; -use crate::TileCoord; pub type PgResult = Result; diff --git a/martin/src/pg/pg_source.rs b/martin/src/pg/pg_source.rs index f639e3d5b..8f1b34712 100644 --- a/martin/src/pg/pg_source.rs +++ b/martin/src/pg/pg_source.rs @@ -3,14 +3,14 @@ use deadpool_postgres::tokio_postgres::types::{ToSql, Type}; use log::debug; use martin_tile_utils::Encoding::Uncompressed; use martin_tile_utils::Format::Mvt; -use martin_tile_utils::TileInfo; +use martin_tile_utils::{TileCoord, TileInfo}; use tilejson::TileJSON; use crate::pg::pool::PgPool; use crate::pg::utils::query_to_json; use crate::pg::PgError::{GetTileError, GetTileWithQueryError, PrepareQueryError}; use crate::source::{Source, TileData, UrlQuery}; -use crate::{MartinResult, TileCoord}; +use crate::MartinResult; #[derive(Clone, Debug)] pub struct PgSource { diff --git a/martin/src/pmtiles/mod.rs b/martin/src/pmtiles/mod.rs index 3b0c134f9..c24b823b7 100644 --- a/martin/src/pmtiles/mod.rs +++ b/martin/src/pmtiles/mod.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use async_trait::async_trait; use log::{trace, warn}; -use martin_tile_utils::{Encoding, Format, TileInfo}; +use martin_tile_utils::{Encoding, Format, TileCoord, TileInfo}; use pmtiles::async_reader::AsyncPmTilesReader; use pmtiles::cache::{DirCacheResult, DirectoryCache}; use pmtiles::reqwest::Client; @@ -23,7 +23,7 @@ use crate::file_config::{ConfigExtras, FileError, FileResult, SourceConfigExtras use crate::source::UrlQuery; use crate::utils::cache::get_cached_value; use crate::utils::{CacheKey, CacheValue, OptMainCache}; -use crate::{MartinResult, Source, TileCoord, TileData}; +use crate::{MartinResult, Source, TileData}; #[derive(Clone, Debug)] pub struct PmtCache { diff --git a/martin/src/source.rs b/martin/src/source.rs index ba04293b9..879fa4592 100644 --- a/martin/src/source.rs +++ b/martin/src/source.rs @@ -4,11 +4,11 @@ use std::fmt::Debug; use actix_web::error::ErrorNotFound; use async_trait::async_trait; use log::debug; -use martin_tile_utils::TileInfo; +use martin_tile_utils::{TileCoord, TileInfo}; use serde::{Deserialize, Serialize}; use tilejson::TileJSON; -use crate::{MartinResult, TileCoord}; +use crate::MartinResult; pub type TileData = Vec; pub type UrlQuery = HashMap; diff --git a/martin/src/srv/server.rs b/martin/src/srv/server.rs index 80f11bf24..fba334e86 100755 --- a/martin/src/srv/server.rs +++ b/martin/src/srv/server.rs @@ -159,12 +159,12 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server #[cfg(test)] pub mod tests { use async_trait::async_trait; - use martin_tile_utils::{Encoding, Format, TileInfo}; + use martin_tile_utils::{Encoding, Format, TileCoord, TileInfo}; use tilejson::TileJSON; use super::*; use crate::source::{Source, TileData}; - use crate::{TileCoord, UrlQuery}; + use crate::UrlQuery; #[derive(Debug, Clone)] pub struct TestSource { diff --git a/martin/src/srv/tiles.rs b/martin/src/srv/tiles.rs index fe592180a..7d9689a01 100755 --- a/martin/src/srv/tiles.rs +++ b/martin/src/srv/tiles.rs @@ -8,7 +8,9 @@ use actix_web::web::{Data, Path, Query}; use actix_web::{route, HttpMessage, HttpRequest, HttpResponse, Result as ActixResult}; use futures::future::try_join_all; use log::trace; -use martin_tile_utils::{Encoding, Format, TileInfo}; +use martin_tile_utils::{ + decode_brotli, decode_gzip, encode_brotli, encode_gzip, Encoding, Format, TileCoord, TileInfo, +}; use serde::Deserialize; use crate::args::PreferredEncoding; @@ -16,11 +18,8 @@ use crate::source::{Source, TileSources, UrlQuery}; use crate::srv::server::map_internal_error; use crate::srv::SrvConfig; use crate::utils::cache::get_or_insert_cached_value; -use crate::utils::{ - decode_brotli, decode_gzip, encode_brotli, encode_gzip, CacheKey, CacheValue, MainCache, - OptMainCache, -}; -use crate::{Tile, TileCoord, TileData}; +use crate::utils::{CacheKey, CacheValue, MainCache, OptMainCache}; +use crate::{Tile, TileData}; static SUPPORTED_ENC: &[HeaderEnc] = &[ HeaderEnc::gzip(), diff --git a/martin/src/utils/cache.rs b/martin/src/utils/cache.rs index f1b948744..9923a2355 100755 --- a/martin/src/utils/cache.rs +++ b/martin/src/utils/cache.rs @@ -1,6 +1,7 @@ +use martin_tile_utils::TileCoord; use moka::future::Cache; -use crate::{TileCoord, TileData}; +use crate::TileData; pub type MainCache = Cache; pub type OptMainCache = Option; diff --git a/martin/src/utils/mod.rs b/martin/src/utils/mod.rs index 306da7e55..a6f519f0e 100644 --- a/martin/src/utils/mod.rs +++ b/martin/src/utils/mod.rs @@ -15,6 +15,3 @@ pub use rectangle::{append_rect, TileRect}; mod utilities; pub use utilities::*; - -mod xyz; -pub use xyz::TileCoord; diff --git a/martin/src/utils/utilities.rs b/martin/src/utils/utilities.rs index 8ed5af5ec..55b85341f 100644 --- a/martin/src/utils/utilities.rs +++ b/martin/src/utils/utilities.rs @@ -1,9 +1,6 @@ -use std::io::{Read as _, Write as _}; use std::sync::OnceLock; use actix_web::http::Uri; -use flate2::read::GzDecoder; -use flate2::write::GzEncoder; use crate::MartinError::BasePathError; use crate::{MartinError, MartinResult}; @@ -22,32 +19,6 @@ pub fn init_aws_lc_tls() -> MartinResult<()> { .map_err(|e| MartinError::InternalError(e.into())) } -pub fn decode_gzip(data: &[u8]) -> Result, std::io::Error> { - let mut decoder = GzDecoder::new(data); - let mut decompressed = Vec::new(); - decoder.read_to_end(&mut decompressed)?; - Ok(decompressed) -} - -pub fn encode_gzip(data: &[u8]) -> Result, std::io::Error> { - let mut encoder = GzEncoder::new(Vec::new(), flate2::Compression::default()); - encoder.write_all(data)?; - encoder.finish() -} - -pub fn decode_brotli(data: &[u8]) -> Result, std::io::Error> { - let mut decoder = brotli::Decompressor::new(data, 4096); - let mut decompressed = Vec::new(); - decoder.read_to_end(&mut decompressed)?; - Ok(decompressed) -} - -pub fn encode_brotli(data: &[u8]) -> Result, std::io::Error> { - let mut encoder = brotli::CompressorWriter::new(Vec::new(), 4096, 11, 22); - encoder.write_all(data)?; - Ok(encoder.into_inner()) -} - pub fn parse_base_path(path: &str) -> MartinResult { if !path.starts_with('/') { return Err(BasePathError(path.to_string())); diff --git a/martin/src/utils/xyz.rs b/martin/src/utils/xyz.rs deleted file mode 100644 index 1a968207e..000000000 --- a/martin/src/utils/xyz.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::fmt::{Display, Formatter}; - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct TileCoord { - pub z: u8, - pub x: u32, - pub y: u32, -} - -impl Display for TileCoord { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if f.alternate() { - write!(f, "{}/{}/{}", self.z, self.x, self.y) - } else { - write!(f, "{},{},{}", self.z, self.x, self.y) - } - } -} diff --git a/martin/tests/mb_server_test.rs b/martin/tests/mb_server_test.rs index 95bb70746..f8bfe6b1a 100644 --- a/martin/tests/mb_server_test.rs +++ b/martin/tests/mb_server_test.rs @@ -4,7 +4,7 @@ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; use martin::srv::SrvConfig; -use martin::{decode_brotli, decode_gzip}; +use martin_tile_utils::{decode_brotli, decode_gzip}; use tilejson::TileJSON; pub mod utils; diff --git a/martin/tests/pg_function_source_test.rs b/martin/tests/pg_function_source_test.rs index 8d891b51b..f10af4829 100644 --- a/martin/tests/pg_function_source_test.rs +++ b/martin/tests/pg_function_source_test.rs @@ -3,7 +3,7 @@ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; -use martin::TileCoord; +use martin_tile_utils::TileCoord; pub mod utils; pub use utils::*; diff --git a/martin/tests/pg_table_source_test.rs b/martin/tests/pg_table_source_test.rs index d4179167f..ed9983ec3 100644 --- a/martin/tests/pg_table_source_test.rs +++ b/martin/tests/pg_table_source_test.rs @@ -3,8 +3,7 @@ use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; -use martin::TileCoord; - +use martin_tile_utils::TileCoord; pub mod utils; pub use utils::*; diff --git a/martin/tests/pmt_server_test.rs b/martin/tests/pmt_server_test.rs index 422d82cde..73db79dd7 100644 --- a/martin/tests/pmt_server_test.rs +++ b/martin/tests/pmt_server_test.rs @@ -3,8 +3,8 @@ use actix_web::test::{call_service, read_body, read_body_json, TestRequest}; use ctor::ctor; use indoc::indoc; use insta::assert_yaml_snapshot; -use martin::decode_gzip; use martin::srv::SrvConfig; +use martin_tile_utils::decode_gzip; use tilejson::TileJSON; pub mod utils; diff --git a/mbtiles/Cargo.toml b/mbtiles/Cargo.toml index 1f22df562..d56fbdee8 100644 --- a/mbtiles/Cargo.toml +++ b/mbtiles/Cargo.toml @@ -2,7 +2,7 @@ lints.workspace = true [package] name = "mbtiles" -version = "0.9.1" +version = "0.10.0" authors = ["Yuri Astrakhan ", "MapLibre contributors"] description = "A simple low-level MbTiles access and processing library, with some tile format detection and other relevant heuristics." keywords = ["mbtiles", "maps", "tiles", "mvt", "tilejson"] @@ -14,29 +14,34 @@ rust-version.workspace = true [features] default = ["cli"] -cli = ["dep:anyhow", "dep:clap", "dep:env_logger", "dep:serde_yaml", "dep:tokio"] +cli = ["dep:anyhow", "dep:clap", "dep:env_logger", "dep:serde_yaml"] [dependencies] enum-display.workspace = true +flume.workspace = true futures.workspace = true itertools.workspace = true log.workspace = true martin-tile-utils.workspace = true +md5.workspace = true +num_cpus.workspace = true serde.workspace = true serde_json.workspace = true serde_with.workspace = true size_format.workspace = true +sqlite-compressions.workspace = true sqlite-hashes.workspace = true sqlx.workspace = true thiserror.workspace = true tilejson.workspace = true +tokio = { workspace = true, features = ["rt-multi-thread"] } +xxhash-rust.workspace = true # Bin dependencies anyhow = { workspace = true, optional = true } clap = { workspace = true, optional = true } env_logger = { workspace = true, optional = true } serde_yaml = { workspace = true, optional = true } -tokio = { workspace = true, features = ["rt-multi-thread"], optional = true } [dev-dependencies] # For testing, might as well use the same async framework as the Martin itself diff --git a/mbtiles/src/bin/mbtiles.rs b/mbtiles/src/bin/mbtiles.rs index 26992c236..7093c2bbd 100644 --- a/mbtiles/src/bin/mbtiles.rs +++ b/mbtiles/src/bin/mbtiles.rs @@ -4,7 +4,7 @@ use clap::{Parser, Subcommand}; use log::error; use mbtiles::{ apply_patch, AggHashType, CopyDuplicateMode, CopyType, IntegrityCheckType, MbtResult, - MbtTypeCli, Mbtiles, MbtilesCopier, UpdateZoomType, + MbtTypeCli, Mbtiles, MbtilesCopier, PatchType, UpdateZoomType, }; use tilejson::Bounds; @@ -115,6 +115,9 @@ pub struct CopyArgs { /// Use `mbtiles apply-patch` to apply the patch file in-place, without making a copy of the original. #[arg(long, conflicts_with("diff_with_file"))] apply_patch: Option, + /// Specify the type of patch file to generate. + #[arg(long, requires("diff_with_file"), default_value_t=PatchType::default())] + patch_type: PatchType, } #[allow(clippy::doc_markdown)] @@ -126,6 +129,9 @@ pub struct DiffArgs { file2: PathBuf, /// Output file to write the resulting difference to diff: PathBuf, + /// Specify the type of patch file to generate. + #[arg(long, default_value_t=PatchType::default())] + patch_type: PatchType, #[command(flatten)] pub options: SharedCopyOpts, @@ -175,11 +181,12 @@ impl SharedCopyOpts { dst_file: PathBuf, diff_with_file: Option, apply_patch: Option, + patch_type: PatchType, ) -> MbtilesCopier { MbtilesCopier { src_file, dst_file, - diff_with_file, + diff_with_file: diff_with_file.map(|p| (p, patch_type)), apply_patch, // Shared copy: self.copy, @@ -232,13 +239,18 @@ async fn main_int() -> anyhow::Result<()> { args.dst_file, args.diff_with_file, args.apply_patch, + args.patch_type, ); copier.run().await?; } Commands::Diff(args) => { - let copier = args - .options - .into_copier(args.file1, args.diff, Some(args.file2), None); + let copier = args.options.into_copier( + args.file1, + args.diff, + Some(args.file2), + None, + args.patch_type, + ); copier.run().await?; } Commands::ApplyPatch { @@ -317,6 +329,7 @@ mod tests { use clap::error::ErrorKind; use clap::Parser; use mbtiles::CopyDuplicateMode; + use mbtiles::PatchType::Whole; use super::*; use crate::Commands::{ApplyPatch, Copy, Diff, MetaGetValue, MetaSetValue, Validate}; @@ -527,6 +540,7 @@ mod tests { file1: PathBuf::from("file1.mbtiles"), file2: PathBuf::from("file2.mbtiles"), diff: PathBuf::from("../delta.mbtiles"), + patch_type: Whole, options: SharedCopyOpts { on_duplicate: Some(CopyDuplicateMode::Override), ..Default::default() diff --git a/mbtiles/src/bindiff.rs b/mbtiles/src/bindiff.rs new file mode 100644 index 000000000..e6ad0dbe3 --- /dev/null +++ b/mbtiles/src/bindiff.rs @@ -0,0 +1,390 @@ +use std::future::Future; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::Ordering::Relaxed; +use std::sync::Arc; +use std::time::Instant; + +use flume::{bounded, Receiver, Sender}; +use futures::TryStreamExt; +use log::{debug, error, info}; +use martin_tile_utils::{decode_brotli, decode_gzip, encode_brotli, encode_gzip, TileCoord}; +use sqlite_compressions::{BsdiffRawDiffer, Differ as _}; +use sqlx::{query, Executor, Row, SqliteConnection}; +use xxhash_rust::xxh3::xxh3_64; + +use crate::MbtType::{Flat, FlatWithHash, Normalized}; +use crate::PatchType::Whole; +use crate::{ + create_bsdiffraw_tables, get_bsdiff_tbl_name, MbtError, MbtResult, MbtType, Mbtiles, PatchType, +}; + +pub trait BinDiffer: Sized + Send + Sync + 'static { + fn query( + &self, + sql_where: String, + tx_wrk: Sender, + ) -> impl Future> + Send; + + fn process(&self, value: S) -> MbtResult; + + fn before_insert( + &self, + conn: &mut SqliteConnection, + ) -> impl Future> + Send; + + fn insert( + &self, + value: T, + conn: &mut SqliteConnection, + ) -> impl Future> + Send; + + async fn run(self, conn: &mut SqliteConnection, sql_where: String) -> MbtResult<()> { + let patcher = Arc::new(self); + let has_errors = Arc::new(AtomicBool::new(false)); + let (tx_wrk, rx_wrk) = bounded(num_cpus::get() * 3); + let (tx_ins, rx_ins) = bounded::(num_cpus::get() * 3); + + { + let has_errors = has_errors.clone(); + let patcher = patcher.clone(); + tokio::spawn(async move { + if let Err(e) = patcher.query(sql_where, tx_wrk).await { + error!("Failed to query bindiff data: {e}"); + has_errors.store(true, Relaxed); + } + }); + } + + start_processor_threads(patcher.clone(), rx_wrk, tx_ins, has_errors.clone()); + recv_and_insert(patcher, conn, rx_ins).await?; + + if has_errors.load(Relaxed) { + Err(MbtError::BindiffError) + } else { + Ok(()) + } + } +} + +async fn recv_and_insert>( + patcher: Arc

, + conn: &mut SqliteConnection, + rx_ins: Receiver, +) -> MbtResult<()> { + patcher.before_insert(conn).await?; + conn.execute("BEGIN").await?; + let mut inserted = 0; + let mut last_report_ts = Instant::now(); + while let Ok(res) = rx_ins.recv_async().await { + patcher.insert(res, conn).await?; + inserted += 1; + if inserted % 100 == 0 { + conn.execute("COMMIT").await?; + if last_report_ts.elapsed().as_secs() >= 10 { + info!("Processed {inserted} bindiff tiles"); + last_report_ts = Instant::now(); + } + conn.execute("BEGIN").await?; + } + } + conn.execute("COMMIT").await?; + info!("Finished processing {inserted} bindiff tiles"); + + Ok(()) +} + +// Both tx and rcv must be consumed, or it will run forever +#[allow(clippy::needless_pass_by_value)] +fn start_processor_threads>( + patcher: Arc

, + rx_wrk: Receiver, + tx_ins: Sender, + has_errors: Arc, +) { + (0..num_cpus::get()).for_each(|_| { + let rx_wrk = rx_wrk.clone(); + let tx_ins = tx_ins.clone(); + let has_errors = has_errors.clone(); + let patcher = patcher.clone(); + tokio::spawn(async move { + while let Ok(wrk) = rx_wrk.recv_async().await { + if match patcher.process(wrk) { + Ok(res) => tx_ins.send_async(res).await.is_err(), + Err(e) => { + error!("Failed to process bindiff data: {e}"); + true + } + } { + has_errors.store(true, Relaxed); + } + // also stop processing if another processor stopped + if has_errors.load(Relaxed) { + break; + } + } + }); + }); +} + +pub struct DifferBefore { + coord: TileCoord, + old_tile_data: Vec, + new_tile_data: Vec, +} + +pub struct DifferAfter { + coord: TileCoord, + data: Vec, + new_tile_hash: u64, +} + +pub struct BinDiffDiffer { + src_mbt: Mbtiles, + dif_mbt: Mbtiles, + dif_type: MbtType, + patch_type: PatchType, + insert_sql: String, +} + +impl BinDiffDiffer { + pub fn new( + src_mbt: Mbtiles, + dif_mbt: Mbtiles, + dif_type: MbtType, + patch_type: PatchType, + ) -> Self { + assert_ne!(patch_type, Whole, "Invalid for BinDiffDiffer"); + let insert_sql = format!( + "INSERT INTO {}(zoom_level, tile_column, tile_row, patch_data, tile_xxh3_64_hash) VALUES (?, ?, ?, ?, ?)", + get_bsdiff_tbl_name(patch_type)); + Self { + src_mbt, + dif_mbt, + dif_type, + patch_type, + insert_sql, + } + } +} + +impl BinDiffer for BinDiffDiffer { + async fn query(&self, sql_where: String, tx_wrk: Sender) -> MbtResult<()> { + let diff_tiles = match self.dif_type { + Flat => "diffDb.tiles", + FlatWithHash => "diffDb.tiles_with_hash", + Normalized { .. } => { + " + (SELECT zoom_level, tile_column, tile_row, tile_data, map.tile_id AS tile_hash + FROM diffDb.map JOIN diffDb.images ON diffDb.map.tile_id = diffDb.images.tile_id)" + } + }; + + let sql = format!( + " + SELECT srcTiles.zoom_level + , srcTiles.tile_column + , srcTiles.tile_row + , srcTiles.tile_data old_tile_data + , difTiles.tile_data new_tile_data + FROM tiles AS srcTiles JOIN {diff_tiles} AS difTiles + ON srcTiles.zoom_level = difTiles.zoom_level + AND srcTiles.tile_column = difTiles.tile_column + AND srcTiles.tile_row = difTiles.tile_row + WHERE srcTiles.tile_data != difTiles.tile_data {sql_where}" + ); + + let mut conn = self.src_mbt.open_readonly().await?; + self.dif_mbt.attach_to(&mut conn, "diffDb").await?; + debug!("Querying source data with {sql}"); + let mut rows = query(&sql).fetch(&mut conn); + + while let Some(row) = rows.try_next().await? { + let work = DifferBefore { + coord: TileCoord { + z: row.get(0), + x: row.get(1), + y: row.get(2), + }, + old_tile_data: row.get(3), + new_tile_data: row.get(4), + }; + if tx_wrk.send_async(work).await.is_err() { + break; // the receiver has been dropped + } + } + + Ok(()) + } + + fn process(&self, value: DifferBefore) -> MbtResult { + let mut old_tile = value.old_tile_data; + let mut new_tile = value.new_tile_data; + if self.patch_type == PatchType::BinDiffGz { + old_tile = decode_gzip(&old_tile).inspect_err(|e| { + error!("Unable to gzip-decode source tile {:?}: {e}", value.coord); + })?; + new_tile = decode_gzip(&new_tile).inspect_err(|e| { + error!("Unable to gzip-decode diff tile {:?}: {e}", value.coord); + })?; + } + let new_tile_hash = xxh3_64(&new_tile); + let data = BsdiffRawDiffer::diff(&old_tile, &new_tile).expect("BinDiff failure"); + let data = encode_brotli(&data)?; + + Ok(DifferAfter { + coord: value.coord, + data, + new_tile_hash, + }) + } + + async fn before_insert(&self, conn: &mut SqliteConnection) -> MbtResult<()> { + create_bsdiffraw_tables(conn, self.patch_type).await + } + + async fn insert(&self, value: DifferAfter, conn: &mut SqliteConnection) -> MbtResult<()> { + #[allow(clippy::cast_possible_wrap)] + query(self.insert_sql.as_str()) + .bind(value.coord.z) + .bind(value.coord.x) + .bind(value.coord.y) + .bind(value.data) + .bind(value.new_tile_hash as i64) + .execute(&mut *conn) + .await?; + Ok(()) + } +} + +pub struct ApplierBefore { + coord: TileCoord, + tile_data: Vec, + patch_data: Vec, + uncompressed_tile_hash: u64, +} + +pub struct ApplierAfter { + coord: TileCoord, + data: Vec, + new_tile_hash: String, +} + +pub struct BinDiffPatcher { + src_mbt: Mbtiles, + dif_mbt: Mbtiles, + dst_type: MbtType, + patch_type: PatchType, +} + +impl BinDiffPatcher { + pub fn new( + src_mbt: Mbtiles, + dif_mbt: Mbtiles, + dst_type: MbtType, + patch_type: PatchType, + ) -> Self { + Self { + src_mbt, + dif_mbt, + dst_type, + patch_type, + } + } +} + +impl BinDiffer for BinDiffPatcher { + async fn query(&self, sql_where: String, tx_wrk: Sender) -> MbtResult<()> { + let tbl = get_bsdiff_tbl_name(self.patch_type); + let sql = format!( + " + SELECT srcTiles.zoom_level + , srcTiles.tile_column + , srcTiles.tile_row + , srcTiles.tile_data + , patch_data + , tile_xxh3_64_hash + FROM tiles AS srcTiles JOIN diffDb.{tbl} AS difTiles + ON srcTiles.zoom_level = difTiles.zoom_level + AND srcTiles.tile_column = difTiles.tile_column + AND srcTiles.tile_row = difTiles.tile_row + WHERE TRUE {sql_where}" + ); + + let mut conn = self.src_mbt.open_readonly().await?; + self.dif_mbt.attach_to(&mut conn, "diffDb").await?; + debug!("Querying {tbl} table with {sql}"); + let mut rows = query(&sql).fetch(&mut conn); + + while let Some(row) = rows.try_next().await? { + let work = ApplierBefore { + coord: TileCoord { + z: row.get(0), + x: row.get(1), + y: row.get(2), + }, + tile_data: row.get(3), + patch_data: row.get(4), + #[allow(clippy::cast_sign_loss)] + uncompressed_tile_hash: row.get::(5) as u64, + }; + if tx_wrk.send_async(work).await.is_err() { + break; // the receiver has been dropped + } + } + + Ok(()) + } + + fn process(&self, value: ApplierBefore) -> MbtResult { + let tile_data = decode_gzip(&value.tile_data) + .inspect_err(|e| error!("Unable to gzip-decode source tile {:?}: {e}", value.coord))?; + let patch_data = decode_brotli(&value.patch_data) + .inspect_err(|e| error!("Unable to brotli-decode patch data {:?}: {e}", value.coord))?; + let new_tile = BsdiffRawDiffer::patch(&tile_data, &patch_data) + .inspect_err(|e| error!("Unable to patch tile {:?}: {e}", value.coord))?; + let new_tile_hash = xxh3_64(&new_tile); + if new_tile_hash != value.uncompressed_tile_hash { + return Err(MbtError::BinDiffIncorrectTileHash( + value.coord.to_string(), + value.uncompressed_tile_hash.to_string(), + new_tile_hash.to_string(), + )); + } + + let data = encode_gzip(&new_tile)?; + + Ok(ApplierAfter { + coord: value.coord, + new_tile_hash: if self.dst_type == FlatWithHash { + format!("{:X}", md5::compute(&data)) + } else { + String::default() // This is a fast noop, no memory alloc is performed + }, + data, + }) + } + + async fn before_insert(&self, _conn: &mut SqliteConnection) -> MbtResult<()> { + Ok(()) + } + + async fn insert(&self, value: ApplierAfter, conn: &mut SqliteConnection) -> MbtResult<()> { + let mut q = query( + match self.dst_type { + Flat =>"INSERT INTO tiles (zoom_level, tile_column, tile_row, tile_data) VALUES (?, ?, ?, ?)", + FlatWithHash => "INSERT INTO tiles_with_hash (zoom_level, tile_column, tile_row, tile_data, tile_hash) VALUES (?, ?, ?, ?, ?)", + v @ Normalized { .. } => return Err(MbtError::BinDiffRequiresFlatWithHash(v)), + }) + .bind(value.coord.z) + .bind(value.coord.x) + .bind(value.coord.y) + .bind(value.data); + + if self.dst_type == FlatWithHash { + q = q.bind(value.new_tile_hash); + } + + q.execute(&mut *conn).await?; + Ok(()) + } +} diff --git a/mbtiles/src/copier.rs b/mbtiles/src/copier.rs index a550b8460..e87c76ecc 100644 --- a/mbtiles/src/copier.rs +++ b/mbtiles/src/copier.rs @@ -10,6 +10,7 @@ use sqlite_hashes::rusqlite::Connection; use sqlx::{query, Connection as _, Executor as _, Row, SqliteConnection}; use tilejson::Bounds; +use crate::bindiff::{BinDiffDiffer, BinDiffPatcher, BinDiffer as _}; use crate::errors::MbtResult; use crate::mbtiles::PatchFileInfo; use crate::queries::{ @@ -18,9 +19,11 @@ use crate::queries::{ use crate::AggHashType::Verify; use crate::IntegrityCheckType::Quick; use crate::MbtType::{Flat, FlatWithHash, Normalized}; +use crate::PatchType::{BinDiffGz, BinDiffRaw, Whole}; use crate::{ - invert_y_value, reset_db_settings, CopyType, MbtError, MbtType, MbtTypeCli, Mbtiles, - AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY, + action_with_rusqlite, get_bsdiff_tbl_name, invert_y_value, reset_db_settings, AggHashType, + CopyType, MbtError, MbtType, MbtTypeCli, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, + AGG_TILES_HASH_BEFORE_APPLY, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumDisplay)] @@ -32,6 +35,19 @@ pub enum CopyDuplicateMode { Abort, } +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, EnumDisplay)] +#[enum_display(case = "Kebab")] +#[cfg_attr(feature = "cli", derive(clap::ValueEnum))] +pub enum PatchType { + /// Patch file will contain the entire tile if it is different from the source + #[default] + Whole, + /// Use bin-diff to store only the bytes changed between two versions of each tile. Treats content as gzipped blobs, decoding them before diffing. + BinDiffGz, + /// Use bin-diff to store only the bytes changed between two versions of each tile. Treats content as blobs without any special encoding. + BinDiffRaw, +} + impl CopyDuplicateMode { #[must_use] pub fn to_sql(&self) -> &'static str { @@ -65,8 +81,8 @@ pub struct MbtilesCopier { pub zoom_levels: Vec, /// Bounding box to copy, in the format `min_lon,min_lat,max_lon,max_lat`. Can be used multiple times. pub bbox: Vec, - /// Compare source file with this file, and only copy non-identical tiles to destination. - pub diff_with_file: Option, + /// Compare source file with this file, and only copy non-identical tiles to destination. Also specifies the type of patch to generate. + pub diff_with_file: Option<(PathBuf, PatchType)>, /// Apply a patch file while copying src to dst. pub apply_patch: Option, /// Skip generating a global hash for mbtiles validation. By default, `mbtiles` will compute `agg_tiles_hash` metadata value. @@ -109,7 +125,7 @@ impl MbtileCopierInt { if options.src_file == options.dst_file { return Err(MbtError::SameSourceAndDestination(options.src_file)); } - if let Some(diff_file) = &options.diff_with_file { + if let Some((diff_file, _)) = &options.diff_with_file { if options.src_file == *diff_file || options.dst_file == *diff_file { return Err(MbtError::SameDiffAndSourceOrDestination(options.src_file)); } @@ -128,9 +144,10 @@ impl MbtileCopierInt { } pub async fn run(self) -> MbtResult { - if let Some(diff_file) = &self.options.diff_with_file { + if let Some((diff_file, patch_type)) = &self.options.diff_with_file { let mbt = Mbtiles::new(diff_file)?; - self.run_with_diff(mbt).await + let patch_type = *patch_type; + self.run_with_diff(mbt, patch_type).await } else if let Some(patch_file) = &self.options.apply_patch { let mbt = Mbtiles::new(patch_file)?; self.run_with_patch(mbt).await @@ -193,7 +210,11 @@ impl MbtileCopierInt { } /// Compare two files, and write their difference to the diff file - async fn run_with_diff(self, dif_mbt: Mbtiles) -> MbtResult { + async fn run_with_diff( + self, + dif_mbt: Mbtiles, + patch_type: PatchType, + ) -> MbtResult { let mut dif_conn = dif_mbt.open_readonly().await?; let dif_info = dif_mbt.examine_diff(&mut dif_conn).await?; dif_mbt.assert_hashes(&dif_info, self.options.force)?; @@ -210,14 +231,23 @@ impl MbtileCopierInt { dif_mbt.attach_to(&mut conn, "diffDb").await?; let dst_type = self.options.dst_type().unwrap_or(src_info.mbt_type); + if patch_type != Whole && matches!(dst_type, Normalized { .. }) { + return Err(MbtError::BinDiffRequiresFlatWithHash(dst_type)); + } + info!( - "Comparing {src_mbt} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_path} ({dst_type})", + "Comparing {src_mbt} ({src_type}) and {dif_path} ({dif_type}) {what}into a new file {dst_path} ({dst_type}){patch}", src_mbt = self.src_mbt, src_type = src_info.mbt_type, dif_path = dif_mbt.filepath(), dif_type = dif_info.mbt_type, what = self.copy_text(), - dst_path = self.dst_mbt.filepath() + dst_path = self.dst_mbt.filepath(), + patch = match patch_type { + Whole => {""} + BinDiffGz => {" with bin-diff"} + BinDiffRaw => {" with bin-diff-raw"} + } ); self.init_schema(&mut conn, src_info.mbt_type, dst_type) @@ -226,10 +256,21 @@ impl MbtileCopierInt { &mut conn, CopyDuplicateMode::Override, dst_type, - &get_select_from_with_diff(dif_info.mbt_type, dst_type), + &get_select_from_with_diff(dif_info.mbt_type, dst_type, patch_type), ) .await?; + // Bindiff copying uses separate threads to read and write data, so we need + // to open a separate connection to source+diff files to avoid locking issues + detach_db(&mut conn, "diffDb").await?; + detach_db(&mut conn, "sourceDb").await?; + + if patch_type != Whole { + BinDiffDiffer::new(self.src_mbt.clone(), dif_mbt, dif_info.mbt_type, patch_type) + .run(&mut conn, self.get_where_clause("srcTiles.")) + .await?; + } + if let Some(hash) = src_info.agg_tiles_hash { self.dst_mbt .set_metadata_value(&mut conn, AGG_TILES_HASH_BEFORE_APPLY, &hash) @@ -246,8 +287,6 @@ impl MbtileCopierInt { self.dst_mbt.update_agg_tiles_hash(&mut conn).await?; } - detach_db(&mut conn, "diffDb").await?; - detach_db(&mut conn, "sourceDb").await?; self.validate(&self.dst_mbt, &mut conn).await?; Ok(conn) @@ -262,6 +301,10 @@ impl MbtileCopierInt { dif_conn.close().await?; let src_type = self.validate_src_file().await?.mbt_type; + let dst_type = self.options.dst_type().unwrap_or(src_type); + if dif_info.patch_type != Whole && matches!(dst_type, Normalized { .. }) { + return Err(MbtError::BinDiffRequiresFlatWithHash(dst_type)); + } let mut conn = self.dst_mbt.open_or_new().await?; if !is_empty_database(&mut conn).await? { @@ -271,49 +314,76 @@ impl MbtileCopierInt { self.src_mbt.attach_to(&mut conn, "sourceDb").await?; dif_mbt.attach_to(&mut conn, "diffDb").await?; - let dst_type = self.options.dst_type().unwrap_or(src_type); - info!("Applying patch from {dif_path} ({dif_type}) to {src_mbt} ({src_type}) {what}into a new file {dst_path} ({dst_type})", + info!("Applying patch from {dif_path} ({dif_type}) to {src_mbt} ({src_type}) {what}into a new file {dst_path} ({dst_type}){patch}", dif_path = dif_mbt.filepath(), dif_type = dif_info.mbt_type, src_mbt = self.src_mbt, what = self.copy_text(), - dst_path = self.dst_mbt.filepath()); + dst_path = self.dst_mbt.filepath(), + patch = match dif_info.patch_type { + Whole => {""} + BinDiffGz => {" with bin-diff"} + BinDiffRaw => {" with bin-diff-raw"} + } + ); self.init_schema(&mut conn, src_type, dst_type).await?; self.copy_with_rusqlite( &mut conn, CopyDuplicateMode::Override, dst_type, - &get_select_from_apply_patch(src_type, dif_info.mbt_type, dst_type), + &get_select_from_apply_patch(src_type, &dif_info, dst_type), ) .await?; + detach_db(&mut conn, "diffDb").await?; + detach_db(&mut conn, "sourceDb").await?; + + if dif_info.patch_type != Whole { + BinDiffPatcher::new( + self.src_mbt.clone(), + dif_mbt.clone(), + dst_type, + dif_info.patch_type, + ) + .run(&mut conn, self.get_where_clause("srcTiles.")) + .await?; + } + // TODO: perhaps disable all except --copy all when using with diffs, or else is not making much sense if self.options.copy.copy_tiles() && !self.options.skip_agg_tiles_hash { self.dst_mbt.update_agg_tiles_hash(&mut conn).await?; - - let new_hash = self.dst_mbt.get_agg_tiles_hash(&mut conn).await?; - match (dif_info.agg_tiles_hash_after_apply, new_hash) { - (Some(expected), Some(actual)) if expected != actual => { - let err = MbtError::AggHashMismatchAfterApply( - dif_mbt.filepath().to_string(), - expected, - self.dst_mbt.filepath().to_string(), - actual, - ); - if !self.options.force { - return Err(err); + if dif_info.patch_type == BinDiffGz { + info!("Skipping {AGG_TILES_HASH_AFTER_APPLY} validation because re-gzip-ing could produce different tile data. Each bindiff-ed tile was still verified with a hash value"); + } else { + let new_hash = self.dst_mbt.get_agg_tiles_hash(&mut conn).await?; + match (dif_info.agg_tiles_hash_after_apply, new_hash) { + (Some(expected), Some(actual)) if expected != actual => { + let err = MbtError::AggHashMismatchAfterApply( + dif_mbt.filepath().to_string(), + expected, + self.dst_mbt.filepath().to_string(), + actual, + ); + if !self.options.force { + return Err(err); + } + warn!("{err}"); } - warn!("{err}"); + _ => {} } - _ => {} } } - detach_db(&mut conn, "diffDb").await?; - detach_db(&mut conn, "sourceDb").await?; + let hash_type = if dif_info.patch_type == BinDiffGz || self.options.skip_agg_tiles_hash { + AggHashType::Off + } else { + Verify + }; - self.validate(&self.dst_mbt, &mut conn).await?; + if self.options.validate { + self.dst_mbt.validate(&mut conn, Quick, hash_type).await?; + } Ok(conn) } @@ -350,22 +420,17 @@ impl MbtileCopierInt { dst_type: MbtType, select_from: &str, ) -> Result<(), MbtError> { - // SAFETY: This must be scoped to make sure the handle is dropped before we continue using conn - // Make sure not to execute any other queries while the handle is locked - let mut handle_lock = conn.lock_handle().await?; - let handle = handle_lock.as_raw_handle().as_ptr(); - - // SAFETY: this is safe as long as handle_lock is valid. We will drop the lock. - let rusqlite_conn = unsafe { Connection::from_handle(handle) }?; - if self.options.copy.copy_tiles() { - self.copy_tiles(&rusqlite_conn, dst_type, on_duplicate, select_from)?; + action_with_rusqlite(conn, |c| { + self.copy_tiles(c, dst_type, on_duplicate, select_from) + }) + .await?; } else { debug!("Skipping copying tiles"); } if self.options.copy.copy_metadata() { - self.copy_metadata(&rusqlite_conn, on_duplicate) + action_with_rusqlite(conn, |c| self.copy_metadata(c, on_duplicate)).await } else { debug!("Skipping copying metadata"); Ok(()) @@ -433,7 +498,7 @@ impl MbtileCopierInt { select_from: &str, ) -> Result<(), MbtError> { let on_dupl = on_duplicate.to_sql(); - let where_clause = self.get_where_clause(); + let where_clause = self.get_where_clause(""); let sql_cond = Self::get_on_duplicate_sql_cond(on_duplicate, dst_type); let sql = match dst_type { @@ -511,7 +576,7 @@ impl MbtileCopierInt { // DB objects must be created in a specific order: tables, views, triggers, indexes. let sql_objects = conn .fetch_all( - "SELECT sql + "SELECT sql, tbl_name, type FROM sourceDb.sqlite_schema WHERE tbl_name IN ('metadata', 'tiles', 'map', 'images', 'tiles_with_hash') AND type IN ('table', 'view', 'trigger', 'index') @@ -525,6 +590,11 @@ impl MbtileCopierInt { .await?; for row in sql_objects { + debug!( + "Creating {typ} {tbl_name}...", + typ = row.get::<&str, _>(2), + tbl_name = row.get::<&str, _>(1), + ); query(row.get(0)).execute(&mut *conn).await?; } if dst.is_normalized() { @@ -566,18 +636,18 @@ impl MbtileCopierInt { /// Format SQL WHERE clause and return it along with the query arguments. /// Note that there is no risk of SQL injection here, as the arguments are integers. - fn get_where_clause(&self) -> String { + fn get_where_clause(&self, prefix: &str) -> String { let mut sql = if !&self.options.zoom_levels.is_empty() { let zooms = self.options.zoom_levels.iter().join(","); - format!(" AND zoom_level IN ({zooms})") + format!(" AND {prefix}zoom_level IN ({zooms})") } else if let Some(min_zoom) = self.options.min_zoom { if let Some(max_zoom) = self.options.max_zoom { - format!(" AND zoom_level BETWEEN {min_zoom} AND {max_zoom}") + format!(" AND {prefix}zoom_level BETWEEN {min_zoom} AND {max_zoom}") } else { - format!(" AND zoom_level >= {min_zoom}") + format!(" AND {prefix}zoom_level >= {min_zoom}") } } else if let Some(max_zoom) = self.options.max_zoom { - format!(" AND zoom_level <= {max_zoom}") + format!(" AND {prefix}zoom_level <= {max_zoom}") } else { String::new() }; @@ -600,7 +670,8 @@ impl MbtileCopierInt { } writeln!( sql, - "((tile_column * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_x} AND {max_x} AND (tile_row * (1 << ({MAX_ZOOM} - zoom_level))) BETWEEN {min_y} AND {max_y})", + "(({prefix}tile_column * (1 << ({MAX_ZOOM} - {prefix}zoom_level))) BETWEEN {min_x} AND {max_x} \ + AND ({prefix}tile_row * (1 << ({MAX_ZOOM} - {prefix}zoom_level))) BETWEEN {min_y} AND {max_y})", ).unwrap(); } sql.push(')'); @@ -610,7 +681,11 @@ impl MbtileCopierInt { } } -fn get_select_from_apply_patch(src_type: MbtType, dif_type: MbtType, dst_type: MbtType) -> String { +fn get_select_from_apply_patch( + src_type: MbtType, + dif_info: &PatchFileInfo, + dst_type: MbtType, +) -> String { fn query_for_dst(frm_db: &'static str, frm_type: MbtType, to_type: MbtType) -> String { match to_type { Flat => format!("{frm_db}.tiles"), @@ -648,13 +723,30 @@ fn get_select_from_apply_patch(src_type: MbtType, dif_type: MbtType, dst_type: M format!( ", COALESCE({}, {}) as tile_hash", - get_tile_hash_expr("difTiles", dif_type), + get_tile_hash_expr("difTiles", dif_info.mbt_type), get_tile_hash_expr("srcTiles", src_type) ) }; let src_tiles = query_for_dst("sourceDb", src_type, dst_type); - let diff_tiles = query_for_dst("diffDb", dif_type, dst_type); + let diff_tiles = query_for_dst("diffDb", dif_info.mbt_type, dst_type); + + let (bindiff_from, bindiff_cond) = if dif_info.patch_type == Whole { + (String::new(), "") + } else { + // do not copy any tiles that are in the patch table + let tbl = get_bsdiff_tbl_name(dif_info.patch_type); + ( + format!( + " + LEFT JOIN diffDb.{tbl} AS bdTbl + ON bdTbl.zoom_level = srcTiles.zoom_level + AND bdTbl.tile_column = srcTiles.tile_column + AND bdTbl.tile_row = srcTiles.tile_row" + ), + "AND bdTbl.patch_data ISNULL", + ) + }; // Take dif tile_data if it is set, otherwise take the one from src // Skip tiles if src and dif both have a matching index, but the dif tile_data is NULL @@ -669,11 +761,16 @@ fn get_select_from_apply_patch(src_type: MbtType, dif_type: MbtType, dst_type: M ON srcTiles.zoom_level = difTiles.zoom_level AND srcTiles.tile_column = difTiles.tile_column AND srcTiles.tile_row = difTiles.tile_row - WHERE (difTiles.zoom_level ISNULL OR difTiles.tile_data NOTNULL)" + {bindiff_from} + WHERE (difTiles.zoom_level ISNULL OR difTiles.tile_data NOTNULL) {bindiff_cond}" ) } -fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String { +fn get_select_from_with_diff( + dif_type: MbtType, + dst_type: MbtType, + patch_type: PatchType, +) -> String { let tile_hash_expr; let diff_tiles; if dst_type == Flat { @@ -695,6 +792,11 @@ fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String { }; } + let sql_cond = if patch_type == Whole { + "OR srcTiles.tile_data != difTiles.tile_data" + } else { + "" + }; format!( " SELECT COALESCE(srcTiles.zoom_level, difTiles.zoom_level) as zoom_level @@ -706,9 +808,9 @@ fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String { ON srcTiles.zoom_level = difTiles.zoom_level AND srcTiles.tile_column = difTiles.tile_column AND srcTiles.tile_row = difTiles.tile_row - WHERE (srcTiles.tile_data != difTiles.tile_data - OR srcTiles.tile_data ISNULL - OR difTiles.tile_data ISNULL)" + WHERE (srcTiles.tile_data ISNULL + OR difTiles.tile_data ISNULL + {sql_cond})" ) } @@ -920,7 +1022,7 @@ mod tests { let opt = MbtilesCopier { src_file: src.clone(), dst_file: dst.clone(), - diff_with_file: Some(diff_file.clone()), + diff_with_file: Some((diff_file.clone(), Whole)), force: true, ..Default::default() }; diff --git a/mbtiles/src/errors.rs b/mbtiles/src/errors.rs index 2f4e60924..9009d1987 100644 --- a/mbtiles/src/errors.rs +++ b/mbtiles/src/errors.rs @@ -95,6 +95,21 @@ pub enum MbtError { #[error("The {AGG_TILES_HASH_AFTER_APPLY}='{1}' in patch file {0} does not match {AGG_TILES_HASH}='{3}' in the file {2} after the patch was applied")] AggHashMismatchAfterApply(String, String, String, String), + + #[error("MBTile of type {0} is not supported when using bin-diff. The bin-diff format only works with flat and flat-with-hash MBTiles files.")] + BinDiffRequiresFlatWithHash(MbtType), + + #[error("Applying bindiff to tile {0} resulted in mismatching hash: expecting `{1}` != computed uncompressed value `{2}`")] + BinDiffIncorrectTileHash(String, String, String), + + #[error("Internal error creating bin-diff table")] + BindiffError, + + #[error("BinDiff patch files can be only applied with `mbtiles copy --apply-patch` command")] + UnsupportedPatchType, + + #[error(transparent)] + IoError(#[from] std::io::Error), } pub type MbtResult = Result; diff --git a/mbtiles/src/lib.rs b/mbtiles/src/lib.rs index 1f54ebb66..6359a2601 100644 --- a/mbtiles/src/lib.rs +++ b/mbtiles/src/lib.rs @@ -4,7 +4,7 @@ pub use sqlx; mod copier; -pub use copier::{CopyDuplicateMode, MbtilesCopier}; +pub use copier::{CopyDuplicateMode, MbtilesCopier, PatchType}; mod errors; pub use errors::{MbtError, MbtResult}; @@ -29,7 +29,10 @@ mod summary; mod update; pub use update::UpdateZoomType; +mod bindiff; + mod validation; + pub use validation::{ calc_agg_tiles_hash, AggHashType, IntegrityCheckType, MbtType, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY, diff --git a/mbtiles/src/mbtiles.rs b/mbtiles/src/mbtiles.rs index ebd2e5c2d..04323cafb 100644 --- a/mbtiles/src/mbtiles.rs +++ b/mbtiles/src/mbtiles.rs @@ -5,12 +5,13 @@ use std::path::Path; use enum_display::EnumDisplay; use log::debug; use serde::{Deserialize, Serialize}; +use sqlite_compressions::{register_bsdiffraw_functions, register_gzip_functions}; use sqlite_hashes::register_md5_functions; use sqlx::sqlite::SqliteConnectOptions; use sqlx::{query, Connection as _, Executor, SqliteConnection, SqliteExecutor, Statement}; use crate::errors::{MbtError, MbtResult}; -use crate::{invert_y_value, CopyDuplicateMode, MbtType}; +use crate::{invert_y_value, CopyDuplicateMode, MbtType, PatchType}; #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize, EnumDisplay)] #[enum_display(case = "Kebab")] @@ -47,6 +48,7 @@ pub struct PatchFileInfo { pub agg_tiles_hash: Option, pub agg_tiles_hash_before_apply: Option, pub agg_tiles_hash_after_apply: Option, + pub patch_type: PatchType, } #[derive(Clone, Debug)] @@ -101,7 +103,7 @@ impl Mbtiles { async fn open_int(opt: &SqliteConnectOptions) -> Result { let mut conn = SqliteConnection::connect_with(opt).await?; - attach_hash_fn(&mut conn).await?; + attach_sqlite_fn(&mut conn).await?; Ok(conn) } @@ -221,13 +223,15 @@ impl Mbtiles { } } -pub async fn attach_hash_fn(conn: &mut SqliteConnection) -> MbtResult<()> { +pub async fn attach_sqlite_fn(conn: &mut SqliteConnection) -> MbtResult<()> { let mut handle_lock = conn.lock_handle().await?; let handle = handle_lock.as_raw_handle().as_ptr(); // Safety: we know that the handle is a SQLite connection is locked and is not used anywhere else. // The registered functions will be dropped when SQLX drops DB connection. let rc = unsafe { sqlite_hashes::rusqlite::Connection::from_handle(handle) }?; register_md5_functions(&rc)?; + register_bsdiffraw_functions(&rc)?; + register_gzip_functions(&rc)?; Ok(()) } diff --git a/mbtiles/src/patcher.rs b/mbtiles/src/patcher.rs index 6650021cf..163b5f7fb 100644 --- a/mbtiles/src/patcher.rs +++ b/mbtiles/src/patcher.rs @@ -5,6 +5,7 @@ use sqlx::{query, Connection as _}; use crate::queries::detach_db; use crate::MbtType::{Flat, FlatWithHash, Normalized}; +use crate::PatchType::Whole; use crate::{ MbtError, MbtResult, MbtType, Mbtiles, AGG_TILES_HASH, AGG_TILES_HASH_AFTER_APPLY, AGG_TILES_HASH_BEFORE_APPLY, @@ -16,6 +17,9 @@ pub async fn apply_patch(base_file: PathBuf, patch_file: PathBuf, force: bool) - let mut conn = patch_mbt.open_readonly().await?; let patch_info = patch_mbt.examine_diff(&mut conn).await?; + if patch_info.patch_type != Whole { + return Err(MbtError::UnsupportedPatchType); + } patch_mbt.validate_diff_info(&patch_info, force)?; let patch_type = patch_info.mbt_type; conn.close().await?; diff --git a/mbtiles/src/queries.rs b/mbtiles/src/queries.rs index ade3bf19e..7443a406e 100644 --- a/mbtiles/src/queries.rs +++ b/mbtiles/src/queries.rs @@ -1,10 +1,11 @@ use log::debug; use martin_tile_utils::MAX_ZOOM; -use sqlx::{query, Executor as _, SqliteExecutor}; +use sqlite_compressions::rusqlite::Connection; +use sqlx::{query, Executor as _, Row, SqliteConnection, SqliteExecutor}; use crate::errors::MbtResult; use crate::MbtError::InvalidZoomValue; -use crate::MbtType; +use crate::{MbtType, PatchType}; /// Returns true if the database is empty (no tables/indexes/...) pub async fn is_empty_database(conn: &mut T) -> MbtResult @@ -209,6 +210,75 @@ where Ok(()) } +#[must_use] +pub fn get_bsdiff_tbl_name(patch_type: PatchType) -> &'static str { + match patch_type { + PatchType::BinDiffRaw => "bsdiffraw", + PatchType::BinDiffGz => "bsdiffrawgz", + PatchType::Whole => panic!("Unexpected PatchType::Whole"), + } +} + +pub async fn create_bsdiffraw_tables(conn: &mut T, patch_type: PatchType) -> MbtResult<()> +where + for<'e> &'e mut T: SqliteExecutor<'e>, +{ + let tbl = get_bsdiff_tbl_name(patch_type); + debug!("Creating if needed bin-diff table: {tbl}(z,x,y,data,hash)"); + let sql = format!( + "CREATE TABLE IF NOT EXISTS {tbl} ( + zoom_level integer NOT NULL, + tile_column integer NOT NULL, + tile_row integer NOT NULL, + patch_data blob NOT NULL, + tile_xxh3_64_hash integer NOT NULL, + PRIMARY KEY(zoom_level, tile_column, tile_row));" + ); + + conn.execute(sql.as_str()).await?; + Ok(()) +} + +/// Check if `MBTiles` has a table or a view named `bsdiffraw` or `bsdiffrawgz` with needed fields, +/// and return the corresponding patch type. If missing, return `PatchType::Whole` +pub async fn get_patch_type(conn: &mut T) -> MbtResult +where + for<'e> &'e mut T: SqliteExecutor<'e>, +{ + for (tbl, pt) in [ + ("bsdiffraw", PatchType::BinDiffRaw), + ("bsdiffrawgz", PatchType::BinDiffGz), + ] { + // 'bsdiffraw' or 'bsdiffrawgz' table or view columns and their types are as expected: + // 5 columns (zoom_level, tile_column, tile_row, tile_data, tile_hash). + // The order is not important + let sql = format!( + "SELECT ( + SELECT COUNT(*) = 5 + FROM pragma_table_info('{tbl}') + WHERE ((name = 'zoom_level' AND type = 'INTEGER') + OR (name = 'tile_column' AND type = 'INTEGER') + OR (name = 'tile_row' AND type = 'INTEGER') + OR (name = 'patch_data' AND type = 'BLOB') + OR (name = 'tile_xxh3_64_hash' AND type = 'INTEGER')) + -- + ) as is_valid;" + ); + + if query(&sql) + .fetch_one(&mut *conn) + .await? + .get::, _>(0) + .unwrap_or_default() + == 1 + { + return Ok(pt); + } + } + + Ok(PatchType::Whole) +} + pub async fn create_normalized_tables(conn: &mut T) -> MbtResult<()> where for<'e> &'e mut T: SqliteExecutor<'e>, @@ -300,6 +370,7 @@ where } } +/// Execute `DETACH DATABASE` command pub async fn detach_db(conn: &mut T, name: &str) -> MbtResult<()> where for<'e> &'e mut T: SqliteExecutor<'e>, @@ -324,6 +395,7 @@ fn validate_zoom(zoom: Option, zoom_name: &'static str) -> MbtResult

Changelog

Sourced from log's changelog.

[0.4.22] - 2024-06-27

What's Changed

New Contributors

Full Changelog: https://github.com/rust-lang/log/compare/0.4.21...0.4.22

Commits
  • d5ba2cf Merge pull request #634 from rust-lang/cargo/0.4.22
  • d1a8306 prepare for 0.4.22 release
  • 46894ef Merge pull request #633 from rust-lang/feat/panic-info
  • e0d389c Merge pull request #632 from rust-lang/feat/loosen-atomics
  • c9e5e13 use Location::caller() for file and line info
  • 507b672 loosen orderings for logger initialization
  • c879b01 Merge pull request #628 from Thomasdezeeuw/fix-warnings
  • 405fdb4 Merge pull request #627 from Thomasdezeeuw/check-features
  • 1307ade Remove unneeded import
  • 710560e Don't use --all-features in CI
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=log&package-manager=cargo&previous-version=0.4.21&new-version=0.4.22)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04870c214..d19b7265f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2332,9 +2332,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "martin" From e939b388b8ea547ae4cbd794f2182f46eb51d676 Mon Sep 17 00:00:00 2001 From: Josh Lee Date: Fri, 28 Jun 2024 11:51:58 -0400 Subject: [PATCH 157/164] Typo fix (#1388) I'm torn between "Run this bash script to create this file" and "The file should look like this" and open to ideas for clarity, but I think adding the backslash is more likely to be noticed by someone who creates the file without using the heredoc than the other way around. Fixes #1335 --- docs/src/run-with-lambda.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/run-with-lambda.md b/docs/src/run-with-lambda.md index e7c462705..de2cd3f1a 100644 --- a/docs/src/run-with-lambda.md +++ b/docs/src/run-with-lambda.md @@ -60,7 +60,7 @@ Every zip-based Lambda function runs a file called `bootstrap`. cat <src/bootstrap #!/bin/sh set -eu -exec martin --config ${_HANDLER}.yaml +exec martin --config \${_HANDLER}.yaml EOF ``` From b814ac0f966e9edab9a31c7a097e1a0d379bedbd Mon Sep 17 00:00:00 2001 From: Teebo <1559534+tbo47@users.noreply.github.com> Date: Sat, 29 Jun 2024 17:49:49 +0000 Subject: [PATCH 158/164] fix curl url for linux mbtiles demo (#1387) Co-authored-by: tbo47 Co-authored-by: Yuri Astrakhan --- docs/src/quick-start-linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/quick-start-linux.md b/docs/src/quick-start-linux.md index b169c9891..aa7ebb09c 100644 --- a/docs/src/quick-start-linux.md +++ b/docs/src/quick-start-linux.md @@ -5,7 +5,7 @@ mkdir martin cd martin # Download some sample data -curl -L -O https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles +curl -L -O https://github.com/maplibre/martin/raw/main/tests/fixtures/mbtiles/world_cities.mbtiles # Download the latest version of Martin binary, extract it, and make it executable curl -L -O https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-gnu.tar.gz From 3e7c7e52d80563cd5a1f412ea46b9c4abbe0bf1b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 29 Jun 2024 13:52:36 -0400 Subject: [PATCH 159/164] Fix sample data download links --- docs/src/quick-start-macos.md | 2 +- docs/src/quick-start-windows.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/quick-start-macos.md b/docs/src/quick-start-macos.md index 5da4c70a2..5d9054d4a 100644 --- a/docs/src/quick-start-macos.md +++ b/docs/src/quick-start-macos.md @@ -1,6 +1,6 @@ ## Quick start on macOS -1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). +1. Download some [demo tiles](https://github.com/maplibre/martin/raw/main/tests/fixtures/mbtiles/world_cities.mbtiles). 2. Download the latest version of Martin from the [release page](https://github.com/maplibre/martin/releases/latest). diff --git a/docs/src/quick-start-windows.md b/docs/src/quick-start-windows.md index e66fafbf3..ae9fa046f 100644 --- a/docs/src/quick-start-windows.md +++ b/docs/src/quick-start-windows.md @@ -1,6 +1,6 @@ ## Quick start on Windows -1. Download some [demo tiles](https://github.com/maplibre/martin/blob/main/tests/fixtures/mbtiles/world_cities.mbtiles). +1. Download some [demo tiles](https://github.com/maplibre/martin/raw/main/tests/fixtures/mbtiles/world_cities.mbtiles). 2. Download the latest Windows version of Martin from the [release page](https://github.com/maplibre/martin/releases): [martin-x86_64-pc-windows-msvc.zip](https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-pc-windows-msvc.zip) From 0c5302d7d051aca0b79be14a77e93a0a8b42008e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:48:44 +0000 Subject: [PATCH 160/164] chore(deps): Bump serde_with from 3.8.1 to 3.8.2 (#1389) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.8.1 to 3.8.2.
Release notes

Sourced from serde_with's releases.

serde_with v3.8.2

Changed

  • Bump MSRV to 1.67, since that is required for the time dependency. The time version needed to be updated for nightly compatibility.

Fixed

Commits
  • 2274dd1 Bump version to 3.8.2 (#761)
  • e9e7a7e Bump version to 3.8.2
  • c9d9672 Implement JsonSchemaAs for OneOrMany instead of JsonSchema (#760)
  • dee706a Implement JsonSchemaAs for OneOrMany instead of JsonSchema
  • f74b460 Fix two clippy issues (#755)
  • 3ae4424 Fix two clippy issues
  • 729e8d2 Replace future deprecated functions from chrono (#752)
  • 685338f Replace future deprecated functions from chrono
  • 9593f93 Enable the unexpected_cfgs lint now that it can be configured via `Cargo.to...
  • 242286c Enable the unexpected_cfgs lint now that it can be configured via Cargo.toml
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_with&package-manager=cargo&previous-version=3.8.1&new-version=3.8.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d19b7265f..df64c948d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2265,7 +2265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -3843,9 +3843,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "079f3a42cd87588d924ed95b533f8d30a483388c4e400ab736a7058e34f16169" dependencies = [ "base64 0.22.1", "chrono", @@ -3861,9 +3861,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "bc03aad67c1d26b7de277d51c86892e7d9a0110a2fe44bf6b26cc569fba302d6" dependencies = [ "darling", "proc-macro2", From 49ae0569136f35ba95d76bd3a325ff48c293cf9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:51:25 +0000 Subject: [PATCH 161/164] chore(deps): Bump serde_json from 1.0.118 to 1.0.119 (#1391) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.118 to 1.0.119.
Release notes

Sourced from serde_json's releases.

v1.0.119

Commits
  • b48b9a3 Release 1.0.119
  • 8878cd7 Make shift_insert available for inlining like other Map methods
  • 352b7ab Document the cfg required for Map::shift_insert to exist
  • c17e63f Merge pull request #1149 from joshka/master
  • 309ef6b Add Map::shift_insert()
  • a9e089a Merge pull request #1146 from haouvw/master
  • a83fe96 chore: remove repeat words
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.118&new-version=1.0.119)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df64c948d..26870ad71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3799,9 +3799,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" dependencies = [ "itoa", "ryu", From 3421c1257b4f1a7963e08b751e32f79923673ba4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:51:45 +0000 Subject: [PATCH 162/164] chore(deps): Bump clap from 4.5.7 to 4.5.8 (#1390) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.7 to 4.5.8.
Release notes

Sourced from clap's releases.

v4.5.8

[4.5.8] - 2024-06-28

Fixes

  • Reduce extra flushes
Changelog

Sourced from clap's changelog.

[4.5.8] - 2024-06-28

Fixes

  • Reduce extra flushes
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.7&new-version=4.5.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26870ad71..0c0f4407a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -749,9 +749,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -759,9 +759,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -771,9 +771,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck 0.5.0", "proc-macro2", From abdaccb88ac747ca380fa0ceadd3800f446ad249 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:52:39 +0000 Subject: [PATCH 163/164] chore(deps): Bump subst from 0.3.2 to 0.3.3 (#1392) Bumps [subst](https://github.com/fizyr/subst) from 0.3.2 to 0.3.3.
Changelog

Sourced from subst's changelog.

Version 0.3.3 - 2024-06-29

  • [add][minor] Add support for substitution in all string values of TOML data.
  • [add][minor] Add support for substitution in all string values of JSON data.
Commits
  • c7f313f Bump version to 0.3.3.
  • 084354d Merge pull request #23 from fizyr/json
  • 39fd59e Add comments to the features in the package manifest.
  • e97b9e0 Add support for substituting string values in JSON.
  • 4e1d60d Merge pull request #22 from fizyr/toml
  • 92f701f Use doc-cfg in docs-rs build.
  • 9e7016f Add support for substituting string values in TOML.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=subst&package-manager=cargo&previous-version=0.3.2&new-version=0.3.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c0f4407a..9b5a80780 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4327,9 +4327,9 @@ dependencies = [ [[package]] name = "subst" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95bc3d9b5ec35dabec6f7ac966e073ef28d4881c6a2009567632ab721df6203" +checksum = "266d3fe7ffc582b3a0c3fe36cdc88d5635a1c2d53e7c3f813c901d7bd1d34ba0" dependencies = [ "memchr", "serde", From 01d01a633c52993d9d6db9696685e341b422aafc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 02:59:05 +0000 Subject: [PATCH 164/164] chore(deps): Bump serde_json from 1.0.119 to 1.0.120 (#1396) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.119 to 1.0.120.
Release notes

Sourced from serde_json's releases.

v1.0.120

  • Correctly specify required version of indexmap dependency (#1152, thanks @​cforycki)
Commits
  • bcedc3d Release 1.0.120
  • 962c0fb Merge pull request #1152 from cforycki/fix/index-map-minimal-version
  • 3480fed fix: indexmap minimal version with Map::shift_insert()
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.119&new-version=1.0.120)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b5a80780..94383ba10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3799,9 +3799,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.119" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu",