├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENCE-APACHE ├── LICENCE-MIT ├── README.md ├── clean.sh ├── src └── main.rs └── templates └── relnotes.md /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: reqwest 10 | versions: 11 | - 0.11.1 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | runs-on: ${{ matrix.os }} 6 | steps: 7 | - uses: actions/checkout@v4 8 | - run: rustup default ${{ matrix.channel }} 9 | - name: Build 10 | run: cargo build --tests --workspace 11 | - name: Test 12 | run: cargo test --workspace 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest, windows-latest] 16 | channel: [stable, beta, nightly] 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | release.md 2 | /target 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "android-tzdata" 31 | version = "0.1.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 34 | 35 | [[package]] 36 | name = "android_system_properties" 37 | version = "0.1.5" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 40 | dependencies = [ 41 | "libc", 42 | ] 43 | 44 | [[package]] 45 | name = "askama" 46 | version = "0.11.1" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" 49 | dependencies = [ 50 | "askama_derive", 51 | "askama_escape", 52 | "askama_shared", 53 | ] 54 | 55 | [[package]] 56 | name = "askama_derive" 57 | version = "0.11.2" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" 60 | dependencies = [ 61 | "askama_shared", 62 | "proc-macro2", 63 | "syn 1.0.109", 64 | ] 65 | 66 | [[package]] 67 | name = "askama_escape" 68 | version = "0.10.3" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" 71 | 72 | [[package]] 73 | name = "askama_shared" 74 | version = "0.12.2" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" 77 | dependencies = [ 78 | "askama_escape", 79 | "mime", 80 | "mime_guess", 81 | "nom", 82 | "proc-macro2", 83 | "quote", 84 | "syn 1.0.109", 85 | ] 86 | 87 | [[package]] 88 | name = "autocfg" 89 | version = "1.4.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 92 | 93 | [[package]] 94 | name = "backtrace" 95 | version = "0.3.74" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 98 | dependencies = [ 99 | "addr2line", 100 | "cfg-if", 101 | "libc", 102 | "miniz_oxide", 103 | "object", 104 | "rustc-demangle", 105 | "windows-targets 0.52.6", 106 | ] 107 | 108 | [[package]] 109 | name = "base64" 110 | version = "0.21.7" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 113 | 114 | [[package]] 115 | name = "bit-set" 116 | version = "0.8.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" 119 | dependencies = [ 120 | "bit-vec", 121 | ] 122 | 123 | [[package]] 124 | name = "bit-vec" 125 | version = "0.8.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" 128 | 129 | [[package]] 130 | name = "bitflags" 131 | version = "1.3.2" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 134 | 135 | [[package]] 136 | name = "bitflags" 137 | version = "2.6.0" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 140 | 141 | [[package]] 142 | name = "bumpalo" 143 | version = "3.16.0" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 146 | 147 | [[package]] 148 | name = "bytes" 149 | version = "1.8.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" 152 | 153 | [[package]] 154 | name = "cc" 155 | version = "1.2.1" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" 158 | dependencies = [ 159 | "shlex", 160 | ] 161 | 162 | [[package]] 163 | name = "cfg-if" 164 | version = "1.0.0" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 167 | 168 | [[package]] 169 | name = "chrono" 170 | version = "0.4.38" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 173 | dependencies = [ 174 | "android-tzdata", 175 | "iana-time-zone", 176 | "js-sys", 177 | "num-traits", 178 | "wasm-bindgen", 179 | "windows-targets 0.52.6", 180 | ] 181 | 182 | [[package]] 183 | name = "core-foundation" 184 | version = "0.9.4" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 187 | dependencies = [ 188 | "core-foundation-sys", 189 | "libc", 190 | ] 191 | 192 | [[package]] 193 | name = "core-foundation-sys" 194 | version = "0.8.7" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 197 | 198 | [[package]] 199 | name = "displaydoc" 200 | version = "0.2.5" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 203 | dependencies = [ 204 | "proc-macro2", 205 | "quote", 206 | "syn 2.0.87", 207 | ] 208 | 209 | [[package]] 210 | name = "encoding_rs" 211 | version = "0.8.35" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 214 | dependencies = [ 215 | "cfg-if", 216 | ] 217 | 218 | [[package]] 219 | name = "equivalent" 220 | version = "1.0.1" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 223 | 224 | [[package]] 225 | name = "errno" 226 | version = "0.3.9" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 229 | dependencies = [ 230 | "libc", 231 | "windows-sys 0.52.0", 232 | ] 233 | 234 | [[package]] 235 | name = "fancy-regex" 236 | version = "0.14.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" 239 | dependencies = [ 240 | "bit-set", 241 | "regex-automata", 242 | "regex-syntax", 243 | ] 244 | 245 | [[package]] 246 | name = "fastrand" 247 | version = "2.2.0" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" 250 | 251 | [[package]] 252 | name = "fnv" 253 | version = "1.0.7" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 256 | 257 | [[package]] 258 | name = "foreign-types" 259 | version = "0.3.2" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 262 | dependencies = [ 263 | "foreign-types-shared", 264 | ] 265 | 266 | [[package]] 267 | name = "foreign-types-shared" 268 | version = "0.1.1" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 271 | 272 | [[package]] 273 | name = "form_urlencoded" 274 | version = "1.2.1" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 277 | dependencies = [ 278 | "percent-encoding", 279 | ] 280 | 281 | [[package]] 282 | name = "futures-channel" 283 | version = "0.3.31" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 286 | dependencies = [ 287 | "futures-core", 288 | ] 289 | 290 | [[package]] 291 | name = "futures-core" 292 | version = "0.3.31" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 295 | 296 | [[package]] 297 | name = "futures-io" 298 | version = "0.3.31" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 301 | 302 | [[package]] 303 | name = "futures-sink" 304 | version = "0.3.31" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 307 | 308 | [[package]] 309 | name = "futures-task" 310 | version = "0.3.31" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 313 | 314 | [[package]] 315 | name = "futures-util" 316 | version = "0.3.31" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 319 | dependencies = [ 320 | "futures-core", 321 | "futures-io", 322 | "futures-task", 323 | "memchr", 324 | "pin-project-lite", 325 | "pin-utils", 326 | "slab", 327 | ] 328 | 329 | [[package]] 330 | name = "gimli" 331 | version = "0.31.1" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 334 | 335 | [[package]] 336 | name = "h2" 337 | version = "0.3.26" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 340 | dependencies = [ 341 | "bytes", 342 | "fnv", 343 | "futures-core", 344 | "futures-sink", 345 | "futures-util", 346 | "http", 347 | "indexmap", 348 | "slab", 349 | "tokio", 350 | "tokio-util", 351 | "tracing", 352 | ] 353 | 354 | [[package]] 355 | name = "hashbrown" 356 | version = "0.15.1" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" 359 | 360 | [[package]] 361 | name = "hermit-abi" 362 | version = "0.3.9" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 365 | 366 | [[package]] 367 | name = "http" 368 | version = "0.2.12" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 371 | dependencies = [ 372 | "bytes", 373 | "fnv", 374 | "itoa", 375 | ] 376 | 377 | [[package]] 378 | name = "http-body" 379 | version = "0.4.6" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 382 | dependencies = [ 383 | "bytes", 384 | "http", 385 | "pin-project-lite", 386 | ] 387 | 388 | [[package]] 389 | name = "httparse" 390 | version = "1.9.5" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 393 | 394 | [[package]] 395 | name = "httpdate" 396 | version = "1.0.3" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 399 | 400 | [[package]] 401 | name = "hyper" 402 | version = "0.14.31" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" 405 | dependencies = [ 406 | "bytes", 407 | "futures-channel", 408 | "futures-core", 409 | "futures-util", 410 | "h2", 411 | "http", 412 | "http-body", 413 | "httparse", 414 | "httpdate", 415 | "itoa", 416 | "pin-project-lite", 417 | "socket2", 418 | "tokio", 419 | "tower-service", 420 | "tracing", 421 | "want", 422 | ] 423 | 424 | [[package]] 425 | name = "hyper-tls" 426 | version = "0.5.0" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 429 | dependencies = [ 430 | "bytes", 431 | "hyper", 432 | "native-tls", 433 | "tokio", 434 | "tokio-native-tls", 435 | ] 436 | 437 | [[package]] 438 | name = "iana-time-zone" 439 | version = "0.1.61" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 442 | dependencies = [ 443 | "android_system_properties", 444 | "core-foundation-sys", 445 | "iana-time-zone-haiku", 446 | "js-sys", 447 | "wasm-bindgen", 448 | "windows-core", 449 | ] 450 | 451 | [[package]] 452 | name = "iana-time-zone-haiku" 453 | version = "0.1.2" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 456 | dependencies = [ 457 | "cc", 458 | ] 459 | 460 | [[package]] 461 | name = "icu_collections" 462 | version = "1.5.0" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 465 | dependencies = [ 466 | "displaydoc", 467 | "yoke", 468 | "zerofrom", 469 | "zerovec", 470 | ] 471 | 472 | [[package]] 473 | name = "icu_locid" 474 | version = "1.5.0" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 477 | dependencies = [ 478 | "displaydoc", 479 | "litemap", 480 | "tinystr", 481 | "writeable", 482 | "zerovec", 483 | ] 484 | 485 | [[package]] 486 | name = "icu_locid_transform" 487 | version = "1.5.0" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 490 | dependencies = [ 491 | "displaydoc", 492 | "icu_locid", 493 | "icu_locid_transform_data", 494 | "icu_provider", 495 | "tinystr", 496 | "zerovec", 497 | ] 498 | 499 | [[package]] 500 | name = "icu_locid_transform_data" 501 | version = "1.5.0" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 504 | 505 | [[package]] 506 | name = "icu_normalizer" 507 | version = "1.5.0" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 510 | dependencies = [ 511 | "displaydoc", 512 | "icu_collections", 513 | "icu_normalizer_data", 514 | "icu_properties", 515 | "icu_provider", 516 | "smallvec", 517 | "utf16_iter", 518 | "utf8_iter", 519 | "write16", 520 | "zerovec", 521 | ] 522 | 523 | [[package]] 524 | name = "icu_normalizer_data" 525 | version = "1.5.0" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 528 | 529 | [[package]] 530 | name = "icu_properties" 531 | version = "1.5.1" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 534 | dependencies = [ 535 | "displaydoc", 536 | "icu_collections", 537 | "icu_locid_transform", 538 | "icu_properties_data", 539 | "icu_provider", 540 | "tinystr", 541 | "zerovec", 542 | ] 543 | 544 | [[package]] 545 | name = "icu_properties_data" 546 | version = "1.5.0" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 549 | 550 | [[package]] 551 | name = "icu_provider" 552 | version = "1.5.0" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 555 | dependencies = [ 556 | "displaydoc", 557 | "icu_locid", 558 | "icu_provider_macros", 559 | "stable_deref_trait", 560 | "tinystr", 561 | "writeable", 562 | "yoke", 563 | "zerofrom", 564 | "zerovec", 565 | ] 566 | 567 | [[package]] 568 | name = "icu_provider_macros" 569 | version = "1.5.0" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 572 | dependencies = [ 573 | "proc-macro2", 574 | "quote", 575 | "syn 2.0.87", 576 | ] 577 | 578 | [[package]] 579 | name = "idna" 580 | version = "1.0.3" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 583 | dependencies = [ 584 | "idna_adapter", 585 | "smallvec", 586 | "utf8_iter", 587 | ] 588 | 589 | [[package]] 590 | name = "idna_adapter" 591 | version = "1.2.0" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 594 | dependencies = [ 595 | "icu_normalizer", 596 | "icu_properties", 597 | ] 598 | 599 | [[package]] 600 | name = "indexmap" 601 | version = "2.6.0" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" 604 | dependencies = [ 605 | "equivalent", 606 | "hashbrown", 607 | ] 608 | 609 | [[package]] 610 | name = "ipnet" 611 | version = "2.10.1" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" 614 | 615 | [[package]] 616 | name = "itoa" 617 | version = "1.0.11" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 620 | 621 | [[package]] 622 | name = "js-sys" 623 | version = "0.3.72" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" 626 | dependencies = [ 627 | "wasm-bindgen", 628 | ] 629 | 630 | [[package]] 631 | name = "libc" 632 | version = "0.2.162" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" 635 | 636 | [[package]] 637 | name = "linux-raw-sys" 638 | version = "0.4.14" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 641 | 642 | [[package]] 643 | name = "litemap" 644 | version = "0.7.3" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" 647 | 648 | [[package]] 649 | name = "log" 650 | version = "0.4.22" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 653 | 654 | [[package]] 655 | name = "memchr" 656 | version = "2.7.4" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 659 | 660 | [[package]] 661 | name = "mime" 662 | version = "0.3.17" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 665 | 666 | [[package]] 667 | name = "mime_guess" 668 | version = "2.0.5" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 671 | dependencies = [ 672 | "mime", 673 | "unicase", 674 | ] 675 | 676 | [[package]] 677 | name = "minimal-lexical" 678 | version = "0.2.1" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 681 | 682 | [[package]] 683 | name = "miniz_oxide" 684 | version = "0.8.0" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 687 | dependencies = [ 688 | "adler2", 689 | ] 690 | 691 | [[package]] 692 | name = "mio" 693 | version = "1.0.2" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 696 | dependencies = [ 697 | "hermit-abi", 698 | "libc", 699 | "wasi", 700 | "windows-sys 0.52.0", 701 | ] 702 | 703 | [[package]] 704 | name = "native-tls" 705 | version = "0.2.12" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" 708 | dependencies = [ 709 | "libc", 710 | "log", 711 | "openssl", 712 | "openssl-probe", 713 | "openssl-sys", 714 | "schannel", 715 | "security-framework", 716 | "security-framework-sys", 717 | "tempfile", 718 | ] 719 | 720 | [[package]] 721 | name = "nom" 722 | version = "7.1.3" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 725 | dependencies = [ 726 | "memchr", 727 | "minimal-lexical", 728 | ] 729 | 730 | [[package]] 731 | name = "num-traits" 732 | version = "0.2.19" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 735 | dependencies = [ 736 | "autocfg", 737 | ] 738 | 739 | [[package]] 740 | name = "object" 741 | version = "0.36.5" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 744 | dependencies = [ 745 | "memchr", 746 | ] 747 | 748 | [[package]] 749 | name = "once_cell" 750 | version = "1.20.2" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 753 | 754 | [[package]] 755 | name = "openssl" 756 | version = "0.10.68" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" 759 | dependencies = [ 760 | "bitflags 2.6.0", 761 | "cfg-if", 762 | "foreign-types", 763 | "libc", 764 | "once_cell", 765 | "openssl-macros", 766 | "openssl-sys", 767 | ] 768 | 769 | [[package]] 770 | name = "openssl-macros" 771 | version = "0.1.1" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 774 | dependencies = [ 775 | "proc-macro2", 776 | "quote", 777 | "syn 2.0.87", 778 | ] 779 | 780 | [[package]] 781 | name = "openssl-probe" 782 | version = "0.1.5" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 785 | 786 | [[package]] 787 | name = "openssl-sys" 788 | version = "0.9.104" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" 791 | dependencies = [ 792 | "cc", 793 | "libc", 794 | "pkg-config", 795 | "vcpkg", 796 | ] 797 | 798 | [[package]] 799 | name = "percent-encoding" 800 | version = "2.3.1" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 803 | 804 | [[package]] 805 | name = "pin-project-lite" 806 | version = "0.2.15" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 809 | 810 | [[package]] 811 | name = "pin-utils" 812 | version = "0.1.0" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 815 | 816 | [[package]] 817 | name = "pkg-config" 818 | version = "0.3.31" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 821 | 822 | [[package]] 823 | name = "proc-macro2" 824 | version = "1.0.89" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" 827 | dependencies = [ 828 | "unicode-ident", 829 | ] 830 | 831 | [[package]] 832 | name = "quote" 833 | version = "1.0.37" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 836 | dependencies = [ 837 | "proc-macro2", 838 | ] 839 | 840 | [[package]] 841 | name = "regex-automata" 842 | version = "0.4.9" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 845 | dependencies = [ 846 | "aho-corasick", 847 | "memchr", 848 | "regex-syntax", 849 | ] 850 | 851 | [[package]] 852 | name = "regex-syntax" 853 | version = "0.8.5" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 856 | 857 | [[package]] 858 | name = "relnotes" 859 | version = "0.1.0" 860 | dependencies = [ 861 | "askama", 862 | "chrono", 863 | "fancy-regex", 864 | "reqwest", 865 | "serde", 866 | "serde_json", 867 | ] 868 | 869 | [[package]] 870 | name = "reqwest" 871 | version = "0.11.27" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" 874 | dependencies = [ 875 | "base64", 876 | "bytes", 877 | "encoding_rs", 878 | "futures-core", 879 | "futures-util", 880 | "h2", 881 | "http", 882 | "http-body", 883 | "hyper", 884 | "hyper-tls", 885 | "ipnet", 886 | "js-sys", 887 | "log", 888 | "mime", 889 | "native-tls", 890 | "once_cell", 891 | "percent-encoding", 892 | "pin-project-lite", 893 | "rustls-pemfile", 894 | "serde", 895 | "serde_json", 896 | "serde_urlencoded", 897 | "sync_wrapper", 898 | "system-configuration", 899 | "tokio", 900 | "tokio-native-tls", 901 | "tower-service", 902 | "url", 903 | "wasm-bindgen", 904 | "wasm-bindgen-futures", 905 | "web-sys", 906 | "winreg", 907 | ] 908 | 909 | [[package]] 910 | name = "rustc-demangle" 911 | version = "0.1.24" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 914 | 915 | [[package]] 916 | name = "rustix" 917 | version = "0.38.40" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" 920 | dependencies = [ 921 | "bitflags 2.6.0", 922 | "errno", 923 | "libc", 924 | "linux-raw-sys", 925 | "windows-sys 0.52.0", 926 | ] 927 | 928 | [[package]] 929 | name = "rustls-pemfile" 930 | version = "1.0.4" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" 933 | dependencies = [ 934 | "base64", 935 | ] 936 | 937 | [[package]] 938 | name = "ryu" 939 | version = "1.0.18" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 942 | 943 | [[package]] 944 | name = "schannel" 945 | version = "0.1.26" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" 948 | dependencies = [ 949 | "windows-sys 0.59.0", 950 | ] 951 | 952 | [[package]] 953 | name = "security-framework" 954 | version = "2.11.1" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 957 | dependencies = [ 958 | "bitflags 2.6.0", 959 | "core-foundation", 960 | "core-foundation-sys", 961 | "libc", 962 | "security-framework-sys", 963 | ] 964 | 965 | [[package]] 966 | name = "security-framework-sys" 967 | version = "2.12.1" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" 970 | dependencies = [ 971 | "core-foundation-sys", 972 | "libc", 973 | ] 974 | 975 | [[package]] 976 | name = "serde" 977 | version = "1.0.215" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" 980 | dependencies = [ 981 | "serde_derive", 982 | ] 983 | 984 | [[package]] 985 | name = "serde_derive" 986 | version = "1.0.215" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" 989 | dependencies = [ 990 | "proc-macro2", 991 | "quote", 992 | "syn 2.0.87", 993 | ] 994 | 995 | [[package]] 996 | name = "serde_json" 997 | version = "1.0.132" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" 1000 | dependencies = [ 1001 | "itoa", 1002 | "memchr", 1003 | "ryu", 1004 | "serde", 1005 | ] 1006 | 1007 | [[package]] 1008 | name = "serde_urlencoded" 1009 | version = "0.7.1" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1012 | dependencies = [ 1013 | "form_urlencoded", 1014 | "itoa", 1015 | "ryu", 1016 | "serde", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "shlex" 1021 | version = "1.3.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1024 | 1025 | [[package]] 1026 | name = "slab" 1027 | version = "0.4.9" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1030 | dependencies = [ 1031 | "autocfg", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "smallvec" 1036 | version = "1.13.2" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1039 | 1040 | [[package]] 1041 | name = "socket2" 1042 | version = "0.5.7" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 1045 | dependencies = [ 1046 | "libc", 1047 | "windows-sys 0.52.0", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "stable_deref_trait" 1052 | version = "1.2.0" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1055 | 1056 | [[package]] 1057 | name = "syn" 1058 | version = "1.0.109" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1061 | dependencies = [ 1062 | "proc-macro2", 1063 | "quote", 1064 | "unicode-ident", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "syn" 1069 | version = "2.0.87" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" 1072 | dependencies = [ 1073 | "proc-macro2", 1074 | "quote", 1075 | "unicode-ident", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "sync_wrapper" 1080 | version = "0.1.2" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 1083 | 1084 | [[package]] 1085 | name = "synstructure" 1086 | version = "0.13.1" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1089 | dependencies = [ 1090 | "proc-macro2", 1091 | "quote", 1092 | "syn 2.0.87", 1093 | ] 1094 | 1095 | [[package]] 1096 | name = "system-configuration" 1097 | version = "0.5.1" 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" 1099 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" 1100 | dependencies = [ 1101 | "bitflags 1.3.2", 1102 | "core-foundation", 1103 | "system-configuration-sys", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "system-configuration-sys" 1108 | version = "0.5.0" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" 1111 | dependencies = [ 1112 | "core-foundation-sys", 1113 | "libc", 1114 | ] 1115 | 1116 | [[package]] 1117 | name = "tempfile" 1118 | version = "3.14.0" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" 1121 | dependencies = [ 1122 | "cfg-if", 1123 | "fastrand", 1124 | "once_cell", 1125 | "rustix", 1126 | "windows-sys 0.59.0", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "tinystr" 1131 | version = "0.7.6" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1134 | dependencies = [ 1135 | "displaydoc", 1136 | "zerovec", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "tokio" 1141 | version = "1.41.1" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" 1144 | dependencies = [ 1145 | "backtrace", 1146 | "bytes", 1147 | "libc", 1148 | "mio", 1149 | "pin-project-lite", 1150 | "socket2", 1151 | "windows-sys 0.52.0", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "tokio-native-tls" 1156 | version = "0.3.1" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1159 | dependencies = [ 1160 | "native-tls", 1161 | "tokio", 1162 | ] 1163 | 1164 | [[package]] 1165 | name = "tokio-util" 1166 | version = "0.7.12" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 1169 | dependencies = [ 1170 | "bytes", 1171 | "futures-core", 1172 | "futures-sink", 1173 | "pin-project-lite", 1174 | "tokio", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "tower-service" 1179 | version = "0.3.3" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1182 | 1183 | [[package]] 1184 | name = "tracing" 1185 | version = "0.1.40" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1188 | dependencies = [ 1189 | "pin-project-lite", 1190 | "tracing-core", 1191 | ] 1192 | 1193 | [[package]] 1194 | name = "tracing-core" 1195 | version = "0.1.32" 1196 | source = "registry+https://github.com/rust-lang/crates.io-index" 1197 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1198 | dependencies = [ 1199 | "once_cell", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "try-lock" 1204 | version = "0.2.5" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1207 | 1208 | [[package]] 1209 | name = "unicase" 1210 | version = "2.8.0" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" 1213 | 1214 | [[package]] 1215 | name = "unicode-ident" 1216 | version = "1.0.13" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 1219 | 1220 | [[package]] 1221 | name = "url" 1222 | version = "2.5.3" 1223 | source = "registry+https://github.com/rust-lang/crates.io-index" 1224 | checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" 1225 | dependencies = [ 1226 | "form_urlencoded", 1227 | "idna", 1228 | "percent-encoding", 1229 | ] 1230 | 1231 | [[package]] 1232 | name = "utf16_iter" 1233 | version = "1.0.5" 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" 1235 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 1236 | 1237 | [[package]] 1238 | name = "utf8_iter" 1239 | version = "1.0.4" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 1242 | 1243 | [[package]] 1244 | name = "vcpkg" 1245 | version = "0.2.15" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1248 | 1249 | [[package]] 1250 | name = "want" 1251 | version = "0.3.1" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1254 | dependencies = [ 1255 | "try-lock", 1256 | ] 1257 | 1258 | [[package]] 1259 | name = "wasi" 1260 | version = "0.11.0+wasi-snapshot-preview1" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1263 | 1264 | [[package]] 1265 | name = "wasm-bindgen" 1266 | version = "0.2.95" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" 1269 | dependencies = [ 1270 | "cfg-if", 1271 | "once_cell", 1272 | "wasm-bindgen-macro", 1273 | ] 1274 | 1275 | [[package]] 1276 | name = "wasm-bindgen-backend" 1277 | version = "0.2.95" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" 1280 | dependencies = [ 1281 | "bumpalo", 1282 | "log", 1283 | "once_cell", 1284 | "proc-macro2", 1285 | "quote", 1286 | "syn 2.0.87", 1287 | "wasm-bindgen-shared", 1288 | ] 1289 | 1290 | [[package]] 1291 | name = "wasm-bindgen-futures" 1292 | version = "0.4.45" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" 1295 | dependencies = [ 1296 | "cfg-if", 1297 | "js-sys", 1298 | "wasm-bindgen", 1299 | "web-sys", 1300 | ] 1301 | 1302 | [[package]] 1303 | name = "wasm-bindgen-macro" 1304 | version = "0.2.95" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" 1307 | dependencies = [ 1308 | "quote", 1309 | "wasm-bindgen-macro-support", 1310 | ] 1311 | 1312 | [[package]] 1313 | name = "wasm-bindgen-macro-support" 1314 | version = "0.2.95" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" 1317 | dependencies = [ 1318 | "proc-macro2", 1319 | "quote", 1320 | "syn 2.0.87", 1321 | "wasm-bindgen-backend", 1322 | "wasm-bindgen-shared", 1323 | ] 1324 | 1325 | [[package]] 1326 | name = "wasm-bindgen-shared" 1327 | version = "0.2.95" 1328 | source = "registry+https://github.com/rust-lang/crates.io-index" 1329 | checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" 1330 | 1331 | [[package]] 1332 | name = "web-sys" 1333 | version = "0.3.72" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" 1336 | dependencies = [ 1337 | "js-sys", 1338 | "wasm-bindgen", 1339 | ] 1340 | 1341 | [[package]] 1342 | name = "windows-core" 1343 | version = "0.52.0" 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" 1345 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 1346 | dependencies = [ 1347 | "windows-targets 0.52.6", 1348 | ] 1349 | 1350 | [[package]] 1351 | name = "windows-sys" 1352 | version = "0.48.0" 1353 | source = "registry+https://github.com/rust-lang/crates.io-index" 1354 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1355 | dependencies = [ 1356 | "windows-targets 0.48.5", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "windows-sys" 1361 | version = "0.52.0" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1364 | dependencies = [ 1365 | "windows-targets 0.52.6", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "windows-sys" 1370 | version = "0.59.0" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1373 | dependencies = [ 1374 | "windows-targets 0.52.6", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "windows-targets" 1379 | version = "0.48.5" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1382 | dependencies = [ 1383 | "windows_aarch64_gnullvm 0.48.5", 1384 | "windows_aarch64_msvc 0.48.5", 1385 | "windows_i686_gnu 0.48.5", 1386 | "windows_i686_msvc 0.48.5", 1387 | "windows_x86_64_gnu 0.48.5", 1388 | "windows_x86_64_gnullvm 0.48.5", 1389 | "windows_x86_64_msvc 0.48.5", 1390 | ] 1391 | 1392 | [[package]] 1393 | name = "windows-targets" 1394 | version = "0.52.6" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1397 | dependencies = [ 1398 | "windows_aarch64_gnullvm 0.52.6", 1399 | "windows_aarch64_msvc 0.52.6", 1400 | "windows_i686_gnu 0.52.6", 1401 | "windows_i686_gnullvm", 1402 | "windows_i686_msvc 0.52.6", 1403 | "windows_x86_64_gnu 0.52.6", 1404 | "windows_x86_64_gnullvm 0.52.6", 1405 | "windows_x86_64_msvc 0.52.6", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "windows_aarch64_gnullvm" 1410 | version = "0.48.5" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1413 | 1414 | [[package]] 1415 | name = "windows_aarch64_gnullvm" 1416 | version = "0.52.6" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1419 | 1420 | [[package]] 1421 | name = "windows_aarch64_msvc" 1422 | version = "0.48.5" 1423 | source = "registry+https://github.com/rust-lang/crates.io-index" 1424 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1425 | 1426 | [[package]] 1427 | name = "windows_aarch64_msvc" 1428 | version = "0.52.6" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1431 | 1432 | [[package]] 1433 | name = "windows_i686_gnu" 1434 | version = "0.48.5" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1437 | 1438 | [[package]] 1439 | name = "windows_i686_gnu" 1440 | version = "0.52.6" 1441 | source = "registry+https://github.com/rust-lang/crates.io-index" 1442 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1443 | 1444 | [[package]] 1445 | name = "windows_i686_gnullvm" 1446 | version = "0.52.6" 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" 1448 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1449 | 1450 | [[package]] 1451 | name = "windows_i686_msvc" 1452 | version = "0.48.5" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1455 | 1456 | [[package]] 1457 | name = "windows_i686_msvc" 1458 | version = "0.52.6" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1461 | 1462 | [[package]] 1463 | name = "windows_x86_64_gnu" 1464 | version = "0.48.5" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1467 | 1468 | [[package]] 1469 | name = "windows_x86_64_gnu" 1470 | version = "0.52.6" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1473 | 1474 | [[package]] 1475 | name = "windows_x86_64_gnullvm" 1476 | version = "0.48.5" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1479 | 1480 | [[package]] 1481 | name = "windows_x86_64_gnullvm" 1482 | version = "0.52.6" 1483 | source = "registry+https://github.com/rust-lang/crates.io-index" 1484 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1485 | 1486 | [[package]] 1487 | name = "windows_x86_64_msvc" 1488 | version = "0.48.5" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1491 | 1492 | [[package]] 1493 | name = "windows_x86_64_msvc" 1494 | version = "0.52.6" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1497 | 1498 | [[package]] 1499 | name = "winreg" 1500 | version = "0.50.0" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 1503 | dependencies = [ 1504 | "cfg-if", 1505 | "windows-sys 0.48.0", 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "write16" 1510 | version = "1.0.0" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 1513 | 1514 | [[package]] 1515 | name = "writeable" 1516 | version = "0.5.5" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 1519 | 1520 | [[package]] 1521 | name = "yoke" 1522 | version = "0.7.4" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" 1525 | dependencies = [ 1526 | "serde", 1527 | "stable_deref_trait", 1528 | "yoke-derive", 1529 | "zerofrom", 1530 | ] 1531 | 1532 | [[package]] 1533 | name = "yoke-derive" 1534 | version = "0.7.4" 1535 | source = "registry+https://github.com/rust-lang/crates.io-index" 1536 | checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" 1537 | dependencies = [ 1538 | "proc-macro2", 1539 | "quote", 1540 | "syn 2.0.87", 1541 | "synstructure", 1542 | ] 1543 | 1544 | [[package]] 1545 | name = "zerofrom" 1546 | version = "0.1.4" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" 1549 | dependencies = [ 1550 | "zerofrom-derive", 1551 | ] 1552 | 1553 | [[package]] 1554 | name = "zerofrom-derive" 1555 | version = "0.1.4" 1556 | source = "registry+https://github.com/rust-lang/crates.io-index" 1557 | checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" 1558 | dependencies = [ 1559 | "proc-macro2", 1560 | "quote", 1561 | "syn 2.0.87", 1562 | "synstructure", 1563 | ] 1564 | 1565 | [[package]] 1566 | name = "zerovec" 1567 | version = "0.10.4" 1568 | source = "registry+https://github.com/rust-lang/crates.io-index" 1569 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 1570 | dependencies = [ 1571 | "yoke", 1572 | "zerofrom", 1573 | "zerovec-derive", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "zerovec-derive" 1578 | version = "0.10.3" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 1581 | dependencies = [ 1582 | "proc-macro2", 1583 | "quote", 1584 | "syn 2.0.87", 1585 | ] 1586 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "relnotes" 3 | version = "0.1.0" 4 | authors = ["Erin Power "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | reqwest = { version = "0.11", features = ["blocking", "json"] } 9 | chrono = "0.4" 10 | serde = "1" 11 | serde_json = "1" 12 | askama = { version = "0.11", default-features = false } 13 | fancy-regex = "0.14.0" 14 | -------------------------------------------------------------------------------- /LICENCE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Aaron Power 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /LICENCE-MIT: -------------------------------------------------------------------------------- 1 | MIT License (MIT) 2 | 3 | Copyright (c) 2016 Aaron Power 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # relnotes: Generate release notes for "The Rust Programming Language" 2 | This utility pulls all pull requests made against `rust-lang/rust` and 3 | `rust-lang/cargo` within the latest release cycle and prints out a markdown 4 | document containing all the pull requests, categorised into their respective 5 | sections where possible, and prints the document to `stdout`. 6 | 7 | ## Requirements 8 | `relnotes` uses the GitHub API to generate the release notes, as such you need 9 | a valid GitHub API key. `relnotes` will look for `GITHUB_TOKEN` in the 10 | environment and use that key when sending requests. 11 | 12 | **small warning:** `relnotes` makes a lot of requests as GitHub only allows you to 13 | look at 100 PRs in a single page. It is not recommended to call `relnotes` 14 | multiple times as you can hit the GitHub's rate limit quite easily. Please refer 15 | to [GitHub's Rate Limit documentation](https://developer.github.com/v4/guides/resource-limitations/#rate-limit) for more information. 16 | 17 | ## Usage 18 | `version_number` is the version number of the rust release. e.g. `1.28.0` 19 | ``` 20 | cargo run --release > release.md 21 | ``` 22 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$OSTYPE" == "darwin"* ]]; then 4 | inplace=(-i '') 5 | else 6 | inplace=-i 7 | fi 8 | 9 | rg '\[([^]]*)\]: ' -o release.md > defs 10 | rg '\[([^]]*)\]$' -o release.md > used 11 | 12 | for word in `cat defs`; do 13 | pattern=$(echo "$word" | sed 's@\[@\\[@g' | sed 's@]@\\]@g' | sed 's@/@\\/@g') 14 | in_used=$(echo "$word" | sed 's@:.*@@') 15 | if ! fgrep -q "$in_used" used; then 16 | sed $inplace -e "/^$pattern/d" release.md 17 | fi 18 | done 19 | 20 | rm defs used 21 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::collections::HashMap; 3 | use std::env; 4 | 5 | use askama::Template; 6 | use chrono::prelude::*; 7 | use chrono::Duration; 8 | 9 | use reqwest::header::HeaderMap; 10 | use serde_json as json; 11 | 12 | const SKIP_LABELS: &[&str] = &["rollup"]; 13 | 14 | const RELNOTES_LABELS: &[&str] = &[ 15 | "relnotes", 16 | "relnotes-perf", 17 | "finished-final-comment-period", 18 | "needs-fcp", 19 | ]; 20 | 21 | #[derive(Clone, Template)] 22 | #[template(path = "relnotes.md", escape = "none")] 23 | struct ReleaseNotes { 24 | version: String, 25 | date: NaiveDate, 26 | 27 | language_relnotes: String, 28 | compiler_relnotes: String, 29 | platform_relnotes: String, 30 | libraries_relnotes: String, 31 | stabilized_apis_relnotes: String, 32 | const_stabilized_apis_relnotes: String, 33 | cargo_relnotes: String, 34 | rustdoc_relnotes: String, 35 | compat_relnotes: String, 36 | internal_changes_relnotes: String, 37 | other_relnotes: String, 38 | } 39 | 40 | fn main() { 41 | let mut draft = false; 42 | let mut opt_version = None; 43 | for arg in env::args().skip(1) { 44 | match arg.as_bytes() { 45 | b"--draft" => draft = true, 46 | [b'1', b'.', ..] => opt_version = Some(arg), 47 | _ => panic!("unrecognized argument: {arg:?}"), 48 | } 49 | } 50 | let version = 51 | opt_version.expect("A version number (xx.yy.zz) for the Rust release is required."); 52 | let today = Utc::now().date_naive(); 53 | 54 | // A known rust release date. (1.42.0) 55 | let mut end = Utc 56 | .with_ymd_and_hms(2020, 3, 12, 0, 0, 0) 57 | .single() 58 | .unwrap() 59 | .date_naive(); 60 | let six_weeks = Duration::weeks(6); 61 | 62 | // Get the most recent rust release date. 63 | while today - end > six_weeks { 64 | end = end + six_weeks; 65 | } 66 | 67 | let issues = get_issues_by_milestone(&version, "rust"); 68 | let mut tracking_rust = TrackingIssues::collect(&issues); 69 | 70 | // Skips some PRs that aren't themselves interesting. 71 | let in_release = issues.iter().filter(|v| { 72 | !v["labels"]["nodes"] 73 | .as_array() 74 | .unwrap() 75 | .iter() 76 | .any(|o| SKIP_LABELS.contains(&o["name"].as_str().unwrap())) 77 | }); 78 | 79 | let relnotes = in_release 80 | .into_iter() 81 | .filter(|o| has_tags(o, RELNOTES_LABELS)) 82 | .collect::>(); 83 | 84 | let Sections { 85 | language_relnotes, 86 | compiler_relnotes, 87 | platform_relnotes, 88 | libraries_relnotes, 89 | stabilized_apis_relnotes, 90 | const_stabilized_apis_relnotes, 91 | rustdoc_relnotes, 92 | compat_relnotes, 93 | internal_changes_relnotes, 94 | other_relnotes, 95 | } = to_sections(relnotes, &mut tracking_rust, draft); 96 | 97 | let cargo_issues = get_issues_by_milestone(&version, "cargo"); 98 | 99 | let cargo_relnotes = { 100 | let relnotes = cargo_issues 101 | .iter() 102 | .filter(|o| has_tags(o, RELNOTES_LABELS)) 103 | .collect::>(); 104 | 105 | relnotes 106 | .iter() 107 | .map(|o| { 108 | format!( 109 | "- [{title}]({url}/)", 110 | title = o["title"].as_str().unwrap(), 111 | url = o["url"].as_str().unwrap(), 112 | ) 113 | }) 114 | .collect::>() 115 | .join("\n") 116 | }; 117 | 118 | for issue in tracking_rust.issues.values() { 119 | for (section, (used, _)) in issue.sections.iter() { 120 | if issue.raw["labels"]["nodes"] 121 | .as_array() 122 | .unwrap() 123 | .iter() 124 | .any(|l| l["name"] == "relnotes-tracking-issue") 125 | && issue.raw["state"] == "CLOSED" 126 | { 127 | assert!( 128 | !*used, 129 | "{} <{}> used despite tracking issue being closed", 130 | issue.raw["title"].as_str().unwrap(), 131 | issue.raw["url"].as_str().unwrap() 132 | ); 133 | continue; 134 | } 135 | 136 | if *used { 137 | continue; 138 | } 139 | 140 | eprintln!( 141 | "Did not use {:?} from {} <{}> (parsed as providing for #{}, check if that is milestoned correctly)", 142 | section, 143 | issue.raw["title"].as_str().unwrap(), 144 | issue.raw["url"].as_str().unwrap(), 145 | issue.for_number, 146 | ); 147 | } 148 | } 149 | 150 | let relnotes = ReleaseNotes { 151 | version, 152 | date: end + six_weeks, 153 | 154 | language_relnotes, 155 | compiler_relnotes, 156 | platform_relnotes, 157 | libraries_relnotes, 158 | rustdoc_relnotes, 159 | stabilized_apis_relnotes, 160 | const_stabilized_apis_relnotes, 161 | cargo_relnotes, 162 | internal_changes_relnotes, 163 | compat_relnotes, 164 | other_relnotes, 165 | }; 166 | 167 | println!("{}", relnotes.render().unwrap()); 168 | } 169 | 170 | fn get_issues_by_milestone(version: &str, repo_name: &'static str) -> Vec { 171 | let mut out = get_issues_by_milestone_inner(version, repo_name, "issues"); 172 | out.extend(get_issues_by_milestone_inner( 173 | version, 174 | repo_name, 175 | "pullRequests", 176 | )); 177 | out.sort_unstable_by_key(|v| v["number"].as_u64().unwrap()); 178 | out.dedup_by_key(|v| v["number"].as_u64().unwrap()); 179 | out 180 | } 181 | 182 | fn get_issues_by_milestone_inner( 183 | version: &str, 184 | repo_name: &'static str, 185 | ty: &str, 186 | ) -> Vec { 187 | use reqwest::blocking::Client; 188 | 189 | let headers = request_header(); 190 | let mut args = BTreeMap::new(); 191 | if ty == "pullRequests" { 192 | args.insert("states", String::from("[MERGED]")); 193 | } 194 | args.insert("last", String::from("100")); 195 | let mut issues = Vec::new(); 196 | 197 | loop { 198 | let query = format!( 199 | r#" 200 | query {{ 201 | repository(owner: "rust-lang", name: "{repo_name}") {{ 202 | milestones(query: "{version}", first: 1) {{ 203 | totalCount 204 | nodes {{ 205 | {ty}({args}) {{ 206 | nodes {{ 207 | number 208 | title 209 | url 210 | body 211 | state 212 | labels(last: 100) {{ 213 | nodes {{ 214 | name 215 | }} 216 | }} 217 | }} 218 | pageInfo {{ 219 | startCursor 220 | }} 221 | }} 222 | }} 223 | }} 224 | }} 225 | }}"#, 226 | repo_name = repo_name, 227 | version = version, 228 | ty = ty, 229 | args = args 230 | .iter() 231 | .map(|(k, v)| format!("{}: {}", k, v)) 232 | .collect::>() 233 | .join(",") 234 | ) 235 | .replace(" ", "") 236 | .replace("\n", " ") 237 | .replace('"', "\\\""); 238 | 239 | let json_query = format!("{{\"query\": \"{}\"}}", query); 240 | 241 | let client = Client::new(); 242 | 243 | let response = client 244 | .post("https://api.github.com/graphql") 245 | .headers(headers.clone()) 246 | .body(json_query) 247 | .send() 248 | .unwrap(); 249 | let status = response.status(); 250 | let json = response.json::().unwrap(); 251 | if !status.is_success() { 252 | panic!("API Error {}: {}", status, json); 253 | } 254 | 255 | let milestones_data = json["data"]["repository"]["milestones"].clone(); 256 | assert_eq!( 257 | milestones_data["totalCount"].as_u64().unwrap(), 258 | 1, 259 | "More than one milestone matched the query \"{version}\". Please be more specific.", 260 | version = version 261 | ); 262 | let pull_requests_data = milestones_data["nodes"][0][ty].clone(); 263 | 264 | let mut pull_requests = pull_requests_data["nodes"].as_array().unwrap().clone(); 265 | issues.append(&mut pull_requests); 266 | 267 | match &pull_requests_data["pageInfo"]["startCursor"] { 268 | json::Value::String(cursor) => { 269 | args.insert("before", format!("\"{}\"", cursor)); 270 | } 271 | json::Value::Null => { 272 | break issues; 273 | } 274 | _ => unreachable!(), 275 | } 276 | } 277 | } 278 | 279 | fn request_header() -> HeaderMap { 280 | use reqwest::header::*; 281 | let token = env::var("GITHUB_TOKEN").expect("Set GITHUB_TOKEN to a valid token"); 282 | let mut headers = HeaderMap::new(); 283 | headers.insert(CONTENT_TYPE, "application/json".parse().unwrap()); 284 | headers.insert(ACCEPT, "application/json".parse().unwrap()); 285 | headers.insert(AUTHORIZATION, format!("Bearer {}", token).parse().unwrap()); 286 | headers.insert(USER_AGENT, "Rust-relnotes/0.1.0".parse().unwrap()); 287 | headers 288 | } 289 | 290 | struct TrackingIssues { 291 | // Maps the issue/PR number *tracked* by the issue in `json::Value`. 292 | // 293 | // bool is tracking whether we've used that issue already. 294 | issues: HashMap, 295 | } 296 | 297 | #[derive(Debug)] 298 | struct TrackingIssue { 299 | for_number: u64, 300 | raw: json::Value, 301 | // Section name -> (used, lines) 302 | sections: HashMap)>, 303 | } 304 | 305 | impl TrackingIssues { 306 | fn collect(all: &[json::Value]) -> Self { 307 | const PREFIX: &str = "Tracking issue for release notes of #"; 308 | const MARKDOWN: &str = r"(?ms)^(`{3,})markdown\r?\n(.*?)^\1\r?\n"; 309 | 310 | let markdown_re = fancy_regex::Regex::new(MARKDOWN).unwrap(); 311 | let mut tracking_issues = HashMap::new(); 312 | for o in all.iter() { 313 | let title = o["title"].as_str().unwrap(); 314 | if let Some(tail) = title.strip_prefix(PREFIX) { 315 | let for_number = tail[..tail.find(':').unwrap()].parse::().unwrap(); 316 | let mut sections = HashMap::new(); 317 | let body = o["body"].as_str().unwrap(); 318 | 319 | let Ok(Some(captures)) = markdown_re.captures(body) else { 320 | let issue = &o["number"]; 321 | eprintln!("WARNING: skipping {issue}, markdown not found:"); 322 | eprintln!(" {body:?}"); 323 | continue; 324 | }; 325 | let relnotes = &captures[2]; 326 | 327 | let mut in_section = None; 328 | for line in relnotes.lines() { 329 | if line.trim().is_empty() { 330 | continue; 331 | } 332 | 333 | if let Some(header) = line.strip_prefix("# ") { 334 | in_section = Some(header); 335 | continue; 336 | } 337 | 338 | if let Some(section) = in_section { 339 | sections 340 | .entry(section.to_owned()) 341 | .or_insert_with(|| (false, vec![])) 342 | .1 343 | .push(line.to_owned()); 344 | } 345 | } 346 | tracking_issues.insert( 347 | for_number, 348 | TrackingIssue { 349 | for_number, 350 | raw: o.clone(), 351 | sections, 352 | }, 353 | ); 354 | } 355 | } 356 | Self { 357 | issues: tracking_issues, 358 | } 359 | } 360 | } 361 | 362 | fn map_to_line_items<'a>( 363 | iter: impl IntoIterator, 364 | tracking_issues: &mut TrackingIssues, 365 | by_section: &mut HashMap<&'static str, String>, 366 | draft: bool, 367 | ) { 368 | for o in iter { 369 | let title = o["title"].as_str().unwrap(); 370 | if title.starts_with("Tracking issue for release notes of #") { 371 | continue; 372 | } 373 | let number = o["number"].as_u64().unwrap(); 374 | 375 | if let Some(issue) = tracking_issues.issues.get_mut(&number) { 376 | // If the tracking issue is closed, skip. 377 | if issue.raw["state"] == "CLOSED" { 378 | continue; 379 | } 380 | 381 | for (section, (used, lines)) in issue.sections.iter_mut() { 382 | if let Some((_, contents)) = by_section 383 | .iter_mut() 384 | .find(|(s, _)| s.eq_ignore_ascii_case(section)) 385 | { 386 | *used = true; 387 | for line in lines.iter() { 388 | contents.push_str(line); 389 | contents.push('\n'); 390 | } 391 | if draft { 392 | contents.push_str(&format!( 393 | " [:pencil:]({})\n", 394 | issue.raw["url"].as_str().unwrap(), 395 | )); 396 | } 397 | } 398 | } 399 | 400 | // If we have a dedicated tracking issue, don't use our default rules. 401 | continue; 402 | } 403 | 404 | // In the future we expect to have increasingly few things fall into this category, as 405 | // things are added to the dedicated tracking issue category in triagebot (today mostly 406 | // FCPs are missing). 407 | 408 | let section = if has_tags(o, &["C-future-compatibility"]) { 409 | "Compatibility Notes" 410 | } else if has_tags(o, &["T-libs", "T-libs-api"]) { 411 | "Library" 412 | } else if has_tags(o, &["T-lang"]) { 413 | "Language" 414 | } else if has_tags(o, &["T-compiler"]) { 415 | "Compiler" 416 | } else { 417 | "Other" 418 | }; 419 | by_section.get_mut(section).unwrap().push_str(&format!( 420 | "- [{title}]({url}/)\n", 421 | title = o["title"].as_str().unwrap(), 422 | url = o["url"].as_str().unwrap(), 423 | )); 424 | } 425 | } 426 | 427 | fn has_tags<'a>(o: &'a json::Value, tags: &[&str]) -> bool { 428 | o["labels"]["nodes"] 429 | .as_array() 430 | .unwrap() 431 | .iter() 432 | .any(|o| tags.iter().any(|tag| o["name"] == *tag)) 433 | } 434 | 435 | struct Sections { 436 | language_relnotes: String, 437 | compiler_relnotes: String, 438 | platform_relnotes: String, 439 | libraries_relnotes: String, 440 | stabilized_apis_relnotes: String, 441 | const_stabilized_apis_relnotes: String, 442 | rustdoc_relnotes: String, 443 | compat_relnotes: String, 444 | internal_changes_relnotes: String, 445 | other_relnotes: String, 446 | } 447 | 448 | fn to_sections<'a>( 449 | iter: impl IntoIterator, 450 | mut tracking: &mut TrackingIssues, 451 | draft: bool, 452 | ) -> Sections { 453 | let mut by_section = HashMap::new(); 454 | by_section.insert("Language", String::new()); 455 | by_section.insert("Compiler", String::new()); 456 | by_section.insert("Libraries", String::new()); 457 | by_section.insert("Stabilized APIs", String::new()); 458 | by_section.insert("Const Stabilized APIs", String::new()); 459 | by_section.insert("Rustdoc", String::new()); 460 | by_section.insert("Compatibility Notes", String::new()); 461 | by_section.insert("Internal Changes", String::new()); 462 | by_section.insert("Platform Support", String::new()); 463 | by_section.insert("Other", String::new()); 464 | 465 | map_to_line_items(iter, &mut tracking, &mut by_section, draft); 466 | 467 | Sections { 468 | language_relnotes: by_section.remove("Language").unwrap(), 469 | compiler_relnotes: by_section.remove("Compiler").unwrap(), 470 | platform_relnotes: by_section.remove("Platform Support").unwrap(), 471 | libraries_relnotes: by_section.remove("Libraries").unwrap(), 472 | stabilized_apis_relnotes: by_section.remove("Stabilized APIs").unwrap(), 473 | const_stabilized_apis_relnotes: by_section.remove("Const Stabilized APIs").unwrap(), 474 | rustdoc_relnotes: by_section.remove("Rustdoc").unwrap(), 475 | compat_relnotes: by_section.remove("Compatibility Notes").unwrap(), 476 | internal_changes_relnotes: by_section.remove("Internal Changes").unwrap(), 477 | other_relnotes: by_section.remove("Other").unwrap(), 478 | } 479 | } 480 | -------------------------------------------------------------------------------- /templates/relnotes.md: -------------------------------------------------------------------------------- 1 | Version {{version}} ({{date}}) 2 | ========================== 3 | 4 | 5 | 6 | Language 7 | -------- 8 | {{language_relnotes}} 9 | 10 | 11 | 12 | Compiler 13 | -------- 14 | {{compiler_relnotes}} 15 | 16 | 17 | 18 | Platform Support 19 | ---------------- 20 | {{platform_relnotes}} 21 | 22 | Refer to Rust's [platform support page][platform-support-doc] 23 | for more information on Rust's tiered platform support. 24 | 25 | [platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html 26 | 27 | 28 | 29 | Libraries 30 | --------- 31 | {{libraries_relnotes}} 32 | 33 | 34 | 35 | Stabilized APIs 36 | --------------- 37 | 38 | {{stabilized_apis_relnotes}} 39 | 40 | These previously stable APIs are now stable in const contexts: 41 | 42 | {{const_stabilized_apis_relnotes}} 43 | 44 | 45 | 46 | Cargo 47 | ----- 48 | {{cargo_relnotes}} 49 | 50 | 51 | 52 | Rustdoc 53 | ----- 54 | {{rustdoc_relnotes}} 55 | 56 | 57 | 58 | Compatibility Notes 59 | ------------------- 60 | {{compat_relnotes}} 61 | 62 | 63 | 64 | Internal Changes 65 | ---------------- 66 | 67 | These changes do not affect any public interfaces of Rust, but they represent 68 | significant improvements to the performance or internals of rustc and related 69 | tools. 70 | 71 | {{internal_changes_relnotes}} 72 | 73 | 74 | Other 75 | ----- 76 | 77 | {{other_relnotes}} 78 | --------------------------------------------------------------------------------