Permalink
Browse files

Move some logic into Whateverable::Bisection

Also some refactoring in Bisectable.
  • Loading branch information...
AlexDaniel committed Sep 16, 2018
1 parent 62e5fe5 commit a7ddc02ac2c5e159bff41072fe2e8d376ca50fa6
Showing with 212 additions and 121 deletions.
  1. +2 −1 META6.json
  2. +154 −0 lib/Whateverable/Bisection.pm6
  3. +55 −119 xbin/Bisectable.p6
  4. +1 −1 xt/bisectable.t
@@ -1,7 +1,7 @@
{
"perl" : "6.c",
"name" : "Whateverable",
"version" : "1.0.1",
"version" : "1.0.2",
"description" : "Different IRC bots that operate on a bunch of prebuilt Rakudo versions",
"authors" : [
"Aleks-Daniel Jakimenko-Aleksejev <alex.jakimenko@gmail.com>",
@@ -10,6 +10,7 @@
"license" : "AGPL-3.0-or-later",
"provides" : {
"Whateverable" : "lib/Whateverable.pm6",
"Whateverable::Bisection" : "lib/Whateverable/Bisection.pm6",
"Whateverable::Bits" : "lib/Whateverable/Bits.pm6",
"Whateverable::Builds" : "lib/Whateverable/Builds.pm6",
"Whateverable::Config" : "lib/Whateverable/Config.pm6",
@@ -0,0 +1,154 @@
# Copyright © 2016-2018
# Aleks-Daniel Jakimenko-Aleksejev <alex.jakimenko@gmail.com>
# Copyright © 2016
# Daniel Green <ddgreen@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use Whateverable::Bits;
use Whateverable::Builds;
use Whateverable::Config;
use Whateverable::Output;
use Whateverable::Running;
unit module Whateverable::Bisection;
enum RevisionType is export <Old New Skip>;
#↓ Use this to bisect stuff across a bunch of builds
#↓ It can be used to bisect anything (not just Rakudo), it
#↓ all depends on what you provide in &runner and :$repo-cwd.
sub run-bisect(&runner = &standard-runner, #← Something to run on every revision
&decider = &adaptive-decider, #← Something to classify the result from &runner
:$skip-missing-builds = True, #← True to Skip if not build-exists
:$repo-cwd, #← Repo path where we will run `git bisect`
*%custom, #← Anything that may be needed in &runner or &decider
) is export {
my $status;
my $first-new-commit;
my @bisect-log = gather loop {
NEXT take »»»»» {- x 73}; # looks a bit nicer this way
my $current-commit = get-output(cwd => $repo-cwd,
<git rev-parse HEAD>)<output>;
take »»»»» Testing $current-commit;
if $skip-missing-builds and not build-exists $current-commit {
take »»»»» Build does not exist, skip this commit;
return Skip # skip non-existent builds
}
my $run-result = &runner( :$current-commit, |%custom);
my $revision-type = &decider($run-result, :$current-commit, |%custom);
my $result = get-output cwd => $repo-cwd,
<git bisect>, $revision-type.lc;
$status = $result<exit-code>;
if $result<output> ~~ /^^ (\S+) ‘ is the first new commit’ / {
$first-new-commit = ~$0;
last
}
last if $status ≠ 0;
LAST take $result<output>
}
my $log = @bisect-log.join(\n);
%( :$log, :$status, :$first-new-commit )
}
#↓ Runs a file containing a code snippet. Needs :$code-file custom arg.
sub standard-runner(:$current-commit!, :$code-file!, *%_) is export {
run-snippet $current-commit, $code-file
}
#↓ Takes an output of run-snippet or get-output and uses it to decide
#↓ what to do. You must provide exactly one named
#↓ argument ($old-exit-code, $old-exit-signal, $old-output).
#↓ Generally it considers any deviation from $old-* to be the New
#↓ behavior, so effectively it finds the first change. Whether
#↓ that change is good or not is left for user discretion, here we
#↓ just work with Old / New / Skip concepts.
sub adaptive-decider($result,
:$current-commit,
:$old-exit-code,
:$old-exit-signal,
:$old-output,
*%_) is export {
if $result<exit-code> < 0 { # TODO use something different. … like what?
take »»»»» Cannot test this commit. Reason: $result<output>;
take »»»»» Therefore, skipping this revision;
return Skip # skip failed builds
}
take »»»»» Script output:;
my $short-output = shorten $result<output>, $CONFIG<bisectable><trim-chars>;
take $short-output;
if $short-output ne $result<output> {
take »»»»» (output was trimmed because it is too large)
}
take »»»»» Script exit code: $result<exit-code>;
take »»»»» Script exit signal: {signal-to-text $result<signal>}
if $result<signal>;
if $result<exit-code> == 125 {
take »»»»» Exit code 125 means “skip”;
take Therefore, skipping this revision as you requested;
return Skip # somebody did “exit 125” in their code on purpose
}
# compare signals
with $old-exit-signal {
take »»»»» Bisecting by exit signal;
take »»»»» Current exit signal is {signal-to-text $result<signal>},
~ exit signal on “old” revision is {signal-to-text $old-exit-signal};
if $old-exit-signal ≠ 0 {
take »»»»» Note that on “old” revision exit signal is normally
~ {signal-to-text 0}, you are probably trying
~ to find when something was fixed
}
take »»»»» If exit signal is not the same as on “old” revision,
~ this revision will be marked as “new”;
my $revision-type = $result<signal> == $old-exit-signal ?? Old !! New;
take »»»»» Therefore, marking this revision as “{$revision-type.lc}”;
return $revision-type
}
# compare exit code (typically like a normal 「git bisect run …」)
with $old-exit-code {
take »»»»» Bisecting by exit code;
take »»»»» Current exit code is $result<exit-code>,
~ exit code on “old” revision is $old-exit-code;
if $old-exit-code ≠ 0 {
take »»»»» Note that on “old” revision exit code is normally 0,
~ you are probably trying to find when something was fixed
}
take »»»»» If exit code is not the same as on “old” revision,
~ this revision will be marked as “new”;
my $revision-type = $result<exit-code> == $old-exit-code ?? Old !! New;
take »»»»» Therefore, marking this revision as “{$revision-type.lc}”;
return $revision-type
}
# compare the output
with $old-output {
take »»»»» Bisecting by output;
take »»»»» Output on “old” revision is:;
take $old-output;
my $revision-type = $result<output> eq $old-output ?? Old !! New;
take »»»»» The output is {$revision-type == Old
?? identical !! different};
take »»»»» Therefore, marking this revision as “{$revision-type.lc}”;
return $revision-type
}
}
Oops, something went wrong.

0 comments on commit a7ddc02

Please sign in to comment.