stacker (empty) → 0.0.0.0
raw patch · 46 files changed
+5737/−0 lines, 46 filesdep +aesondep +ansi-terminaldep +base
Dependencies added: aeson, ansi-terminal, base, bytestring, containers, directory, file-embed, filepath, optparse-applicative, process, stacker, tasty, tasty-golden, temporary, text, yaml
Files
- CHANGELOG.md +7/−0
- LICENSE +28/−0
- README.md +264/−0
- app/Main.hs +9/−0
- data/ghc.csv +59/−0
- data/lts.csv +610/−0
- data/nightly.csv +3096/−0
- src/Analysis.hs +134/−0
- src/CSV.hs +322/−0
- src/ColorOption.hs +21/−0
- src/Commands.hs +213/−0
- src/Config.hs +49/−0
- src/Git.hs +56/−0
- src/License.hs +9/−0
- src/Options.hs +110/−0
- src/PathUtil.hs +98/−0
- src/StackYaml.hs +139/−0
- src/Types.hs +100/−0
- src/XDG.hs +30/−0
- stacker.cabal +126/−0
- test/Main.hs +16/−0
- test/TestBump.hs +60/−0
- test/TestDryRun.hs +53/−0
- test/golden/dry-run-files.golden +2/−0
- test/golden/dry-run-recursive.golden +6/−0
- test/golden/dry-run.golden +8/−0
- test/golden/tests/stack-9.0.yaml +9/−0
- test/golden/tests/stack-9.10.yaml +6/−0
- test/golden/tests/stack-9.12.yaml +1/−0
- test/golden/tests/stack-9.2.yaml +2/−0
- test/golden/tests/stack-9.4.yaml +15/−0
- test/golden/tests/stack-9.6.yaml +10/−0
- test/golden/tests/stack-9.8.yaml +1/−0
- test/golden/tests/stack.yaml +6/−0
- test/recursive/other/stack.yaml +3/−0
- test/recursive/stack-9.6.yaml +3/−0
- test/recursive/subdir1/stack-9.8.yaml +3/−0
- test/recursive/subdir1/subdir2/stack-9.10.yaml +3/−0
- test/tests/stack-9.0.yaml +9/−0
- test/tests/stack-9.10.yaml +6/−0
- test/tests/stack-9.12.yaml +1/−0
- test/tests/stack-9.2.yaml +2/−0
- test/tests/stack-9.4.yaml +15/−0
- test/tests/stack-9.6.yaml +10/−0
- test/tests/stack-9.8.yaml +1/−0
- test/tests/stack.yaml +6/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+0.0.0.0+=======++Initial release.+* Tested with GHC 9.4.8 - 9.12.4.++_Andreas Abel, 2026-04-08_
+ LICENSE view
@@ -0,0 +1,28 @@+BSD 3-Clause License++Copyright (c) 2025, Andreas Abel++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++2. 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.++3. Neither the name of the copyright holder nor the names of its+ 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 HOLDER 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.
+ README.md view
@@ -0,0 +1,264 @@+# stacker++Bump snapshots (aka resolvers) in `stack*.yaml` files.++The `stacker` tools goes through the given files (or all `stack*.yaml` files in the current directory),+inspects the value of the `snapshot:` (or `resolver:`) field and upgrades it in the following way:++1. If the value is pointing to a LTS snapshot, e.g., `lts-24.10`,+ it will bump it to the latest version of this LTS+ (at the time of writing this is `lts-24.36`).++2. If the value is pointing to a nightly release and this nightly+ belongs to a GHC major version for which an LTS exists,+ it will bump it to the latest LTS for this GHC version.+ For instance, `nightly-2024-12-15` is for GHC 9.10.1,+ but there is LTS series 24 for GHC 9.10,+ so the snapshot will be bumped to `lts-24.36`,+ the latest of the LTS series 24.++3. If the value is pointing to a nightly release for a GHC major version+ that has no LTS yet, it will be bumped to the latest nightly snapshot+ for this GHC major version.+ For instance, snapshot `nightly-2025-10-10` is for GHC 9.12.2,+ and there is no LTS series for GHC 9.12 yet (at the time of writing),+ so the snapshot value will be bumped to `nightly-2026-04-01`,+ the latest nightly (at the time of writing this).++## Example++```+$ stacker++stack-8.10.yaml lts-18.28 ✓ up to date+stack-8.2.yaml lts-11.22 ✓ up to date+stack-8.4.yaml lts-12.26 ✓ up to date+stack-8.6.yaml lts-14.27 ✓ up to date+stack-8.8.yaml lts-16.31 ✓ up to date+stack-9.0.yaml lts-19.33 ✓ up to date+stack-9.10.yaml lts-24.28 → bump to lts-24.36+stack-9.12.yaml nightly-2025-10-14 → bump to nightly-2026-04-01+stack-9.2.yaml lts-20.26 ✓ up to date+stack-9.4.yaml lts-21.25 ✓ up to date+stack-9.6.yaml lts-22.44 ✓ up to date+stack-9.8.yaml lts-23.28 ✓ up to date+stack.yaml nightly-2025-10-14 = symlink to stack-9.12.yaml+```+```+$ stacker bump++Updating stack-9.10.yaml+Updating stack-9.12.yaml+```++## Synopsis++`stacker` understands the following essential commands:++| Command | Description |+|----------------------|----------------------------------------------------------------------------------|+| `bump [FILES...]` | Updates FILES (all `stack*.yaml` files if none specified) |+| `dry-run [FILES...]` | Shows what updates would be performed by the respective `bump` (default command) |+| `config` | Configures `stacker` |+| `update` | Updates its database of Stackage snapshots |+| `info` | Prints table mapping GHC major versions to their latest snapshots |++These can be modified with the following option(s):++| Option | Values | Description |+|---------------|-------------------------|--------------------------------------------------------------------|+| `--color` | `always`,`never`,`auto` | Colored output? (Default: `auto`) |+| `--recursive` | (flag) | Search for `stack*.yaml` files in all subdirectories (short: `-r`) |++When `--color=auto` is used (the default), colors are disabled+if the `NO_COLOR` environment variable is set to any value,+following the standard described at https://no-color.org.+Colors can still be forced on with `--color=always` even when `NO_COLOR` is set.++**Note:** The `--recursive` flag can only be used with `bump` and `dry-run` commands+when no explicit FILES are specified. If you provide explicit file arguments,+you cannot use the `--recursive` flag.++It also has the following inessential commands (standard options) that just give information about itself:++| Command | Alternatives | Description |+|-------------------|---------------------|-------------------------------------------------------------------------------------|+| `version` | `--version`, `-V` | Prints version and copyright info |+| `numeric-version` | `--numeric-version` | Prints just the version number |+| `license` | `--license` | Prints the license text (BSD 3-clause) |+| `help` | `--help`, `-h` | Prints `--version`, one paragraph description of functionality, and list of options |++`stacker` runs on the 3 major platforms Linux, macOS, and Windows.++## Data files++`stacker` comes with 3 data files that are copied into its+XDG-conform application directory (`$XDG_STATE_HOME/stacker`)+whenever the program is invoked and they do not exist there yet.++1. `lts.csv` containing a map from LTS version to GHC version, e.g.+ ```+ ...+ 22.42,9.6.6+ 22.43,9.6.6+ 22.44,9.6.7+ 23.1,9,8.4+ 23.2,9.8.4+ ...+ 23.28,9.8.4+ 24.1,9.10.1+ ...+ ```++2. `nightly.csv` containing a map from nightly version to GHC version, e.g.+ ```+ ...+ 2024-01-01,9.8.1+ ...+ 2025-07-07,9.10.2+ ...+ 2025-12-08,9.12.2+ 2025-12-09,9.12.2+ ```++3. `ghc.csv` containing a map from GHC version to its latest LTS or nightly snapshot, e.g.+ ```+ ...+ 9.2.8,lts-20.26+ 9.4.5,lts-21.7+ ...+ 9.4.8,lts-21.25+ 9.6.3,lts-22.6+ ...+ 9.6.6,lts-22.43+ 9.6.7,lts-22.44+ ...+ 9.10.3,lts-24.36+ 9.12.4,nightly-2026-04-01+ ```++These data files determine the results of `bump` (and its preview by `dry-run`).++## `bump` command++`stacker bump` looks for all `stack*.yaml` files in the current directory and updates them as described above.++Alternatively, you can specify specific files to bump:+```+stacker bump stack-9.6.yaml stack-9.8.yaml+```++To search for `stack*.yaml` files recursively in all subdirectories:+```+stacker bump --recursive+```+or+```+stacker bump -r+```++Only the content of the `snapshot:` and `resolver:` fields will be updated,+everything else will remain literally the same, including comments and whitespace.++## `dry-run` command++This command is also run if no command is given to `stacker`.+It prints a table with all `stack*.yaml` files in the current directory,+their `snapshot` (which can also be given in the `resolver` field), and what action to take (if any).++Alternatively, you can specify specific files to check:+```+stacker dry-run stack-9.6.yaml stack-9.8.yaml+```++To search for `stack*.yaml` files recursively in all subdirectories:+```+stacker dry-run --recursive+```+or+```+stacker dry-run -r+```++Example output:+```+stack-9.2.yaml lts-20.26 ✓ up to date+stack-9.4.yaml lts-21.25 ✓ up to date+stack-9.6.yaml lts-22.43 → bump to lts-22.44+stack-9.8.yaml lts-23.1 → bump to lts-23.28+stack-9.10.yaml nightly-2024-07-07 → bump to lts-24.36+stack-9.12.yaml nightly-2025-10-03 → bump to nightly-2026-04-01+```+When coloring is on, the `stack*.yml` column is printed in bold, `✓ up to date` in green and any bump action in bright yellow.++Internally, `bump` and `dry-run` share the analysis phase that reads the `stack*.yaml` and creates for each an action plan,+yet `dry-run` just pretty-prints this plan as detailed above whereas `bump` executes it.++## Configuration (optional)++`stacker update` regenerates its information about GHC versions and Stackage snapshots from the repository+https://github.com/commercialhaskell/stackage-snapshots .++If you have a clone of this repository already, you might want to configure `stacker` to use it+so it does not make its own clone (which takes ~2GB of disk space).++By default, `stacker` stores information about the Stackage snapshots+in its XDG-conform application directory (`$XDG_STATE_HOME/stacker`),+by creating a shallow git clone of said repository there+(typically `$XDG_STATE_HOME/stacker/stackage-snapshots`).++With the command+```+ stacker config repo path/to/dir+```+the stackage-snapshots repository will be instead searched for in `path/to/dir`.+The effect of the `config` command is to write file `config.yaml`+in the XDG-conform configuration directory (`$XDG_CONFIG_HOME/stacker`)+with the following content:+```yaml+# stacker configuration++repo: /absolute/path/to/dir+```+where `/absolute/path/to/dir` is the `path/to/dir` turned into an absolute path.++Whenever `stacker` is started with an essential command,+it will attempt to read this configuration file and extract the value of `repo`, if it is given.+We shall refer to this value as `$REPO`.+It defaults to `$XDG_STATE_HOME/stacker/stackage-snapshots` if not configured.++## `update` command++`stacker update` first prints the path to the repo (value of `$REPO`).+If the repo does not exist,+it will be created as a shallow git clone of https://github.com/commercialhaskell/stackage-snapshots .++Once created, it will only be updated by `stacker update`, and then only if its `master` branch is checked out.+If another branch is checked out, the `update` command exits with an error.++The `update` command then regenerates then three files `lts.csv`, `nightly.csv` and `ghc.csv` in `$XDG_STATE_HOME/stacker/`.++## `info` command++`stacker info` prints the following things in YAML format:+1. `repo: $REPO`+2. A map between each latest major GHC version and its corresponding latest LTS or nightly snapshot,+ as read from `ghc.csv`. Example:+ ```yaml+ snapshots:+ ...+ 9.2.8: lts-20.26+ 9.4.8: lts-21.25+ 9.6.7: lts-22.44+ 9.8.4: lts-23.28+ 9.10.3: lts-24.36+ 9.12.4: nightly-2026-04-01+ ```++## Testing++This project is accompanied by a golden value testsuite (framework `tasty-golden`) that tests the `dry-run` and `bump` commands.++## License++BSD 3-clause.
+ app/Main.hs view
@@ -0,0 +1,9 @@+module Main where++import Options (parseOptions)+import Commands (runCommand)++main :: IO ()+main = do+ opts <- parseOptions+ runCommand opts
+ data/ghc.csv view
@@ -0,0 +1,59 @@+7.8.3,lts-0.7+7.8.4,lts-2.22+7.10.1,nightly-2015-08-04+7.10.2,lts-3.22+7.10.3,lts-6.35+8.0.1,lts-7.24+8.0.2,lts-9.21+8.2.1,nightly-2017-11-24+8.2.2,lts-11.22+8.4.1,nightly-2018-04-21+8.4.2,nightly-2018-05-30+8.4.3,lts-12.14+8.4.4,lts-12.26+8.6.1,nightly-2018-11-11+8.6.2,nightly-2018-12-17+8.6.3,lts-13.11+8.6.4,lts-13.19+8.6.5,lts-14.27+8.8.1,nightly-2020-01-21+8.8.2,lts-15.3+8.8.3,lts-16.11+8.8.4,lts-16.31+8.10.1,nightly-2020-08-16+8.10.2,nightly-2020-12-14+8.10.3,lts-17.2+8.10.4,lts-18.6+8.10.6,lts-18.8+8.10.7,lts-18.28+9.0.1,nightly-2022-01-06+9.0.2,lts-19.33+9.2.2,nightly-2022-06-06+9.2.3,nightly-2022-07-31+9.2.4,nightly-2022-11-12+9.2.5,lts-20.11+9.2.6,lts-20.12+9.2.7,lts-20.24+9.2.8,lts-20.26+9.4.3,nightly-2022-12-26+9.4.4,nightly-2023-04-24+9.4.5,lts-21.7+9.4.6,lts-21.11+9.4.7,lts-21.21+9.4.8,lts-21.25+9.6.2,nightly-2023-09-30+9.6.3,lts-22.6+9.6.4,lts-22.20+9.6.5,lts-22.27+9.6.6,lts-22.43+9.6.7,lts-22.44+9.8.1,nightly-2024-03-07+9.8.2,nightly-2024-10-21+9.8.3,nightly-2024-12-04+9.8.4,lts-23.28+9.10.1,nightly-2025-05-05+9.10.2,lts-24.11+9.10.3,lts-24.36+9.12.2,nightly-2025-12-30+9.12.3,nightly-2026-03-28+9.12.4,nightly-2026-04-07
+ data/lts.csv view
@@ -0,0 +1,610 @@+0.0,7.8.3+0.1,7.8.3+0.2,7.8.3+0.3,7.8.3+0.4,7.8.3+0.5,7.8.3+0.6,7.8.3+0.7,7.8.3+1.0,7.8.4+1.1,7.8.4+1.2,7.8.4+1.4,7.8.4+1.5,7.8.4+1.7,7.8.4+1.8,7.8.4+1.9,7.8.4+1.10,7.8.4+1.11,7.8.4+1.12,7.8.4+1.13,7.8.4+1.14,7.8.4+1.15,7.8.4+2.0,7.8.4+2.1,7.8.4+2.2,7.8.4+2.3,7.8.4+2.4,7.8.4+2.5,7.8.4+2.6,7.8.4+2.7,7.8.4+2.8,7.8.4+2.9,7.8.4+2.10,7.8.4+2.11,7.8.4+2.12,7.8.4+2.13,7.8.4+2.14,7.8.4+2.15,7.8.4+2.16,7.8.4+2.17,7.8.4+2.18,7.8.4+2.19,7.8.4+2.20,7.8.4+2.21,7.8.4+2.22,7.8.4+3.0,7.10.2+3.1,7.10.2+3.2,7.10.2+3.3,7.10.2+3.4,7.10.2+3.5,7.10.2+3.6,7.10.2+3.7,7.10.2+3.8,7.10.2+3.9,7.10.2+3.10,7.10.2+3.11,7.10.2+3.12,7.10.2+3.13,7.10.2+3.14,7.10.2+3.15,7.10.2+3.16,7.10.2+3.17,7.10.2+3.18,7.10.2+3.19,7.10.2+3.20,7.10.2+3.21,7.10.2+3.22,7.10.2+4.0,7.10.3+4.1,7.10.3+4.2,7.10.3+5.0,7.10.3+5.1,7.10.3+5.2,7.10.3+5.3,7.10.3+5.4,7.10.3+5.5,7.10.3+5.6,7.10.3+5.7,7.10.3+5.8,7.10.3+5.9,7.10.3+5.10,7.10.3+5.11,7.10.3+5.12,7.10.3+5.13,7.10.3+5.14,7.10.3+5.15,7.10.3+5.16,7.10.3+5.17,7.10.3+5.18,7.10.3+6.0,7.10.3+6.1,7.10.3+6.2,7.10.3+6.3,7.10.3+6.4,7.10.3+6.5,7.10.3+6.6,7.10.3+6.7,7.10.3+6.8,7.10.3+6.9,7.10.3+6.10,7.10.3+6.11,7.10.3+6.12,7.10.3+6.13,7.10.3+6.14,7.10.3+6.15,7.10.3+6.16,7.10.3+6.17,7.10.3+6.18,7.10.3+6.19,7.10.3+6.20,7.10.3+6.21,7.10.3+6.22,7.10.3+6.23,7.10.3+6.24,7.10.3+6.25,7.10.3+6.26,7.10.3+6.27,7.10.3+6.28,7.10.3+6.29,7.10.3+6.30,7.10.3+6.31,7.10.3+6.32,7.10.3+6.33,7.10.3+6.34,7.10.3+6.35,7.10.3+7.0,8.0.1+7.1,8.0.1+7.2,8.0.1+7.3,8.0.1+7.4,8.0.1+7.5,8.0.1+7.6,8.0.1+7.7,8.0.1+7.8,8.0.1+7.9,8.0.1+7.10,8.0.1+7.11,8.0.1+7.12,8.0.1+7.13,8.0.1+7.14,8.0.1+7.15,8.0.1+7.16,8.0.1+7.17,8.0.1+7.18,8.0.1+7.19,8.0.1+7.20,8.0.1+7.21,8.0.1+7.22,8.0.1+7.23,8.0.1+7.24,8.0.1+8.0,8.0.2+8.1,8.0.2+8.2,8.0.2+8.3,8.0.2+8.4,8.0.2+8.5,8.0.2+8.6,8.0.2+8.7,8.0.2+8.8,8.0.2+8.9,8.0.2+8.10,8.0.2+8.11,8.0.2+8.12,8.0.2+8.13,8.0.2+8.14,8.0.2+8.15,8.0.2+8.16,8.0.2+8.17,8.0.2+8.18,8.0.2+8.19,8.0.2+8.20,8.0.2+8.21,8.0.2+8.22,8.0.2+8.23,8.0.2+8.24,8.0.2+9.0,8.0.2+9.1,8.0.2+9.2,8.0.2+9.3,8.0.2+9.4,8.0.2+9.5,8.0.2+9.6,8.0.2+9.7,8.0.2+9.8,8.0.2+9.9,8.0.2+9.10,8.0.2+9.11,8.0.2+9.12,8.0.2+9.13,8.0.2+9.14,8.0.2+9.15,8.0.2+9.16,8.0.2+9.17,8.0.2+9.18,8.0.2+9.19,8.0.2+9.20,8.0.2+9.21,8.0.2+10.0,8.2.2+10.1,8.2.2+10.2,8.2.2+10.3,8.2.2+10.4,8.2.2+10.5,8.2.2+10.6,8.2.2+10.7,8.2.2+10.8,8.2.2+10.9,8.2.2+10.10,8.2.2+11.0,8.2.2+11.1,8.2.2+11.2,8.2.2+11.3,8.2.2+11.4,8.2.2+11.5,8.2.2+11.6,8.2.2+11.7,8.2.2+11.8,8.2.2+11.9,8.2.2+11.10,8.2.2+11.11,8.2.2+11.12,8.2.2+11.13,8.2.2+11.14,8.2.2+11.15,8.2.2+11.16,8.2.2+11.17,8.2.2+11.18,8.2.2+11.19,8.2.2+11.20,8.2.2+11.21,8.2.2+11.22,8.2.2+12.0,8.4.3+12.1,8.4.3+12.2,8.4.3+12.3,8.4.3+12.4,8.4.3+12.5,8.4.3+12.6,8.4.3+12.7,8.4.3+12.8,8.4.3+12.9,8.4.3+12.10,8.4.3+12.11,8.4.3+12.12,8.4.3+12.13,8.4.3+12.14,8.4.3+12.15,8.4.4+12.16,8.4.4+12.17,8.4.4+12.18,8.4.4+12.19,8.4.4+12.20,8.4.4+12.21,8.4.4+12.22,8.4.4+12.23,8.4.4+12.24,8.4.4+12.25,8.4.4+12.26,8.4.4+13.0,8.6.3+13.1,8.6.3+13.2,8.6.3+13.3,8.6.3+13.4,8.6.3+13.5,8.6.3+13.6,8.6.3+13.7,8.6.3+13.8,8.6.3+13.9,8.6.3+13.10,8.6.3+13.11,8.6.3+13.12,8.6.4+13.13,8.6.4+13.14,8.6.4+13.15,8.6.4+13.16,8.6.4+13.17,8.6.4+13.18,8.6.4+13.19,8.6.4+13.20,8.6.5+13.21,8.6.5+13.22,8.6.5+13.23,8.6.5+13.24,8.6.5+13.25,8.6.5+13.26,8.6.5+13.27,8.6.5+13.28,8.6.5+13.29,8.6.5+13.30,8.6.5+14.0,8.6.5+14.1,8.6.5+14.2,8.6.5+14.3,8.6.5+14.4,8.6.5+14.5,8.6.5+14.6,8.6.5+14.7,8.6.5+14.8,8.6.5+14.9,8.6.5+14.10,8.6.5+14.11,8.6.5+14.12,8.6.5+14.13,8.6.5+14.14,8.6.5+14.15,8.6.5+14.16,8.6.5+14.17,8.6.5+14.18,8.6.5+14.19,8.6.5+14.20,8.6.5+14.21,8.6.5+14.22,8.6.5+14.23,8.6.5+14.24,8.6.5+14.25,8.6.5+14.26,8.6.5+14.27,8.6.5+15.0,8.8.2+15.1,8.8.2+15.2,8.8.2+15.3,8.8.2+15.4,8.8.3+15.5,8.8.3+15.6,8.8.3+15.7,8.8.3+15.8,8.8.3+15.9,8.8.3+15.10,8.8.3+15.11,8.8.3+15.12,8.8.3+15.13,8.8.3+15.14,8.8.3+15.15,8.8.3+15.16,8.8.3+16.0,8.8.3+16.1,8.8.3+16.2,8.8.3+16.3,8.8.3+16.4,8.8.3+16.5,8.8.3+16.6,8.8.3+16.7,8.8.3+16.8,8.8.3+16.9,8.8.3+16.10,8.8.3+16.11,8.8.3+16.12,8.8.4+16.13,8.8.4+16.14,8.8.4+16.15,8.8.4+16.16,8.8.4+16.17,8.8.4+16.18,8.8.4+16.19,8.8.4+16.20,8.8.4+16.21,8.8.4+16.22,8.8.4+16.23,8.8.4+16.24,8.8.4+16.25,8.8.4+16.26,8.8.4+16.27,8.8.4+16.28,8.8.4+16.29,8.8.4+16.30,8.8.4+16.31,8.8.4+17.0,8.10.3+17.1,8.10.3+17.2,8.10.3+17.3,8.10.4+17.4,8.10.4+17.5,8.10.4+17.6,8.10.4+17.7,8.10.4+17.8,8.10.4+17.9,8.10.4+17.10,8.10.4+17.11,8.10.4+17.12,8.10.4+17.13,8.10.4+17.14,8.10.4+17.15,8.10.4+18.0,8.10.4+18.1,8.10.4+18.2,8.10.4+18.3,8.10.4+18.4,8.10.4+18.5,8.10.4+18.6,8.10.4+18.7,8.10.6+18.8,8.10.6+18.9,8.10.7+18.10,8.10.7+18.11,8.10.7+18.12,8.10.7+18.13,8.10.7+18.14,8.10.7+18.15,8.10.7+18.16,8.10.7+18.17,8.10.7+18.18,8.10.7+18.19,8.10.7+18.20,8.10.7+18.21,8.10.7+18.22,8.10.7+18.23,8.10.7+18.24,8.10.7+18.25,8.10.7+18.26,8.10.7+18.27,8.10.7+18.28,8.10.7+19.0,9.0.2+19.1,9.0.2+19.2,9.0.2+19.3,9.0.2+19.4,9.0.2+19.5,9.0.2+19.6,9.0.2+19.7,9.0.2+19.8,9.0.2+19.9,9.0.2+19.10,9.0.2+19.11,9.0.2+19.12,9.0.2+19.13,9.0.2+19.14,9.0.2+19.15,9.0.2+19.16,9.0.2+19.17,9.0.2+19.18,9.0.2+19.19,9.0.2+19.20,9.0.2+19.21,9.0.2+19.22,9.0.2+19.23,9.0.2+19.24,9.0.2+19.25,9.0.2+19.26,9.0.2+19.27,9.0.2+19.28,9.0.2+19.29,9.0.2+19.30,9.0.2+19.31,9.0.2+19.32,9.0.2+19.33,9.0.2+20.0,9.2.5+20.1,9.2.5+20.2,9.2.5+20.3,9.2.5+20.4,9.2.5+20.5,9.2.5+20.6,9.2.5+20.7,9.2.5+20.8,9.2.5+20.9,9.2.5+20.10,9.2.5+20.11,9.2.5+20.12,9.2.6+20.13,9.2.7+20.14,9.2.7+20.15,9.2.7+20.16,9.2.7+20.17,9.2.7+20.18,9.2.7+20.19,9.2.7+20.20,9.2.7+20.21,9.2.7+20.22,9.2.7+20.23,9.2.7+20.24,9.2.7+20.25,9.2.8+20.26,9.2.8+21.0,9.4.5+21.1,9.4.5+21.2,9.4.5+21.3,9.4.5+21.4,9.4.5+21.5,9.4.5+21.6,9.4.5+21.7,9.4.5+21.8,9.4.6+21.9,9.4.6+21.10,9.4.6+21.11,9.4.6+21.12,9.4.7+21.13,9.4.7+21.14,9.4.7+21.15,9.4.7+21.16,9.4.7+21.17,9.4.7+21.18,9.4.7+21.19,9.4.7+21.20,9.4.7+21.21,9.4.7+21.22,9.4.8+21.23,9.4.8+21.24,9.4.8+21.25,9.4.8+22.0,9.6.3+22.1,9.6.3+22.2,9.6.3+22.3,9.6.3+22.4,9.6.3+22.5,9.6.3+22.6,9.6.3+22.7,9.6.4+22.8,9.6.4+22.9,9.6.4+22.10,9.6.4+22.11,9.6.4+22.12,9.6.4+22.13,9.6.4+22.14,9.6.4+22.15,9.6.4+22.16,9.6.4+22.17,9.6.4+22.18,9.6.4+22.19,9.6.4+22.20,9.6.4+22.21,9.6.5+22.22,9.6.5+22.23,9.6.5+22.24,9.6.5+22.25,9.6.5+22.26,9.6.5+22.27,9.6.5+22.28,9.6.6+22.29,9.6.6+22.30,9.6.6+22.31,9.6.6+22.32,9.6.6+22.33,9.6.6+22.34,9.6.6+22.35,9.6.6+22.36,9.6.6+22.37,9.6.6+22.38,9.6.6+22.39,9.6.6+22.40,9.6.6+22.41,9.6.6+22.42,9.6.6+22.43,9.6.6+22.44,9.6.7+23.0,9.8.4+23.1,9.8.4+23.2,9.8.4+23.3,9.8.4+23.4,9.8.4+23.5,9.8.4+23.6,9.8.4+23.7,9.8.4+23.8,9.8.4+23.9,9.8.4+23.10,9.8.4+23.11,9.8.4+23.12,9.8.4+23.13,9.8.4+23.14,9.8.4+23.15,9.8.4+23.16,9.8.4+23.17,9.8.4+23.18,9.8.4+23.19,9.8.4+23.20,9.8.4+23.21,9.8.4+23.22,9.8.4+23.23,9.8.4+23.24,9.8.4+23.25,9.8.4+23.26,9.8.4+23.27,9.8.4+23.28,9.8.4+24.0,9.10.2+24.1,9.10.2+24.2,9.10.2+24.3,9.10.2+24.4,9.10.2+24.5,9.10.2+24.6,9.10.2+24.7,9.10.2+24.8,9.10.2+24.9,9.10.2+24.10,9.10.2+24.11,9.10.2+24.12,9.10.3+24.13,9.10.3+24.14,9.10.3+24.15,9.10.3+24.16,9.10.3+24.17,9.10.3+24.18,9.10.3+24.19,9.10.3+24.20,9.10.3+24.21,9.10.3+24.22,9.10.3+24.23,9.10.3+24.24,9.10.3+24.25,9.10.3+24.26,9.10.3+24.27,9.10.3+24.28,9.10.3+24.29,9.10.3+24.30,9.10.3+24.31,9.10.3+24.32,9.10.3+24.33,9.10.3+24.34,9.10.3+24.35,9.10.3+24.36,9.10.3
+ data/nightly.csv view
@@ -0,0 +1,3096 @@+2014-12-14,7.8.3+2014-12-16,7.8.3+2014-12-20,7.8.3+2014-12-24,7.8.4+2015-01-01,7.8.4+2015-01-03,7.8.4+2015-01-12,7.8.4+2015-01-17,7.8.4+2015-01-20,7.8.4+2015-01-22,7.8.4+2015-02-02,7.8.4+2015-02-05,7.8.4+2015-02-10,7.8.4+2015-02-12,7.8.4+2015-02-18,7.8.4+2015-02-27,7.8.4+2015-03-05,7.8.4+2015-03-11,7.8.4+2015-03-13,7.8.4+2015-03-16,7.8.4+2015-03-17,7.8.4+2015-03-19,7.8.4+2015-03-24,7.8.4+2015-03-25,7.8.4+2015-03-29,7.8.4+2015-03-30,7.8.4+2015-04-01,7.8.4+2015-04-02,7.8.4+2015-04-17,7.8.4+2015-04-18,7.8.4+2015-04-19,7.8.4+2015-04-22,7.8.4+2015-04-23,7.8.4+2015-04-24,7.8.4+2015-04-25,7.8.4+2015-04-27,7.8.4+2015-04-28,7.8.4+2015-04-29,7.8.4+2015-04-30,7.8.4+2015-05-01,7.8.4+2015-05-02,7.8.4+2015-05-03,7.8.4+2015-05-04,7.8.4+2015-05-05,7.10.1+2015-05-06,7.10.1+2015-05-07,7.10.1+2015-05-08,7.10.1+2015-05-09,7.10.1+2015-05-11,7.10.1+2015-05-13,7.10.1+2015-05-14,7.10.1+2015-05-15,7.10.1+2015-05-16,7.10.1+2015-05-17,7.10.1+2015-05-18,7.10.1+2015-05-19,7.10.1+2015-05-21,7.10.1+2015-05-22,7.10.1+2015-05-25,7.10.1+2015-05-26,7.10.1+2015-05-27,7.10.1+2015-05-28,7.10.1+2015-05-29,7.10.1+2015-05-31,7.10.1+2015-06-01,7.10.1+2015-06-02,7.10.1+2015-06-03,7.10.1+2015-06-04,7.10.1+2015-06-05,7.10.1+2015-06-07,7.10.1+2015-06-08,7.10.1+2015-06-09,7.10.1+2015-06-10,7.10.1+2015-06-11,7.10.1+2015-06-12,7.10.1+2015-06-13,7.10.1+2015-06-14,7.10.1+2015-06-15,7.10.1+2015-06-16,7.10.1+2015-06-17,7.10.1+2015-06-18,7.10.1+2015-06-19,7.10.1+2015-06-21,7.10.1+2015-06-22,7.10.1+2015-06-23,7.10.1+2015-06-24,7.10.1+2015-06-25,7.10.1+2015-06-26,7.10.1+2015-06-28,7.10.1+2015-06-29,7.10.1+2015-06-30,7.10.1+2015-07-01,7.10.1+2015-07-02,7.10.1+2015-07-03,7.10.1+2015-07-05,7.10.1+2015-07-06,7.10.1+2015-07-07,7.10.1+2015-07-08,7.10.1+2015-07-09,7.10.1+2015-07-10,7.10.1+2015-07-11,7.10.1+2015-07-12,7.10.1+2015-07-13,7.10.1+2015-07-14,7.10.1+2015-07-15,7.10.1+2015-07-17,7.10.1+2015-07-18,7.10.1+2015-07-19,7.10.1+2015-07-21,7.10.1+2015-07-22,7.10.1+2015-07-23,7.10.1+2015-07-24,7.10.1+2015-07-25,7.10.1+2015-07-26,7.10.1+2015-07-27,7.10.1+2015-07-28,7.10.1+2015-07-29,7.10.1+2015-07-30,7.10.1+2015-08-03,7.10.1+2015-08-04,7.10.1+2015-08-06,7.10.2+2015-08-07,7.10.2+2015-08-08,7.10.2+2015-08-09,7.10.2+2015-08-10,7.10.2+2015-08-11,7.10.2+2015-08-12,7.10.2+2015-08-13,7.10.2+2015-08-14,7.10.2+2015-08-15,7.10.2+2015-08-16,7.10.2+2015-08-17,7.10.2+2015-08-18,7.10.2+2015-08-19,7.10.2+2015-08-20,7.10.2+2015-08-21,7.10.2+2015-08-24,7.10.2+2015-08-25,7.10.2+2015-08-26,7.10.2+2015-08-27,7.10.2+2015-08-30,7.10.2+2015-08-31,7.10.2+2015-09-01,7.10.2+2015-09-02,7.10.2+2015-09-03,7.10.2+2015-09-04,7.10.2+2015-09-05,7.10.2+2015-09-06,7.10.2+2015-09-07,7.10.2+2015-09-09,7.10.2+2015-09-10,7.10.2+2015-09-11,7.10.2+2015-09-12,7.10.2+2015-09-13,7.10.2+2015-09-17,7.10.2+2015-09-18,7.10.2+2015-09-19,7.10.2+2015-09-20,7.10.2+2015-09-21,7.10.2+2015-09-24,7.10.2+2015-09-25,7.10.2+2015-09-26,7.10.2+2015-09-27,7.10.2+2015-09-28,7.10.2+2015-09-29,7.10.2+2015-09-30,7.10.2+2015-10-01,7.10.2+2015-10-04,7.10.2+2015-10-05,7.10.2+2015-10-06,7.10.2+2015-10-07,7.10.2+2015-10-08,7.10.2+2015-10-09,7.10.2+2015-10-12,7.10.2+2015-10-13,7.10.2+2015-10-14,7.10.2+2015-10-15,7.10.2+2015-10-17,7.10.2+2015-10-18,7.10.2+2015-10-19,7.10.2+2015-10-20,7.10.2+2015-10-21,7.10.2+2015-10-22,7.10.2+2015-10-23,7.10.2+2015-10-24,7.10.2+2015-10-25,7.10.2+2015-10-26,7.10.2+2015-10-27,7.10.2+2015-10-28,7.10.2+2015-10-30,7.10.2+2015-10-31,7.10.2+2015-11-01,7.10.2+2015-11-02,7.10.2+2015-11-03,7.10.2+2015-11-04,7.10.2+2015-11-06,7.10.2+2015-11-08,7.10.2+2015-11-09,7.10.2+2015-11-10,7.10.2+2015-11-11,7.10.2+2015-11-12,7.10.2+2015-11-13,7.10.2+2015-11-14,7.10.2+2015-11-15,7.10.2+2015-11-16,7.10.2+2015-11-17,7.10.2+2015-11-18,7.10.2+2015-11-19,7.10.2+2015-11-21,7.10.2+2015-11-22,7.10.2+2015-11-23,7.10.2+2015-11-24,7.10.2+2015-11-25,7.10.2+2015-11-26,7.10.2+2015-11-27,7.10.2+2015-11-28,7.10.2+2015-11-29,7.10.2+2015-11-30,7.10.2+2015-12-01,7.10.2+2015-12-02,7.10.2+2015-12-03,7.10.2+2015-12-04,7.10.2+2015-12-05,7.10.2+2015-12-06,7.10.2+2015-12-07,7.10.2+2015-12-08,7.10.2+2015-12-09,7.10.2+2015-12-10,7.10.2+2015-12-11,7.10.2+2015-12-12,7.10.2+2015-12-13,7.10.2+2015-12-14,7.10.2+2015-12-16,7.10.3+2015-12-17,7.10.3+2015-12-18,7.10.3+2015-12-19,7.10.3+2015-12-20,7.10.3+2015-12-21,7.10.3+2015-12-22,7.10.3+2015-12-24,7.10.3+2015-12-25,7.10.3+2015-12-26,7.10.3+2015-12-27,7.10.3+2015-12-28,7.10.3+2015-12-29,7.10.3+2015-12-30,7.10.3+2015-12-31,7.10.3+2016-01-01,7.10.3+2016-01-02,7.10.3+2016-01-03,7.10.3+2016-01-04,7.10.3+2016-01-05,7.10.3+2016-01-06,7.10.3+2016-01-07,7.10.3+2016-01-08,7.10.3+2016-01-09,7.10.3+2016-01-10,7.10.3+2016-01-11,7.10.3+2016-01-14,7.10.3+2016-01-16,7.10.3+2016-01-19,7.10.3+2016-01-22,7.10.3+2016-01-23,7.10.3+2016-01-24,7.10.3+2016-01-26,7.10.3+2016-01-27,7.10.3+2016-01-29,7.10.3+2016-01-30,7.10.3+2016-01-31,7.10.3+2016-02-01,7.10.3+2016-02-02,7.10.3+2016-02-03,7.10.3+2016-02-04,7.10.3+2016-02-05,7.10.3+2016-02-08,7.10.3+2016-02-09,7.10.3+2016-02-10,7.10.3+2016-02-11,7.10.3+2016-02-13,7.10.3+2016-02-14,7.10.3+2016-02-15,7.10.3+2016-02-16,7.10.3+2016-02-17,7.10.3+2016-02-18,7.10.3+2016-02-19,7.10.3+2016-02-20,7.10.3+2016-02-22,7.10.3+2016-02-23,7.10.3+2016-02-24,7.10.3+2016-02-25,7.10.3+2016-02-26,7.10.3+2016-02-27,7.10.3+2016-02-28,7.10.3+2016-02-29,7.10.3+2016-03-01,7.10.3+2016-03-02,7.10.3+2016-03-03,7.10.3+2016-03-04,7.10.3+2016-03-06,7.10.3+2016-03-07,7.10.3+2016-03-08,7.10.3+2016-03-09,7.10.3+2016-03-10,7.10.3+2016-03-11,7.10.3+2016-03-12,7.10.3+2016-03-13,7.10.3+2016-03-14,7.10.3+2016-03-15,7.10.3+2016-03-16,7.10.3+2016-03-17,7.10.3+2016-03-18,7.10.3+2016-03-19,7.10.3+2016-03-20,7.10.3+2016-03-21,7.10.3+2016-03-22,7.10.3+2016-03-23,7.10.3+2016-03-24,7.10.3+2016-03-25,7.10.3+2016-03-27,7.10.3+2016-03-28,7.10.3+2016-03-29,7.10.3+2016-03-30,7.10.3+2016-03-31,7.10.3+2016-04-01,7.10.3+2016-04-02,7.10.3+2016-04-03,7.10.3+2016-04-04,7.10.3+2016-04-05,7.10.3+2016-04-06,7.10.3+2016-04-07,7.10.3+2016-04-08,7.10.3+2016-04-09,7.10.3+2016-04-10,7.10.3+2016-04-12,7.10.3+2016-04-13,7.10.3+2016-04-14,7.10.3+2016-04-15,7.10.3+2016-04-16,7.10.3+2016-04-17,7.10.3+2016-04-18,7.10.3+2016-04-19,7.10.3+2016-04-20,7.10.3+2016-04-25,7.10.3+2016-04-26,7.10.3+2016-04-27,7.10.3+2016-04-28,7.10.3+2016-04-29,7.10.3+2016-04-30,7.10.3+2016-05-01,7.10.3+2016-05-02,7.10.3+2016-05-03,7.10.3+2016-05-04,7.10.3+2016-05-05,7.10.3+2016-05-06,7.10.3+2016-05-07,7.10.3+2016-05-08,7.10.3+2016-05-12,7.10.3+2016-05-13,7.10.3+2016-05-16,7.10.3+2016-05-17,7.10.3+2016-05-18,7.10.3+2016-05-19,7.10.3+2016-05-20,7.10.3+2016-05-21,7.10.3+2016-05-23,7.10.3+2016-05-24,7.10.3+2016-05-25,7.10.3+2016-05-26,8.0.1+2016-05-27,8.0.1+2016-05-28,8.0.1+2016-05-29,8.0.1+2016-05-30,8.0.1+2016-05-31,8.0.1+2016-06-01,8.0.1+2016-06-02,8.0.1+2016-06-03,8.0.1+2016-06-04,8.0.1+2016-06-05,8.0.1+2016-06-06,8.0.1+2016-06-07,8.0.1+2016-06-08,8.0.1+2016-06-09,8.0.1+2016-06-10,8.0.1+2016-06-11,8.0.1+2016-06-12,8.0.1+2016-06-13,8.0.1+2016-06-14,8.0.1+2016-06-15,8.0.1+2016-06-16,8.0.1+2016-06-17,8.0.1+2016-06-18,8.0.1+2016-06-19,8.0.1+2016-06-20,8.0.1+2016-06-21,8.0.1+2016-06-22,8.0.1+2016-06-26,8.0.1+2016-06-27,8.0.1+2016-06-28,8.0.1+2016-06-29,8.0.1+2016-06-30,8.0.1+2016-07-01,8.0.1+2016-07-02,8.0.1+2016-07-03,8.0.1+2016-07-04,8.0.1+2016-07-05,8.0.1+2016-07-06,8.0.1+2016-07-07,8.0.1+2016-07-08,8.0.1+2016-07-09,8.0.1+2016-07-10,8.0.1+2016-07-11,8.0.1+2016-07-13,8.0.1+2016-07-14,8.0.1+2016-07-15,8.0.1+2016-07-16,8.0.1+2016-07-17,8.0.1+2016-07-18,8.0.1+2016-07-19,8.0.1+2016-07-26,8.0.1+2016-07-27,8.0.1+2016-07-28,8.0.1+2016-07-29,8.0.1+2016-07-30,8.0.1+2016-07-31,8.0.1+2016-08-01,8.0.1+2016-08-02,8.0.1+2016-08-04,8.0.1+2016-08-05,8.0.1+2016-08-06,8.0.1+2016-08-11,8.0.1+2016-08-12,8.0.1+2016-08-13,8.0.1+2016-08-14,8.0.1+2016-08-15,8.0.1+2016-08-16,8.0.1+2016-08-17,8.0.1+2016-08-18,8.0.1+2016-08-19,8.0.1+2016-08-20,8.0.1+2016-08-21,8.0.1+2016-08-22,8.0.1+2016-08-23,8.0.1+2016-08-24,8.0.1+2016-08-25,8.0.1+2016-08-26,8.0.1+2016-08-27,8.0.1+2016-08-28,8.0.1+2016-08-29,8.0.1+2016-08-30,8.0.1+2016-08-31,8.0.1+2016-09-01,8.0.1+2016-09-02,8.0.1+2016-09-03,8.0.1+2016-09-04,8.0.1+2016-09-07,8.0.1+2016-09-08,8.0.1+2016-09-09,8.0.1+2016-09-10,8.0.1+2016-09-11,8.0.1+2016-09-12,8.0.1+2016-09-13,8.0.1+2016-09-14,8.0.1+2016-09-15,8.0.1+2016-09-16,8.0.1+2016-09-17,8.0.1+2016-09-18,8.0.1+2016-09-19,8.0.1+2016-09-20,8.0.1+2016-09-21,8.0.1+2016-09-22,8.0.1+2016-09-23,8.0.1+2016-09-24,8.0.1+2016-09-26,8.0.1+2016-09-27,8.0.1+2016-09-28,8.0.1+2016-09-29,8.0.1+2016-09-30,8.0.1+2016-10-01,8.0.1+2016-10-02,8.0.1+2016-10-03,8.0.1+2016-10-04,8.0.1+2016-10-05,8.0.1+2016-10-06,8.0.1+2016-10-07,8.0.1+2016-10-10,8.0.1+2016-10-11,8.0.1+2016-10-13,8.0.1+2016-10-14,8.0.1+2016-10-15,8.0.1+2016-10-16,8.0.1+2016-10-17,8.0.1+2016-10-18,8.0.1+2016-10-19,8.0.1+2016-10-20,8.0.1+2016-10-21,8.0.1+2016-10-22,8.0.1+2016-10-23,8.0.1+2016-10-24,8.0.1+2016-10-25,8.0.1+2016-10-26,8.0.1+2016-10-27,8.0.1+2016-10-28,8.0.1+2016-10-29,8.0.1+2016-10-30,8.0.1+2016-10-31,8.0.1+2016-11-01,8.0.1+2016-11-02,8.0.1+2016-11-03,8.0.1+2016-11-04,8.0.1+2016-11-05,8.0.1+2016-11-06,8.0.1+2016-11-07,8.0.1+2016-11-08,8.0.1+2016-11-09,8.0.1+2016-11-10,8.0.1+2016-11-11,8.0.1+2016-11-12,8.0.1+2016-11-13,8.0.1+2016-11-15,8.0.1+2016-11-16,8.0.1+2016-11-17,8.0.1+2016-11-18,8.0.1+2016-11-19,8.0.1+2016-11-22,8.0.1+2016-11-23,8.0.1+2016-11-24,8.0.1+2016-11-25,8.0.1+2016-11-26,8.0.1+2016-11-28,8.0.1+2016-11-29,8.0.1+2016-11-30,8.0.1+2016-12-01,8.0.1+2016-12-02,8.0.1+2016-12-03,8.0.1+2016-12-04,8.0.1+2016-12-05,8.0.1+2016-12-06,8.0.1+2016-12-07,8.0.1+2016-12-08,8.0.1+2016-12-09,8.0.1+2016-12-10,8.0.1+2016-12-11,8.0.1+2016-12-12,8.0.1+2016-12-13,8.0.1+2016-12-14,8.0.1+2016-12-15,8.0.1+2016-12-16,8.0.1+2016-12-17,8.0.1+2016-12-18,8.0.1+2016-12-19,8.0.1+2016-12-20,8.0.1+2016-12-21,8.0.1+2016-12-22,8.0.1+2016-12-23,8.0.1+2016-12-27,8.0.1+2016-12-28,8.0.1+2016-12-29,8.0.1+2016-12-30,8.0.1+2016-12-31,8.0.1+2017-01-06,8.0.1+2017-01-07,8.0.1+2017-01-09,8.0.1+2017-01-10,8.0.1+2017-01-12,8.0.1+2017-01-13,8.0.1+2017-01-14,8.0.1+2017-01-16,8.0.1+2017-01-17,8.0.1+2017-01-25,8.0.2+2017-01-26,8.0.2+2017-01-27,8.0.2+2017-01-28,8.0.2+2017-01-29,8.0.2+2017-01-30,8.0.2+2017-01-31,8.0.2+2017-02-01,8.0.2+2017-02-02,8.0.2+2017-02-03,8.0.2+2017-02-05,8.0.2+2017-02-06,8.0.2+2017-02-07,8.0.2+2017-02-08,8.0.2+2017-02-09,8.0.2+2017-02-10,8.0.2+2017-02-11,8.0.2+2017-02-12,8.0.2+2017-02-13,8.0.2+2017-02-16,8.0.2+2017-02-18,8.0.2+2017-02-19,8.0.2+2017-02-20,8.0.2+2017-02-21,8.0.2+2017-02-22,8.0.2+2017-02-23,8.0.2+2017-02-24,8.0.2+2017-02-25,8.0.2+2017-02-26,8.0.2+2017-02-28,8.0.2+2017-03-01,8.0.2+2017-03-02,8.0.2+2017-03-03,8.0.2+2017-03-04,8.0.2+2017-03-05,8.0.2+2017-03-06,8.0.2+2017-03-07,8.0.2+2017-03-08,8.0.2+2017-03-09,8.0.2+2017-03-10,8.0.2+2017-03-11,8.0.2+2017-03-12,8.0.2+2017-03-13,8.0.2+2017-03-14,8.0.2+2017-03-15,8.0.2+2017-03-17,8.0.2+2017-03-19,8.0.2+2017-03-20,8.0.2+2017-03-23,8.0.2+2017-03-24,8.0.2+2017-03-25,8.0.2+2017-03-27,8.0.2+2017-03-28,8.0.2+2017-03-29,8.0.2+2017-03-30,8.0.2+2017-03-31,8.0.2+2017-04-01,8.0.2+2017-04-02,8.0.2+2017-04-05,8.0.2+2017-04-06,8.0.2+2017-04-07,8.0.2+2017-04-08,8.0.2+2017-04-09,8.0.2+2017-04-10,8.0.2+2017-04-11,8.0.2+2017-04-12,8.0.2+2017-04-13,8.0.2+2017-04-14,8.0.2+2017-04-17,8.0.2+2017-04-18,8.0.2+2017-04-19,8.0.2+2017-04-21,8.0.2+2017-04-22,8.0.2+2017-04-23,8.0.2+2017-04-24,8.0.2+2017-04-26,8.0.2+2017-04-27,8.0.2+2017-04-28,8.0.2+2017-04-30,8.0.2+2017-05-01,8.0.2+2017-05-02,8.0.2+2017-05-03,8.0.2+2017-05-05,8.0.2+2017-05-06,8.0.2+2017-05-07,8.0.2+2017-05-10,8.0.2+2017-05-11,8.0.2+2017-05-12,8.0.2+2017-05-13,8.0.2+2017-05-14,8.0.2+2017-05-15,8.0.2+2017-05-16,8.0.2+2017-05-17,8.0.2+2017-05-18,8.0.2+2017-05-19,8.0.2+2017-05-20,8.0.2+2017-05-22,8.0.2+2017-05-23,8.0.2+2017-05-24,8.0.2+2017-05-25,8.0.2+2017-05-26,8.0.2+2017-05-27,8.0.2+2017-05-28,8.0.2+2017-05-30,8.0.2+2017-06-01,8.0.2+2017-06-02,8.0.2+2017-06-10,8.0.2+2017-06-11,8.0.2+2017-06-12,8.0.2+2017-06-13,8.0.2+2017-06-14,8.0.2+2017-06-15,8.0.2+2017-06-16,8.0.2+2017-06-18,8.0.2+2017-06-19,8.0.2+2017-06-20,8.0.2+2017-06-21,8.0.2+2017-06-22,8.0.2+2017-06-23,8.0.2+2017-06-26,8.0.2+2017-06-28,8.0.2+2017-06-29,8.0.2+2017-06-30,8.0.2+2017-07-02,8.0.2+2017-07-03,8.0.2+2017-07-04,8.0.2+2017-07-05,8.0.2+2017-07-06,8.0.2+2017-07-09,8.0.2+2017-07-10,8.0.2+2017-07-11,8.0.2+2017-07-12,8.0.2+2017-07-13,8.0.2+2017-07-14,8.0.2+2017-07-15,8.0.2+2017-07-16,8.0.2+2017-07-17,8.0.2+2017-07-18,8.0.2+2017-07-19,8.0.2+2017-07-20,8.0.2+2017-07-21,8.0.2+2017-07-25,8.0.2+2017-07-31,8.2.1+2017-08-01,8.2.1+2017-08-02,8.2.1+2017-08-03,8.2.1+2017-08-04,8.2.1+2017-08-05,8.2.1+2017-08-06,8.2.1+2017-08-07,8.2.1+2017-08-08,8.2.1+2017-08-09,8.2.1+2017-08-10,8.2.1+2017-08-11,8.2.1+2017-08-12,8.2.1+2017-08-13,8.2.1+2017-08-14,8.2.1+2017-08-15,8.2.1+2017-08-17,8.2.1+2017-08-19,8.2.1+2017-08-20,8.2.1+2017-08-24,8.2.1+2017-08-25,8.2.1+2017-08-28,8.2.1+2017-08-29,8.2.1+2017-08-30,8.2.1+2017-08-31,8.2.1+2017-09-01,8.2.1+2017-09-02,8.2.1+2017-09-03,8.2.1+2017-09-04,8.2.1+2017-09-05,8.2.1+2017-09-06,8.2.1+2017-09-07,8.2.1+2017-09-09,8.2.1+2017-09-10,8.2.1+2017-09-13,8.2.1+2017-09-14,8.2.1+2017-09-15,8.2.1+2017-09-16,8.2.1+2017-09-17,8.2.1+2017-09-18,8.2.1+2017-09-19,8.2.1+2017-09-20,8.2.1+2017-09-25,8.2.1+2017-09-26,8.2.1+2017-09-28,8.2.1+2017-09-29,8.2.1+2017-10-02,8.2.1+2017-10-03,8.2.1+2017-10-04,8.2.1+2017-10-05,8.2.1+2017-10-06,8.2.1+2017-10-07,8.2.1+2017-10-08,8.2.1+2017-10-09,8.2.1+2017-10-10,8.2.1+2017-10-11,8.2.1+2017-10-12,8.2.1+2017-10-13,8.2.1+2017-10-17,8.2.1+2017-10-18,8.2.1+2017-10-19,8.2.1+2017-10-20,8.2.1+2017-10-21,8.2.1+2017-10-22,8.2.1+2017-10-23,8.2.1+2017-10-25,8.2.1+2017-10-26,8.2.1+2017-10-27,8.2.1+2017-10-28,8.2.1+2017-10-30,8.2.1+2017-10-31,8.2.1+2017-11-01,8.2.1+2017-11-02,8.2.1+2017-11-03,8.2.1+2017-11-04,8.2.1+2017-11-05,8.2.1+2017-11-06,8.2.1+2017-11-07,8.2.1+2017-11-08,8.2.1+2017-11-09,8.2.1+2017-11-10,8.2.1+2017-11-13,8.2.1+2017-11-14,8.2.1+2017-11-15,8.2.1+2017-11-16,8.2.1+2017-11-17,8.2.1+2017-11-18,8.2.1+2017-11-19,8.2.1+2017-11-20,8.2.1+2017-11-21,8.2.1+2017-11-22,8.2.1+2017-11-23,8.2.1+2017-11-24,8.2.1+2017-11-25,8.2.2+2017-11-27,8.2.2+2017-11-28,8.2.2+2017-11-29,8.2.2+2017-11-30,8.2.2+2017-12-01,8.2.2+2017-12-05,8.2.2+2017-12-06,8.2.2+2017-12-07,8.2.2+2017-12-08,8.2.2+2017-12-09,8.2.2+2017-12-10,8.2.2+2017-12-13,8.2.2+2017-12-14,8.2.2+2017-12-15,8.2.2+2017-12-16,8.2.2+2017-12-18,8.2.2+2017-12-19,8.2.2+2017-12-20,8.2.2+2017-12-21,8.2.2+2017-12-22,8.2.2+2017-12-23,8.2.2+2017-12-24,8.2.2+2017-12-27,8.2.2+2017-12-28,8.2.2+2017-12-29,8.2.2+2017-12-30,8.2.2+2017-12-31,8.2.2+2018-01-01,8.2.2+2018-01-02,8.2.2+2018-01-03,8.2.2+2018-01-04,8.2.2+2018-01-05,8.2.2+2018-01-06,8.2.2+2018-01-07,8.2.2+2018-01-09,8.2.2+2018-01-14,8.2.2+2018-01-15,8.2.2+2018-01-16,8.2.2+2018-01-17,8.2.2+2018-01-18,8.2.2+2018-01-21,8.2.2+2018-01-24,8.2.2+2018-01-25,8.2.2+2018-01-26,8.2.2+2018-01-27,8.2.2+2018-01-29,8.2.2+2018-02-07,8.2.2+2018-02-08,8.2.2+2018-02-09,8.2.2+2018-02-10,8.2.2+2018-02-11,8.2.2+2018-02-16,8.2.2+2018-02-17,8.2.2+2018-02-18,8.2.2+2018-02-20,8.2.2+2018-02-21,8.2.2+2018-02-22,8.2.2+2018-02-23,8.2.2+2018-02-24,8.2.2+2018-02-26,8.2.2+2018-02-27,8.2.2+2018-02-28,8.2.2+2018-03-01,8.2.2+2018-03-04,8.2.2+2018-03-05,8.2.2+2018-03-06,8.2.2+2018-03-07,8.2.2+2018-03-10,8.2.2+2018-03-12,8.2.2+2018-03-13,8.4.1+2018-03-14,8.4.1+2018-03-15,8.4.1+2018-03-16,8.4.1+2018-03-17,8.4.1+2018-03-18,8.4.1+2018-03-19,8.4.1+2018-03-20,8.4.1+2018-03-21,8.4.1+2018-03-22,8.4.1+2018-03-23,8.4.1+2018-03-24,8.4.1+2018-03-25,8.4.1+2018-03-26,8.4.1+2018-03-28,8.4.1+2018-03-29,8.4.1+2018-03-30,8.4.1+2018-03-31,8.4.1+2018-04-01,8.4.1+2018-04-02,8.4.1+2018-04-03,8.4.1+2018-04-04,8.4.1+2018-04-05,8.4.1+2018-04-08,8.4.1+2018-04-09,8.4.1+2018-04-10,8.4.1+2018-04-11,8.4.1+2018-04-12,8.4.1+2018-04-13,8.4.1+2018-04-14,8.4.1+2018-04-15,8.4.1+2018-04-16,8.4.1+2018-04-17,8.4.1+2018-04-18,8.4.1+2018-04-19,8.4.1+2018-04-20,8.4.1+2018-04-21,8.4.1+2018-04-23,8.4.2+2018-04-24,8.4.2+2018-04-25,8.4.2+2018-04-26,8.4.2+2018-04-27,8.4.2+2018-04-28,8.4.2+2018-04-29,8.4.2+2018-04-30,8.4.2+2018-05-01,8.4.2+2018-05-02,8.4.2+2018-05-03,8.4.2+2018-05-04,8.4.2+2018-05-05,8.4.2+2018-05-06,8.4.2+2018-05-08,8.4.2+2018-05-09,8.4.2+2018-05-10,8.4.2+2018-05-11,8.4.2+2018-05-12,8.4.2+2018-05-13,8.4.2+2018-05-14,8.4.2+2018-05-15,8.4.2+2018-05-16,8.4.2+2018-05-17,8.4.2+2018-05-18,8.4.2+2018-05-19,8.4.2+2018-05-20,8.4.2+2018-05-21,8.4.2+2018-05-22,8.4.2+2018-05-23,8.4.2+2018-05-25,8.4.2+2018-05-26,8.4.2+2018-05-27,8.4.2+2018-05-28,8.4.2+2018-05-29,8.4.2+2018-05-30,8.4.2+2018-06-01,8.4.3+2018-06-02,8.4.3+2018-06-05,8.4.3+2018-06-06,8.4.3+2018-06-07,8.4.3+2018-06-08,8.4.3+2018-06-09,8.4.3+2018-06-10,8.4.3+2018-06-11,8.4.3+2018-06-12,8.4.3+2018-06-13,8.4.3+2018-06-14,8.4.3+2018-06-15,8.4.3+2018-06-16,8.4.3+2018-06-17,8.4.3+2018-06-18,8.4.3+2018-06-19,8.4.3+2018-06-20,8.4.3+2018-06-21,8.4.3+2018-06-22,8.4.3+2018-06-23,8.4.3+2018-06-24,8.4.3+2018-06-25,8.4.3+2018-06-26,8.4.3+2018-06-27,8.4.3+2018-06-28,8.4.3+2018-06-29,8.4.3+2018-07-04,8.4.3+2018-07-05,8.4.3+2018-07-06,8.4.3+2018-07-08,8.4.3+2018-07-09,8.4.3+2018-07-10,8.4.3+2018-07-11,8.4.3+2018-07-12,8.4.3+2018-07-13,8.4.3+2018-07-14,8.4.3+2018-07-16,8.4.3+2018-07-17,8.4.3+2018-07-18,8.4.3+2018-07-19,8.4.3+2018-07-20,8.4.3+2018-07-21,8.4.3+2018-07-24,8.4.3+2018-07-25,8.4.3+2018-07-26,8.4.3+2018-07-28,8.4.3+2018-07-29,8.4.3+2018-07-30,8.4.3+2018-07-31,8.4.3+2018-08-01,8.4.3+2018-08-02,8.4.3+2018-08-03,8.4.3+2018-08-04,8.4.3+2018-08-05,8.4.3+2018-08-06,8.4.3+2018-08-07,8.4.3+2018-08-08,8.4.3+2018-08-09,8.4.3+2018-08-10,8.4.3+2018-08-11,8.4.3+2018-08-12,8.4.3+2018-08-13,8.4.3+2018-08-14,8.4.3+2018-08-15,8.4.3+2018-08-16,8.4.3+2018-08-17,8.4.3+2018-08-20,8.4.3+2018-08-21,8.4.3+2018-08-29,8.4.3+2018-08-30,8.4.3+2018-08-31,8.4.3+2018-09-01,8.4.3+2018-09-02,8.4.3+2018-09-03,8.4.3+2018-09-05,8.4.3+2018-09-06,8.4.3+2018-09-07,8.4.3+2018-09-09,8.4.3+2018-09-13,8.4.3+2018-09-14,8.4.3+2018-09-15,8.4.3+2018-09-16,8.4.3+2018-09-17,8.4.3+2018-09-18,8.4.3+2018-09-20,8.4.3+2018-09-21,8.4.3+2018-09-22,8.4.3+2018-09-23,8.4.3+2018-09-25,8.4.3+2018-09-26,8.4.3+2018-09-27,8.4.3+2018-09-28,8.4.3+2018-09-29,8.6.1+2018-09-30,8.6.1+2018-10-01,8.6.1+2018-10-02,8.6.1+2018-10-03,8.6.1+2018-10-04,8.6.1+2018-10-05,8.6.1+2018-10-06,8.6.1+2018-10-07,8.6.1+2018-10-08,8.6.1+2018-10-09,8.6.1+2018-10-10,8.6.1+2018-10-11,8.6.1+2018-10-12,8.6.1+2018-10-13,8.6.1+2018-10-14,8.6.1+2018-10-15,8.6.1+2018-10-16,8.6.1+2018-10-17,8.6.1+2018-10-18,8.6.1+2018-10-19,8.6.1+2018-10-20,8.6.1+2018-10-21,8.6.1+2018-10-22,8.6.1+2018-10-23,8.6.1+2018-10-24,8.6.1+2018-10-25,8.6.1+2018-10-26,8.6.1+2018-10-28,8.6.1+2018-10-29,8.6.1+2018-10-30,8.6.1+2018-10-31,8.6.1+2018-11-01,8.6.1+2018-11-02,8.6.1+2018-11-05,8.6.1+2018-11-06,8.6.1+2018-11-07,8.6.1+2018-11-08,8.6.1+2018-11-09,8.6.1+2018-11-10,8.6.1+2018-11-11,8.6.1+2018-11-12,8.6.2+2018-11-13,8.6.2+2018-11-14,8.6.2+2018-11-15,8.6.2+2018-11-16,8.6.2+2018-11-17,8.6.2+2018-11-18,8.6.2+2018-11-19,8.6.2+2018-11-20,8.6.2+2018-11-21,8.6.2+2018-11-22,8.6.2+2018-11-23,8.6.2+2018-11-24,8.6.2+2018-11-27,8.6.2+2018-11-28,8.6.2+2018-11-29,8.6.2+2018-11-30,8.6.2+2018-12-01,8.6.2+2018-12-02,8.6.2+2018-12-03,8.6.2+2018-12-04,8.6.2+2018-12-05,8.6.2+2018-12-06,8.6.2+2018-12-07,8.6.2+2018-12-08,8.6.2+2018-12-09,8.6.2+2018-12-10,8.6.2+2018-12-11,8.6.2+2018-12-12,8.6.2+2018-12-13,8.6.2+2018-12-14,8.6.2+2018-12-15,8.6.2+2018-12-17,8.6.2+2018-12-18,8.6.3+2018-12-19,8.6.3+2018-12-20,8.6.3+2018-12-21,8.6.3+2018-12-22,8.6.3+2018-12-23,8.6.3+2018-12-24,8.6.3+2018-12-25,8.6.3+2018-12-26,8.6.3+2018-12-27,8.6.3+2018-12-28,8.6.3+2018-12-29,8.6.3+2018-12-31,8.6.3+2019-01-03,8.6.3+2019-01-04,8.6.3+2019-01-05,8.6.3+2019-01-06,8.6.3+2019-01-07,8.6.3+2019-01-09,8.6.3+2019-01-10,8.6.3+2019-01-11,8.6.3+2019-01-12,8.6.3+2019-01-13,8.6.3+2019-01-14,8.6.3+2019-01-15,8.6.3+2019-01-16,8.6.3+2019-01-17,8.6.3+2019-01-18,8.6.3+2019-01-19,8.6.3+2019-01-20,8.6.3+2019-01-21,8.6.3+2019-01-22,8.6.3+2019-01-23,8.6.3+2019-01-24,8.6.3+2019-01-25,8.6.3+2019-01-26,8.6.3+2019-01-27,8.6.3+2019-01-28,8.6.3+2019-01-29,8.6.3+2019-01-30,8.6.3+2019-02-02,8.6.3+2019-02-04,8.6.3+2019-02-05,8.6.3+2019-02-06,8.6.3+2019-02-07,8.6.3+2019-02-08,8.6.3+2019-02-09,8.6.3+2019-02-11,8.6.3+2019-02-12,8.6.3+2019-02-13,8.6.3+2019-02-14,8.6.3+2019-02-15,8.6.3+2019-02-16,8.6.3+2019-02-17,8.6.3+2019-02-18,8.6.3+2019-02-19,8.6.3+2019-02-20,8.6.3+2019-02-22,8.6.3+2019-02-23,8.6.3+2019-02-24,8.6.3+2019-02-25,8.6.3+2019-02-26,8.6.3+2019-02-27,8.6.3+2019-03-02,8.6.3+2019-03-03,8.6.3+2019-03-04,8.6.3+2019-03-05,8.6.3+2019-03-06,8.6.3+2019-03-07,8.6.4+2019-03-08,8.6.4+2019-03-09,8.6.4+2019-03-10,8.6.4+2019-03-11,8.6.4+2019-03-12,8.6.4+2019-03-13,8.6.4+2019-03-14,8.6.4+2019-03-15,8.6.4+2019-03-16,8.6.4+2019-03-17,8.6.4+2019-03-18,8.6.4+2019-03-19,8.6.4+2019-03-20,8.6.4+2019-03-21,8.6.4+2019-03-22,8.6.4+2019-03-23,8.6.4+2019-03-24,8.6.4+2019-03-25,8.6.4+2019-03-26,8.6.4+2019-03-27,8.6.4+2019-03-28,8.6.4+2019-03-29,8.6.4+2019-03-30,8.6.4+2019-03-31,8.6.4+2019-04-01,8.6.4+2019-04-02,8.6.4+2019-04-03,8.6.4+2019-04-04,8.6.4+2019-04-05,8.6.4+2019-04-08,8.6.4+2019-04-09,8.6.4+2019-04-10,8.6.4+2019-04-11,8.6.4+2019-04-12,8.6.4+2019-04-14,8.6.4+2019-04-15,8.6.4+2019-04-16,8.6.4+2019-04-18,8.6.4+2019-04-19,8.6.4+2019-04-21,8.6.4+2019-04-22,8.6.4+2019-04-23,8.6.4+2019-04-24,8.6.4+2019-04-25,8.6.4+2019-04-26,8.6.4+2019-04-27,8.6.4+2019-04-28,8.6.4+2019-04-30,8.6.5+2019-05-01,8.6.5+2019-05-03,8.6.5+2019-05-04,8.6.5+2019-05-05,8.6.5+2019-05-06,8.6.5+2019-05-07,8.6.5+2019-05-08,8.6.5+2019-05-09,8.6.5+2019-05-10,8.6.5+2019-05-11,8.6.5+2019-05-12,8.6.5+2019-05-13,8.6.5+2019-05-15,8.6.5+2019-05-16,8.6.5+2019-05-17,8.6.5+2019-05-18,8.6.5+2019-05-20,8.6.5+2019-05-21,8.6.5+2019-05-22,8.6.5+2019-05-23,8.6.5+2019-05-24,8.6.5+2019-05-25,8.6.5+2019-05-26,8.6.5+2019-05-27,8.6.5+2019-05-28,8.6.5+2019-05-29,8.6.5+2019-05-30,8.6.5+2019-05-31,8.6.5+2019-06-01,8.6.5+2019-06-02,8.6.5+2019-06-03,8.6.5+2019-06-04,8.6.5+2019-06-05,8.6.5+2019-06-06,8.6.5+2019-06-08,8.6.5+2019-06-09,8.6.5+2019-06-10,8.6.5+2019-06-11,8.6.5+2019-06-12,8.6.5+2019-06-17,8.6.5+2019-06-19,8.6.5+2019-06-20,8.6.5+2019-06-21,8.6.5+2019-06-26,8.6.5+2019-06-27,8.6.5+2019-06-28,8.6.5+2019-07-02,8.6.5+2019-07-03,8.6.5+2019-07-04,8.6.5+2019-07-05,8.6.5+2019-07-06,8.6.5+2019-07-07,8.6.5+2019-07-10,8.6.5+2019-07-11,8.6.5+2019-07-12,8.6.5+2019-07-13,8.6.5+2019-07-14,8.6.5+2019-07-15,8.6.5+2019-07-16,8.6.5+2019-07-17,8.6.5+2019-07-18,8.6.5+2019-07-19,8.6.5+2019-07-20,8.6.5+2019-07-21,8.6.5+2019-07-22,8.6.5+2019-07-23,8.6.5+2019-07-24,8.6.5+2019-07-25,8.6.5+2019-07-26,8.6.5+2019-07-27,8.6.5+2019-07-29,8.6.5+2019-07-30,8.6.5+2019-07-31,8.6.5+2019-08-01,8.6.5+2019-08-02,8.6.5+2019-08-03,8.6.5+2019-08-04,8.6.5+2019-08-06,8.6.5+2019-08-07,8.6.5+2019-08-11,8.6.5+2019-08-12,8.6.5+2019-08-16,8.6.5+2019-08-17,8.6.5+2019-08-18,8.6.5+2019-08-19,8.6.5+2019-08-20,8.6.5+2019-08-22,8.6.5+2019-08-23,8.6.5+2019-08-24,8.6.5+2019-08-25,8.6.5+2019-08-26,8.6.5+2019-08-27,8.6.5+2019-08-28,8.6.5+2019-08-29,8.6.5+2019-08-30,8.6.5+2019-08-31,8.6.5+2019-09-01,8.6.5+2019-09-02,8.6.5+2019-09-04,8.6.5+2019-09-08,8.6.5+2019-09-11,8.6.5+2019-09-12,8.6.5+2019-09-13,8.6.5+2019-09-14,8.6.5+2019-09-15,8.6.5+2019-09-16,8.6.5+2019-09-17,8.6.5+2019-09-18,8.6.5+2019-09-19,8.6.5+2019-09-20,8.6.5+2019-09-21,8.6.5+2019-09-26,8.8.1+2019-09-27,8.8.1+2019-09-28,8.8.1+2019-09-29,8.8.1+2019-09-30,8.8.1+2019-10-02,8.8.1+2019-10-04,8.8.1+2019-10-05,8.8.1+2019-10-06,8.8.1+2019-10-07,8.8.1+2019-10-10,8.8.1+2019-10-13,8.8.1+2019-10-14,8.8.1+2019-10-15,8.8.1+2019-10-18,8.8.1+2019-10-19,8.8.1+2019-10-20,8.8.1+2019-10-21,8.8.1+2019-10-22,8.8.1+2019-10-23,8.8.1+2019-10-24,8.8.1+2019-10-25,8.8.1+2019-10-26,8.8.1+2019-10-27,8.8.1+2019-10-28,8.8.1+2019-10-29,8.8.1+2019-10-30,8.8.1+2019-10-31,8.8.1+2019-11-01,8.8.1+2019-11-02,8.8.1+2019-11-04,8.8.1+2019-11-05,8.8.1+2019-11-06,8.8.1+2019-11-07,8.8.1+2019-11-08,8.8.1+2019-11-09,8.8.1+2019-11-10,8.8.1+2019-11-11,8.8.1+2019-11-17,8.8.1+2019-11-19,8.8.1+2019-11-20,8.8.1+2019-11-21,8.8.1+2019-11-24,8.8.1+2019-11-25,8.8.1+2019-11-28,8.8.1+2019-11-29,8.8.1+2019-12-05,8.8.1+2019-12-06,8.8.1+2019-12-07,8.8.1+2019-12-08,8.8.1+2019-12-09,8.8.1+2019-12-10,8.8.1+2019-12-11,8.8.1+2019-12-12,8.8.1+2019-12-13,8.8.1+2019-12-15,8.8.1+2019-12-16,8.8.1+2019-12-17,8.8.1+2019-12-18,8.8.1+2019-12-19,8.8.1+2019-12-20,8.8.1+2019-12-21,8.8.1+2019-12-22,8.8.1+2019-12-23,8.8.1+2019-12-24,8.8.1+2019-12-25,8.8.1+2019-12-26,8.8.1+2019-12-27,8.8.1+2019-12-28,8.8.1+2019-12-29,8.8.1+2019-12-30,8.8.1+2019-12-31,8.8.1+2020-01-01,8.8.1+2020-01-02,8.8.1+2020-01-03,8.8.1+2020-01-04,8.8.1+2020-01-05,8.8.1+2020-01-06,8.8.1+2020-01-07,8.8.1+2020-01-08,8.8.1+2020-01-15,8.8.1+2020-01-16,8.8.1+2020-01-17,8.8.1+2020-01-19,8.8.1+2020-01-21,8.8.1+2020-01-24,8.8.2+2020-01-25,8.8.2+2020-01-29,8.8.2+2020-01-30,8.8.2+2020-01-31,8.8.2+2020-02-02,8.8.2+2020-02-03,8.8.2+2020-02-04,8.8.2+2020-02-06,8.8.2+2020-02-07,8.8.2+2020-02-08,8.8.2+2020-02-11,8.8.2+2020-02-12,8.8.2+2020-02-13,8.8.2+2020-02-14,8.8.2+2020-02-15,8.8.2+2020-02-16,8.8.2+2020-02-17,8.8.2+2020-02-19,8.8.2+2020-02-20,8.8.2+2020-02-21,8.8.2+2020-02-22,8.8.2+2020-02-23,8.8.2+2020-02-24,8.8.2+2020-02-25,8.8.2+2020-02-26,8.8.2+2020-02-27,8.8.2+2020-02-28,8.8.2+2020-02-29,8.8.2+2020-03-01,8.8.2+2020-03-02,8.8.2+2020-03-03,8.8.2+2020-03-04,8.8.2+2020-03-06,8.8.2+2020-03-07,8.8.2+2020-03-08,8.8.2+2020-03-09,8.8.2+2020-03-10,8.8.3+2020-03-11,8.8.3+2020-03-12,8.8.3+2020-03-13,8.8.3+2020-03-14,8.8.3+2020-03-16,8.8.3+2020-03-17,8.8.3+2020-03-18,8.8.3+2020-03-21,8.8.3+2020-03-22,8.8.3+2020-03-23,8.8.3+2020-03-24,8.8.3+2020-03-25,8.8.3+2020-03-26,8.8.3+2020-03-28,8.8.3+2020-03-29,8.8.3+2020-03-30,8.8.3+2020-04-01,8.8.3+2020-04-02,8.8.3+2020-04-03,8.8.3+2020-04-04,8.8.3+2020-04-05,8.8.3+2020-04-07,8.8.3+2020-04-08,8.8.3+2020-04-09,8.8.3+2020-04-10,8.8.3+2020-04-11,8.8.3+2020-04-12,8.8.3+2020-04-13,8.8.3+2020-04-15,8.8.3+2020-04-16,8.8.3+2020-04-17,8.8.3+2020-04-18,8.8.3+2020-04-21,8.8.3+2020-04-22,8.8.3+2020-04-23,8.8.3+2020-04-24,8.8.3+2020-04-25,8.8.3+2020-04-26,8.8.3+2020-04-27,8.8.3+2020-04-28,8.8.3+2020-04-29,8.8.3+2020-04-30,8.8.3+2020-05-01,8.8.3+2020-05-03,8.8.3+2020-05-04,8.8.3+2020-05-05,8.8.3+2020-05-06,8.8.3+2020-05-07,8.8.3+2020-05-10,8.8.3+2020-05-11,8.8.3+2020-05-12,8.8.3+2020-05-13,8.8.3+2020-05-14,8.8.3+2020-05-15,8.8.3+2020-05-16,8.8.3+2020-05-19,8.8.3+2020-05-22,8.8.3+2020-05-23,8.8.3+2020-05-26,8.8.3+2020-05-30,8.8.3+2020-05-31,8.8.3+2020-06-01,8.8.3+2020-06-02,8.8.3+2020-06-03,8.8.3+2020-06-04,8.8.3+2020-06-05,8.8.3+2020-06-06,8.8.3+2020-06-08,8.8.3+2020-06-09,8.8.3+2020-06-10,8.8.3+2020-06-11,8.8.3+2020-06-12,8.8.3+2020-06-13,8.8.3+2020-06-15,8.8.3+2020-06-16,8.8.3+2020-06-17,8.10.1+2020-06-18,8.10.1+2020-06-19,8.10.1+2020-06-20,8.10.1+2020-06-21,8.10.1+2020-06-22,8.10.1+2020-06-24,8.10.1+2020-06-25,8.10.1+2020-06-26,8.10.1+2020-06-27,8.10.1+2020-06-28,8.10.1+2020-06-29,8.10.1+2020-07-04,8.10.1+2020-07-06,8.10.1+2020-07-07,8.10.1+2020-07-08,8.10.1+2020-07-09,8.10.1+2020-07-10,8.10.1+2020-07-11,8.10.1+2020-07-12,8.10.1+2020-07-13,8.10.1+2020-07-14,8.10.1+2020-07-15,8.10.1+2020-07-16,8.10.1+2020-07-17,8.10.1+2020-07-18,8.10.1+2020-07-19,8.10.1+2020-07-21,8.10.1+2020-07-22,8.10.1+2020-07-23,8.10.1+2020-07-24,8.10.1+2020-07-27,8.10.1+2020-07-28,8.10.1+2020-07-29,8.10.1+2020-07-30,8.10.1+2020-07-31,8.10.1+2020-08-01,8.10.1+2020-08-02,8.10.1+2020-08-03,8.10.1+2020-08-08,8.10.1+2020-08-09,8.10.1+2020-08-10,8.10.1+2020-08-11,8.10.1+2020-08-12,8.10.1+2020-08-13,8.10.1+2020-08-14,8.10.1+2020-08-15,8.10.1+2020-08-16,8.10.1+2020-08-17,8.10.2+2020-08-18,8.10.2+2020-08-19,8.10.2+2020-08-20,8.10.2+2020-08-21,8.10.2+2020-08-22,8.10.2+2020-08-23,8.10.2+2020-08-25,8.10.2+2020-08-26,8.10.2+2020-08-27,8.10.2+2020-08-28,8.10.2+2020-08-29,8.10.2+2020-08-30,8.10.2+2020-08-31,8.10.2+2020-09-01,8.10.2+2020-09-02,8.10.2+2020-09-03,8.10.2+2020-09-05,8.10.2+2020-09-06,8.10.2+2020-09-07,8.10.2+2020-09-09,8.10.2+2020-09-10,8.10.2+2020-09-13,8.10.2+2020-09-14,8.10.2+2020-09-15,8.10.2+2020-09-16,8.10.2+2020-09-17,8.10.2+2020-09-18,8.10.2+2020-09-19,8.10.2+2020-09-20,8.10.2+2020-09-21,8.10.2+2020-09-22,8.10.2+2020-09-23,8.10.2+2020-09-24,8.10.2+2020-09-25,8.10.2+2020-09-26,8.10.2+2020-09-27,8.10.2+2020-09-28,8.10.2+2020-09-29,8.10.2+2020-10-02,8.10.2+2020-10-03,8.10.2+2020-10-05,8.10.2+2020-10-06,8.10.2+2020-10-07,8.10.2+2020-10-08,8.10.2+2020-10-09,8.10.2+2020-10-10,8.10.2+2020-10-11,8.10.2+2020-10-12,8.10.2+2020-10-13,8.10.2+2020-10-14,8.10.2+2020-10-15,8.10.2+2020-10-16,8.10.2+2020-10-17,8.10.2+2020-10-18,8.10.2+2020-10-19,8.10.2+2020-10-20,8.10.2+2020-10-22,8.10.2+2020-10-23,8.10.2+2020-10-25,8.10.2+2020-10-26,8.10.2+2020-10-27,8.10.2+2020-10-28,8.10.2+2020-10-29,8.10.2+2020-10-30,8.10.2+2020-10-31,8.10.2+2020-11-01,8.10.2+2020-11-03,8.10.2+2020-11-04,8.10.2+2020-11-06,8.10.2+2020-11-08,8.10.2+2020-11-10,8.10.2+2020-11-11,8.10.2+2020-11-15,8.10.2+2020-11-16,8.10.2+2020-11-17,8.10.2+2020-11-18,8.10.2+2020-11-19,8.10.2+2020-11-20,8.10.2+2020-11-21,8.10.2+2020-11-22,8.10.2+2020-11-23,8.10.2+2020-11-27,8.10.2+2020-11-28,8.10.2+2020-12-01,8.10.2+2020-12-02,8.10.2+2020-12-03,8.10.2+2020-12-04,8.10.2+2020-12-05,8.10.2+2020-12-06,8.10.2+2020-12-07,8.10.2+2020-12-08,8.10.2+2020-12-09,8.10.2+2020-12-10,8.10.2+2020-12-12,8.10.2+2020-12-13,8.10.2+2020-12-14,8.10.2+2021-01-01,8.10.3+2021-01-02,8.10.3+2021-01-03,8.10.3+2021-01-04,8.10.3+2021-01-05,8.10.3+2021-01-09,8.10.3+2021-01-10,8.10.3+2021-01-11,8.10.3+2021-01-13,8.10.3+2021-01-14,8.10.3+2021-01-15,8.10.3+2021-01-16,8.10.3+2021-01-17,8.10.3+2021-01-19,8.10.3+2021-01-20,8.10.3+2021-01-25,8.10.3+2021-01-26,8.10.3+2021-01-27,8.10.3+2021-01-28,8.10.3+2021-01-29,8.10.3+2021-01-30,8.10.3+2021-02-01,8.10.3+2021-02-02,8.10.3+2021-02-03,8.10.3+2021-02-04,8.10.3+2021-02-05,8.10.3+2021-02-06,8.10.3+2021-02-09,8.10.3+2021-02-10,8.10.3+2021-02-11,8.10.4+2021-02-12,8.10.4+2021-02-23,8.10.4+2021-02-24,8.10.4+2021-02-25,8.10.4+2021-02-27,8.10.4+2021-02-28,8.10.4+2021-03-01,8.10.4+2021-03-05,8.10.4+2021-03-06,8.10.4+2021-03-07,8.10.4+2021-03-09,8.10.4+2021-03-10,8.10.4+2021-03-11,8.10.4+2021-03-12,8.10.4+2021-03-13,8.10.4+2021-03-14,8.10.4+2021-03-17,8.10.4+2021-03-18,8.10.4+2021-03-19,8.10.4+2021-03-20,8.10.4+2021-03-21,8.10.4+2021-03-24,8.10.4+2021-03-25,8.10.4+2021-03-26,8.10.4+2021-03-27,8.10.4+2021-03-28,8.10.4+2021-03-29,8.10.4+2021-03-30,8.10.4+2021-03-31,8.10.4+2021-04-01,8.10.4+2021-04-02,8.10.4+2021-04-06,8.10.4+2021-04-14,8.10.4+2021-04-15,8.10.4+2021-04-19,8.10.4+2021-04-22,8.10.4+2021-04-23,8.10.4+2021-04-24,8.10.4+2021-04-25,8.10.4+2021-04-26,8.10.4+2021-04-27,8.10.4+2021-04-28,8.10.4+2021-04-29,8.10.4+2021-04-30,8.10.4+2021-05-01,8.10.4+2021-05-02,8.10.4+2021-05-03,8.10.4+2021-05-04,8.10.4+2021-05-05,8.10.4+2021-05-06,8.10.4+2021-05-07,8.10.4+2021-05-08,8.10.4+2021-05-09,8.10.4+2021-05-10,8.10.4+2021-05-14,8.10.4+2021-05-15,8.10.4+2021-05-16,8.10.4+2021-05-19,8.10.4+2021-05-20,8.10.4+2021-05-23,8.10.4+2021-05-25,8.10.4+2021-05-26,8.10.4+2021-05-27,8.10.4+2021-05-28,8.10.4+2021-05-31,8.10.4+2021-06-01,8.10.4+2021-06-10,8.10.4+2021-06-14,8.10.4+2021-06-19,9.0.1+2021-06-20,9.0.1+2021-06-21,9.0.1+2021-06-24,9.0.1+2021-06-29,9.0.1+2021-06-30,9.0.1+2021-07-01,9.0.1+2021-07-02,9.0.1+2021-07-03,9.0.1+2021-07-04,9.0.1+2021-07-06,9.0.1+2021-07-07,9.0.1+2021-07-08,9.0.1+2021-07-09,9.0.1+2021-07-11,9.0.1+2021-07-12,9.0.1+2021-07-13,9.0.1+2021-07-14,9.0.1+2021-07-15,9.0.1+2021-07-16,9.0.1+2021-07-17,9.0.1+2021-07-18,9.0.1+2021-07-19,9.0.1+2021-07-20,9.0.1+2021-07-21,9.0.1+2021-07-22,9.0.1+2021-07-23,9.0.1+2021-07-28,9.0.1+2021-07-29,9.0.1+2021-07-30,9.0.1+2021-07-31,9.0.1+2021-08-01,9.0.1+2021-08-03,9.0.1+2021-08-04,9.0.1+2021-08-05,9.0.1+2021-08-06,9.0.1+2021-08-07,9.0.1+2021-08-08,9.0.1+2021-08-13,9.0.1+2021-08-14,9.0.1+2021-08-15,9.0.1+2021-08-16,9.0.1+2021-08-17,9.0.1+2021-08-19,9.0.1+2021-08-20,9.0.1+2021-08-21,9.0.1+2021-08-22,9.0.1+2021-08-23,9.0.1+2021-08-24,9.0.1+2021-08-25,9.0.1+2021-08-26,9.0.1+2021-08-27,9.0.1+2021-08-28,9.0.1+2021-08-29,9.0.1+2021-09-01,9.0.1+2021-09-02,9.0.1+2021-09-06,9.0.1+2021-09-07,9.0.1+2021-09-08,9.0.1+2021-09-09,9.0.1+2021-09-10,9.0.1+2021-09-11,9.0.1+2021-09-12,9.0.1+2021-09-16,9.0.1+2021-09-17,9.0.1+2021-09-18,9.0.1+2021-09-29,9.0.1+2021-09-30,9.0.1+2021-10-01,9.0.1+2021-10-02,9.0.1+2021-10-05,9.0.1+2021-10-07,9.0.1+2021-10-12,9.0.1+2021-10-13,9.0.1+2021-10-18,9.0.1+2021-10-19,9.0.1+2021-10-20,9.0.1+2021-10-21,9.0.1+2021-10-22,9.0.1+2021-10-23,9.0.1+2021-10-24,9.0.1+2021-10-25,9.0.1+2021-10-26,9.0.1+2021-10-27,9.0.1+2021-10-29,9.0.1+2021-11-06,9.0.1+2021-11-12,9.0.1+2021-11-14,9.0.1+2021-11-15,9.0.1+2021-11-19,9.0.1+2021-11-26,9.0.1+2021-11-27,9.0.1+2021-11-28,9.0.1+2021-12-03,9.0.1+2021-12-04,9.0.1+2021-12-06,9.0.1+2021-12-07,9.0.1+2021-12-08,9.0.1+2021-12-10,9.0.1+2021-12-11,9.0.1+2021-12-12,9.0.1+2021-12-13,9.0.1+2021-12-14,9.0.1+2021-12-15,9.0.1+2021-12-16,9.0.1+2021-12-17,9.0.1+2021-12-18,9.0.1+2021-12-19,9.0.1+2021-12-20,9.0.1+2021-12-21,9.0.1+2021-12-22,9.0.1+2021-12-23,9.0.1+2021-12-24,9.0.1+2021-12-25,9.0.1+2021-12-26,9.0.1+2021-12-29,9.0.1+2021-12-30,9.0.1+2022-01-02,9.0.1+2022-01-03,9.0.1+2022-01-04,9.0.1+2022-01-05,9.0.1+2022-01-06,9.0.1+2022-01-10,9.0.2+2022-01-13,9.0.2+2022-01-14,9.0.2+2022-01-15,9.0.2+2022-01-19,9.0.2+2022-01-20,9.0.2+2022-01-22,9.0.2+2022-01-23,9.0.2+2022-01-24,9.0.2+2022-01-25,9.0.2+2022-01-26,9.0.2+2022-01-27,9.0.2+2022-01-31,9.0.2+2022-02-01,9.0.2+2022-02-05,9.0.2+2022-02-07,9.0.2+2022-02-10,9.0.2+2022-02-11,9.0.2+2022-02-12,9.0.2+2022-02-14,9.0.2+2022-02-15,9.0.2+2022-02-16,9.0.2+2022-02-17,9.0.2+2022-02-18,9.0.2+2022-02-19,9.0.2+2022-02-24,9.0.2+2022-02-25,9.0.2+2022-02-26,9.0.2+2022-02-27,9.0.2+2022-03-02,9.0.2+2022-03-03,9.0.2+2022-03-09,9.0.2+2022-03-10,9.0.2+2022-03-12,9.0.2+2022-03-13,9.0.2+2022-03-14,9.0.2+2022-03-15,9.0.2+2022-03-16,9.0.2+2022-03-17,9.0.2+2022-03-19,9.2.2+2022-03-20,9.2.2+2022-03-21,9.2.2+2022-03-22,9.2.2+2022-03-23,9.2.2+2022-03-24,9.2.2+2022-03-25,9.2.2+2022-03-26,9.2.2+2022-03-27,9.2.2+2022-03-28,9.2.2+2022-03-29,9.2.2+2022-03-30,9.2.2+2022-03-31,9.2.2+2022-04-01,9.2.2+2022-04-02,9.2.2+2022-04-03,9.2.2+2022-04-04,9.2.2+2022-04-05,9.2.2+2022-04-06,9.2.2+2022-04-07,9.2.2+2022-04-08,9.2.2+2022-04-09,9.2.2+2022-04-10,9.2.2+2022-04-11,9.2.2+2022-04-12,9.2.2+2022-04-13,9.2.2+2022-04-14,9.2.2+2022-04-15,9.2.2+2022-04-16,9.2.2+2022-04-18,9.2.2+2022-04-19,9.2.2+2022-04-20,9.2.2+2022-04-21,9.2.2+2022-04-22,9.2.2+2022-04-23,9.2.2+2022-04-24,9.2.2+2022-04-25,9.2.2+2022-04-26,9.2.2+2022-04-27,9.2.2+2022-04-28,9.2.2+2022-05-03,9.2.2+2022-05-05,9.2.2+2022-05-11,9.2.2+2022-05-12,9.2.2+2022-05-14,9.2.2+2022-05-18,9.2.2+2022-05-19,9.2.2+2022-05-20,9.2.2+2022-05-25,9.2.2+2022-05-26,9.2.2+2022-05-27,9.2.2+2022-05-28,9.2.2+2022-05-29,9.2.2+2022-05-30,9.2.2+2022-05-31,9.2.2+2022-06-01,9.2.2+2022-06-02,9.2.2+2022-06-03,9.2.2+2022-06-04,9.2.2+2022-06-05,9.2.2+2022-06-06,9.2.2+2022-06-08,9.2.3+2022-06-09,9.2.3+2022-06-10,9.2.3+2022-06-11,9.2.3+2022-06-12,9.2.3+2022-06-13,9.2.3+2022-06-14,9.2.3+2022-06-15,9.2.3+2022-06-17,9.2.3+2022-06-18,9.2.3+2022-06-19,9.2.3+2022-06-20,9.2.3+2022-06-21,9.2.3+2022-06-22,9.2.3+2022-06-24,9.2.3+2022-06-25,9.2.3+2022-06-26,9.2.3+2022-06-27,9.2.3+2022-06-28,9.2.3+2022-06-29,9.2.3+2022-06-30,9.2.3+2022-07-01,9.2.3+2022-07-03,9.2.3+2022-07-04,9.2.3+2022-07-05,9.2.3+2022-07-06,9.2.3+2022-07-07,9.2.3+2022-07-10,9.2.3+2022-07-11,9.2.3+2022-07-12,9.2.3+2022-07-13,9.2.3+2022-07-14,9.2.3+2022-07-15,9.2.3+2022-07-16,9.2.3+2022-07-17,9.2.3+2022-07-18,9.2.3+2022-07-19,9.2.3+2022-07-20,9.2.3+2022-07-21,9.2.3+2022-07-23,9.2.3+2022-07-26,9.2.3+2022-07-27,9.2.3+2022-07-28,9.2.3+2022-07-29,9.2.3+2022-07-30,9.2.3+2022-07-31,9.2.3+2022-08-01,9.2.4+2022-08-02,9.2.4+2022-08-03,9.2.4+2022-08-04,9.2.4+2022-08-14,9.2.4+2022-08-15,9.2.4+2022-08-16,9.2.4+2022-08-17,9.2.4+2022-08-18,9.2.4+2022-08-19,9.2.4+2022-08-24,9.2.4+2022-08-26,9.2.4+2022-08-29,9.2.4+2022-08-30,9.2.4+2022-09-01,9.2.4+2022-09-02,9.2.4+2022-09-03,9.2.4+2022-09-04,9.2.4+2022-09-05,9.2.4+2022-09-06,9.2.4+2022-09-07,9.2.4+2022-09-08,9.2.4+2022-09-09,9.2.4+2022-09-10,9.2.4+2022-09-11,9.2.4+2022-09-12,9.2.4+2022-09-14,9.2.4+2022-09-15,9.2.4+2022-09-16,9.2.4+2022-09-17,9.2.4+2022-09-19,9.2.4+2022-09-20,9.2.4+2022-09-21,9.2.4+2022-09-22,9.2.4+2022-09-23,9.2.4+2022-09-24,9.2.4+2022-09-25,9.2.4+2022-09-26,9.2.4+2022-09-27,9.2.4+2022-09-28,9.2.4+2022-09-29,9.2.4+2022-09-30,9.2.4+2022-10-05,9.2.4+2022-10-06,9.2.4+2022-10-07,9.2.4+2022-10-08,9.2.4+2022-10-10,9.2.4+2022-10-11,9.2.4+2022-10-17,9.2.4+2022-10-18,9.2.4+2022-10-22,9.2.4+2022-10-23,9.2.4+2022-10-24,9.2.4+2022-10-25,9.2.4+2022-10-26,9.2.4+2022-10-27,9.2.4+2022-10-28,9.2.4+2022-10-29,9.2.4+2022-10-30,9.2.4+2022-10-31,9.2.4+2022-11-01,9.2.4+2022-11-02,9.2.4+2022-11-03,9.2.4+2022-11-04,9.2.4+2022-11-05,9.2.4+2022-11-07,9.2.4+2022-11-08,9.2.4+2022-11-11,9.2.4+2022-11-12,9.2.4+2022-11-14,9.2.5+2022-11-15,9.2.5+2022-11-16,9.2.5+2022-11-17,9.2.5+2022-11-19,9.4.3+2022-11-20,9.4.3+2022-11-21,9.4.3+2022-11-22,9.4.3+2022-11-23,9.4.3+2022-11-24,9.4.3+2022-11-25,9.4.3+2022-11-26,9.4.3+2022-11-28,9.4.3+2022-11-29,9.4.3+2022-11-30,9.4.3+2022-12-01,9.4.3+2022-12-02,9.4.3+2022-12-03,9.4.3+2022-12-04,9.4.3+2022-12-05,9.4.3+2022-12-06,9.4.3+2022-12-07,9.4.3+2022-12-08,9.4.3+2022-12-09,9.4.3+2022-12-12,9.4.3+2022-12-16,9.4.3+2022-12-17,9.4.3+2022-12-21,9.4.3+2022-12-22,9.4.3+2022-12-23,9.4.3+2022-12-25,9.4.3+2022-12-26,9.4.3+2023-01-01,9.4.4+2023-01-02,9.4.4+2023-01-03,9.4.4+2023-01-05,9.4.4+2023-01-06,9.4.4+2023-01-08,9.4.4+2023-01-10,9.4.4+2023-01-11,9.4.4+2023-01-12,9.4.4+2023-01-13,9.4.4+2023-01-14,9.4.4+2023-01-15,9.4.4+2023-01-18,9.4.4+2023-01-20,9.4.4+2023-01-21,9.4.4+2023-01-22,9.4.4+2023-01-23,9.4.4+2023-01-24,9.4.4+2023-01-25,9.4.4+2023-01-28,9.4.4+2023-01-29,9.4.4+2023-01-30,9.4.4+2023-01-31,9.4.4+2023-02-03,9.4.4+2023-02-04,9.4.4+2023-02-05,9.4.4+2023-02-06,9.4.4+2023-02-07,9.4.4+2023-02-08,9.4.4+2023-02-09,9.4.4+2023-02-12,9.4.4+2023-02-13,9.4.4+2023-02-14,9.4.4+2023-02-23,9.4.4+2023-02-27,9.4.4+2023-03-03,9.4.4+2023-03-04,9.4.4+2023-03-05,9.4.4+2023-03-06,9.4.4+2023-03-07,9.4.4+2023-03-08,9.4.4+2023-03-09,9.4.4+2023-03-10,9.4.4+2023-03-11,9.4.4+2023-03-12,9.4.4+2023-03-13,9.4.4+2023-03-14,9.4.4+2023-03-15,9.4.4+2023-03-16,9.4.4+2023-03-17,9.4.4+2023-03-18,9.4.4+2023-03-19,9.4.4+2023-03-20,9.4.4+2023-03-22,9.4.4+2023-03-23,9.4.4+2023-03-24,9.4.4+2023-03-26,9.4.4+2023-03-27,9.4.4+2023-03-28,9.4.4+2023-03-29,9.4.4+2023-03-30,9.4.4+2023-03-31,9.4.4+2023-04-01,9.4.4+2023-04-02,9.4.4+2023-04-03,9.4.4+2023-04-04,9.4.4+2023-04-05,9.4.4+2023-04-09,9.4.4+2023-04-13,9.4.4+2023-04-14,9.4.4+2023-04-15,9.4.4+2023-04-16,9.4.4+2023-04-17,9.4.4+2023-04-18,9.4.4+2023-04-19,9.4.4+2023-04-20,9.4.4+2023-04-21,9.4.4+2023-04-23,9.4.4+2023-04-24,9.4.4+2023-04-25,9.4.5+2023-04-28,9.4.5+2023-04-29,9.4.5+2023-04-30,9.4.5+2023-05-01,9.4.5+2023-05-02,9.4.5+2023-05-03,9.4.5+2023-05-04,9.4.5+2023-05-05,9.4.5+2023-05-06,9.4.5+2023-05-07,9.4.5+2023-05-08,9.4.5+2023-05-10,9.4.5+2023-05-11,9.4.5+2023-05-12,9.4.5+2023-05-13,9.4.5+2023-05-14,9.4.5+2023-05-15,9.4.5+2023-05-16,9.4.5+2023-05-17,9.4.5+2023-05-19,9.4.5+2023-05-20,9.4.5+2023-05-21,9.4.5+2023-05-22,9.4.5+2023-05-23,9.4.5+2023-05-24,9.4.5+2023-05-25,9.4.5+2023-05-26,9.4.5+2023-05-27,9.4.5+2023-05-28,9.4.5+2023-05-29,9.4.5+2023-05-30,9.4.5+2023-05-31,9.4.5+2023-06-03,9.4.5+2023-06-04,9.4.5+2023-06-08,9.4.5+2023-06-10,9.4.5+2023-06-11,9.4.5+2023-06-12,9.4.5+2023-06-13,9.4.5+2023-06-14,9.4.5+2023-06-15,9.4.5+2023-06-16,9.4.5+2023-06-17,9.4.5+2023-06-18,9.4.5+2023-06-19,9.4.5+2023-06-20,9.4.5+2023-06-21,9.4.5+2023-06-22,9.6.2+2023-06-23,9.6.2+2023-06-24,9.6.2+2023-06-25,9.6.2+2023-06-26,9.6.2+2023-06-27,9.6.2+2023-06-29,9.6.2+2023-06-30,9.6.2+2023-07-01,9.6.2+2023-07-03,9.6.2+2023-07-04,9.6.2+2023-07-05,9.6.2+2023-07-06,9.6.2+2023-07-07,9.6.2+2023-07-09,9.6.2+2023-07-10,9.6.2+2023-07-13,9.6.2+2023-07-14,9.6.2+2023-07-15,9.6.2+2023-07-16,9.6.2+2023-07-17,9.6.2+2023-07-18,9.6.2+2023-07-19,9.6.2+2023-07-20,9.6.2+2023-07-21,9.6.2+2023-07-22,9.6.2+2023-07-24,9.6.2+2023-07-25,9.6.2+2023-07-26,9.6.2+2023-07-27,9.6.2+2023-07-28,9.6.2+2023-07-29,9.6.2+2023-08-01,9.6.2+2023-08-02,9.6.2+2023-08-04,9.6.2+2023-08-05,9.6.2+2023-08-06,9.6.2+2023-08-09,9.6.2+2023-08-10,9.6.2+2023-08-11,9.6.2+2023-08-12,9.6.2+2023-08-13,9.6.2+2023-08-14,9.6.2+2023-08-15,9.6.2+2023-08-16,9.6.2+2023-08-17,9.6.2+2023-08-19,9.6.2+2023-08-20,9.6.2+2023-08-21,9.6.2+2023-08-22,9.6.2+2023-08-23,9.6.2+2023-08-24,9.6.2+2023-08-25,9.6.2+2023-08-26,9.6.2+2023-08-27,9.6.2+2023-08-28,9.6.2+2023-08-29,9.6.2+2023-09-03,9.6.2+2023-09-08,9.6.2+2023-09-09,9.6.2+2023-09-13,9.6.2+2023-09-14,9.6.2+2023-09-15,9.6.2+2023-09-16,9.6.2+2023-09-17,9.6.2+2023-09-18,9.6.2+2023-09-19,9.6.2+2023-09-20,9.6.2+2023-09-21,9.6.2+2023-09-22,9.6.2+2023-09-24,9.6.2+2023-09-25,9.6.2+2023-09-26,9.6.2+2023-09-27,9.6.2+2023-09-30,9.6.2+2023-10-01,9.6.3+2023-10-02,9.6.3+2023-10-03,9.6.3+2023-10-04,9.6.3+2023-10-09,9.6.3+2023-10-13,9.6.3+2023-10-14,9.6.3+2023-10-15,9.6.3+2023-10-16,9.6.3+2023-10-17,9.6.3+2023-10-18,9.6.3+2023-10-19,9.6.3+2023-10-20,9.6.3+2023-10-21,9.6.3+2023-10-22,9.6.3+2023-10-23,9.6.3+2023-10-24,9.6.3+2023-10-25,9.6.3+2023-10-26,9.6.3+2023-10-27,9.6.3+2023-10-28,9.6.3+2023-10-29,9.6.3+2023-10-30,9.6.3+2023-10-31,9.6.3+2023-11-01,9.6.3+2023-11-02,9.6.3+2023-11-03,9.6.3+2023-11-04,9.6.3+2023-11-05,9.6.3+2023-11-06,9.6.3+2023-11-07,9.6.3+2023-11-08,9.6.3+2023-11-09,9.6.3+2023-11-10,9.6.3+2023-11-13,9.6.3+2023-11-14,9.6.3+2023-11-15,9.6.3+2023-11-16,9.6.3+2023-11-17,9.6.3+2023-11-18,9.6.3+2023-11-19,9.6.3+2023-11-20,9.6.3+2023-11-21,9.6.3+2023-11-22,9.6.3+2023-11-23,9.6.3+2023-11-24,9.6.3+2023-11-25,9.6.3+2023-11-26,9.6.3+2023-11-27,9.6.3+2023-11-28,9.6.3+2023-11-29,9.6.3+2023-11-30,9.6.3+2023-12-01,9.6.3+2023-12-02,9.6.3+2023-12-03,9.6.3+2023-12-04,9.6.3+2023-12-05,9.6.3+2023-12-06,9.6.3+2023-12-07,9.6.3+2023-12-08,9.6.3+2023-12-09,9.6.3+2023-12-10,9.6.3+2023-12-11,9.6.3+2023-12-12,9.6.3+2023-12-13,9.6.3+2023-12-14,9.6.3+2023-12-15,9.6.3+2023-12-16,9.6.3+2023-12-17,9.6.3+2023-12-18,9.6.3+2023-12-19,9.6.3+2023-12-22,9.6.3+2023-12-23,9.6.3+2023-12-25,9.6.3+2023-12-26,9.6.3+2023-12-27,9.8.1+2023-12-28,9.8.1+2023-12-29,9.8.1+2023-12-30,9.8.1+2023-12-31,9.8.1+2024-01-01,9.8.1+2024-01-02,9.8.1+2024-01-03,9.8.1+2024-01-04,9.8.1+2024-01-05,9.8.1+2024-01-06,9.8.1+2024-01-07,9.8.1+2024-01-08,9.8.1+2024-01-09,9.8.1+2024-01-10,9.8.1+2024-01-11,9.8.1+2024-01-12,9.8.1+2024-01-13,9.8.1+2024-01-14,9.8.1+2024-01-15,9.8.1+2024-01-16,9.8.1+2024-01-17,9.8.1+2024-01-19,9.8.1+2024-01-20,9.8.1+2024-01-21,9.8.1+2024-01-22,9.8.1+2024-01-23,9.8.1+2024-01-26,9.8.1+2024-01-29,9.8.1+2024-01-30,9.8.1+2024-01-31,9.8.1+2024-02-01,9.8.1+2024-02-02,9.8.1+2024-02-03,9.8.1+2024-02-04,9.8.1+2024-02-05,9.8.1+2024-02-06,9.8.1+2024-02-07,9.8.1+2024-02-08,9.8.1+2024-02-09,9.8.1+2024-02-10,9.8.1+2024-02-11,9.8.1+2024-02-12,9.8.1+2024-02-15,9.8.1+2024-02-16,9.8.1+2024-02-17,9.8.1+2024-02-18,9.8.1+2024-02-19,9.8.1+2024-02-20,9.8.1+2024-02-21,9.8.1+2024-02-22,9.8.1+2024-02-24,9.8.1+2024-02-25,9.8.1+2024-02-26,9.8.1+2024-02-27,9.8.1+2024-02-28,9.8.1+2024-02-29,9.8.1+2024-03-01,9.8.1+2024-03-05,9.8.1+2024-03-06,9.8.1+2024-03-07,9.8.1+2024-03-08,9.8.2+2024-03-10,9.8.2+2024-03-11,9.8.2+2024-03-12,9.8.2+2024-03-13,9.8.2+2024-03-14,9.8.2+2024-03-19,9.8.2+2024-03-20,9.8.2+2024-03-23,9.8.2+2024-03-24,9.8.2+2024-03-26,9.8.2+2024-03-27,9.8.2+2024-03-28,9.8.2+2024-03-29,9.8.2+2024-03-30,9.8.2+2024-03-31,9.8.2+2024-04-01,9.8.2+2024-04-02,9.8.2+2024-04-03,9.8.2+2024-04-04,9.8.2+2024-04-05,9.8.2+2024-04-06,9.8.2+2024-04-07,9.8.2+2024-04-08,9.8.2+2024-04-10,9.8.2+2024-04-11,9.8.2+2024-04-12,9.8.2+2024-04-14,9.8.2+2024-04-17,9.8.2+2024-04-18,9.8.2+2024-04-19,9.8.2+2024-04-20,9.8.2+2024-04-21,9.8.2+2024-04-22,9.8.2+2024-04-24,9.8.2+2024-04-25,9.8.2+2024-04-26,9.8.2+2024-04-27,9.8.2+2024-04-29,9.8.2+2024-04-30,9.8.2+2024-05-01,9.8.2+2024-05-02,9.8.2+2024-05-03,9.8.2+2024-05-04,9.8.2+2024-05-05,9.8.2+2024-05-06,9.8.2+2024-05-10,9.8.2+2024-05-11,9.8.2+2024-05-13,9.8.2+2024-05-14,9.8.2+2024-05-15,9.8.2+2024-05-16,9.8.2+2024-05-18,9.8.2+2024-05-19,9.8.2+2024-05-20,9.8.2+2024-05-21,9.8.2+2024-05-22,9.8.2+2024-05-23,9.8.2+2024-05-24,9.8.2+2024-05-25,9.8.2+2024-05-26,9.8.2+2024-05-27,9.8.2+2024-05-28,9.8.2+2024-05-29,9.8.2+2024-05-30,9.8.2+2024-05-31,9.8.2+2024-06-01,9.8.2+2024-06-02,9.8.2+2024-06-03,9.8.2+2024-06-04,9.8.2+2024-06-07,9.8.2+2024-06-08,9.8.2+2024-06-09,9.8.2+2024-06-10,9.8.2+2024-06-12,9.8.2+2024-06-13,9.8.2+2024-06-14,9.8.2+2024-06-15,9.8.2+2024-06-16,9.8.2+2024-06-17,9.8.2+2024-06-18,9.8.2+2024-06-19,9.8.2+2024-06-20,9.8.2+2024-06-21,9.8.2+2024-06-22,9.8.2+2024-06-28,9.8.2+2024-06-30,9.8.2+2024-07-01,9.8.2+2024-07-02,9.8.2+2024-07-03,9.8.2+2024-07-04,9.8.2+2024-07-05,9.8.2+2024-07-08,9.8.2+2024-07-09,9.8.2+2024-07-11,9.8.2+2024-07-12,9.8.2+2024-07-13,9.8.2+2024-07-15,9.8.2+2024-07-16,9.8.2+2024-07-17,9.8.2+2024-07-18,9.8.2+2024-07-19,9.8.2+2024-07-20,9.8.2+2024-07-21,9.8.2+2024-07-22,9.8.2+2024-07-23,9.8.2+2024-07-24,9.8.2+2024-07-25,9.8.2+2024-07-26,9.8.2+2024-07-27,9.8.2+2024-07-28,9.8.2+2024-07-29,9.8.2+2024-07-30,9.8.2+2024-08-02,9.8.2+2024-08-08,9.8.2+2024-08-09,9.8.2+2024-08-10,9.8.2+2024-08-11,9.8.2+2024-08-12,9.8.2+2024-08-13,9.8.2+2024-08-16,9.8.2+2024-08-17,9.8.2+2024-08-18,9.8.2+2024-08-19,9.8.2+2024-08-20,9.8.2+2024-08-21,9.8.2+2024-08-22,9.8.2+2024-08-23,9.8.2+2024-08-24,9.8.2+2024-08-25,9.8.2+2024-08-26,9.8.2+2024-09-02,9.8.2+2024-09-03,9.8.2+2024-09-04,9.8.2+2024-09-07,9.8.2+2024-09-08,9.8.2+2024-09-09,9.8.2+2024-09-10,9.8.2+2024-09-11,9.8.2+2024-09-12,9.8.2+2024-09-13,9.8.2+2024-09-14,9.8.2+2024-09-15,9.8.2+2024-09-16,9.8.2+2024-09-17,9.8.2+2024-09-18,9.8.2+2024-09-19,9.8.2+2024-09-20,9.8.2+2024-09-22,9.8.2+2024-09-23,9.8.2+2024-09-24,9.8.2+2024-09-25,9.8.2+2024-09-26,9.8.2+2024-09-29,9.8.2+2024-09-30,9.8.2+2024-10-01,9.8.2+2024-10-02,9.8.2+2024-10-03,9.8.2+2024-10-04,9.8.2+2024-10-05,9.8.2+2024-10-06,9.8.2+2024-10-07,9.8.2+2024-10-08,9.8.2+2024-10-09,9.8.2+2024-10-10,9.8.2+2024-10-11,9.8.2+2024-10-21,9.8.2+2024-10-22,9.8.3+2024-10-23,9.8.3+2024-10-24,9.8.3+2024-10-25,9.8.3+2024-10-26,9.8.3+2024-10-27,9.8.3+2024-10-28,9.8.3+2024-10-29,9.8.3+2024-10-30,9.8.3+2024-10-31,9.8.3+2024-11-01,9.8.3+2024-11-02,9.8.3+2024-11-03,9.8.3+2024-11-04,9.8.3+2024-11-05,9.8.3+2024-11-06,9.8.3+2024-11-07,9.8.3+2024-11-08,9.8.3+2024-11-09,9.8.3+2024-11-10,9.8.3+2024-11-11,9.8.3+2024-11-12,9.8.3+2024-11-18,9.8.3+2024-11-19,9.8.3+2024-11-20,9.8.3+2024-11-21,9.8.3+2024-11-22,9.8.3+2024-11-23,9.8.3+2024-11-24,9.8.3+2024-11-25,9.8.3+2024-11-26,9.8.3+2024-11-27,9.8.3+2024-11-28,9.8.3+2024-11-29,9.8.3+2024-11-30,9.8.3+2024-12-03,9.8.3+2024-12-04,9.8.3+2024-12-05,9.8.4+2024-12-07,9.8.4+2024-12-08,9.8.4+2024-12-09,9.8.4+2024-12-11,9.10.1+2024-12-12,9.10.1+2024-12-13,9.10.1+2024-12-15,9.10.1+2024-12-16,9.10.1+2024-12-17,9.10.1+2024-12-18,9.10.1+2024-12-19,9.10.1+2024-12-20,9.10.1+2024-12-21,9.10.1+2024-12-22,9.10.1+2024-12-23,9.10.1+2024-12-24,9.10.1+2024-12-25,9.10.1+2024-12-26,9.10.1+2024-12-27,9.10.1+2024-12-28,9.10.1+2024-12-29,9.10.1+2024-12-30,9.10.1+2024-12-31,9.10.1+2025-01-01,9.10.1+2025-01-02,9.10.1+2025-01-03,9.10.1+2025-01-04,9.10.1+2025-01-05,9.10.1+2025-01-06,9.10.1+2025-01-08,9.10.1+2025-01-10,9.10.1+2025-01-11,9.10.1+2025-01-12,9.10.1+2025-01-13,9.10.1+2025-01-14,9.10.1+2025-01-15,9.10.1+2025-01-16,9.10.1+2025-01-17,9.10.1+2025-01-18,9.10.1+2025-01-19,9.10.1+2025-01-20,9.10.1+2025-01-21,9.10.1+2025-01-23,9.10.1+2025-01-25,9.10.1+2025-01-27,9.10.1+2025-01-29,9.10.1+2025-01-30,9.10.1+2025-01-31,9.10.1+2025-02-01,9.10.1+2025-02-02,9.10.1+2025-02-03,9.10.1+2025-02-04,9.10.1+2025-02-05,9.10.1+2025-02-06,9.10.1+2025-02-07,9.10.1+2025-02-08,9.10.1+2025-02-09,9.10.1+2025-02-10,9.10.1+2025-02-11,9.10.1+2025-02-12,9.10.1+2025-02-13,9.10.1+2025-02-14,9.10.1+2025-02-15,9.10.1+2025-02-16,9.10.1+2025-02-17,9.10.1+2025-02-18,9.10.1+2025-02-19,9.10.1+2025-02-20,9.10.1+2025-02-23,9.10.1+2025-02-24,9.10.1+2025-02-25,9.10.1+2025-02-26,9.10.1+2025-02-27,9.10.1+2025-02-28,9.10.1+2025-03-01,9.10.1+2025-03-05,9.10.1+2025-03-06,9.10.1+2025-03-07,9.10.1+2025-03-09,9.10.1+2025-03-10,9.10.1+2025-03-11,9.10.1+2025-03-13,9.10.1+2025-03-14,9.10.1+2025-03-15,9.10.1+2025-03-16,9.10.1+2025-03-17,9.10.1+2025-03-19,9.10.1+2025-03-20,9.10.1+2025-03-22,9.10.1+2025-03-23,9.10.1+2025-03-24,9.10.1+2025-03-25,9.10.1+2025-03-26,9.10.1+2025-03-27,9.10.1+2025-03-28,9.10.1+2025-03-29,9.10.1+2025-03-30,9.10.1+2025-03-31,9.10.1+2025-04-01,9.10.1+2025-04-02,9.10.1+2025-04-03,9.10.1+2025-04-04,9.10.1+2025-04-05,9.10.1+2025-04-06,9.10.1+2025-04-07,9.10.1+2025-04-08,9.10.1+2025-04-09,9.10.1+2025-04-10,9.10.1+2025-04-11,9.10.1+2025-04-12,9.10.1+2025-04-13,9.10.1+2025-04-14,9.10.1+2025-04-15,9.10.1+2025-04-16,9.10.1+2025-04-17,9.10.1+2025-04-18,9.10.1+2025-04-19,9.10.1+2025-04-20,9.10.1+2025-04-21,9.10.1+2025-04-22,9.10.1+2025-04-23,9.10.1+2025-04-24,9.10.1+2025-04-30,9.10.1+2025-05-01,9.10.1+2025-05-02,9.10.1+2025-05-03,9.10.1+2025-05-04,9.10.1+2025-05-05,9.10.1+2025-05-06,9.10.2+2025-05-07,9.10.2+2025-05-08,9.10.2+2025-05-09,9.10.2+2025-05-10,9.10.2+2025-05-11,9.10.2+2025-05-13,9.10.2+2025-05-14,9.10.2+2025-05-15,9.10.2+2025-05-16,9.10.2+2025-05-17,9.10.2+2025-05-18,9.10.2+2025-05-19,9.10.2+2025-05-20,9.10.2+2025-05-21,9.10.2+2025-05-22,9.10.2+2025-05-23,9.10.2+2025-05-24,9.10.2+2025-05-25,9.10.2+2025-05-26,9.10.2+2025-05-27,9.10.2+2025-05-28,9.10.2+2025-06-11,9.10.2+2025-06-12,9.10.2+2025-06-13,9.10.2+2025-06-14,9.10.2+2025-06-15,9.10.2+2025-06-16,9.10.2+2025-06-17,9.10.2+2025-06-18,9.10.2+2025-06-29,9.10.2+2025-07-01,9.10.2+2025-07-02,9.10.2+2025-07-03,9.10.2+2025-07-04,9.10.2+2025-07-05,9.10.2+2025-07-06,9.10.2+2025-07-07,9.10.2+2025-07-08,9.10.2+2025-07-09,9.10.2+2025-07-10,9.10.2+2025-07-11,9.10.2+2025-07-12,9.10.2+2025-07-13,9.10.2+2025-07-14,9.10.2+2025-07-15,9.12.2+2025-07-16,9.12.2+2025-07-17,9.12.2+2025-07-18,9.12.2+2025-07-19,9.12.2+2025-07-20,9.12.2+2025-07-21,9.12.2+2025-07-22,9.12.2+2025-07-23,9.12.2+2025-07-24,9.12.2+2025-07-25,9.12.2+2025-07-26,9.12.2+2025-07-28,9.12.2+2025-07-29,9.12.2+2025-07-30,9.12.2+2025-07-31,9.12.2+2025-08-01,9.12.2+2025-08-02,9.12.2+2025-08-03,9.12.2+2025-08-04,9.12.2+2025-08-05,9.12.2+2025-08-06,9.12.2+2025-08-07,9.12.2+2025-08-08,9.12.2+2025-08-11,9.12.2+2025-08-12,9.12.2+2025-08-13,9.12.2+2025-08-14,9.12.2+2025-08-15,9.12.2+2025-08-16,9.12.2+2025-08-17,9.12.2+2025-08-18,9.12.2+2025-08-19,9.12.2+2025-08-20,9.12.2+2025-08-21,9.12.2+2025-08-22,9.12.2+2025-08-23,9.12.2+2025-08-27,9.12.2+2025-08-28,9.12.2+2025-08-29,9.12.2+2025-08-30,9.12.2+2025-08-31,9.12.2+2025-09-01,9.12.2+2025-09-02,9.12.2+2025-09-03,9.12.2+2025-09-04,9.12.2+2025-09-05,9.12.2+2025-09-06,9.12.2+2025-09-09,9.12.2+2025-09-10,9.12.2+2025-09-11,9.12.2+2025-09-12,9.12.2+2025-09-13,9.12.2+2025-09-14,9.12.2+2025-09-15,9.12.2+2025-09-16,9.12.2+2025-09-18,9.12.2+2025-09-19,9.12.2+2025-09-20,9.12.2+2025-09-21,9.12.2+2025-09-22,9.12.2+2025-09-23,9.12.2+2025-09-24,9.12.2+2025-09-25,9.12.2+2025-09-26,9.12.2+2025-09-28,9.12.2+2025-09-29,9.12.2+2025-09-30,9.12.2+2025-10-01,9.12.2+2025-10-02,9.12.2+2025-10-04,9.12.2+2025-10-05,9.12.2+2025-10-06,9.12.2+2025-10-07,9.12.2+2025-10-08,9.12.2+2025-10-09,9.12.2+2025-10-10,9.12.2+2025-10-11,9.12.2+2025-10-12,9.12.2+2025-10-13,9.12.2+2025-10-14,9.12.2+2025-10-15,9.12.2+2025-10-16,9.12.2+2025-10-17,9.12.2+2025-10-18,9.12.2+2025-10-19,9.12.2+2025-10-20,9.12.2+2025-10-21,9.12.2+2025-10-22,9.12.2+2025-10-23,9.12.2+2025-10-24,9.12.2+2025-10-25,9.12.2+2025-10-26,9.12.2+2025-10-29,9.12.2+2025-10-30,9.12.2+2025-10-31,9.12.2+2025-11-01,9.12.2+2025-11-03,9.12.2+2025-11-04,9.12.2+2025-11-06,9.12.2+2025-11-07,9.12.2+2025-11-08,9.12.2+2025-11-09,9.12.2+2025-11-10,9.12.2+2025-11-11,9.12.2+2025-11-12,9.12.2+2025-11-13,9.12.2+2025-11-14,9.12.2+2025-11-15,9.12.2+2025-11-16,9.12.2+2025-11-17,9.12.2+2025-11-18,9.12.2+2025-11-19,9.12.2+2025-11-21,9.12.2+2025-11-22,9.12.2+2025-11-23,9.12.2+2025-11-24,9.12.2+2025-11-25,9.12.2+2025-11-26,9.12.2+2025-11-27,9.12.2+2025-11-28,9.12.2+2025-11-29,9.12.2+2025-11-30,9.12.2+2025-12-01,9.12.2+2025-12-02,9.12.2+2025-12-03,9.12.2+2025-12-04,9.12.2+2025-12-05,9.12.2+2025-12-06,9.12.2+2025-12-07,9.12.2+2025-12-08,9.12.2+2025-12-09,9.12.2+2025-12-10,9.12.2+2025-12-14,9.12.2+2025-12-15,9.12.2+2025-12-16,9.12.2+2025-12-17,9.12.2+2025-12-18,9.12.2+2025-12-19,9.12.2+2025-12-20,9.12.2+2025-12-21,9.12.2+2025-12-22,9.12.2+2025-12-23,9.12.2+2025-12-24,9.12.2+2025-12-25,9.12.2+2025-12-26,9.12.2+2025-12-28,9.12.2+2025-12-29,9.12.2+2025-12-30,9.12.2+2025-12-31,9.12.3+2026-01-01,9.12.3+2026-01-02,9.12.3+2026-01-03,9.12.3+2026-01-04,9.12.3+2026-01-05,9.12.3+2026-01-06,9.12.3+2026-01-07,9.12.3+2026-01-08,9.12.3+2026-01-09,9.12.3+2026-01-10,9.12.3+2026-01-11,9.12.3+2026-01-12,9.12.3+2026-01-13,9.12.3+2026-01-14,9.12.3+2026-01-15,9.12.3+2026-01-16,9.12.3+2026-01-17,9.12.3+2026-01-18,9.12.3+2026-01-19,9.12.3+2026-01-20,9.12.3+2026-01-21,9.12.3+2026-01-22,9.12.3+2026-01-23,9.12.3+2026-01-24,9.12.3+2026-01-25,9.12.3+2026-01-26,9.12.3+2026-02-05,9.12.3+2026-02-06,9.12.3+2026-02-07,9.12.3+2026-02-08,9.12.3+2026-02-09,9.12.3+2026-02-10,9.12.3+2026-02-14,9.12.3+2026-02-15,9.12.3+2026-02-16,9.12.3+2026-02-17,9.12.3+2026-02-18,9.12.3+2026-02-19,9.12.3+2026-02-20,9.12.3+2026-02-21,9.12.3+2026-02-22,9.12.3+2026-02-23,9.12.3+2026-02-24,9.12.3+2026-02-27,9.12.3+2026-03-02,9.12.3+2026-03-03,9.12.3+2026-03-04,9.12.3+2026-03-05,9.12.3+2026-03-06,9.12.3+2026-03-07,9.12.3+2026-03-08,9.12.3+2026-03-09,9.12.3+2026-03-10,9.12.3+2026-03-11,9.12.3+2026-03-12,9.12.3+2026-03-13,9.12.3+2026-03-14,9.12.3+2026-03-15,9.12.3+2026-03-16,9.12.3+2026-03-17,9.12.3+2026-03-18,9.12.3+2026-03-19,9.12.3+2026-03-20,9.12.3+2026-03-22,9.12.3+2026-03-23,9.12.3+2026-03-24,9.12.3+2026-03-25,9.12.3+2026-03-27,9.12.3+2026-03-28,9.12.3+2026-03-29,9.12.4+2026-03-30,9.12.4+2026-03-31,9.12.4+2026-04-01,9.12.4+2026-04-02,9.12.4+2026-04-03,9.12.4+2026-04-04,9.12.4+2026-04-05,9.12.4+2026-04-06,9.12.4+2026-04-07,9.12.4
+ src/Analysis.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE OverloadedStrings #-}++module Analysis+ ( analyzeStackYaml+ , analyzeAllStackYamls+ , analyzeStackYamls+ ) where++import Prelude hiding (min, span)++import Control.Monad (filterM)+import Data.Functor ((<&>))+import Data.List (maximumBy)+import Data.Map.Strict qualified as Map+import Data.Maybe (catMaybes)+import Data.Ord (comparing)+import Data.Text (Text)+import Data.Text qualified as T+import System.Directory (doesFileExist)+import Text.Printf (printf)++import Types (Action(..), SnapshotDB(..), LTSVersion(..), NightlyVersion(..), GHCVersion(..), Snapshot(..))+import StackYaml (parseStackYaml, findStackYamlFiles, findStackYamlFilesRecursive, getSymlinkMap)++-- | Analyze a single stack.yaml file+analyzeStackYaml :: SnapshotDB -> Map.Map FilePath FilePath -> FilePath -> IO (Maybe Action)+analyzeStackYaml db symlinkMap file = do+ -- Check if this file is a symlink to another stack*.yaml file in our list+ let symlinkTarget = Map.lookup file symlinkMap++ parseStackYaml file <&> \case+ Nothing -> Nothing+ Just (oldSnap, isResolver, span) -> do+ let newSnap = determineNewSnapshot db oldSnap+ Just $ Action file oldSnap newSnap isResolver span symlinkTarget++-- | Analyze specific stack*.yaml files, or all if empty list+-- If recursive is True, search recursively in all subdirectories+analyzeStackYamls :: SnapshotDB -> [FilePath] -> Bool -> IO [Action]+analyzeStackYamls db files recursive = do+ -- Get files to analyze: either auto-discover or use provided list+ -- Non-existent files are silently filtered out+ filesToAnalyze <- + if null files + then if recursive+ then findStackYamlFilesRecursive+ else findStackYamlFiles+ else filterM doesFileExist files+ symlinkMap <- getSymlinkMap filesToAnalyze+ results <- mapM (analyzeStackYaml db symlinkMap) filesToAnalyze+ return $ catMaybes results++-- | Analyze all stack*.yaml files in the current directory+analyzeAllStackYamls :: SnapshotDB -> IO [Action]+analyzeAllStackYamls db = analyzeStackYamls db [] False++-- | Determine the new snapshot for a given old snapshot+determineNewSnapshot :: SnapshotDB -> Text -> Maybe Text+determineNewSnapshot db oldSnap+ | T.isPrefixOf "lts-" oldSnap = determineLTSBump db oldSnap+ | T.isPrefixOf "nightly-" oldSnap = determineNightlyBump db oldSnap+ | otherwise = Nothing++-- | Determine bump for LTS snapshot+determineLTSBump :: SnapshotDB -> Text -> Maybe Text+determineLTSBump db oldSnap = do+ oldVersion <- parseLTSSnapshot oldSnap+ -- Find the latest LTS with the same major version+ let sameMajor = filter (\(LTSVersion maj _, _) -> maj == ltsMajor oldVersion) $ Map.toList (dbLTS db)+ if null sameMajor+ then Nothing+ else do+ let (latestVersion, _) = maximumBy (comparing fst) sameMajor+ let newSnap = formatSnapshot (LTS latestVersion)+ if newSnap == oldSnap+ then Nothing -- Already up to date+ else Just newSnap++-- | Determine bump for nightly snapshot+determineNightlyBump :: SnapshotDB -> Text -> Maybe Text+determineNightlyBump db oldSnap = do+ oldVersion <- parseNightlySnapshot oldSnap+ oldGHC <- Map.lookup oldVersion (dbNightly db)+ -- Get GHC major version (e.g., (9,6) from GHCVersion 9 6 1)+ let ghcMajor = getGHCMajor oldGHC+ -- Find if there's an LTS for this GHC major version+ let ltsForGHC = filter (\(_, ghc) -> getGHCMajor ghc == ghcMajor) $ Map.toList (dbLTS db)+ if not (null ltsForGHC)+ then do+ -- Bump to latest LTS for this GHC major+ let (latestLTS, _) = maximumBy (comparing fst) ltsForGHC+ return $ formatSnapshot (LTS latestLTS)+ else do+ -- Bump to latest nightly for this GHC major+ let nightliesForGHC = filter (\(_, ghc) -> getGHCMajor ghc == ghcMajor) $ Map.toList (dbNightly db)+ if null nightliesForGHC+ then Nothing+ else do+ let (latestNightly, _) = maximumBy (comparing fst) nightliesForGHC+ let newSnap = formatSnapshot (Nightly latestNightly)+ if newSnap == oldSnap+ then Nothing+ else Just newSnap++-- | Get GHC major version from full version (e.g., (9,6) from GHCVersion 9 6 1)+getGHCMajor :: GHCVersion -> (Int, Int)+getGHCMajor (GHCVersion maj1 maj2 _) = (maj1, maj2)++-- | Parse LTS snapshot string+parseLTSSnapshot :: Text -> Maybe LTSVersion+parseLTSSnapshot snap =+ case T.splitOn "." (T.drop 4 snap) of -- Remove "lts-"+ [majStr, minStr] ->+ case (reads $ T.unpack majStr, reads $ T.unpack minStr) of+ ([(maj, "")], [(min, "")]) -> Just $ LTSVersion maj min+ _ -> Nothing+ _ -> Nothing++-- | Parse nightly snapshot string+parseNightlySnapshot :: Text -> Maybe NightlyVersion+parseNightlySnapshot snap =+ case T.splitOn "-" (T.drop 8 snap) of -- Remove "nightly-"+ [yearStr, monthStr, dayStr] ->+ case (reads $ T.unpack yearStr, reads $ T.unpack monthStr, reads $ T.unpack dayStr) of+ ([(year, "")], [(month, "")], [(day, "")]) -> Just $ NightlyVersion year month day+ _ -> Nothing+ _ -> Nothing++-- | Format a snapshot as a string+formatSnapshot :: Snapshot -> Text+formatSnapshot (LTS (LTSVersion maj min)) =+ "lts-" <> T.pack (show maj) <> "." <> T.pack (show min)+formatSnapshot (Nightly (NightlyVersion year month day)) =+ T.pack $ "nightly-" ++ printf "%d-%02d-%02d" year month day
+ src/CSV.hs view
@@ -0,0 +1,322 @@+{-# LANGUAGE OverloadedStrings #-}++module CSV+ ( generateCSVs+ , loadSnapshotDB+ , ensureCSVFiles+ ) where++import Prelude hiding (lines, min)++import Control.Monad (unless)+import Data.List (sortBy, sortOn)+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.Ord (comparing)+import Data.Text (Text)+import Data.Text qualified as T+import Data.Text.IO qualified as TIO+import System.Directory (listDirectory, doesFileExist, createDirectoryIfMissing)+import System.FilePath (takeExtension)+import PathUtil ((</>))+import Data.Yaml qualified as Yaml+import Data.Yaml ((.:))+import Data.Aeson qualified as Aeson+import Text.Printf (printf)+import Types (LTSVersion(..), NightlyVersion(..), GHCVersion(..), Snapshot(..), SnapshotDB(..))+import XDG (getStateDir)+import System.IO (stderr)+import Paths_stacker (getDataDir)+import System.Directory qualified as Dir++-- Helper functions for parsing+parseGHCVersionText :: Text -> Maybe GHCVersion+parseGHCVersionText txt =+ case T.splitOn "." txt of+ [maj1Str, maj2Str, minStr] ->+ case (reads $ T.unpack maj1Str, reads $ T.unpack maj2Str, reads $ T.unpack minStr) of+ ([(maj1, "")], [(maj2, "")], [(minV, "")]) -> Just $ GHCVersion maj1 maj2 minV+ _ -> Nothing+ _ -> Nothing++parseNightlyVersionText :: Text -> Maybe NightlyVersion+parseNightlyVersionText txt =+ case T.splitOn "-" txt of+ [yearStr, monthStr, dayStr] ->+ case (reads $ T.unpack yearStr, reads $ T.unpack monthStr, reads $ T.unpack dayStr) of+ ([(year, "")], [(month, "")], [(day, "")]) -> Just $ NightlyVersion year month day+ _ -> Nothing+ _ -> Nothing++-- Helper functions for formatting+formatGHCVersion :: GHCVersion -> Text+formatGHCVersion (GHCVersion maj1 maj2 minV) =+ T.pack $ show maj1 ++ "." ++ show maj2 ++ "." ++ show minV++formatNightlyVersion :: NightlyVersion -> Text+formatNightlyVersion (NightlyVersion year month day) =+ T.pack $ printf "%d-%02d-%02d" year month day++-- | Ensure CSV files exist in state directory, copying from data directory if needed+ensureCSVFiles :: IO ()+ensureCSVFiles = do+ stateDir <- getStateDir+ createDirectoryIfMissing True stateDir++ dataDir <- getDataDir++ -- Check if any CSV file is missing+ ghcExists <- doesFileExist (stateDir </> "ghc.csv")+ ltsExists <- doesFileExist (stateDir </> "lts.csv")+ nightlyExists <- doesFileExist (stateDir </> "nightly.csv")++ unless (ghcExists && ltsExists && nightlyExists) $ do+ TIO.hPutStrLn stderr "Copying CSV files from data directory..."+ -- Copy all three CSV files from data directory+ Dir.copyFile (dataDir </> "ghc.csv") (stateDir </> "ghc.csv")+ Dir.copyFile (dataDir </> "lts.csv") (stateDir </> "lts.csv")+ Dir.copyFile (dataDir </> "nightly.csv") (stateDir </> "nightly.csv")++-- | Generate CSV files from the stackage-snapshots repository+generateCSVs :: FilePath -> IO ()+generateCSVs repoPath = do+ stateDir <- getStateDir+ createDirectoryIfMissing True stateDir++ TIO.hPutStrLn stderr $ "Processing snapshot database. This might take a couple of minutes..."++ -- Process LTS snapshots+ TIO.hPutStrLn stderr $ "Processing LTSs..."+ ltsMap <- processLTSSnapshots (repoPath </> "lts")+ writeLTSCSV (stateDir </> "lts.csv") ltsMap++ -- Process nightly snapshots+ TIO.hPutStrLn stderr $ "Processing nightlys..."+ nightlyMap <- processNightlySnapshots (repoPath </> "nightly")+ writeNightlyCSV (stateDir </> "nightly.csv") nightlyMap++ -- Generate GHC version map+ TIO.hPutStrLn stderr $ "Computing latest snapshot per GHC version..."+ let ghcMap = generateGHCMap ltsMap nightlyMap+ writeGHCCSV (stateDir </> "ghc.csv") ghcMap++ TIO.hPutStrLn stderr $ "Done processing snapshot database."++-- | Process LTS snapshots (structure: lts/major/minor.yaml)+processLTSSnapshots :: FilePath -> IO [(LTSVersion, GHCVersion)]+processLTSSnapshots ltsDir = do+ majorDirs <- listDirectory ltsDir+ let sortedMajors = sortOn (\s -> read s :: Int) $ filter (all (`elem` ("0123456789" :: String))) majorDirs+ concat <$> mapM (processMajor ltsDir) sortedMajors+ where+ processMajor dir majorStr = do+ case reads majorStr of+ [(major, "")] -> do+ let majorPath = dir </> majorStr+ minorFiles <- listDirectory majorPath+ let sortedMinors = sortOn (\s -> read (take (length s - 5) s) :: Int) $+ filter (\s -> takeExtension s == ".yaml") minorFiles+ mapM (processMinor majorPath major) sortedMinors+ _ -> return []+ processMinor dir major fname+ | takeExtension fname == ".yaml" = do+ let minorStr = take (length fname - 5) fname+ case reads minorStr of+ [(minor, "")] -> do+ ghc <- extractGHCVersion (dir </> fname)+ return (LTSVersion major minor, ghc)+ _ -> error $ "Invalid minor version format in " ++ fname +++ ": expected integer, got '" ++ minorStr ++ "'"+ | otherwise = error $ "Unexpected file in LTS directory: " ++ fname +++ " (expected .yaml extension)"++-- | Process nightly snapshots (structure: nightly/year/month/day.yaml)+processNightlySnapshots :: FilePath -> IO [(NightlyVersion, GHCVersion)]+processNightlySnapshots nightlyDir = do+ yearDirs <- listDirectory nightlyDir+ let sortedYears = sortOn (\s -> read s :: Int) $ filter (all (`elem` ("0123456789" :: String))) yearDirs+ concat <$> mapM (processYear nightlyDir) sortedYears+ where+ processYear dir yearStr = do+ case reads yearStr of+ [(year, "")] -> do+ let yearPath = dir </> yearStr+ monthDirs <- listDirectory yearPath+ let sortedMonths = sortOn (\s -> read s :: Int) $ filter (all (`elem` ("0123456789" :: String))) monthDirs+ months <- mapM (processMonth yearPath year) sortedMonths+ return $ concat months+ _ -> return []+ processMonth dir year monthStr = do+ case reads monthStr of+ [(month, "")] -> do+ let monthPath = dir </> monthStr+ dayFiles <- listDirectory monthPath+ let sortedDays = sortOn (\s -> read (take (length s - 5) s) :: Int) $+ filter (\s -> takeExtension s == ".yaml") dayFiles+ mapM (processDay monthPath year month) sortedDays+ _ -> return []+ processDay dir year month fname+ | takeExtension fname == ".yaml" = do+ case reads $ take (length fname - 5) fname of+ [(day, "")] -> do+ ghc <- extractGHCVersion (dir </> fname)+ return (NightlyVersion year month day, ghc)+ _ -> error $ "Invalid day in " ++ fname+ | otherwise = error $ "Unexpected file in nightly directory: " ++ fname +++ " (expected .yaml extension)"++-- | Extract GHC version from a snapshot YAML file+extractGHCVersion :: FilePath -> IO GHCVersion+extractGHCVersion file = do+ result <- Yaml.decodeFileEither file+ case result of+ Left err -> error $ "Failed to parse " ++ file ++ ": " ++ show err+ Right (Aeson.Object obj) ->+ -- Try new format first (nested under resolver)+ case Yaml.parseMaybe (.: "resolver") obj of+ Just (Aeson.Object resolverObj) ->+ case Yaml.parseMaybe (.: "compiler") resolverObj of+ Just (Aeson.String compiler) ->+ parseCompiler compiler+ _ -> error $ "No compiler field in resolver in " ++ file+ _ ->+ -- Try old format (compiler at top level)+ case Yaml.parseMaybe (.: "compiler") obj of+ Just (Aeson.String compiler) ->+ parseCompiler compiler+ _ -> error $ "No compiler field in " ++ file+ _ -> error $ "Invalid YAML in " ++ file+ where+ parseCompiler compiler =+ case parseGHCVersionText (T.drop 4 compiler) of+ Just ghc -> return ghc+ Nothing -> error $ "Invalid GHC version format in " ++ file ++ ": " ++ T.unpack compiler++-- | Write LTS CSV file+writeLTSCSV :: FilePath -> [(LTSVersion, GHCVersion)] -> IO ()+writeLTSCSV path entries = do+ let sorted = sortBy (comparing fst) entries+ let lines = map formatLTSEntry sorted+ TIO.writeFile path $ T.unlines lines+ where+ formatLTSEntry (LTSVersion maj min, ghc) =+ T.pack (show maj) <> "." <> T.pack (show min) <> "," <> formatGHCVersion ghc++-- | Write nightly CSV file+writeNightlyCSV :: FilePath -> [(NightlyVersion, GHCVersion)] -> IO ()+writeNightlyCSV path entries = do+ let sorted = sortBy (comparing fst) entries+ let lines = map formatNightlyEntry sorted+ TIO.writeFile path $ T.unlines lines+ where+ formatNightlyEntry (nightly, ghc) =+ formatNightlyVersion nightly <> "," <> formatGHCVersion ghc++-- | Generate GHC version map from LTS and nightly maps+generateGHCMap :: [(LTSVersion, GHCVersion)] -> [(NightlyVersion, GHCVersion)] -> Map GHCVersion Snapshot+generateGHCMap ltsEntries nightlyEntries =+ let ltsMap = foldr insertLTS Map.empty ltsEntries+ nightlyMap = foldr insertNightly Map.empty nightlyEntries+ in Map.union ltsMap nightlyMap+ where+ insertLTS (lts, ghc) m =+ Map.insertWith (\_ old -> old) ghc (LTS lts) m+ insertNightly (nightly, ghc) m =+ Map.insertWith (\_ old -> old) ghc (Nightly nightly) m++-- | Write GHC CSV file+writeGHCCSV :: FilePath -> Map GHCVersion Snapshot -> IO ()+writeGHCCSV path ghcMap = do+ let sorted = sortBy (comparing fst) $ Map.toList ghcMap+ let lines = map formatGHCEntry sorted+ TIO.writeFile path $ T.unlines lines+ where+ formatGHCEntry (ghc, LTS (LTSVersion maj min)) =+ formatGHCVersion ghc <> ",lts-" <> T.pack (show maj) <> "." <> T.pack (show min)+ formatGHCEntry (ghc, Nightly nightly) =+ formatGHCVersion ghc <> ",nightly-" <> formatNightlyVersion nightly++-- | Load snapshot database from CSV files+loadSnapshotDB :: IO SnapshotDB+loadSnapshotDB = do+ stateDir <- getStateDir++ ltsMap <- readLTSCSV (stateDir </> "lts.csv")+ nightlyMap <- readNightlyCSV (stateDir </> "nightly.csv")+ ghcMap <- readGHCCSV (stateDir </> "ghc.csv")++ return $ SnapshotDB ltsMap nightlyMap ghcMap++-- | Read LTS CSV file+readLTSCSV :: FilePath -> IO (Map LTSVersion GHCVersion)+readLTSCSV path = do+ exists <- doesFileExist path+ if not exists+ then return Map.empty+ else do+ content <- TIO.readFile path+ let entries = map parseLTSLine $ T.lines content+ return $ Map.fromList $ concat entries+ where+ parseLTSLine line =+ case T.splitOn "," line of+ [ver, ghcText] ->+ case T.splitOn "." ver of+ [majStr, minStr] ->+ case (reads $ T.unpack majStr, reads $ T.unpack minStr, parseGHCVersionText ghcText) of+ ([(maj, "")], [(min, "")], Just ghc) ->+ [(LTSVersion maj min, ghc)]+ _ -> []+ _ -> []+ _ -> []++-- | Read nightly CSV file+readNightlyCSV :: FilePath -> IO (Map NightlyVersion GHCVersion)+readNightlyCSV path = do+ exists <- doesFileExist path+ if not exists+ then return Map.empty+ else do+ content <- TIO.readFile path+ let entries = map parseNightlyLine $ T.lines content+ return $ Map.fromList $ concat entries+ where+ parseNightlyLine line =+ case T.splitOn "," line of+ [dateText, ghcText] ->+ case (parseNightlyVersionText dateText, parseGHCVersionText ghcText) of+ (Just nightly, Just ghc) -> [(nightly, ghc)]+ _ -> []+ _ -> []++-- | Read GHC CSV file+readGHCCSV :: FilePath -> IO (Map GHCVersion Snapshot)+readGHCCSV path = do+ exists <- doesFileExist path+ if not exists+ then return Map.empty+ else do+ content <- TIO.readFile path+ let entries = map parseGHCLine $ T.lines content+ return $ Map.fromList $ concat entries+ where+ parseGHCLine line =+ case T.splitOn "," line of+ [ghcText, snap] ->+ case (parseGHCVersionText ghcText, parseSnapshot snap) of+ (Just ghc, Just s) -> [(ghc, s)]+ _ -> []+ _ -> []+ parseSnapshot snap+ | T.isPrefixOf "lts-" snap =+ case T.splitOn "." (T.drop 4 snap) of+ [majStr, minStr] ->+ case (reads $ T.unpack majStr, reads $ T.unpack minStr) of+ ([(maj, "")], [(min, "")]) -> Just $ LTS $ LTSVersion maj min+ _ -> Nothing+ _ -> Nothing+ | T.isPrefixOf "nightly-" snap =+ case parseNightlyVersionText (T.drop 8 snap) of+ Just nightly -> Just $ Nightly nightly+ Nothing -> Nothing+ | otherwise = Nothing
+ src/ColorOption.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings #-}++module ColorOption+ ( ColorWhen(..)+ , shouldUseColor+ ) where++import Types (ColorWhen(..))+import System.IO (hIsTerminalDevice, stdout)+import System.Environment (lookupEnv)++-- | Determine if color should be used based on the color option+shouldUseColor :: ColorWhen -> IO Bool+shouldUseColor Always = return True+shouldUseColor Never = return False+shouldUseColor Auto = do+ -- Respect NO_COLOR environment variable per https://no-color.org+ noColor <- lookupEnv "NO_COLOR"+ case noColor of+ Just _ -> return False -- NO_COLOR is set, disable colors+ Nothing -> hIsTerminalDevice stdout -- Check if stdout is a terminal
+ src/Commands.hs view
@@ -0,0 +1,213 @@+{-# LANGUAGE OverloadedStrings #-}++module Commands+ ( runCommand+ ) where++import Control.Monad (forM_, when)+import Data.List (sortBy)+import Data.Map.Strict qualified as Map+import Data.Ord (comparing)+import Data.Text (Text)+import Data.Text qualified as T+import System.Console.ANSI+import System.Directory (makeAbsolute)+import System.Exit (die)+import Text.Printf (printf)+import Types+import Config+import CSV+import Git+import Analysis+import StackYaml+import ColorOption+import License (licenseText)+import XDG qualified++-- | Run a command+runCommand :: Options -> IO ()+runCommand opts = do+ useColor <- shouldUseColor (optColor opts)+ case optCommand opts of+ Version -> printVersion+ NumericVersion -> putStrLn appVersion+ PrintLicense -> putStrLn licenseText+ Help -> do+ -- Manually render help text+ -- While not ideal, this ensures help works. The structure mirrors optparse-applicative's output.+ putStrLn $ "stacker version " ++ appVersion+ putStrLn ""+ putStrLn "Usage: stacker [COMMAND | (-V|--version) | --numeric-version |"+ putStrLn " --license | (-h|--help)] [--color WHEN]"+ putStrLn ""+ putStrLn " A tool to bump snapshots (resolvers) in stack*.yaml files"+ putStrLn ""+ putStrLn "Available commands:"+ putStrLn " bump [FILES...] Update FILES (or all stack*.yaml files in current directory if none specified)"+ putStrLn " Use --recursive/-r to search subdirectories"+ putStrLn " dry-run [FILES...] Show what would be updated by 'bump' (default)"+ putStrLn " Use --recursive/-r to search subdirectories"+ putStrLn " update Update stackage snapshots database"+ putStrLn " info Print GHC version to snapshot mapping"+ putStrLn " config Configure stacker"+ putStrLn ""+ putStrLn "Available options:"+ putStrLn " --color WHEN Use colored output (always, never, auto)"+ putStrLn " -r,--recursive Search subdirectories for stack*.yaml files"+ putStrLn " (commands bump and dry-run)"+ putStrLn ""+ putStrLn "Inessential commands:"+ putStrLn " version Print version information (also: -V, --version)"+ putStrLn " numeric-version Print version number (also: --numeric-version)"+ putStrLn " license Print license text (also: --license)"+ putStrLn " help Print this help (also: -h, --help)"+ putStrLn ""+ putStrLn "Option form of inessential commands:"+ putStrLn " -V,--version Print version information"+ putStrLn " --numeric-version Print version number"+ putStrLn " --license Print license text"+ putStrLn " -h,--help Print help"+ putStrLn ""+ putStrLn "For more information, see the README"+ Config configCmd -> runConfig configCmd -- Handle config first!+ cmd -> runEssentialCommand useColor cmd++-- | Run an essential command (requires CSV files)+runEssentialCommand :: Bool -> Command -> IO ()+runEssentialCommand useColor cmd = do+ -- Ensure CSV files exist (copy from data dir if needed)+ ensureCSVFiles++ case cmd of+ DryRun files recursive -> runDryRun useColor files recursive+ Bump files recursive -> runBump files recursive+ Update -> do+ -- Only for Update command, ensure repo exists and update it+ repoPath <- getRepoPath+ ensureRepo repoPath+ runUpdate repoPath+ Info -> do+ -- Info command shows the repo path+ repoPath <- getRepoPath+ runInfo repoPath+ _ -> return ()++-- | Print version information+printVersion :: IO ()+printVersion = do+ putStrLn $ appName ++ " version " ++ appVersion+ putStrLn copyright++-- | Print text with optional color formatting+withColor :: Bool -> [SGR] -> IO () -> IO ()+withColor useColor sgr action = do+ when useColor $ setSGR sgr+ action+ when useColor $ setSGR [Reset]++-- | Run dry-run command+runDryRun :: Bool -> [FilePath] -> Bool -> IO ()+runDryRun useColor files recursive = do+ -- Validate: recursive cannot be used with explicit files+ when (recursive && not (null files)) $+ die "Error: --recursive cannot be used with explicit file arguments"+ + db <- loadSnapshotDB+ actions <- analyzeStackYamls db files recursive++ -- Sort actions by filename+ let sortedActions = sortBy (comparing actionFile) actions+ + -- Calculate the maximum filename length for proper alignment (add 2 for padding)+ let maxFileLen = case sortedActions of+ [] -> 20+ acts -> max 20 (maximum (map (length . actionFile) acts) + 2)++ forM_ sortedActions $ \action -> do+ printActionWithWidth useColor maxFileLen action++-- | Print an action with a specified column width for filenames+printActionWithWidth :: Bool -> Int -> Action -> IO ()+printActionWithWidth useColor fileWidth action = do+ let file = actionFile action+ let oldSnap = actionOldSnapshot action+ let newSnap = actionNewSnapshot action+ let symlinkTarget = actionSymlinkTarget action++ -- Print with proper alignment (file padded to fileWidth chars, oldSnap to 25 chars)+ withColor useColor [SetConsoleIntensity BoldIntensity] $+ putStr $ padRight fileWidth file++ putStr $ padRight 25 (T.unpack oldSnap)++ case symlinkTarget of+ Just target -> do+ -- This is a symlink to another stack*.yaml file+ withColor useColor [SetColor Foreground Dull White] $ do+ putStr "= symlink to "+ putStr target+ Nothing ->+ case newSnap of+ Nothing -> do+ withColor useColor [SetColor Foreground Vivid Green] $+ putStr "✓ up to date"+ Just new -> do+ withColor useColor [SetColor Foreground Vivid Yellow] $ do+ putStr "→ bump to "+ putStr $ T.unpack new++ putStrLn ""++-- | Pad string to the right+padRight :: Int -> String -> String+padRight n s = take n (s ++ repeat ' ')++-- | Run bump command+runBump :: [FilePath] -> Bool -> IO ()+runBump files recursive = do+ -- Validate: recursive cannot be used with explicit files+ when (recursive && not (null files)) $+ die "Error: --recursive cannot be used with explicit file arguments"+ + db <- loadSnapshotDB+ actions <- analyzeStackYamls db files recursive+ mapM_ (applyAction True) actions++-- | Run update command+runUpdate :: FilePath -> IO ()+runUpdate repoPath = do+ putStrLn $ "Repository: " ++ repoPath+ updateRepo repoPath+ generateCSVs repoPath++-- | Run info command+runInfo :: FilePath -> IO ()+runInfo repoPath = do+ putStrLn $ "repo: " ++ repoPath+ db <- loadSnapshotDB+ putStrLn "snapshots:"++ let ghcEntries = Map.toAscList (dbGHC db)+ forM_ ghcEntries $ \(ghc, snapshot) -> do+ putStrLn $ " " ++ formatGHCVersionText ghc ++ ": " ++ T.unpack (formatSnapshotText snapshot)++-- | Format GHC version as text+formatGHCVersionText :: GHCVersion -> String+formatGHCVersionText (GHCVersion maj1 maj2 minV) =+ show maj1 ++ "." ++ show maj2 ++ "." ++ show minV++-- | Format snapshot as text+formatSnapshotText :: Snapshot -> Text+formatSnapshotText (LTS (LTSVersion major minor)) =+ "lts-" <> T.pack (show major) <> "." <> T.pack (show minor)+formatSnapshotText (Nightly (NightlyVersion year month day)) =+ T.pack $ "nightly-" ++ printf "%d-%02d-%02d" year month day++-- | Run config command+runConfig :: ConfigCmd -> IO ()+runConfig (SetRepo path) = do+ absPath <- makeAbsolute path+ saveConfig $ AppConfig (Just absPath)+ putStrLn $ "Repository path set to: " ++ absPath+ configFile <- XDG.getConfigFile+ putStrLn $ "Configuration saved to: " ++ configFile
+ src/Config.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-orphans #-}++module Config+ ( loadConfig+ , saveConfig+ , getRepoPath+ ) where++import Data.Yaml (decodeFileEither, encodeFile, FromJSON(..), ToJSON(..), (.:?), (.=), object, withObject)+import System.Directory (createDirectoryIfMissing, doesFileExist)+import System.FilePath (takeDirectory)+import Types (AppConfig(..))+import XDG (getConfigFile, getRepoDir)++instance FromJSON AppConfig where+ parseJSON = withObject "AppConfig" $ \v ->+ AppConfig <$> v .:? "repo"++instance ToJSON AppConfig where+ toJSON (AppConfig repo) = object ["repo" .= repo]++-- | Load configuration from the config file+loadConfig :: IO AppConfig+loadConfig = do+ configFile <- getConfigFile+ exists <- doesFileExist configFile+ if exists+ then do+ result <- decodeFileEither configFile+ case result of+ Left _ -> return $ AppConfig Nothing+ Right config -> return config+ else return $ AppConfig Nothing++-- | Save configuration to the config file+saveConfig :: AppConfig -> IO ()+saveConfig config = do+ configFile <- getConfigFile+ createDirectoryIfMissing True (takeDirectory configFile)+ encodeFile configFile config++-- | Get the repository path, either from config or default+getRepoPath :: IO FilePath+getRepoPath = do+ config <- loadConfig+ case configRepo config of+ Just repo -> return repo+ Nothing -> getRepoDir
+ src/Git.hs view
@@ -0,0 +1,56 @@+module Git+ ( ensureRepo+ , updateRepo+ , getCurrentBranch+ ) where++import System.Directory (doesDirectoryExist, createDirectoryIfMissing)+import System.FilePath (takeDirectory)+import System.Process (readProcess, callProcess)+import System.Exit (exitFailure)+import Control.Exception (catch, SomeException)+import Control.Monad (unless)++stackageSnapshotsUrl :: String+stackageSnapshotsUrl = "https://github.com/commercialhaskell/stackage-snapshots"++-- | Ensure the repository exists, cloning it if necessary+ensureRepo :: FilePath -> IO ()+ensureRepo repoPath = do+ exists <- doesDirectoryExist repoPath+ unless exists $ cloneRepo repoPath++-- | Clone the stackage-snapshots repository+cloneRepo :: FilePath -> IO ()+cloneRepo repoPath = do+ createDirectoryIfMissing True (takeDirectory repoPath)+ putStrLn $ "Downloading repo " ++ stackageSnapshotsUrl ++ " as shallow clone to " ++ repoPath ++ "..."+ callProcess "git" ["clone", "--depth", "1", stackageSnapshotsUrl, repoPath]+ putStrLn "Clone complete."++-- | Get the current branch name+getCurrentBranch :: FilePath -> IO String+getCurrentBranch repoPath = do+ trim <$> readProcess "git" ["-C", repoPath, "rev-parse", "--abbrev-ref", "HEAD"] ""++-- | Update the repository by pulling+updateRepo :: FilePath -> IO ()+updateRepo repoPath = do+ branch <- getCurrentBranch repoPath+ if branch /= "master"+ then do+ putStrLn $ "Error: Repository is on branch '" ++ branch ++ "', not 'master'."+ putStrLn "Cannot update repository when not on master branch."+ exitFailure+ else do+ putStrLn $ "Updating repository at " ++ repoPath ++ "..."+ catch+ (callProcess "git" ["-C", repoPath, "pull"])+ (\(e :: SomeException) -> do+ putStrLn $ "Warning: Failed to update repository: " ++ show e+ return ())+ putStrLn "Update complete."++-- | Trim whitespace from a string+trim :: String -> String+trim = reverse . dropWhile (`elem` " \t\n\r") . reverse . dropWhile (`elem` " \t\n\r")
+ src/License.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE TemplateHaskell #-}++module License (licenseText) where++import Data.FileEmbed (embedStringFile)++-- | BSD-3-Clause license text embedded from LICENSE file+licenseText :: String+licenseText = $(embedStringFile "LICENSE")
+ src/Options.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE OverloadedStrings #-}++module Options+ ( parseOptions+ , optionsParserInfo+ , Options(..)+ ) where++import Data.Char (toLower)+import Options.Applicative+import Types++-- | Parse command-line options+parseOptions :: IO Options+parseOptions = customExecParser (prefs showHelpOnEmpty) optionsParserInfo++-- | Parser info (exported for help rendering)+optionsParserInfo :: ParserInfo Options+optionsParserInfo = info (optionsParser <**> helper)+ ( fullDesc+ <> progDesc "A tool to bump snapshots (resolvers) in stack*.yaml files"+ <> header ("stacker version " ++ appVersion)+ <> footer "For more information, see the README" )++-- | Options parser+-- The parser tries subcommand parsing first (which includes color options),+-- then falls back to top-level options (for version/help flags and default).+-- This allows --color to be specified either before the subcommand+-- (e.g., "stacker --color=never dry-run") or within the subcommand+-- (e.g., "stacker dry-run --color=never file.yaml").+-- Precedence: Subcommand parsers take priority, so "stacker dry-run --color=never"+-- will be parsed by the subcommand parser, not the top-level parser.+optionsParser :: Parser Options+optionsParser = subcommandWithOptions <|> topLevelOptions+ where+ -- Helper to combine a command parser with the color option, creating an Options value+ withColorOption :: Parser Command -> Parser Options+ withColorOption cmdParser = Options <$> cmdParser <*> colorOption+ + -- Subcommand parser that includes color options for each command+ subcommandWithOptions = subparser+ ( command "bump" (info (withColorOption bumpParser) (progDesc "Update stack*.yaml files (optionally specify files, or use --recursive/-r to search subdirectories)"))+ <> command "dry-run" (info (withColorOption dryRunParser) (progDesc "Show what would be updated (default, optionally specify files, or use --recursive/-r to search subdirectories)"))+ <> command "update" (info (withColorOption (pure Update)) (progDesc "Update stackage snapshots database"))+ <> command "info" (info (withColorOption (pure Info)) (progDesc "Print GHC version to snapshot mapping"))+ <> command "config" (info (withColorOption configParser) (progDesc "Configure stacker"))+ <> command "version" (info (withColorOption (pure Version)) (progDesc "Print version information (also: -V, --version)"))+ <> command "numeric-version" (info (withColorOption (pure NumericVersion)) (progDesc "Print version number (also: --numeric-version)"))+ <> command "license" (info (withColorOption (pure PrintLicense)) (progDesc "Print license text (also: --license)"))+ <> command "help" (info (withColorOption (pure Help)) (progDesc "Print this help (also: -h, --help)"))+ )+ + -- Top-level parser for version/help flags and default command when no subcommand is specified+ topLevelOptions = Options+ <$> commandParserTopLevel+ <*> colorOption+ + -- Top-level command parser (for flags)+ commandParserTopLevel = + flag' Version (long "version" <> short 'V' <> help "Print version information")+ <|> flag' NumericVersion (long "numeric-version" <> help "Print version number")+ <|> flag' PrintLicense (long "license" <> help "Print license text")+ <|> flag' Help (long "help" <> short 'h' <> help "Print help")+ <|> (DryRun [] <$> recursiveOption)++-- | Config command parser+configParser :: Parser Command+configParser = Config <$> subparser+ ( command "repo" (info repoParser (progDesc "Set repository path"))+ )++-- | Repo config parser+repoParser :: Parser ConfigCmd+repoParser = SetRepo <$> argument str (metavar "PATH")++-- | Helper to parse file arguments with optional recursive flag+filesParser :: ([FilePath] -> Bool -> Command) -> Parser Command+filesParser cmd = cmd + <$> many (argument str (metavar "FILES..." <> action "file"))+ <*> recursiveOption++-- | Recursive option parser+recursiveOption :: Parser Bool+recursiveOption = switch+ ( long "recursive"+ <> short 'r'+ <> help "Search for stack*.yaml files recursively in all subdirectories" )++-- | Bump command parser+bumpParser :: Parser Command+bumpParser = filesParser Bump++-- | Dry-run command parser+dryRunParser :: Parser Command+dryRunParser = filesParser DryRun++-- | Color option parser+colorOption :: Parser ColorWhen+colorOption = option readColorWhen+ ( long "color"+ <> metavar "WHEN"+ <> value Auto+ <> help "Use colored output (always, never, auto)" )+ where+ readColorWhen = maybeReader $ \s ->+ case map toLower s of+ "always" -> Just Always+ "never" -> Just Never+ "auto" -> Just Auto+ _ -> Nothing
+ src/PathUtil.hs view
@@ -0,0 +1,98 @@+-- | Path utilities for cross-platform compatibility+-- +-- This module provides path utilities that use forward slash (/) as the +-- path separator on all platforms, including Windows. While Windows primarily+-- uses backslash (\), it also accepts forward slash for relative paths,+-- which is what this tool deals with.+--+-- This approach ensures consistent path handling and output across all platforms,+-- avoiding the path separator issues that can occur when using System.FilePath's+-- platform-specific path combinators.+module PathUtil+ ( (</>)+ , normalizeFilePath+ , splitPath+ , joinPath+ , collapseDots+ , takeDirectory+ , takeFileName+ , toForwardSlashes+ ) where++import Data.List (stripPrefix)++-- | Cross-platform path combination using forward slash+-- This ensures consistent behavior across Linux, macOS, and Windows+-- for relative paths (which is what this tool processes).+--+-- Note: This is specifically designed for combining relative path components.+-- For absolute paths or complex path manipulations, System.FilePath should be used.+(</>) :: FilePath -> FilePath -> FilePath+"" </> b = b+a </> "" = a+a </> b = a ++ "/" ++ b++-- | Normalize a file path by removing "./" prefix+-- This is used to ensure consistent output format where paths+-- don't have a leading "./" component.+normalizeFilePath :: FilePath -> FilePath+normalizeFilePath path =+ case stripPrefix "./" path of+ Just rest -> rest+ Nothing -> path++-- | Split a path into components using forward slash as separator+-- Works consistently across all platforms+splitPath :: FilePath -> [String]+splitPath "" = []+splitPath path = split path+ where+ split "" = []+ split s = case break (== '/') s of+ (comp, "") -> [comp]+ (comp, _:rest) -> comp : split rest++-- | Join path components using forward slash+-- Works consistently across all platforms+joinPath :: [String] -> FilePath+joinPath [] = ""+joinPath [x] = x+joinPath (x:xs) = x ++ "/" ++ joinPath xs++-- | Collapse ".." and "." components in a path+-- This normalizes paths like "a/b/../c" to "a/c"+collapseDots :: FilePath -> FilePath+collapseDots path = joinPath $ reverse $ foldl collapseDir [] (splitPath path)+ where+ collapseDir :: [String] -> String -> [String]+ collapseDir acc "." = acc+ collapseDir (prev:rest) ".." | prev /= ".." = rest+ collapseDir acc ".." = ".." : acc+ collapseDir acc dir = dir : acc++-- | Get the directory part of a file path+-- Uses forward slash as separator on all platforms+-- Examples: takeDirectory "a/b/c" = "a/b", takeDirectory "file.txt" = "."+takeDirectory :: FilePath -> FilePath+takeDirectory "" = "."+takeDirectory path =+ case reverse (filter (not . null) (splitPath path)) of+ [] -> "."+ [_] -> "."+ (_:dirs) -> joinPath (reverse dirs)++-- | Get the file name part of a file path+-- Uses forward slash as separator on all platforms+-- Examples: takeFileName "a/b/c.txt" = "c.txt", takeFileName "file.txt" = "file.txt"+takeFileName :: FilePath -> FilePath+takeFileName "" = ""+takeFileName path =+ case reverse (filter (not . null) (splitPath path)) of+ [] -> ""+ (name:_) -> name++-- | Convert backslashes to forward slashes+-- This is needed to normalize paths returned by Windows system calls+-- to use forward slashes consistently+toForwardSlashes :: FilePath -> FilePath+toForwardSlashes = map (\c -> if c == '\\' then '/' else c)
+ src/StackYaml.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE OverloadedStrings #-}++module StackYaml+ ( findStackYamlFiles+ , findStackYamlFilesRecursive+ , parseStackYaml+ , applyAction+ , isStackYaml+ , getSymlinkMap+ ) where++import Control.Monad (filterM, when)+import Data.List (isPrefixOf, isSuffixOf, sort)+import Data.Map.Strict qualified as Map+import Data.Maybe (catMaybes)+import Data.Text (Text)+import Data.Text qualified as T+import Data.Text.IO qualified as TIO+import System.Directory (listDirectory, doesFileExist, pathIsSymbolicLink, getSymbolicLinkTarget, doesDirectoryExist)+import PathUtil ((</>), normalizeFilePath, collapseDots, takeDirectory, takeFileName, toForwardSlashes)+import Types (Action(..))++-- | Check if a filename is a stack*.yaml file+isStackYaml :: FilePath -> Bool+isStackYaml name =+ let fname = takeFileName name+ in "stack" `isPrefixOf` fname && ".yaml" `isSuffixOf` fname++-- | Find all stack*.yaml files in the current directory+findStackYamlFiles :: IO [FilePath]+findStackYamlFiles = do+ files <- listDirectory "."+ let candidates = filter isStackYaml files+ sort <$> filterM doesFileExist candidates++-- | Find all stack*.yaml files recursively in all subdirectories+findStackYamlFilesRecursive :: IO [FilePath]+findStackYamlFilesRecursive = findStackYamlFilesInDir "."++-- | Helper function to find stack*.yaml files recursively in a directory+findStackYamlFilesInDir :: FilePath -> IO [FilePath]+findStackYamlFilesInDir dir = do+ entries <- listDirectory dir+ -- Use custom </> to ensure consistent path output with "/" separator on all platforms+ let fullPaths = map (dir </>) entries+ + -- Process files and directories separately+ files <- filterM doesFileExist fullPaths+ dirs <- filterM doesDirectoryExist fullPaths+ + -- Find stack*.yaml files in current directory, normalize to remove "./" prefix+ let stackYamls = map normalizeFilePath $ filter isStackYaml files+ + -- Recursively search subdirectories+ subResults <- mapM findStackYamlFilesInDir dirs+ + -- Combine and sort all results (all paths are already normalized)+ return $ sort (stackYamls ++ concat subResults)++-- | Get a map of symlinks to their targets (only for symlinks pointing to other stack*.yaml files in the list)+getSymlinkMap :: [FilePath] -> IO (Map.Map FilePath FilePath)+getSymlinkMap files = do+ -- Find symlinks in the list+ symlinks <- filterM pathIsSymbolicLink files++ -- For each symlink, check if it points to another file in the list+ results <- mapM checkSymlink symlinks++ return $ Map.fromList $ catMaybes results+ where+ checkSymlink :: FilePath -> IO (Maybe (FilePath, FilePath))+ checkSymlink link = do+ target <- getSymbolicLinkTarget link+ -- Convert backslashes to forward slashes (Windows compatibility)+ let normalizedTarget = toForwardSlashes target+ -- Resolve the target relative to the symlink's directory+ let symlinkDir = takeDirectory link+ let targetPath = symlinkDir </> normalizedTarget+ -- Normalize and collapse .. components using our custom functions+ let resolvedTarget = normalizeFilePath $ collapseDots targetPath+ -- Check if the target is in our file list+ if resolvedTarget `elem` files+ then return $ Just (link, resolvedTarget)+ else return Nothing++-- | Parse a stack.yaml file to extract the snapshot field+parseStackYaml :: FilePath -> IO (Maybe (Text, Bool, (Int, Int)))+parseStackYaml file = do+ content <- TIO.readFile file+ return $ findSnapshot (T.unpack content) 0+ where+ findSnapshot s pos =+ case findField "snapshot:" s pos of+ Just (value, start, end) -> Just (T.pack value, False, (start, end))+ Nothing ->+ case findField "resolver:" s pos of+ Just (value, start, end) -> Just (T.pack value, True, (start, end))+ Nothing -> Nothing++ findField :: String -> String -> Int -> Maybe (String, Int, Int)+ findField field s pos =+ findFieldHelper field s pos s++ findFieldHelper :: String -> String -> Int -> String -> Maybe (String, Int, Int)+ findFieldHelper _field _orig _pos [] = Nothing+ findFieldHelper field orig pos s@(_:cs)+ | field `isPrefixOf` s =+ let afterField = drop (length field) s+ trimmed = dropWhile (\c -> c `elem` (" \t" :: String)) afterField+ value = takeWhile (`notElem` ("\n\r" :: String)) trimmed+ valueStart = pos + (length orig - length s) + length field + (length afterField - length trimmed)+ valueEnd = valueStart + length value+ in if null value+ then Nothing+ else Just (value, valueStart, valueEnd)+ | otherwise = findFieldHelper field orig pos cs++-- | Apply an action to update a stack.yaml file+applyAction :: Bool -> Action -> IO ()+applyAction verbose action = do+ -- Skip symlinks that point to other stack*.yaml files in the list+ case actionSymlinkTarget action of+ Just _ -> return () -- Skip symlinks+ Nothing ->+ case actionNewSnapshot action of+ Nothing -> return () -- No update needed+ Just newSnap -> do+ when verbose $ putStrLn $ "Updating " ++ actionFile action+ content <- TIO.readFile (actionFile action)+ let (before, after) = splitAtSpan (actionSpan action) content+ let updated = before <> newSnap <> after+ TIO.writeFile (actionFile action) updated++-- | Split text at a character span+splitAtSpan :: (Int, Int) -> Text -> (Text, Text)+splitAtSpan (start, end) text =+ let before = T.take start text+ after = T.drop end text+ in (before, after)
+ src/Types.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE OverloadedStrings #-}++module Types where++import Data.Map.Strict (Map)+import Data.Text (Text)+import Data.Version (showVersion)+import GHC.Generics (Generic)+import Paths_stacker qualified as Paths++-- | LTS version (e.g., "24.23" for lts-24.23)+data LTSVersion = LTSVersion+ { ltsMajor :: Int+ , ltsMinor :: Int+ } deriving (Eq, Ord, Show, Generic)++-- | Nightly version (e.g., "2025-12-09" for nightly-2025-12-09)+data NightlyVersion = NightlyVersion+ { nightlyYear :: Int+ , nightlyMonth :: Int+ , nightlyDay :: Int+ } deriving (Eq, Ord, Show, Generic)++-- | GHC version (e.g., "9.10.1")+data GHCVersion = GHCVersion+ { ghcMajor1 :: Int+ , ghcMajor2 :: Int+ , ghcMinor :: Int+ } deriving (Eq, Ord, Show, Generic)++-- | Snapshot reference+data Snapshot+ = LTS LTSVersion+ | Nightly NightlyVersion+ deriving (Eq, Ord, Show, Generic)++-- | Action to take for a stack*.yaml file+data Action = Action+ { actionFile :: FilePath+ , actionOldSnapshot :: Text+ , actionNewSnapshot :: Maybe Text+ , actionIsResolver :: Bool -- True if 'resolver' field, False if 'snapshot'+ , actionSpan :: (Int, Int) -- Character span to replace+ , actionSymlinkTarget :: Maybe FilePath -- Just target if this is a symlink to another stack*.yaml in the list+ } deriving (Eq, Show, Generic)++-- | Database of snapshots+data SnapshotDB = SnapshotDB+ { dbLTS :: Map LTSVersion GHCVersion+ , dbNightly :: Map NightlyVersion GHCVersion+ , dbGHC :: Map GHCVersion Snapshot+ } deriving (Eq, Show, Generic)++-- | Configuration+data AppConfig = AppConfig+ { configRepo :: Maybe FilePath+ } deriving (Eq, Show, Generic)++-- | Command-line command+data Command+ = Bump [FilePath] Bool -- Optional list of files to bump, recursive flag+ | DryRun [FilePath] Bool -- Optional list of files to check, recursive flag+ | Config ConfigCmd+ | Update+ | Info+ | Version+ | NumericVersion+ | PrintLicense+ | Help+ deriving (Eq, Show)++-- | Config command+data ConfigCmd+ = SetRepo FilePath+ deriving (Eq, Show)++-- | Color option+data ColorWhen+ = Always+ | Never+ | Auto+ deriving (Eq, Show, Read)++-- | Options+data Options = Options+ { optCommand :: Command+ , optColor :: ColorWhen+ } deriving (Eq, Show)++-- | Application version+appVersion :: String+appVersion = showVersion Paths.version++-- | Application name+appName :: String+appName = "stacker"++-- | Copyright information+copyright :: String+copyright = "Copyright (c) 2025 Andreas Abel"
+ src/XDG.hs view
@@ -0,0 +1,30 @@+module XDG+ ( getStateDir+ , getConfigDir+ , getConfigFile+ , getRepoDir+ ) where++import System.Directory (getXdgDirectory, XdgDirectory(..))+import PathUtil ((</>))+import Types (appName)++-- | Get the XDG state directory for the application+getStateDir :: IO FilePath+getStateDir = getXdgDirectory XdgState appName++-- | Get the XDG config directory for the application+getConfigDir :: IO FilePath+getConfigDir = getXdgDirectory XdgConfig appName++-- | Get the path to the config file+getConfigFile :: IO FilePath+getConfigFile = do+ dir <- getConfigDir+ return $ dir </> "config.yaml"++-- | Get the default repository directory+getRepoDir :: IO FilePath+getRepoDir = do+ stateDir <- getStateDir+ return $ stateDir </> "stackage-snapshots"
+ stacker.cabal view
@@ -0,0 +1,126 @@+cabal-version: 3.0+name: stacker+version: 0.0.0.0+synopsis: Bump snapshots in stack.yaml files+description:+ A tool to bump snapshots (resolvers) in stack*.yaml files.+ It upgrades LTS snapshots to the latest version and converts+ nightlies to LTS when available.+license: BSD-3-Clause+license-file: LICENSE+author: Andreas Abel+maintainer: andreas.abel@gu.se+category: Development+build-type: Simple++tested-with:+ GHC == 9.4.8+ GHC == 9.6.7+ GHC == 9.8.4+ GHC == 9.10.3+ GHC == 9.12.4++extra-doc-files:+ CHANGELOG.md+ README.md++extra-source-files:+ test/tests/*.yaml+ test/golden/dry-run.golden+ test/golden/dry-run-files.golden+ test/golden/dry-run-recursive.golden+ test/golden/tests/*.yaml+ test/recursive/stack-9.6.yaml+ test/recursive/subdir1/stack-9.8.yaml+ test/recursive/subdir1/subdir2/stack-9.10.yaml+ test/recursive/other/stack.yaml++data-dir:+ data+data-files:+ ghc.csv+ lts.csv+ nightly.csv++source-repository head+ type: git+ location: https://github.com/andreasabel/stacker.git++common warnings+ ghc-options:+ -Wall+ -Wcompat+ -Wunused-packages+ -Wincomplete-patterns+ default-language:+ Haskell2010+ default-extensions:+ DeriveGeneric+ LambdaCase+ ImportQualifiedPost+ ScopedTypeVariables+ other-extensions:+ OverloadedStrings++library+ import: warnings+ hs-source-dirs: src+ exposed-modules:+ Options+ ColorOption+ License+ Config+ Git+ CSV+ StackYaml+ Analysis+ Commands+ XDG+ Types+ PathUtil+ other-modules:+ Paths_stacker+ autogen-modules:+ Paths_stacker+ build-depends:+ , base >= 4.17 && < 5+ , directory >= 1.3.7.0+ -- XdgState requires directory-1.3.7.0 or higher+ , filepath >= 1.4+ , process >= 1.6+ , text >= 2.0+ , yaml >= 0.11+ , aeson >= 2.0+ , containers >= 0.6+ , optparse-applicative >= 0.17+ , ansi-terminal >= 0.11+ , file-embed >= 0.0.15++executable stacker+ import: warnings+ hs-source-dirs: app+ main-is: Main.hs+ build-depends:+ , base >= 4.17 && < 5+ , stacker++test-suite stacker-test+ import: warnings+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ other-modules:+ TestDryRun+ TestBump+ build-depends:+ , base >= 4.17 && < 5+ , stacker+ , tasty >= 1.4+ , tasty-golden >= 2.3+ , directory >= 1.3.7.0+ , text >= 2.0+ , bytestring >= 0.11+ , temporary >= 1.3+ , process+ build-tool-depends:+ , stacker:stacker
+ test/Main.hs view
@@ -0,0 +1,16 @@+module Main where++import Test.Tasty ( defaultMain, testGroup, TestTree )+import TestDryRun ( dryRunTests )+import TestBump ( bumpTestsIO )++main :: IO ()+main = do+ bumpTests <- bumpTestsIO+ defaultMain $ tests bumpTests++tests :: [TestTree] -> TestTree+tests bumpTests = testGroup "stack-snapshots tests"+ [ testGroup "dry-run tests" dryRunTests+ , testGroup "bump tests" bumpTests+ ]
+ test/TestBump.hs view
@@ -0,0 +1,60 @@+module TestBump (bumpTestsIO) where++import Test.Tasty ( TestTree )+import Test.Tasty.Golden ( goldenVsFileDiff )+import System.Directory (copyFile, setCurrentDirectory, getCurrentDirectory)+import System.IO.Temp (createTempDirectory, getCanonicalTemporaryDirectory)+import Control.Monad (forM_)+import Data.Maybe (catMaybes)++-- Import from library+import StackYaml (findStackYamlFiles, getSymlinkMap, applyAction)+import Analysis (analyzeStackYaml)+import CSV (loadSnapshotDB, ensureCSVFiles)+import PathUtil ((</>))++-- | Generate bump tests - all files are bumped in one temp directory+bumpTestsIO :: IO [TestTree]+bumpTestsIO = do+ -- Ensure CSV files are available+ ensureCSVFiles++ -- Create a temp directory for this test run+ sysTempDir <- getCanonicalTemporaryDirectory+ tempDir <- createTempDirectory sysTempDir "stacker-test"++ -- Find all stack*.yaml files using library function+ cwd <- getCurrentDirectory+ setCurrentDirectory "test/tests"+ stackYamlFiles <- findStackYamlFiles+ setCurrentDirectory cwd++ -- Copy all files to temp directory+ forM_ stackYamlFiles $ \file -> do+ copyFile ("test/tests" </> file) (tempDir </> file)++ -- Run bump logic using library functions+ setCurrentDirectory tempDir++ -- Load snapshot database+ db <- loadSnapshotDB++ -- Get symlink map+ symlinkMap <- getSymlinkMap stackYamlFiles++ -- Get and run actions for each file+ actions <- catMaybes <$> mapM (analyzeStackYaml db symlinkMap) stackYamlFiles+ mapM_ (applyAction False) actions++ setCurrentDirectory cwd++ -- Create a golden test for each file+ return $ map (makeGoldenTest tempDir) stackYamlFiles+ where++ makeGoldenTest tempDir file = goldenVsFileDiff+ ("bump " ++ file)+ (\ref new -> ["diff", "-u", ref, new])+ ("test/golden/tests" </> file)+ (tempDir </> file)+ (return ()) -- Action is empty since bump already ran
+ test/TestDryRun.hs view
@@ -0,0 +1,53 @@+module TestDryRun (dryRunTests) where++import Test.Tasty+import Test.Tasty.Golden+import System.Process (readProcess)+import System.Directory (setCurrentDirectory, getCurrentDirectory)+import Data.ByteString.Lazy qualified as BSL+import Data.Text qualified as T+import Data.Text.Encoding qualified as TE+import Data.List (sort)++dryRunTests :: [TestTree]+dryRunTests =+ [ goldenVsString+ "dry-run output"+ "test/golden/dry-run.golden"+ runDryRunTest+ , goldenVsString+ "dry-run with specific files"+ "test/golden/dry-run-files.golden"+ runDryRunWithFilesTest+ , goldenVsString+ "dry-run with recursive flag"+ "test/golden/dry-run-recursive.golden"+ runDryRunRecursiveTest+ ]++runDryRunTest :: IO BSL.ByteString+runDryRunTest = runDryRun ["dry-run", "--color=never"]++runDryRunWithFilesTest :: IO BSL.ByteString+runDryRunWithFilesTest = runDryRun ["dry-run", "--color=never", "stack-9.6.yaml", "stack-9.8.yaml"]++runDryRunRecursiveTest :: IO BSL.ByteString+runDryRunRecursiveTest = do+ cwd <- getCurrentDirectory+ setCurrentDirectory "test/recursive"+ -- Test that just --recursive works (defaults to dry-run)+ output <- readProcess "stacker" ["--recursive", "--color=never"] ""+ setCurrentDirectory cwd+ -- Sort the output lines for consistent comparison+ let sortedLines = T.unlines $ sort $ T.lines $ T.pack output+ return $ BSL.fromStrict $ TE.encodeUtf8 sortedLines++-- | Helper to run dry-run with specified arguments+runDryRun :: [String] -> IO BSL.ByteString+runDryRun args = do+ cwd <- getCurrentDirectory+ setCurrentDirectory "test/tests"+ output <- readProcess "stacker" args ""+ setCurrentDirectory cwd+ -- Properly encode as UTF-8+ return $ BSL.fromStrict $ TE.encodeUtf8 $ T.pack output
+ test/golden/dry-run-files.golden view
@@ -0,0 +1,2 @@+stack-9.6.yaml nightly-2023-08-04 → bump to lts-22.44+stack-9.8.yaml lts-23.12 → bump to lts-23.28
+ test/golden/dry-run-recursive.golden view
@@ -0,0 +1,6 @@+other/stack.yaml lts-24.20 → bump to lts-24.36+stack-9.6.yaml lts-22.40 → bump to lts-22.44+stack.yaml lts-22.40 = symlink to stack-9.6.yaml+subdir1/stack-9.8.yaml lts-23.20 → bump to lts-23.28+subdir1/stack-other.yaml lts-24.20 = symlink to other/stack.yaml+subdir1/subdir2/stack-9.10.yaml nightly-2025-01-01 → bump to lts-24.36
+ test/golden/dry-run.golden view
@@ -0,0 +1,8 @@+stack-9.0.yaml nightly-2021-12-04 → bump to lts-19.33+stack-9.10.yaml nightly-2025-05-14 → bump to lts-24.36+stack-9.12.yaml nightly-2025-10-05 → bump to nightly-2026-04-07+stack-9.2.yaml lts-20.1 → bump to lts-20.26+stack-9.4.yaml lts-21.20 → bump to lts-21.25+stack-9.6.yaml nightly-2023-08-04 → bump to lts-22.44+stack-9.8.yaml lts-23.12 → bump to lts-23.28+stack.yaml nightly-2025-05-14 = symlink to stack-9.10.yaml
+ test/golden/tests/stack-9.0.yaml view
@@ -0,0 +1,9 @@+snapshot: lts-19.33+compiler: 9.0.2+compiler-check: match-exact++# Well, then...++extra-deps: [base-4.19]+# Doesn't make sense, I know...+
+ test/golden/tests/stack-9.10.yaml view
@@ -0,0 +1,6 @@+resolver: lts-24.36++packages:+ - lib/+ - backends/+ - executable/
+ test/golden/tests/stack-9.12.yaml view
@@ -0,0 +1,1 @@+resolver: nightly-2026-04-07
+ test/golden/tests/stack-9.2.yaml view
@@ -0,0 +1,2 @@+resolver: lts-20.26+#EOF
+ test/golden/tests/stack-9.4.yaml view
@@ -0,0 +1,15 @@+# This tests bumping of lts-21.20 to lts-21.25+# Andreas Abel, 2025-12-10++snapshot: lts-21.25++extra-deps:+- extra-1.18++flag:+ Agda:+ debug: True++extra-deps: [foo-9, bar-10]++# This is already the end.
+ test/golden/tests/stack-9.6.yaml view
@@ -0,0 +1,10 @@+# This tests bumping some old nightly to lts-22.44++# Andreas Abel, 2025-12-10++resolver: lts-22.44++extra-deps:+- kailash-9.1.1+- everest-0.0.0+# - other-1.2.3
+ test/golden/tests/stack-9.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-23.28
+ test/golden/tests/stack.yaml view
@@ -0,0 +1,6 @@+resolver: lts-24.36++packages:+ - lib/+ - backends/+ - executable/
+ test/recursive/other/stack.yaml view
@@ -0,0 +1,3 @@+# Test file for recursive search - other dir++resolver: lts-24.20
+ test/recursive/stack-9.6.yaml view
@@ -0,0 +1,3 @@+# Test file for recursive search - top level++resolver: lts-22.40
+ test/recursive/subdir1/stack-9.8.yaml view
@@ -0,0 +1,3 @@+# Test file for recursive search - subdir1++snapshot: lts-23.20
+ test/recursive/subdir1/subdir2/stack-9.10.yaml view
@@ -0,0 +1,3 @@+# Test file for recursive search - subdir2++snapshot: nightly-2025-01-01
+ test/tests/stack-9.0.yaml view
@@ -0,0 +1,9 @@+snapshot: nightly-2021-12-04+compiler: 9.0.2+compiler-check: match-exact++# Well, then...++extra-deps: [base-4.19]+# Doesn't make sense, I know...+
+ test/tests/stack-9.10.yaml view
@@ -0,0 +1,6 @@+resolver: nightly-2025-05-14++packages:+ - lib/+ - backends/+ - executable/
+ test/tests/stack-9.12.yaml view
@@ -0,0 +1,1 @@+resolver: nightly-2025-10-05
+ test/tests/stack-9.2.yaml view
@@ -0,0 +1,2 @@+resolver: lts-20.1+#EOF
+ test/tests/stack-9.4.yaml view
@@ -0,0 +1,15 @@+# This tests bumping of lts-21.20 to lts-21.25+# Andreas Abel, 2025-12-10++snapshot: lts-21.20++extra-deps:+- extra-1.18++flag:+ Agda:+ debug: True++extra-deps: [foo-9, bar-10]++# This is already the end.
+ test/tests/stack-9.6.yaml view
@@ -0,0 +1,10 @@+# This tests bumping some old nightly to lts-22.44++# Andreas Abel, 2025-12-10++resolver: nightly-2023-08-04++extra-deps:+- kailash-9.1.1+- everest-0.0.0+# - other-1.2.3
+ test/tests/stack-9.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-23.12
+ test/tests/stack.yaml view
@@ -0,0 +1,6 @@+resolver: nightly-2025-05-14++packages:+ - lib/+ - backends/+ - executable/