diff --git a/appveyor.yml b/appveyor.yml index 5d6fdc5..676c4fc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,19 +1,16 @@ +--- cache: -- '%APPDATA%\cabal' -- '%APPDATA%\ghc' + - '%APPDATA%\cabal' + - '%APPDATA%\ghc' install: -- choco install ghc --version 8.2.2 -- refreshenv + - choco install ghc --version 8.2.2 + - refreshenv build_script: -- cabal update -- cabal install alex happy -- cabal install --enable-tests --enable-benchmarks --disable-documentation --only-dependencies + - cabal update + - cabal install alex happy + - cabal install --enable-tests --enable-benchmarks --disable-documentation --only-dependencies test_script: -- cabal test - -branches: - only: - - master + - cabal test diff --git a/stack.yaml b/stack.yaml index c254d76..f34e73b 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,55 +1,56 @@ +--- packages: [.] resolver: lts-6.27 extra-deps: -- HUnit-1.6.0.0 -- QuickCheck-2.11.3 -- aeson-1.4.0.0 -- aeson-compat-0.3.8 -- attoparsec-0.13.2.2 -- attoparsec-iso8601-1.0.0.0 -- base-compat-0.10.4 -- base-orphans-0.5.4 -- bifunctors-5.5.3 -- binary-orphans-0.1.8.0 -- bsb-http-chunked-0.0.0.2 -- bytestring-builder-0.10.8.1.0 -- cabal-doctest-1.0.6 -- case-insensitive-1.2.0.11 -- cpphs-1.20.8 -- exceptions-0.8.3 -- fast-logger-2.4.11 -- github-0.19 -- hspec-2.5.5 -- hspec-core-2.5.5 -- hspec-discover-2.5.5 -- hspec-expectations-0.8.2 -- http-api-data-0.3.8.1 -- http-media-0.7.1.2 -- http-types-0.12.1 -- mmorph-1.1.2 -- natural-transformation-0.4 -- network-2.7.0.2 -- parsec-3.1.13.0 -- quickcheck-io-0.2.0 -- resourcet-1.1.11 -- safe-0.3.17 -- semigroupoids-5.2.1 -- semigroups-0.18.5 -- servant-0.13.0.1 -- servant-server-0.13.0.1 -- singleton-bool-0.1.4 -- split-0.2.3.3 -- string-conversions-0.4.0.1 -- tagged-0.8.6 -- text-1.2.3.0 -- th-abstraction-0.2.8.0 -- transformers-compat-0.5.1.4 -- unix-compat-0.5.0.1 -- unix-time-0.3.8 -- unliftio-core-0.1.1.0 -- vault-0.3.1.1 -- vector-binary-instances-0.2.4 -- vector-instances-3.4 -- wai-extra-3.0.22.0 -- warp-3.2.23 -- word8-0.1.3 + - HUnit-1.6.0.0 + - QuickCheck-2.11.3 + - aeson-1.4.0.0 + - aeson-compat-0.3.8 + - attoparsec-0.13.2.2 + - attoparsec-iso8601-1.0.0.0 + - base-compat-0.10.4 + - base-orphans-0.5.4 + - bifunctors-5.5.3 + - binary-orphans-0.1.8.0 + - bsb-http-chunked-0.0.0.2 + - bytestring-builder-0.10.8.1.0 + - cabal-doctest-1.0.6 + - case-insensitive-1.2.0.11 + - cpphs-1.20.8 + - exceptions-0.8.3 + - fast-logger-2.4.11 + - github-0.19 + - hspec-2.5.5 + - hspec-core-2.5.5 + - hspec-discover-2.5.5 + - hspec-expectations-0.8.2 + - http-api-data-0.3.8.1 + - http-media-0.7.1.2 + - http-types-0.12.1 + - mmorph-1.1.2 + - natural-transformation-0.4 + - network-2.7.0.2 + - parsec-3.1.13.0 + - quickcheck-io-0.2.0 + - resourcet-1.1.11 + - safe-0.3.17 + - semigroupoids-5.2.1 + - semigroups-0.18.5 + - servant-0.13.0.1 + - servant-server-0.13.0.1 + - singleton-bool-0.1.4 + - split-0.2.3.3 + - string-conversions-0.4.0.1 + - tagged-0.8.6 + - text-1.2.3.0 + - th-abstraction-0.2.8.0 + - transformers-compat-0.5.1.4 + - unix-compat-0.5.0.1 + - unix-time-0.3.8 + - unliftio-core-0.1.1.0 + - vault-0.3.1.1 + - vector-binary-instances-0.2.4 + - vector-instances-3.4 + - wai-extra-3.0.22.0 + - warp-3.2.23 + - word8-0.1.3 diff --git a/templates/base.yml b/templates/base.yml deleted file mode 100644 index 9949bf3..0000000 --- a/templates/base.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Base template for all Travis jobs. The language variable can be overridden in -# derived templates or leaf files. No env, addons, script, or anything is -# defined in this template, because there is currently nothing that needs to be -# done on every single build. -language: generic - -# This probably shouldn't be overridden. -branches: - only: - - master - -# Add elements to the special __erase__ field to remove sections that are only -# used during generation and have no meaning to Travis. -__erase__: - - __erase__ diff --git a/templates/haskell.yml b/templates/haskell.yml deleted file mode 100644 index 1059ab6..0000000 --- a/templates/haskell.yml +++ /dev/null @@ -1,118 +0,0 @@ -# This is the Haskell base template. Every derived template in the end needs to -# be derived from 'base'. The inherited template is written without its .yml -# extension. -inherits: base - -# Every Haskell leaf file needs to specify the package name and version. This -# information is used in after_script to tell hpc-coveralls where to look for -# the coverage data. A value of '???' is treated as an error in expansions. This -# allows base packages to document the existence and requirement of certain -# parameters while still forcing leaf files to actually define them rather than -# having them be empty. -package: - name: '???' - version: '???' - -# We have two separate cabal/ghc directories. The 'build' cabal is the one used -# for the package being built as well as any user-provided cabal packages. The -# 'tools' cabal is used for hpc-coveralls, stylish-haskell, and hlint. We keep -# these separate because they have complicated dependencies that can (and -# sometimes do) interfere with the actual user package we want to test. In the -# future we may want to share the -tools directories across all repositories, -# because they are going to end up being identical. -cache: - directories: - - $HOME/.cabal-build - - $HOME/.cabal-tools - - $HOME/.ghc-build - - $HOME/.ghc-tools - -# This is not used by Travis, but instead the values can be used in other parts -# of the configuration. We can't use environment variables in addons for -# instance, so to deduplicate the numbers and allow derived templates to -# override this value in a single place, we use dynamically scoped %% variable -# expansions. -haskell: - cabal: 1.18 - ghc: 7.8.4 - # Leaf files can specify extra packages (like semdoc or pandoc) to be - # installed in the same cabal as their package dependencies. In expansions, - # arrays of strings are joined with a space. E.g. [semdoc, pandoc] will end up - # as "semdoc pandoc" in a %haskell.packages% expansion. - packages: [] - # Some tools may need to be installed in the tools cabal. They can be - # specified here. - tools: [] - -env: CABALVER=%haskell.cabal% GHCVER=%haskell.ghc% -addons: - apt: - sources: - - hvr-ghc - packages: - - alex-3.1.7 - - happy-1.19.5 - - cabal-install-%haskell.cabal% - - ghc-%haskell.ghc% - -# The install, script, after_script, and other shell script listings have a -# 'before' and 'after' value. This tells the generator whether to prepend or -# append that snippet to the inherited snippet. -install: - after: - # We want both .cabal directories on the path, but the currently active one - # should have precedence. After that, the build cabal has precedence and - # then the tools one. - - export PATH=$HOME/.cabal/bin:$PATH - - export PATH=$HOME/.cabal-build/bin:$PATH - - export PATH=$HOME/.cabal-tools/bin:$PATH - # Put ghc, cabal, alex, and happy on the path. - - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/alex/3.1.7/bin:/opt/happy/1.19.5/bin:$PATH - # Get old cabal out of the way. - - rm -rf $HOME/.cabal $HOME/.ghc - # Update tools cabal. - - mkdir -p $HOME/.cabal-tools $HOME/.ghc-tools - - rm -f $HOME/.cabal && ln -s $HOME/.cabal-tools $HOME/.cabal - - rm -f $HOME/.ghc && ln -s $HOME/.ghc-tools $HOME/.ghc - - cabal update - # Update build cabal. - - mkdir -p $HOME/.cabal-build $HOME/.ghc-build - - rm -f $HOME/.cabal && ln -s $HOME/.cabal-build $HOME/.cabal - - rm -f $HOME/.ghc && ln -s $HOME/.ghc-build $HOME/.ghc - - cabal update - -script: - after: - # Install common tools separately in the tools directory, because they have - # incompatible dependencies. - - rm -f $HOME/.cabal && ln -s $HOME/.cabal-tools $HOME/.cabal - - rm -f $HOME/.ghc && ln -s $HOME/.ghc-tools $HOME/.ghc - - cabal install hpc-coveralls stylish-haskell hlint yaml-0.8.27 aeson-0.9.0.1 %haskell.tools% - - curl https://raw.githubusercontent.com/TokTok/toktok-stack/master/tools/stylish-haskell-lhs -o $HOME/.cabal/bin/stylish-haskell-lhs - - chmod +x $HOME/.cabal/bin/stylish-haskell-lhs - # Do the style checks. - - hlint . - - stylish-haskell-lhs -i . - # Check that stylish-haskell had no effect. - - git diff --exit-code - # Install package dependencies in the build cabal. - - rm -f $HOME/.cabal && ln -s $HOME/.cabal-build $HOME/.cabal - - rm -f $HOME/.ghc && ln -s $HOME/.ghc-build $HOME/.ghc - - cabal install --enable-tests --enable-benchmarks --only-dependencies ./ %haskell.packages% - - if [ -n "%haskell.packages%" ]; then cabal install %haskell.packages%; fi - # Now to the actual build. - - cabal configure --enable-tests --enable-benchmarks --enable-library-coverage - - travis_wait cabal test - - cabal check - -after_script: - after: - # hpc-coveralls is in the tools cabal. - - rm -f $HOME/.cabal && ln -s $HOME/.cabal-tools $HOME/.cabal - - rm -f $HOME/.ghc && ln -s $HOME/.ghc-tools $HOME/.ghc - - hpc-coveralls %package.name%-%package.version% - -# Erase fields only used by the Haskell template. -__erase__: - - haskell - - package diff --git a/tools/expand-yaml b/tools/expand-yaml deleted file mode 100755 index 407a4b4..0000000 --- a/tools/expand-yaml +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings FATAL => 'all'; -use utf8; - -use Cwd 'abs_path'; -use Data::Dumper; -use Dir::Self; -use File::Basename; -use YAML::XS qw/LoadFile DumpFile/; - -local $Data::Dumper::Indent = 1; -local $Data::Dumper::Sortkeys = 1; -local $Data::Dumper::Terse = 1; - -my $TEMPLATES = __DIR__ . '/../templates'; - -# Recursively load files and replace 'inherits' fields with the actual parsed -# file contents. -sub load_file { - my ($input) = @_; - return unless -f $input; - my $leaf = LoadFile $input; - - if ($leaf->{inherits}) { - $leaf->{inherits} = do { - my $local_dir = dirname $input; - 0 or load_file("$local_dir/$leaf->{inherits}.yml") - or load_file("$TEMPLATES/$leaf->{inherits}.yml"); - }; - } - - $leaf -} - -sub check_type { - my ($name, $a, $b) = @_; - if (defined $a and defined $b) { - my $aref = ref $a; - my $bref = ref $b; - if ($aref ne $bref) { - die "type of $name is '$aref' in derived data but '$bref' in inherited"; - } - } -} - -# Recursively merge two data structures. The two parameters are expected to be -# hash references. -sub recursive_merge { - my ($dst, $src) = @_; - check_type 'value', $dst, $src; - for my $field (sort keys %$src) { - check_type $field, $dst->{$field}, $src->{$field}; - - for (ref $src->{$field}) { - if ($_ eq 'HASH') { - if (exists $dst->{$field}) { - recursive_merge($dst->{$field}, $src->{$field}); - } else { - $dst->{$field} = $src->{$field}; - } - } elsif ($_ eq 'ARRAY') { - if ($field eq 'after') { - unshift @{ $dst->{$field} }, @{ $src->{$field} }; - } else { - push @{ $dst->{$field} }, @{ $src->{$field} }; - } - } elsif ($_ eq '') { - $dst->{$field} //= $src->{$field}; - } else { - die "unhandled ref type: $_"; - } - } - } -} - -# Merge the inherited templates into one. This starts from the leaf and fills in -# all fields that are not yet set. Also, 'before' and 'after' fields are -# concatenated such that the inherited 'before' comes after the derived one, and -# the inherited 'after' comes before the derived one. -# -# Inheritance is resolved depth-first. I.e. the deepest level is merged first, -# and the leaf is merged last. -sub process_inherits { - my ($data) = @_; - - if (my $parent = delete $data->{inherits}) { - process_inherits($parent); - - # At this point, $parent is fully merged. - recursive_merge($data, $parent); - } -} - -sub process_expansions { - my ($data, $cur) = @_; - - for (ref $cur) { - if ($_ eq 'HASH') { - for my $k (keys %$cur) { - $cur->{$k} = process_expansions($data, $cur->{$k}); - } - } elsif ($_ eq 'ARRAY') { - for my $i (0 .. $#$cur) { - $cur->[$i] = process_expansions($data, $cur->[$i]); - } - } elsif ($_ eq '') { - if (my @expansions = $cur =~ /%([^%]+)%/g) { - # Perform lookups and collect actual values. - @expansions = map { - my @path = split /\./; - my $v = $data; - for my $p (@path) { - die "could not resolve '$_'" - unless exists $v->{$p}; - $v = $v->{$p}; - die "variable '$_' has value '???', which means it must be overridden" - if $v eq '???'; - } - - if (ref $v eq 'HASH') { - die "'$_' expanded to an object and can't be interpolated" - } elsif (ref $v eq 'ARRAY') { - join ' ', @$v - } elsif (ref $v eq '') { - $v - } else { - die "'$_' expanded to an object of unknown type: " . ref $v - } - } @expansions; - - # Perform the actual text replacements. - for my $text (@expansions) { - $cur =~ s/%([^%]+)%/$text/; - } - - # Strip resulting text of leading and trailing whitespace. - $cur =~ s/^\s+//; - $cur =~ s/\s+$//; - } - } else { - die "unhandled type: '$_'" - } - } - - $cur -} - -sub process_before_after { - my ($data) = @_; - - for my $k (keys %$data) { - my $v = $data->{$k}; - if (ref $v eq 'HASH' and (exists $v->{before} or exists $v->{after})) { - $data->{$k} = [ - @{ $v->{before} || [] }, - @{ $v->{after} || [] }, - ]; - } - } -} - -sub process_erase { - my ($data) = @_; - - for my $k (@{ $data->{__erase__} }) { - delete $data->{$k}; - } -} - -my ($input, $output) = @ARGV; -$input and $output or die "Usage: expand-yaml "; - -my $data = load_file (abs_path $input); -process_inherits $data; -process_expansions $data, $data; -process_before_after $data; -process_erase $data; - -open my $outfh, '>', $output or die "Cannot open $output for writing: $!"; -print $outfh "# DO NOT EDIT: This file was generated using the following command:\n"; -print $outfh "# $0 @ARGV\n"; -DumpFile $outfh, $data;