### ----------------------------------------------------
### -- Blin
### -- Licenses: AGPL-3.0-or-later
### -- Authors: Aleks-Daniel Jakimenko-Aleksejev <alex.jakimenko@gmail.com>
### -- File: lib/Blin/Processing.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 2
9e6c424e5f362702380009654e181de857d54c0
2474adb8f699498b6d83a70b91edefc47fd49784
c1d4a2d353defd22989a944981b36532bafd3134
c90ad2a00e06f091543918b5c265dfc851fb5b87
2da32b62793ec8fce4c507886f7686007aa0088b
9ad1cf2a65933f1ee4878d84bdf0970ce9d3aedf
2204a1ad3c16b3695dbe33bb8df9b2b1255c1a43
b64da2964cb1d8e38c001e1d3ca886363326ba0b
1211440c642d6486afccc42b2b376649b3956f23
10d1e1796b820b7c350c2d1c1554da6c761d48fe
917cfaf1274c3fca4e4e0a2e6781ea909d595f77
38960c61595cf51cda5c3e85350df0a8d2e50534
2a8b0ee4709484c4dae8c91e8ae2baeeb94edea2
edec947490e397d02070842dbac60fb5de449870
73abad03eb6f522a6cc42e9747ac9518cad7aea2
f38be9296371b420b8beafd6971aa97d72f041dc
7bf6c6f4818cfbd034e6d279d551f2b10a29384a
4ab552355943fb4d80a5aebea2b28b97b11f6118
55697fa4fcdcd796abfe57cd8f7a72d1f53dd2be
19dd95990001018e1d255ecc366dac0f625fb8bb
b52586b1981c84cbd500ca103f27d1c9a0b91d00
3de47eb04c76ceb3ea0d36bd6057ac1d65395af8
1b3b82d98198e6050f58927b0bb999cf20c86d11
ee7cd7070c2d37a9cab7ecfdfeda4fdef21c186c
2da8192d38f63bda709f9a72a9da2e3963435090
b956e062a73834dd80f246d0e2f5377e405b3883
6e37be5f751aee0a703f4d39aeee29078ea97d23
2ce954d3a731c46c88de90d46fefb8dd0e1a6348
91dd06ea9a2aafddd3db03618cca06640fea9c83
b48c4481bc33c1f9388ef011b01a5d1a641497ec
35ed92bc99307f48de720edc96a091c58b0aad82
82846b624ef3ec78ac848720fb85067947613420
7baae044def074b673fcecc0b75389b6e9cbf834
ab99511246c9fa8006b9d36d85639bfc222d0296
c2725e70917a87afe254d216fc4f78915ade2530
409b3d4de1534eb676536abb2beb5b5d674c6ee2
c848ac590f3282b85ca12c3d1dd9e3626f7aed20
fa77d97952a107b9680b2a258b0c4299873002b6
4a865106c4393dac7b9c0cb094a0fe323d9d1a3e
ee7671649c1972f7ba6a1ea61a9758a5671c2558
9eeaa6f267068dc5566b0cbd71c0ee55adddc294
5c1b5e6eab2721588ba515c5a4c7a47b79483f2c
9bbab7333074ad15082d5729f593131496c47954
3cc214bd344d33148a0a0102137097f5e4b511f5
424d19083afc3a1c39c0b21454eb2f14188863f8
936b5a5f233eb7b14ce8d268dfe9e690101ab243
2aabee80a5bcb7065c797da0b1abeb50b12f83aa
fadfeb2098669d6a7cf13d497d7876820cfca322
d9e12bc437181b330d058132c09fe7556d824077
639dbbd388f5cb341bb15149bf98d64d6f285c1a
0e88cd187f40811500e0ad0be0a6ecc0ef64bc68
63cae004f3aa7e89bdc94cf3db29830702ad693b
6caf58cb418f444c21afc6ff0d2c731c093c8fa6
fad44ff7f581dd1eb4bbb02513e19c4104920395
8905159d89d9ca316a33902da5128077d9a64fa3
825ffb154a0717e8745cca1015e169e480547f64
f94049c42125a7ac25f0d0ce3dcd957534305409
ef1c8f3ea435c81a39df8de525273fc5ac0387ad
4e47144e6122d7f820545d013eb33a69059e80cb
a80a5ae5f84a5edbb7861590d2296ed6fbbdd5db
1a6fa6e4de8922c0638ae05a0a96110a1909b29d
df853a0cd751b48e87c2dd04a7770a899e2fccda
0ec08b60de7bdef2a0205f00431dca0ac6af0cfb
1ef5a970ad6166ebc1a7baf49d9a753724d75ab8
bccb2c88e9ececb7b7bed2872a4ff51026fc8e21
79abb4e9deb4cfb86eaa44d05ee8118f55924320
bf346147007c1c54c2ca42236c71583d0829c68f
130a92b95ddd3ae6760718eaa9bad5c81d552048
f16c03d9af46ec2c85bea6d6e9b275bd5bc1dada
cf606ff24573b16decda58a0a5ef65d2d5d1d8d9
293a3bd48e2a0f1e476bb6cff08c8b5ce18bc2f2
01d8c166b1abb16fb76fae8750af7d1075ee6bef
1a79284ab2eee69a67521a338ae18850a62c662c
b175ba8eeed58b8ac83af158a0618bb79f4d3f8d
478a43a26015bcd267b167239f98ecf1322c4c9e
a9a72473fccc3e9d6b773378d545dc20cbcd51b6
81edd34dec01d05e1d6536cde9e8098ba14fa0bf
d5435e5d528b54d5f003926ad038723759fe774f
a309d67941188ac94e073198e77059dc5b83cb7a
5ada814d33f14ae3e26a9b3e44dcf99041defff9
a813f251ae7500c04afa583b2c01ffce23132997
2709d73632d8873bdc071526159c66c905748bb0
>;

#| Test some $module on some commit ($full-commit-hash)
sub test-module($full-commit-hash, $module,
                :$install=False,
                :$timeout!,
                :$tester!,
                :@always-unpacked, :$testable=True) is export {

    if $full-commit-hash eq @annoying-revisions.any {
        return %(output => ‘This revision is known to divert bisection into the wrong direction’,
                 exit-code => -1, signal => -1, time => -1,)
    }

    build-exists $full-commit-hash;
    my $install-path = $module.install-path;

    if not $install { # Install into a temp directory
        $install-path = tempdir :!unlink;
    }
    LEAVE if not $install {
        rmtree $_ with $install-path;
    }

    mkdir $install-path;

    my @deps = gather $module.deps: True;
    @deps .= unique;

    sub run-it($path) { # basically runs zef
        my $binary-path = $path.IO.add: ‘bin/perl6’;
        my %tweaked-env = %*ENV;
        %tweaked-env<PATH> = join ‘:’, $binary-path.parent, (%tweaked-env<PATH> // Empty);
        %tweaked-env<RAKULIB> = $install-path.IO.absolute; # dump any precomp files here
        %tweaked-env<RAKULIB> ~= ‘,’ ~ $tester.path.add: ‘/lib’;
        %tweaked-env<RAKULIB> = join ‘,’, %tweaked-env<RAKULIB>, # XXX looks fragile
                                   |@deps.map: { ‘inst#’ ~ .install-path.IO.absolute };
        %tweaked-env<ALL_TESTING>     = 1;
        %tweaked-env<NETWORK_TESTING> = 1;
        %tweaked-env<ONLINE_TESTING>  = 1;

        if $binary-path.IO !~~ :e {
            return %(output => ‘Commit exists, but a perl6 executable could not be built for it’,
                     exit-code => -1, signal => -1, time => -1,)
        }

        my $result;
        if $module.test-script { # fake module
            $result = get-output $binary-path,
                      ‘--’,
                      $module.test-script,
                      :stdin(‘’), :$timeout, ENV => %tweaked-env, :!chomp;
        } else { # normal module

            $result = get-output $binary-path,
                      ‘--’,
                      $tester.test-command( :$testable, :$install-path, module-name => $module.name ),
                      :stdin(‘’), :$timeout, ENV => %tweaked-env, :!chomp;
        }
        # XXX ↓ this workaround looks stupid
        $result<exit-code> = 1 if $result<output>.contains: $tester.output-failed;
        $result
    }

    if $full-commit-hash eq @always-unpacked.any {
        return run-it run-smth-build-path $full-commit-hash
    } else {
        return run-smth $full-commit-hash, &run-it
    }
}

#| Perform full processing of a single module.
#| This includes testing it on two revisions, deflapping,
#| and bisecting if needed.
sub process-module(Module $module,
                   :$deflap!,
                   :$start-point-full!, :$end-point-full!,
                   :$timeout!,
                   :$tester!,
                   :@always-unpacked,
                   :$testable=True,
                  ) is export {

    my &alright = -> $result {
        if $result<signal> ≠ 0 {
            # Huh, that means Zef itself segfaulted.
            return $module.done.keep: ZefFailure
        }
        $result<exit-code> == 0
    }

    my $OK = $testable ?? OK !! InstallableButUntested;

    note “🥞🥞🥞 Testing $module.name() (new)”; # (new revision, end point)
    my $new-result = test-module   $end-point-full, $module,
                                 :$timeout,
                                 :$tester,
                                 :@always-unpacked, :$testable,
                                 :install;
    $module.output-new = $new-result<output>;
    spurt $module.install-path.IO.add(‘log-new’), $module.output-new;
    return $module.done.keep: $OK if alright $new-result; # don't even test the old one

    note “🥞🥞🥞 Testing $module.name() (old)”; # (old revision, start point)
    my $old-result = test-module $start-point-full, $module,
                                 :$timeout,
                                 :$tester,
                                 :@always-unpacked, :$testable;
    $module.output-old = $old-result<output>;
    spurt $module.install-path.IO.add(‘log-old’), $module.output-old;

    return $module.done.keep: AlwaysFail unless alright $old-result;

    note “🥞🥞🥞 Testing $module.name() for flappiness”;
    for ^$deflap {
        # Be careful when touching this piece of code. If you break
        # it, all regressions will appear as flappers
        if not alright test-module $start-point-full, $module,
                                   :$timeout,
                                   :$tester,
                                   :@always-unpacked, :$testable {
            return $module.done.keep: Flapper
        }
        # TODO also test end point too and see if we can confirm that
        # it's not a flapper, if it is a flapping regression then
        # deflap on every bisect step?
    }

    note “🥞🥞🥞 Bisecting $module.name()”;
    my $repo-cwd = tempdir :!unlink;
    LEAVE rmtree $_ with $repo-cwd;
    run :out(Nil), :err(Nil), <git clone>, $CONFIG<projects><rakudo-moar><repo-origin>, $repo-cwd;

    my $bisect-start = get-output cwd => $repo-cwd, <git bisect start>;
    my $bisect-old   = get-output cwd => $repo-cwd, <git bisect old>, $start-point-full;
    if $bisect-start<exit-code> ≠ 0 or $bisect-old<exit-code> ≠ 0 {
        return $module.done.keep: BisectFailure
    }
    my $init-result = get-output cwd => $repo-cwd, <git bisect new>, $end-point-full;

    my &runner = -> :$current-commit, *%_ { test-module $current-commit, $module,
                                            :$timeout,
                                            :$tester,
                                            :@always-unpacked, :$testable
                                          };
    my $bisect-result = run-bisect &runner, :$repo-cwd,
                                   old-exit-code => $old-result<exit-code>;

    $module.bisected = $bisect-result<first-new-commit>;
    spurt $module.install-path.IO.add(‘bisect-log’), $bisect-result<log>;
    $module.done.keep: Fail
}


