mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-01-11 14:58:29 +01:00
Move commenter to its own repo
This commit is contained in:
parent
7489d67779
commit
6261b0bac1
17
commenter
17
commenter
@ -1,20 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if ! command -v cargo
|
||||
if ! command -v commenter &> /dev/null
|
||||
then
|
||||
echo "Rust doesn't seem to be installed. https://rustup.rs/"
|
||||
echo "commenter is not installed, get it from https://github.com/bergmark/commenter"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "outdated" ];
|
||||
then
|
||||
if ! command -v latest-version &> /dev/null
|
||||
then
|
||||
echo "This command requires latest-version in your PATH"
|
||||
echo "Install it with: "
|
||||
echo "stack install --stack-yaml etc/commenter/latest-version/stack.yaml"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cargo run -q --release --manifest-path etc/commenter/Cargo.toml $@
|
||||
commenter $@
|
||||
|
||||
3
etc/commenter/.gitignore
vendored
3
etc/commenter/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
/target
|
||||
/comments.txt
|
||||
/out.txt
|
||||
365
etc/commenter/Cargo.lock
generated
365
etc/commenter/Cargo.lock
generated
@ -1,365 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "commenter"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"lazy-regex",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"structopt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex"
|
||||
version = "2.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919a16773ebf2de27e95fc58460110932e55bb0780e23aa51fa5a6b59c9e2b3d"
|
||||
dependencies = [
|
||||
"lazy-regex-proc_macros",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex-proc_macros"
|
||||
version = "2.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fbe6bf0a04af51c07976625d5007e75ed9b8b955befc21c77b3947733496e36"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "commenter"
|
||||
version = "0.2.0"
|
||||
authors = ["Adam Bergmark <adam@bergmark.nl>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy-regex = "2.2.1"
|
||||
regex = "1.5.4"
|
||||
serde = { version = "1.0.133", features = ["derive"] }
|
||||
serde_yaml = "0.8.23"
|
||||
structopt = "0.3.25"
|
||||
@ -1,3 +0,0 @@
|
||||
Helps automate mass-disabling of packages in Stackage's build-constraint.yaml.
|
||||
|
||||
See CURATORS.md for usage instructions.
|
||||
@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
cargo run -- $@
|
||||
@ -1,30 +0,0 @@
|
||||
Copyright Adam Bergmark (c) 2021
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Author name here nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -1 +0,0 @@
|
||||
# latest-version
|
||||
@ -1,2 +0,0 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
@ -1,6 +0,0 @@
|
||||
source-repository-package
|
||||
type: git
|
||||
location: git://github.com/commercialhaskell/pantry.git
|
||||
|
||||
packages: ./latest-version.cabal
|
||||
with-compiler: ghc-8.10.7
|
||||
@ -1,23 +0,0 @@
|
||||
name: latest-version
|
||||
version: 0.1.0.0
|
||||
homepage: https://github.com/githubuser/latest-version#readme
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
author: Adam Bergmark
|
||||
maintainer: adam@bergmark.nl
|
||||
copyright: 2021 Adam Bergmark
|
||||
category: Web
|
||||
build-type: Simple
|
||||
cabal-version: >=1.10
|
||||
extra-source-files: README.md
|
||||
|
||||
executable latest-version
|
||||
ghc-options: -Wall -threaded
|
||||
hs-source-dirs: src
|
||||
main-is: Main.hs
|
||||
default-language: Haskell2010
|
||||
build-depends: base >= 4.7 && < 5
|
||||
, pantry
|
||||
, Cabal
|
||||
, rio
|
||||
, containers
|
||||
@ -1,28 +0,0 @@
|
||||
module Main where
|
||||
|
||||
import Data.List
|
||||
import Distribution.Types.PackageName
|
||||
import Distribution.Types.Version
|
||||
import Pantry
|
||||
import RIO
|
||||
import System.Environment
|
||||
import qualified Data.Map as Map
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
(onlyVersion, packages) <- pure $ case args of
|
||||
"only-version" : packages -> (True, packages)
|
||||
packages -> (False, packages)
|
||||
runPantryApp $ liftIO . putStrLn . unlines_ =<< mapM (latestVersion onlyVersion) packages
|
||||
where
|
||||
-- unlines adds an extra trailing newline which can be annoying...
|
||||
unlines_ = intercalate "\n"
|
||||
|
||||
latestVersion :: (HasPantryConfig env, HasLogFunc env) => Bool -> String -> RIO env String
|
||||
latestVersion onlyVersion name = fmap (displayVersion onlyVersion) . getVersion . mkPackageName $ name
|
||||
where
|
||||
showVersion = intercalate "." . map show . versionNumbers . fst . head . Map.toDescList
|
||||
getVersion = getHackagePackageVersions YesRequireHackageIndex UsePreferredVersions
|
||||
displayVersion True v = showVersion v
|
||||
displayVersion False v = name <> "-" <> showVersion v
|
||||
@ -1,4 +0,0 @@
|
||||
resolver:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/18.yaml
|
||||
packages:
|
||||
- .
|
||||
@ -1,13 +0,0 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages: []
|
||||
snapshots:
|
||||
- completed:
|
||||
size: 586296
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/18.yaml
|
||||
sha256: 63539429076b7ebbab6daa7656cfb079393bf644971156dc349d7c0453694ac2
|
||||
original:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/18.yaml
|
||||
@ -1,574 +0,0 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, LineWriter, Lines, Write};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use lazy_regex::regex;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
pub fn clear() {
|
||||
handle(true, |loc, _lines| match loc {
|
||||
// Add empty array to keep yaml valid
|
||||
Location::Lib => vec![" []".to_owned()],
|
||||
Location::Test | Location::Bench => vec![],
|
||||
});
|
||||
}
|
||||
|
||||
pub fn add(lib: Vec<String>, test: Vec<String>, bench: Vec<String>) {
|
||||
handle(true, |loc, mut lines| {
|
||||
lines.extend(match loc {
|
||||
Location::Lib => lib.clone(),
|
||||
Location::Test => test.clone(),
|
||||
Location::Bench => bench.clone(),
|
||||
});
|
||||
lines.sort();
|
||||
lines
|
||||
});
|
||||
}
|
||||
|
||||
enum VersionTag {
|
||||
Manual(Version),
|
||||
Auto(Version),
|
||||
}
|
||||
|
||||
impl VersionTag {
|
||||
fn tag(&self) -> &'static str {
|
||||
match self {
|
||||
VersionTag::Manual(_) => "manual",
|
||||
VersionTag::Auto(_) => "auto",
|
||||
}
|
||||
}
|
||||
|
||||
fn version(&self) -> &Version {
|
||||
match self {
|
||||
VersionTag::Manual(s) => s,
|
||||
VersionTag::Auto(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outdated() {
|
||||
let mut all: Vec<String> = vec![];
|
||||
let (versioned, disabled) = handle(false, |_loc, lines| {
|
||||
all.extend(lines);
|
||||
vec![]
|
||||
});
|
||||
|
||||
for DisabledPackage { package } in disabled {
|
||||
println!("WARN: {package} is disabled without a noted version");
|
||||
}
|
||||
|
||||
let mut map: BTreeMap<Package, VersionTag> = BTreeMap::new();
|
||||
for VersionedPackage { package, version } in versioned {
|
||||
map.insert(package, VersionTag::Manual(version));
|
||||
}
|
||||
let mut support: BTreeMap<(Package, Version), BTreeSet<(Package, Version)>> = BTreeMap::new();
|
||||
for v in all.into_iter() {
|
||||
let caps = regex!("tried ([^ ]+)-([^,-]+),").captures(&v).unwrap();
|
||||
let package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
map.insert(package.clone(), VersionTag::Auto(version.clone()));
|
||||
|
||||
if let Some(caps) = regex!("does not support: ([^ ]+)-([^-]+)").captures(&v) {
|
||||
let dep_package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let dep_version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
let entry = support.entry((dep_package, dep_version)).or_default();
|
||||
entry.insert((package, version));
|
||||
}
|
||||
}
|
||||
|
||||
let latest_versions = {
|
||||
let mut packages: Vec<Package> = map.iter().map(|(package, _)| package.clone()).collect();
|
||||
packages.append(
|
||||
&mut support
|
||||
.iter()
|
||||
.map(|((package, _), _)| package.clone())
|
||||
.collect(),
|
||||
);
|
||||
latest_version(packages.into_iter())
|
||||
};
|
||||
|
||||
for (package, version) in map {
|
||||
if is_boot(&package) {
|
||||
continue;
|
||||
}
|
||||
let latest = latest_versions.get(&package).unwrap();
|
||||
if version.version() != latest {
|
||||
println!(
|
||||
"{package} mismatch, {tag}: {version}, hackage: {latest}",
|
||||
tag = version.tag(),
|
||||
version = version.version(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for ((package, version), dependents) in support {
|
||||
if is_boot(&package) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let latest = latest_versions.get(&package).unwrap();
|
||||
if &version != latest {
|
||||
let max = 3;
|
||||
let dependents_stripped = dependents.len().saturating_sub(max);
|
||||
let dependents = dependents
|
||||
.into_iter()
|
||||
.take(max)
|
||||
.map(|(p, v)| format!("{p}-{v}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
let dependents = if dependents_stripped > 0 {
|
||||
format!("{dependents} and {dependents_stripped} more")
|
||||
} else {
|
||||
dependents
|
||||
};
|
||||
|
||||
println!(
|
||||
"{package} mismatch, snapshot: {version}, hackage: {latest}, dependents: {dependents}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_boot(package: &Package) -> bool {
|
||||
[
|
||||
"Cabal",
|
||||
"base",
|
||||
"bytestring",
|
||||
"containers",
|
||||
"containers",
|
||||
"directory",
|
||||
"filepath",
|
||||
"deepseq",
|
||||
"ghc",
|
||||
"ghc-bignum",
|
||||
"ghc-boot",
|
||||
"ghc-boot-th",
|
||||
"ghc-prim",
|
||||
"ghc-lib-parser", // not a boot lib, but tied to the GHC version.
|
||||
"integer-gmp",
|
||||
"process",
|
||||
"stm",
|
||||
"template-haskell",
|
||||
"text",
|
||||
"time",
|
||||
]
|
||||
.contains(&&*package.0)
|
||||
}
|
||||
|
||||
fn latest_version(packages: impl Iterator<Item = Package>) -> BTreeMap<Package, Version> {
|
||||
String::from_utf8(
|
||||
Command::new("latest-version")
|
||||
.args(packages.map(|p| p.0))
|
||||
.output()
|
||||
.expect("Could not find latest-version in PATH")
|
||||
.stdout,
|
||||
)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.to_owned()
|
||||
.lines()
|
||||
.map(|s| {
|
||||
let VersionedPackage { package, version } = parse_versioned_package_canonical(s).unwrap();
|
||||
(package, version)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
enum State {
|
||||
LookingForLibBounds,
|
||||
ProcessingLibBounds,
|
||||
LookingForTestBounds,
|
||||
ProcessingTestBounds,
|
||||
LookingForBenchBounds,
|
||||
ProcessingBenchBounds,
|
||||
Done,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
struct VersionedPackage {
|
||||
package: Package,
|
||||
version: Version,
|
||||
}
|
||||
|
||||
fn parse_versioned_package_canonical(s: &str) -> Option<VersionedPackage> {
|
||||
if let Some(caps) = regex!(r#"^(.+)-([\d.]+)$"#).captures(s) {
|
||||
let package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
Some(VersionedPackage { package, version })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_versioned_package_yaml(s: &str) -> Option<VersionedPackage> {
|
||||
if let Some(caps) = regex!(r#"- *([^ ]+) < *0 *# *([\d.]+)"#).captures(s) {
|
||||
let package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
Some(VersionedPackage { package, version })
|
||||
} else if let Some(caps) = regex!(r#"- *([^ ]+) *# *([\d.]+)"#).captures(s) {
|
||||
let package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
Some(VersionedPackage { package, version })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
struct DisabledPackage {
|
||||
package: String,
|
||||
}
|
||||
|
||||
fn parse_disabled_package(s: &str) -> Option<DisabledPackage> {
|
||||
if !regex!(r#"- *([^ ]+) < *0 *# tried"#).is_match(s) {
|
||||
if let Some(caps) = regex!(r#"- *([^ ]+) < *0 *# *\d*[^\d ]"#).captures(s) {
|
||||
let package = caps.get(1).unwrap().as_str().to_owned();
|
||||
Some(DisabledPackage { package })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn handle<F>(write: bool, mut f: F) -> (Vec<VersionedPackage>, Vec<DisabledPackage>)
|
||||
where
|
||||
F: FnMut(Location, Vec<String>) -> Vec<String>,
|
||||
{
|
||||
let path = "build-constraints.yaml";
|
||||
let mut new_lines: Vec<String> = vec![];
|
||||
let mut versioned_packages: Vec<VersionedPackage> = vec![];
|
||||
let mut disabled_packages: Vec<DisabledPackage> = vec![];
|
||||
|
||||
let mut state = State::LookingForLibBounds;
|
||||
let mut buf = vec![];
|
||||
for line in read_lines(path).map(|s| s.unwrap()) {
|
||||
if let Some(versioned_package) = parse_versioned_package_yaml(&line) {
|
||||
versioned_packages.push(versioned_package);
|
||||
} else if let Some(disabled_package) = parse_disabled_package(&line) {
|
||||
disabled_packages.push(disabled_package);
|
||||
}
|
||||
|
||||
match state {
|
||||
State::LookingForLibBounds => {
|
||||
if line == r#" "Library and exe bounds failures":"# {
|
||||
state = State::ProcessingLibBounds;
|
||||
}
|
||||
new_lines.push(line);
|
||||
}
|
||||
State::ProcessingLibBounds => {
|
||||
if line == r#" # End of Library and exe bounds failures"# {
|
||||
new_lines.extend(f(Location::Lib, buf).into_iter());
|
||||
buf = vec![];
|
||||
new_lines.push(line);
|
||||
state = State::LookingForTestBounds;
|
||||
} else {
|
||||
// Remove empty section
|
||||
if line != " []" {
|
||||
buf.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
State::LookingForTestBounds => {
|
||||
if line == r#" # Test bounds issues"# {
|
||||
state = State::ProcessingTestBounds;
|
||||
}
|
||||
new_lines.push(line);
|
||||
}
|
||||
State::ProcessingTestBounds => {
|
||||
if line == r#" # End of Test bounds issues"# {
|
||||
new_lines.extend(f(Location::Test, buf).into_iter());
|
||||
buf = vec![];
|
||||
new_lines.push(line);
|
||||
state = State::LookingForBenchBounds;
|
||||
} else {
|
||||
buf.push(line);
|
||||
}
|
||||
}
|
||||
State::LookingForBenchBounds => {
|
||||
if line == r#" # Benchmark bounds issues"# {
|
||||
state = State::ProcessingBenchBounds;
|
||||
}
|
||||
new_lines.push(line);
|
||||
}
|
||||
State::ProcessingBenchBounds => {
|
||||
if line == r#" # End of Benchmark bounds issues"# {
|
||||
new_lines.extend(f(Location::Bench, buf).into_iter());
|
||||
buf = vec![];
|
||||
new_lines.push(line);
|
||||
state = State::Done;
|
||||
} else {
|
||||
buf.push(line);
|
||||
}
|
||||
}
|
||||
State::Done => {
|
||||
new_lines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if write {
|
||||
let file = File::create(path).unwrap();
|
||||
let mut file = LineWriter::new(file);
|
||||
|
||||
for line in new_lines {
|
||||
file.write_all((line + "\n").as_bytes()).unwrap();
|
||||
}
|
||||
file.flush().unwrap();
|
||||
}
|
||||
|
||||
(versioned_packages, disabled_packages)
|
||||
}
|
||||
|
||||
enum Location {
|
||||
Lib,
|
||||
Test,
|
||||
Bench,
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> Lines<BufReader<File>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(filename).unwrap();
|
||||
BufReader::new(file).lines()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SnapshotYaml {
|
||||
// flags: BTreeMap<Package, BTreeMap<PackageFlag, bool>>,
|
||||
// publish_time
|
||||
packages: Vec<SnapshotPackage>,
|
||||
// hidden
|
||||
// resolver
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SnapshotPackage {
|
||||
hackage: PackageWithVersionAndSha,
|
||||
// pantry-tree
|
||||
}
|
||||
|
||||
#[derive(PartialOrd, Ord, PartialEq, Eq, Clone, Debug)]
|
||||
struct Package(String);
|
||||
|
||||
impl fmt::Display for Package {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
|
||||
struct Version(String);
|
||||
|
||||
impl fmt::Display for Version {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// zstd-0.1.3.0@sha256:4c0a372251068eb6086b8c3a0a9f347488f08b570a7705844ffeb2c720c97223,3723
|
||||
struct PackageWithVersionAndSha {
|
||||
name: Package,
|
||||
version: Version,
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for PackageWithVersionAndSha {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: String = String::deserialize(deserializer)?;
|
||||
let r = regex!(r#"^(.+?)-([.\d]+)@sha256:[\da-z]+,\d+$"#);
|
||||
if let Some(caps) = r.captures(&s) {
|
||||
let name = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
Ok(Self { name, version })
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_value(
|
||||
serde::de::Unexpected::Other(&s),
|
||||
&"Invalid PackageVersionWithSha",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn yaml_from_file<A, P: AsRef<Path>>(path: P) -> Result<A, Box<dyn Error>>
|
||||
where
|
||||
A: for<'de> Deserialize<'de>,
|
||||
{
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
let u = serde_yaml::from_reader(reader)?;
|
||||
Ok(u)
|
||||
}
|
||||
|
||||
struct Snapshot {
|
||||
packages: BTreeMap<Package, Diff<Version>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Diff<A> {
|
||||
Left(A),
|
||||
Right(A),
|
||||
Both(A, A),
|
||||
}
|
||||
|
||||
fn to_diff(a: SnapshotYaml, b: SnapshotYaml) -> Snapshot {
|
||||
let mut packages = BTreeMap::new();
|
||||
for s in a.packages {
|
||||
let package = s.hackage;
|
||||
packages.insert(package.name, Diff::Left(package.version));
|
||||
}
|
||||
for s in b.packages {
|
||||
let package = s.hackage;
|
||||
let name = package.name;
|
||||
let version = package.version;
|
||||
if let Some(a) = packages.remove(&name) {
|
||||
match a {
|
||||
Diff::Left(a) => {
|
||||
if a == version {
|
||||
packages.remove(&name);
|
||||
} else {
|
||||
packages.insert(name, Diff::Both(a, version));
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
packages.insert(name, Diff::Right(version));
|
||||
}
|
||||
}
|
||||
|
||||
Snapshot { packages }
|
||||
}
|
||||
|
||||
pub fn diff_snapshot(a: String, b: String) {
|
||||
let diff = to_diff(yaml_from_file(a).unwrap(), yaml_from_file(b).unwrap());
|
||||
for (name, diff) in diff.packages {
|
||||
let s = match diff {
|
||||
Diff::Left(a) => format!("- {name}-{a}"),
|
||||
Diff::Right(b) => format!("+ {name}-{b}"),
|
||||
Diff::Both(a, b) => format!("~ {name}-{a} -> {b}"),
|
||||
};
|
||||
println!("{s}");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
struct DisabledTransitively {
|
||||
child: VersionedPackage,
|
||||
parent: Package,
|
||||
}
|
||||
|
||||
fn parse_disabled_transitviely(s: &str) -> Option<DisabledTransitively> {
|
||||
let r = regex!(
|
||||
r#"- *([^ ]+) < *0 *# tried [^ ]+-([\d.]+), but its \*[^*]+\* requires the disabled package: ([^ ]+)"#
|
||||
);
|
||||
if let Some(caps) = r.captures(s) {
|
||||
let package = Package(caps.get(1).unwrap().as_str().to_owned());
|
||||
let version = Version(caps.get(2).unwrap().as_str().to_owned());
|
||||
let parent = Package(caps.get(3).unwrap().as_str().to_owned());
|
||||
Some(DisabledTransitively {
|
||||
child: VersionedPackage { package, version },
|
||||
parent,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_disabled_transitviely() {
|
||||
let s = "- Network-NineP < 0 # tried Network-NineP-0.4.7.1, but its *library* requires the disabled package: mstate";
|
||||
assert_eq!(
|
||||
parse_disabled_transitviely(s),
|
||||
Some(DisabledTransitively {
|
||||
child: VersionedPackage {
|
||||
package: Package("Network-NineP".to_owned()),
|
||||
version: Version("0.4.7.1".to_owned())
|
||||
},
|
||||
parent: Package("mstate".to_owned()),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
type M = BTreeMap<Package, (Vec<VersionedPackage>, Option<usize>)>;
|
||||
|
||||
pub fn disabled() {
|
||||
let mut disabled_transitively: Vec<DisabledTransitively> = vec![];
|
||||
handle(false, |loc, lines| {
|
||||
match loc {
|
||||
Location::Lib => disabled_transitively.extend(
|
||||
lines
|
||||
.into_iter()
|
||||
.map(|line| parse_disabled_transitviely(&line))
|
||||
.flatten()
|
||||
.collect::<Vec<_>>(),
|
||||
),
|
||||
Location::Test | Location::Bench => (),
|
||||
}
|
||||
vec![]
|
||||
});
|
||||
|
||||
let mut packages: BTreeSet<Package> = BTreeSet::new();
|
||||
let mut disabled: M = BTreeMap::new();
|
||||
|
||||
for DisabledTransitively { child, parent } in disabled_transitively {
|
||||
packages.insert(child.package.clone());
|
||||
packages.insert(parent.clone());
|
||||
disabled
|
||||
.entry(child.package.clone())
|
||||
.or_insert_with(|| (vec![], None));
|
||||
let t = disabled.entry(parent).or_insert_with(|| (vec![], None));
|
||||
t.0.push(child);
|
||||
}
|
||||
|
||||
let mut packages_len = packages.len();
|
||||
while packages_len > 0 {
|
||||
let mut new_packages: BTreeSet<Package> = BTreeSet::new();
|
||||
for package in packages {
|
||||
let (_, count) = disabled.get(&package).unwrap();
|
||||
if count.is_none() && !process(&package, &mut disabled) {
|
||||
new_packages.insert(package.clone());
|
||||
}
|
||||
}
|
||||
packages = new_packages;
|
||||
packages_len = packages.len();
|
||||
}
|
||||
|
||||
let mut v: Vec<_> = disabled
|
||||
.into_iter()
|
||||
.map(|(package, (_, count))| (count, package))
|
||||
.collect();
|
||||
v.sort();
|
||||
for (count, package) in v {
|
||||
let count = count.unwrap();
|
||||
if count != 0 {
|
||||
println!("{package} is disabled with {count} dependents");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process(package: &Package, m: &mut M) -> bool {
|
||||
let (children, count) = m.get(package).unwrap();
|
||||
assert!(count.is_none(), "{:?}", package);
|
||||
let mut count = 0;
|
||||
for child in children {
|
||||
let (_, child_count) = m
|
||||
.get(&child.package)
|
||||
.unwrap_or_else(|| panic!("{}", child.package));
|
||||
match child_count {
|
||||
None => return false,
|
||||
Some(i) => count += 1 + i,
|
||||
}
|
||||
}
|
||||
m.entry(package.clone())
|
||||
.and_modify(|tup| tup.1 = Some(count))
|
||||
.or_insert_with(|| panic!("{}", package));
|
||||
true
|
||||
}
|
||||
@ -1,231 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, BufRead};
|
||||
|
||||
use lazy_regex::regex;
|
||||
use regex::Regex;
|
||||
use structopt::StructOpt;
|
||||
|
||||
type H = HashMap<Header, Vec<(String, String, String)>>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
enum Header {
|
||||
Versioned { package: String, version: String },
|
||||
Missing { package: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(
|
||||
name = "commenter",
|
||||
about = "Automates generation of bounds in build-constraints.yaml"
|
||||
)]
|
||||
enum Opt {
|
||||
Add,
|
||||
Clear,
|
||||
DiffSnapshot { a: String, b: String },
|
||||
Disabled,
|
||||
Outdated,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::from_args();
|
||||
match opt {
|
||||
Opt::Add => add(),
|
||||
Opt::Clear => commenter::clear(),
|
||||
Opt::DiffSnapshot { a, b } => commenter::diff_snapshot(a, b),
|
||||
Opt::Disabled => commenter::disabled(),
|
||||
Opt::Outdated => commenter::outdated(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_package_with_digit_after_dash() {
|
||||
let line = "- [ ] captcha-2captcha-0.1.0.0 (==0.1.*). Edward Yang <qwbarch@gmail.com> @qwbarch. @qwbarch. Used by: library";
|
||||
let p = parse_package_with_component(line).unwrap();
|
||||
assert_eq!(
|
||||
p,
|
||||
PackageWithComponent {
|
||||
package: "captcha-2captcha",
|
||||
version: "0.1.0.0",
|
||||
component: "library",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct PackageWithComponent<'a> {
|
||||
package: &'a str,
|
||||
version: &'a str,
|
||||
component: &'a str,
|
||||
}
|
||||
|
||||
fn parse_package_with_component(s: &str) -> Option<PackageWithComponent> {
|
||||
let package = regex!(
|
||||
r#"^- \[ \] (?P<package>[0-9a-zA-z][a-zA-Z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)) \(.+?Used by: (?P<component>.+)$"#
|
||||
);
|
||||
if let Some(cap) = package.captures(s) {
|
||||
let package = cap.name("package").unwrap().as_str();
|
||||
let version = cap.name("version").unwrap().as_str();
|
||||
let component = cap.name("component").unwrap().as_str();
|
||||
Some(PackageWithComponent {
|
||||
package,
|
||||
version,
|
||||
component,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_header_versioned() {
|
||||
let s = "aeson-2.0.3.0 ([changelog](http://hackage.haskell.org/package/aeson-2.0.3.0/changelog)) (Adam Bergmark <adam@bergmark.nl> @bergmark, Stackage upper bounds) is out of bounds for:";
|
||||
let p = parse_header_versioned(s).unwrap();
|
||||
assert_eq!(
|
||||
p,
|
||||
Header::Versioned {
|
||||
package: "aeson".to_owned(),
|
||||
version: "2.0.3.0".to_owned()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_header_versioned(s: &str) -> Option<Header> {
|
||||
let header_versioned = regex!(
|
||||
r#"^(?P<package>[\da-zA-z][a-zA-Z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)).+?is out of bounds for:$"#
|
||||
);
|
||||
if let Some(cap) = header_versioned.captures(s) {
|
||||
let package = cap.name("package").unwrap().as_str().to_owned();
|
||||
let version = cap.name("version").unwrap().as_str().to_owned();
|
||||
Some(Header::Versioned { package, version })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn add() {
|
||||
let mut lib_exes: H = Default::default();
|
||||
let mut tests: H = Default::default();
|
||||
let mut benches: H = Default::default();
|
||||
let mut last_header: Option<Header> = None;
|
||||
|
||||
let header_missing =
|
||||
regex!(r#"^(?P<package>[\da-zA-z][a-zA-Z]([a-zA-z0-9.-]*)).+?depended on by:$"#);
|
||||
|
||||
// Ignore everything until the bounds issues show up.
|
||||
let mut process_line = false;
|
||||
|
||||
for line in io::stdin().lock().lines().flatten() {
|
||||
if is_reg_match(&line, regex!(r#"^\s*$"#)) {
|
||||
// noop
|
||||
} else if line == "curator: Snapshot dependency graph contains errors:" {
|
||||
process_line = true;
|
||||
} else if !process_line {
|
||||
println!("[INFO] {line}");
|
||||
} else if let Some(PackageWithComponent {
|
||||
package,
|
||||
version,
|
||||
component,
|
||||
}) = parse_package_with_component(&line)
|
||||
{
|
||||
let root = last_header.clone().unwrap();
|
||||
match component {
|
||||
"library" | "executable" => {
|
||||
insert(&mut lib_exes, root, package, version, component)
|
||||
}
|
||||
"benchmark" => insert(&mut benches, root, package, version, "benchmarks"),
|
||||
"test-suite" => insert(&mut tests, root, package, version, component),
|
||||
_ => panic!("Bad component: {}", component),
|
||||
}
|
||||
} else if let Some(header_versioned) = parse_header_versioned(&line) {
|
||||
last_header = Some(header_versioned);
|
||||
} else if let Some(cap) = header_missing.captures(&line) {
|
||||
let package = cap.name("package").unwrap().as_str().to_owned();
|
||||
last_header = Some(Header::Missing { package });
|
||||
} else {
|
||||
panic!("Unhandled: {:?}", line);
|
||||
}
|
||||
}
|
||||
|
||||
let mut auto_lib_exes = vec![];
|
||||
let mut auto_tests = vec![];
|
||||
let mut auto_benches = vec![];
|
||||
|
||||
if !lib_exes.is_empty() {
|
||||
println!("\nLIBS + EXES\n");
|
||||
}
|
||||
for (header, packages) in lib_exes {
|
||||
for (package, version, component) in packages {
|
||||
let s = printer(" ", &package, true, &version, &component, &header);
|
||||
println!("{s}");
|
||||
auto_lib_exes.push(s);
|
||||
}
|
||||
}
|
||||
|
||||
if !tests.is_empty() {
|
||||
println!("\nTESTS\n");
|
||||
}
|
||||
for (header, packages) in tests {
|
||||
for (package, version, component) in packages {
|
||||
let s = printer(" ", &package, false, &version, &component, &header);
|
||||
println!("{s}");
|
||||
auto_tests.push(s);
|
||||
}
|
||||
}
|
||||
|
||||
if !benches.is_empty() {
|
||||
println!("\nBENCHMARKS\n");
|
||||
}
|
||||
for (header, packages) in benches {
|
||||
for (package, version, component) in packages {
|
||||
let s = printer(" ", &package, false, &version, &component, &header);
|
||||
println!("{s}");
|
||||
auto_benches.push(s);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
println!(
|
||||
"Adding {lib_exes} libs, {tests} tests, {benches} benches to build-constraints.yaml",
|
||||
lib_exes = auto_lib_exes.len(),
|
||||
tests = auto_tests.len(),
|
||||
benches = auto_benches.len()
|
||||
);
|
||||
commenter::add(auto_lib_exes, auto_tests, auto_benches);
|
||||
}
|
||||
|
||||
fn printer(
|
||||
indent: &str,
|
||||
package: &str,
|
||||
lt0: bool,
|
||||
version: &str,
|
||||
component: &str,
|
||||
header: &Header,
|
||||
) -> String {
|
||||
let lt0 = if lt0 { " < 0" } else { "" };
|
||||
format!(
|
||||
"{indent}- {package}{lt0} # tried {package}-{version}, but its *{component}* {cause}",
|
||||
cause = match header {
|
||||
Header::Versioned { package, version } => format!(
|
||||
"does not support: {package}-{version}",
|
||||
package = package,
|
||||
version = version
|
||||
),
|
||||
Header::Missing { package } => format!(
|
||||
"requires the disabled package: {package}",
|
||||
package = package
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn insert(h: &mut H, header: Header, package: &str, version: &str, component: &str) {
|
||||
(*h.entry(header).or_insert_with(Vec::new)).push((
|
||||
package.to_owned(),
|
||||
version.to_owned(),
|
||||
component.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
fn is_reg_match(s: &str, r: &Regex) -> bool {
|
||||
r.captures(s).is_some()
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user