mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-01-13 07:48:31 +01:00
Merge remote-tracking branch 'origin/master' into ghc-9.2
This commit is contained in:
commit
de33001399
72
CURATORS.md
72
CURATORS.md
@ -317,7 +317,7 @@ First run `build.sh` to regenerate updated `ltsXX/work/constraints.yaml` and `lt
|
||||
|
||||
For an LTS minor bump, you'll typically want to:
|
||||
|
||||
* Add constraints to package `range:` fields _under_ the `source:` field in that `constraints.yaml`, and edit `snapshot-incomplete.yaml` to change the version used for that package, if necessary.
|
||||
* Add constraints to package `range:` fields _under_ the `source:` field in that `constraints.yaml` (should not be necessary normally to edit `snapshot-incomplete.yaml` to change the version used for that package).
|
||||
* Add new packages to the `constraints.yaml` file
|
||||
* Test, benchmark, haddock failures can also be added to package fields in the `constraints.yaml` if necessary, though it should be avoided if possible for LTS.
|
||||
|
||||
@ -422,20 +422,16 @@ errors for builds, tests and benchmarks.
|
||||
|
||||
### Large scale enabling/disabling of packages
|
||||
|
||||
`etc/commenter` is a binary that mostly automates the translation of
|
||||
`./check` errors into lines that go into `build-constraints.yaml`. It
|
||||
can only handle bounds issues, compilation issues still need to be
|
||||
handled manually.
|
||||
|
||||
It disables all offending packages/test suites/benchmarks, so it is
|
||||
only meant to be used when we close bounds issues and want to disable
|
||||
packages, and when upgrading GHC.
|
||||
`etc/commenter` is a binary that automates `build-constraints.yaml` workflows.
|
||||
|
||||
#### Setup
|
||||
This is currently a rust program, You can install the rust toolchain
|
||||
by using [rustup](https://rustup.rs/).
|
||||
|
||||
Then `cargo install --locked --path etc/commenter`
|
||||
For some commands you also need etc/commenter/latest-version installed.
|
||||
```
|
||||
stack install --stack-yaml etc/commenter/latest-version/stack.yaml
|
||||
```
|
||||
|
||||
#### Example usage
|
||||
|
||||
@ -456,7 +452,7 @@ testing-feat (GHC 9 bounds issues, Grandfathered dependencies) (not present) dep
|
||||
|
||||
Now run:
|
||||
```
|
||||
./check 2>&1 >/dev/null | commenter add
|
||||
./check 2>&1 >/dev/null | ./commenter add
|
||||
```
|
||||
|
||||
You will get this output:
|
||||
@ -483,8 +479,8 @@ Re-run this command until no more packages are disabled.
|
||||
We can periodically remove all packages under the bounds sections and then re-run the disabling flow above until we get a clean plan. This will automatically pick up packages that have been fixed.
|
||||
|
||||
```
|
||||
commenter clear
|
||||
./check 2>&1 >/dev/null | commenter add
|
||||
./commenter clear
|
||||
./check 2>&1 >/dev/null | ./commenter add
|
||||
```
|
||||
|
||||
Repeat the second command until no updates are made to build-constraints.yaml.
|
||||
@ -493,7 +489,7 @@ Repeat the second command until no updates are made to build-constraints.yaml.
|
||||
|
||||
Run `stack update` before doing this.
|
||||
|
||||
`commenter outdated` looks through all bounds issues and library
|
||||
`./commenter outdated` looks through all bounds issues and library
|
||||
compilation failures and compares the marked version with the latest hackage release. Example output is
|
||||
|
||||
```
|
||||
@ -504,7 +500,7 @@ aeson mismatch, auto: 1.5.6.0, hackage: 2.0.2.0
|
||||
where "manual" means the bound was added manually by a curator,
|
||||
perhaps due to a compilation failure so we could try re-enabling the
|
||||
package. "auto" means it's part of the sections generated by
|
||||
`commenter`, to update that run the `Re-enabling` step as documented
|
||||
`./commenter`, to update that run the `Re-enabling` step as documented
|
||||
above.
|
||||
|
||||
`outdated` only finds packages that are in the auto generated
|
||||
@ -520,7 +516,7 @@ To diff existing snapshots, or to evaluate changes before they end up
|
||||
in a snapshot you can run:
|
||||
|
||||
```
|
||||
commenter diff-snapshot <old-snapshot.yaml> <new-snapshot.yaml>
|
||||
./commenter diff-snapshot <old-snapshot.yaml> <new-snapshot.yaml>
|
||||
```
|
||||
|
||||
Existing snapshots can be retrieved from https://github.com/commercialhaskell/stackage-snapshots. Preliminary snapshots can be generated by running relevant parts of `automated/build.sh`, at the time of writing:
|
||||
@ -533,6 +529,50 @@ TARGET=nightly-2021-01-14 \ # the date doesn't matter
|
||||
curator snapshot
|
||||
```
|
||||
|
||||
#### Pinging maintainers after disabling packages
|
||||
|
||||
After lifting a bound We often have to disable additional packages due
|
||||
to compilation failures. `affected` figures out which packages have
|
||||
been disabled and which maintainers are affected. Note that this does
|
||||
not handle disabled test suites and benchmarks as the snapshots don't
|
||||
contain this information.
|
||||
|
||||
```
|
||||
./commenter affected <old-snapshot.yaml> <new-snapshot.yaml>
|
||||
```
|
||||
|
||||
E.g.:
|
||||
```
|
||||
$ commenter affected ../stackage-snapshots/nightly/2022/1/2.yaml ../stackage-snapshots/nightly/2022/2/7.yaml
|
||||
```
|
||||
```
|
||||
alg-0.2.13.1: Matthew Farkas-Dyck <strake888@gmail.com> @strake
|
||||
butter-0.1.0.6: Matthew Ahrens <matt.p.ahrens@gmail.com> @mpahrens
|
||||
category-0.2.5.0: Matthew Farkas-Dyck <strake888@gmail.com> @strake
|
||||
constraint-0.1.4.0: Matthew Farkas-Dyck <strake888@gmail.com> @strake
|
||||
dl-fedora-0.9.2: Jens Petersen <juhpetersen@gmail.com> @juhp
|
||||
foldable1-0.1.0.0: Matthew Farkas-Dyck <strake888@gmail.com> @strake
|
||||
gitlab-haskell-0.3.2.0: Rob Stewart <robstewart57@gmail.com> @robstewart57
|
||||
hslua-module-doclayout-1.0.0: Albert Krewinkel <albert+stackage@zeitkraut.de> @tarleb
|
||||
util-0.1.17.1: Matthew Farkas-Dyck <strake888@gmail.com> @strake
|
||||
wai-middleware-auth-0.2.5.1: Alexey Kuleshevich <lehins@yandex.ru> @lehins
|
||||
yesod-csp-0.2.5.0: Bob Long <robertjflong@gmail.com> @bobjflong
|
||||
```
|
||||
|
||||
#### Finding disabled packages with lots of dependents
|
||||
|
||||
`./commenter disabled` prints the number of transitive dependents a disabled package has. Low hanging fruit to get a lot of packages included again.
|
||||
|
||||
Example output:
|
||||
```
|
||||
[...]
|
||||
stringable is disabled with 10 dependents
|
||||
llvm-hs is disabled with 12 dependents
|
||||
th-data-compat is disabled with 12 dependents
|
||||
amazonka-core is disabled with 96 dependents
|
||||
gogol-core is disabled with 96 dependents
|
||||
```
|
||||
|
||||
## Adding new curators
|
||||
|
||||
1. Add public ssh key to `~/.ssh/authorized_keys` on build server
|
||||
|
||||
3
automated/dockerfiles/lts-18.27/Dockerfile
Normal file
3
automated/dockerfiles/lts-18.27/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
||||
FROM $DOCKER_REPO:lts-18.26
|
||||
ARG STACK_VERSION=2.7.5
|
||||
RUN wget -qO- https://github.com/commercialhaskell/stack/releases/download/v$STACK_VERSION/stack-$STACK_VERSION-linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C /usr/local/bin '*/stack'
|
||||
90
automated/dockerfiles/lts-18.9/Dockerfile
Normal file
90
automated/dockerfiles/lts-18.9/Dockerfile
Normal file
@ -0,0 +1,90 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
LABEL maintainer="manny@fpcomplete.com"
|
||||
|
||||
ARG GHC_VERSION=8.10.7
|
||||
ARG LTS_SLUG=lts-18.9
|
||||
ARG PID1_VERSION=0.1.2.0
|
||||
ARG STACK_VERSION=2.7.3
|
||||
ARG CUDA_VERSION=10.0
|
||||
ARG JVM_PATH=/usr/lib/jvm/java-8-openjdk-amd64
|
||||
ARG LLVM_PATH=/usr/lib/llvm-7
|
||||
ARG BOOTSTRAP_COMMIT=b1d40e112040a7f44eff47a9fafb6937f5d02dff
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG VARIANT=build
|
||||
ARG STACK_ROOT=/home/stackage/.stack
|
||||
|
||||
#
|
||||
# Set encoding to UTF-8 and PATH to find GHC and cabal/stack-installed binaries.
|
||||
#
|
||||
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
PATH=/root/.local/bin:/usr/local/cuda-$CUDA_VERSION/bin:$STACK_ROOT/programs/x86_64-linux/ghc-$GHC_VERSION/bin:$PATH \
|
||||
CUDA_PATH=/usr/local/cuda-$CUDA_VERSION \
|
||||
CPATH=$JVM_PATH/include:$JVM_PATH/include/linux:$LLVM_PATH/include
|
||||
|
||||
#
|
||||
# Install pre-requisites
|
||||
#
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget netbase ca-certificates g++ gcc libc6-dev libffi-dev libgmp-dev \
|
||||
make xz-utils zlib1g-dev git gnupg libtinfo-dev jq && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
#
|
||||
# Use Stackage's debian-bootstrap.sh script to install system libraries and
|
||||
# tools required to build any Stackage package.
|
||||
# Re-installs 'stack' *after* running debian-bootstrap.sh since that may have
|
||||
# installed a different version.
|
||||
# In the case of 'small' image, just install Stack and GHC.
|
||||
#
|
||||
|
||||
RUN if [ "$VARIANT" != "small" ]; then \
|
||||
wget -qO- https://raw.githubusercontent.com/fpco/stackage/$BOOTSTRAP_COMMIT/debian-bootstrap.sh | sed "s/^GHCVER=9.0.1$/GHCVER=$GHC_VERSION/" | GHCVER=$GHC_VERSION bash; \
|
||||
fi && \
|
||||
wget -qO- https://github.com/commercialhaskell/stack/releases/download/v$STACK_VERSION/stack-$STACK_VERSION-linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C /usr/bin '*/stack' && \
|
||||
if [ "$VARIANT" = "small" ]; then \
|
||||
stack setup --resolver ghc-$GHC_VERSION; \
|
||||
fi && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
cd $STACK_ROOT && \
|
||||
find . -type f -not -path "./programs/x86_64-linux/ghc-$GHC_VERSION/*" -exec rm '{}' \; && \
|
||||
find . -type d -print0 |sort -rz |xargs -0 rmdir 2>/dev/null || true
|
||||
|
||||
#
|
||||
# Configure Stack to use the GHC installed in the Docker image rather than installing its own
|
||||
#
|
||||
|
||||
RUN mkdir /etc/stack/ && \
|
||||
echo "system-ghc: true" >/etc/stack/config.yaml
|
||||
|
||||
#
|
||||
# Use 'stack' to install basic Haskell tools like alex, happy, and cpphs. We
|
||||
# remove most of the STACK_ROOT afterward to save space, but keep the 'share'
|
||||
# files that some of these tools require.
|
||||
#
|
||||
|
||||
RUN stack --resolver=$LTS_SLUG --local-bin-path=/usr/bin install \
|
||||
happy alex cpphs gtk2hs-buildtools hscolour hlint hindent && \
|
||||
cd $STACK_ROOT && \
|
||||
find . -type f -not -path './snapshots/*/share/*' -and -not -path "./programs/x86_64-linux/ghc-$GHC_VERSION/*" -exec rm '{}' \; && \
|
||||
find . -type d -print0 |sort -rz |xargs -0 rmdir 2>/dev/null || true
|
||||
|
||||
#
|
||||
# Install 'pid1' init daemon
|
||||
#
|
||||
|
||||
RUN wget -O- "https://github.com/fpco/pid1/releases/download/v$PID1_VERSION/pid1-$PID1_VERSION-linux-x86_64.tar.gz" | tar xzf - -C /usr/local && \
|
||||
chown root:root /usr/local/sbin && \
|
||||
chown root:root /usr/local/sbin/pid1
|
||||
|
||||
#
|
||||
# Set up pid1 entrypoint and default command
|
||||
#
|
||||
|
||||
ENTRYPOINT ["/usr/local/sbin/pid1"]
|
||||
CMD ["bash"]
|
||||
File diff suppressed because it is too large
Load Diff
9
commenter
Executable file
9
commenter
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if ! command -v commenter &> /dev/null
|
||||
then
|
||||
echo "commenter is not installed, get it from https://github.com/bergmark/commenter"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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
|
||||
hs-source-dirs: src
|
||||
main-is: Main.hs
|
||||
default-language: Haskell2010
|
||||
build-depends: base >= 4.7 && < 5
|
||||
, pantry
|
||||
, Cabal
|
||||
, rio
|
||||
, containers
|
||||
@ -1,18 +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 =
|
||||
runPantryApp $
|
||||
liftIO . putStrLn
|
||||
. intercalate "." . map show . versionNumbers
|
||||
. fst . head . Map.toDescList
|
||||
=<< getHackagePackageVersions YesRequireHackageIndex IgnorePreferredVersions
|
||||
. mkPackageName =<< head <$> liftIO getArgs
|
||||
@ -1,4 +0,0 @@
|
||||
resolver:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/18.yaml
|
||||
packages:
|
||||
- .
|
||||
@ -1,418 +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(String),
|
||||
Auto(String),
|
||||
}
|
||||
|
||||
impl VersionTag {
|
||||
fn tag(&self) -> &'static str {
|
||||
match self {
|
||||
VersionTag::Manual(_) => "manual",
|
||||
VersionTag::Auto(_) => "auto",
|
||||
}
|
||||
}
|
||||
|
||||
fn version(&self) -> &str {
|
||||
match self {
|
||||
VersionTag::Manual(s) => s,
|
||||
VersionTag::Auto(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outdated() {
|
||||
let mut all: Vec<String> = vec![];
|
||||
let versioned = handle(false, |_loc, lines| {
|
||||
all.extend(lines);
|
||||
vec![]
|
||||
});
|
||||
let mut map: BTreeMap<String, VersionTag> = BTreeMap::new();
|
||||
for VersionedPackage { package, version } in versioned {
|
||||
map.insert(package, VersionTag::Manual(version));
|
||||
}
|
||||
let mut support: BTreeMap<(String, String), BTreeSet<(String, String)>> = BTreeMap::new();
|
||||
for v in all.into_iter() {
|
||||
let caps = regex!("tried ([^ ]+)-([^,-]+),").captures(&v).unwrap();
|
||||
let package = caps.get(1).unwrap().as_str().to_owned();
|
||||
let 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 = caps.get(1).unwrap().as_str().to_owned();
|
||||
let dep_version = caps.get(2).unwrap().as_str().to_owned();
|
||||
let entry = support.entry((dep_package, dep_version)).or_default();
|
||||
entry.insert((package, version));
|
||||
}
|
||||
}
|
||||
|
||||
let entries = map.len() + support.len();
|
||||
let mut i = 0;
|
||||
|
||||
for (package, version) in map {
|
||||
if is_boot(&package) {
|
||||
continue;
|
||||
}
|
||||
if i % 100 == 0 {
|
||||
println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
|
||||
}
|
||||
i += 1;
|
||||
let latest = latest_version(&package);
|
||||
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;
|
||||
}
|
||||
|
||||
if i % 100 == 0 {
|
||||
println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
|
||||
}
|
||||
i += 1;
|
||||
let latest = latest_version(&package);
|
||||
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: &str) -> 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)
|
||||
}
|
||||
|
||||
fn latest_version(pkg: &str) -> String {
|
||||
String::from_utf8(
|
||||
Command::new("latest-version")
|
||||
.args([pkg])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
enum State {
|
||||
LookingForLibBounds,
|
||||
ProcessingLibBounds,
|
||||
LookingForTestBounds,
|
||||
ProcessingTestBounds,
|
||||
LookingForBenchBounds,
|
||||
ProcessingBenchBounds,
|
||||
Done,
|
||||
}
|
||||
|
||||
struct VersionedPackage {
|
||||
package: String,
|
||||
version: String,
|
||||
}
|
||||
|
||||
fn parse_versioned_package(s: &str) -> Option<VersionedPackage> {
|
||||
if let Some(caps) = regex!(r#"- *([^ ]+) < *0 *# *([\d.]+)"#).captures(s) {
|
||||
let package = caps.get(1).unwrap().as_str().to_owned();
|
||||
let 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 = caps.get(1).unwrap().as_str().to_owned();
|
||||
let version = caps.get(2).unwrap().as_str().to_owned();
|
||||
Some(VersionedPackage { package, version })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn handle<F>(write: bool, mut f: F) -> Vec<VersionedPackage>
|
||||
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 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(&line) {
|
||||
versioned_packages.push(versioned_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
|
||||
}
|
||||
|
||||
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<PackageName, BTreeMap<PackageFlag, bool>>,
|
||||
// publish_time
|
||||
packages: Vec<SnapshotPackage>,
|
||||
// hidden
|
||||
// resolver
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SnapshotPackage {
|
||||
hackage: PackageWithVersionAndSha,
|
||||
// pantry-tree
|
||||
}
|
||||
|
||||
#[derive(PartialOrd, Ord, PartialEq, Eq, Clone)]
|
||||
struct PackageName(String);
|
||||
|
||||
impl fmt::Display for PackageName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)]
|
||||
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: PackageName,
|
||||
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 = PackageName(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<PackageName, 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}");
|
||||
}
|
||||
}
|
||||
@ -1,169 +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 {
|
||||
Clear,
|
||||
Add,
|
||||
Outdated,
|
||||
DiffSnapshot { a: String, b: String },
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::from_args();
|
||||
match opt {
|
||||
Opt::Clear => commenter::clear(),
|
||||
Opt::Add => add(),
|
||||
Opt::Outdated => commenter::outdated(),
|
||||
Opt::DiffSnapshot { a, b } => commenter::diff_snapshot(a, b),
|
||||
}
|
||||
}
|
||||
|
||||
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_versioned = regex!(
|
||||
r#"^(?P<package>[a-zA-z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)).+?is out of bounds for:$"#
|
||||
);
|
||||
let header_missing = regex!(r#"^(?P<package>[a-zA-z]([a-zA-z0-9.-]*)).+?depended on by:$"#);
|
||||
let package = regex!(
|
||||
r#"^- \[ \] (?P<package>[a-zA-z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)).+?Used by: (?P<component>.+)$"#
|
||||
);
|
||||
|
||||
// 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(cap) = package.captures(&line) {
|
||||
let root = last_header.clone().unwrap();
|
||||
let package = cap.name("package").unwrap().as_str();
|
||||
let version = cap.name("version").unwrap().as_str();
|
||||
let component = cap.name("component").unwrap().as_str();
|
||||
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(cap) = header_versioned.captures(&line) {
|
||||
let package = cap.name("package").unwrap().as_str().to_owned();
|
||||
let version = cap.name("version").unwrap().as_str().to_owned();
|
||||
last_header = Some(Header::Versioned { package, version });
|
||||
} 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