15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#!/usr/bin/perl -w 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# are met: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 1. Redistributions of source code must retain the above copyright 10fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch# notice, this list of conditions and the following disclaimer. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 2. Redistributions in binary form must reproduce the above copyright 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer in the 13fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch# documentation and/or other materials provided with the distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# its contributors may be used to endorse or promote products derived 16fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch# from this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# This script attempts to find the point at which a regression (or progression) 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# of behavior occurred by searching WebKit nightly builds. 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# To override the location where the nightly builds are downloaded or the path 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# to the Safari web browser, create a ~/.bisect-buildsrc file with one or more of 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# the following lines (use "~/" to specify a path from your home directory): 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# $branch = "branch-name"; 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# $nightlyDownloadDirectory = "~/path/to/nightly/downloads"; 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# $safariPath = "/path/to/Safari.app"; 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use strict; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Basename; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Path; 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Spec; 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Temp qw(tempfile); 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use FindBin; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use Getopt::Long; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use Time::HiRes qw(usleep); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use lib $FindBin::Bin; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use webkitdirs qw(safariPathFromSafariBundle); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub createTempFile($); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub downloadNightly($$$); 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findMacOSXVersion(); 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findNearestNightlyIndex(\@$$); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findSafariVersion($); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub loadSettings(); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub makeNightlyList($$$$); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub max($$) { return $_[0] > $_[1] ? $_[0] : $_[1]; } 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub mountAndRunNightly($$$$); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub parseRevisions($$;$); 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub printStatus($$$); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub printTracLink($$); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub promptForTest($); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)loadSettings(); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my %validBranches = map { $_ => 1 } qw(feature-branch trunk); 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $branch = $Settings::branch; 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $nightlyDownloadDirectory = $Settings::nightlyDownloadDirectory; 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $safariPath = $Settings::safariPath; 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my @nightlies; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $isProgression; 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $localOnly; 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my @revisions; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $sanityCheck; 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $showHelp; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $testURL; 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Fix up -r switches in @ARGV 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@ARGV = map { /^(-r)(.+)$/ ? ($1, $2) : $_ } @ARGV; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $result = GetOptions( 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "b|branch=s" => \$branch, 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "d|download-directory=s" => \$nightlyDownloadDirectory, 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "h|help" => \$showHelp, 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "l|local!" => \$localOnly, 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "p|progression!" => \$isProgression, 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "r|revisions=s" => \&parseRevisions, 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "safari-path=s" => \$safariPath, 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "s|sanity-check!" => \$sanityCheck, 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$testURL = shift @ARGV; 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$branch = "feature-branch" if $branch eq "feature"; 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (!exists $validBranches{$branch}) { 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR "ERROR: Invalid branch '$branch'\n"; 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $showHelp = 1; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (!$result || $showHelp || scalar(@ARGV) > 0) { 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR "Search WebKit nightly builds for changes in behavior.\n"; 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR "Usage: " . basename($0) . " [options] [url]\n"; 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR <<END; 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-b|--branch name] name of the nightly build branch (default: trunk) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-d|--download-directory dir] nightly build download directory (default: ~/Library/Caches/WebKit-Nightlies) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-h|--help] show this help message 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-l|--local] only use local (already downloaded) nightlies 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-p|--progression] searching for a progression, not a regression 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-r|--revision M[:N]] specify starting (and optional ending) revisions to search 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [--safari-path path] path to Safari application bundle (default: /Applications/Safari.app) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) [-s|--sanity-check] verify both starting and ending revisions before bisecting 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)END 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) exit 1; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $nightlyWebSite = "http://nightly.webkit.org"; 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $nightlyBuildsURLBase = $nightlyWebSite . File::Spec->catdir("/builds", $branch, "mac"); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $nightlyFilesURLBase = $nightlyWebSite . File::Spec->catdir("/files", $branch, "mac"); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$nightlyDownloadDirectory = glob($nightlyDownloadDirectory) if $nightlyDownloadDirectory =~ /^~/; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$safariPath = glob($safariPath) if $safariPath =~ /^~/; 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$safariPath = safariPathFromSafariBundle($safariPath) if $safariPath =~ m#\.app/*#; 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$nightlyDownloadDirectory = File::Spec->catdir($nightlyDownloadDirectory, $branch); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (! -d $nightlyDownloadDirectory) { 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mkpath($nightlyDownloadDirectory, 0, 0755) || die "Could not create $nightlyDownloadDirectory: $!"; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@nightlies = makeNightlyList($localOnly, $nightlyDownloadDirectory, findMacOSXVersion(), findSafariVersion($safariPath)); 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $startIndex = $revisions[0] ? findNearestNightlyIndex(@nightlies, $revisions[0], 'ceil') : 0; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $endIndex = $revisions[1] ? findNearestNightlyIndex(@nightlies, $revisions[1], 'floor') : $#nightlies; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $tempFile = createTempFile($testURL); 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if ($sanityCheck) { 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $didReproduceBug; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf "\nChecking starting revision r%s...\n", 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $nightlies[$startIndex]->{rev}; 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) downloadNightly($nightlies[$startIndex]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mountAndRunNightly($nightlies[$startIndex]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $didReproduceBug = promptForTest($nightlies[$startIndex]->{rev}); 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $startIndex-- if $didReproduceBug < 0; 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while ($didReproduceBug < 0); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "ERROR: Bug reproduced in starting revision! Do you need to test an earlier revision or for a progression?" 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if $didReproduceBug && !$isProgression; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "ERROR: Bug not reproduced in starting revision! Do you need to test an earlier revision or for a regression?" 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if !$didReproduceBug && $isProgression; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf "\nChecking ending revision r%s...\n", 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $nightlies[$endIndex]->{rev}; 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) downloadNightly($nightlies[$endIndex]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mountAndRunNightly($nightlies[$endIndex]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $didReproduceBug = promptForTest($nightlies[$endIndex]->{rev}); 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $endIndex++ if $didReproduceBug < 0; 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while ($didReproduceBug < 0); 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "ERROR: Bug NOT reproduced in ending revision! Do you need to test a later revision or for a progression?" 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if !$didReproduceBug && !$isProgression; 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "ERROR: Bug reproduced in ending revision! Do you need to test a later revision or for a regression?" 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if $didReproduceBug && $isProgression; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)printStatus($nightlies[$startIndex]->{rev}, $nightlies[$endIndex]->{rev}, $isProgression); 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my %brokenRevisions = (); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)while (abs($endIndex - $startIndex) > 1) { 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $index = $startIndex + int(($endIndex - $startIndex) / 2); 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $didReproduceBug; 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (exists $nightlies[$index]) { 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $buildsLeft = max(max(0, $endIndex - $index - 1), max(0, $index - $startIndex - 1)); 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $plural = $buildsLeft == 1 ? "" : "s"; 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf "\nChecking revision r%s (%d build%s left to test after this)...\n", $nightlies[$index]->{rev}, $buildsLeft, $plural; 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) downloadNightly($nightlies[$index]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mountAndRunNightly($nightlies[$index]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $didReproduceBug = promptForTest($nightlies[$index]->{rev}); 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($didReproduceBug < 0) { 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $brokenRevisions{$nightlies[$index]->{rev}} = $nightlies[$index]->{file}; 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delete $nightlies[$index]; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $endIndex--; 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $index = $startIndex + int(($endIndex - $startIndex) / 2); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while ($didReproduceBug < 0); 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($didReproduceBug && !$isProgression || !$didReproduceBug && $isProgression) { 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $endIndex = $index; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $startIndex = $index; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "\nBroken revisions skipped: r" . join(", r", keys %brokenRevisions) . "\n" 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if scalar keys %brokenRevisions > 0; 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printStatus($nightlies[$startIndex]->{rev}, $nightlies[$endIndex]->{rev}, $isProgression); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)printTracLink($nightlies[$startIndex]->{rev}, $nightlies[$endIndex]->{rev}); 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unlink $tempFile if $tempFile; 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exit 0; 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub createTempFile($) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($url) = @_; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return undef if !$url; 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($fh, $tempFile) = tempfile( 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) basename($0) . "-XXXXXXXX", 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DIR => File::Spec->tmpdir(), 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SUFFIX => ".html", 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) UNLINK => 0, 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ); 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print $fh "<meta http-equiv=\"refresh\" content=\"0; $url\">\n"; 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close($fh); 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $tempFile; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub downloadNightly($$$) 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($filename, $urlBase, $directory) = @_; 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $path = File::Spec->catfile($directory, $filename); 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (! -f $path) { 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "Downloading $filename to $directory...\n"; 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) `curl -# -o '$path' '$urlBase/$filename'`; 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findMacOSXVersion() 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $version; 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open(SW_VERS, "-|", "/usr/bin/sw_vers") || die; 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (<SW_VERS>) { 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $version = $1 if /^ProductVersion:\s+([^\s]+)/; 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(SW_VERS); 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $version; 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findNearestNightlyIndex(\@$$) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($nightlies, $revision, $round) = @_; 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $lowIndex = 0; 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $highIndex = $#{$nightlies}; 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $highIndex if uc($revision) eq 'HEAD' || $revision >= $nightlies->[$highIndex]->{rev}; 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $lowIndex if $revision <= $nightlies->[$lowIndex]->{rev}; 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (abs($highIndex - $lowIndex) > 1) { 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $index = $lowIndex + int(($highIndex - $lowIndex) / 2); 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($revision < $nightlies->[$index]->{rev}) { 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $highIndex = $index; 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif ($revision > $nightlies->[$index]->{rev}) { 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $lowIndex = $index; 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $index; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ($round eq "floor") ? $lowIndex : $highIndex; 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub findSafariVersion($) 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($path) = @_; 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $versionPlist = File::Spec->catdir(dirname(dirname($path)), "version.plist"); 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $version; 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open(PLIST, "< $versionPlist") || die; 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (<PLIST>) { 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m#^\s*<key>CFBundleShortVersionString</key>#) { 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $version = <PLIST>; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $version =~ s#^\s*<string>([0-9.]+)[^<]*</string>\s*[\r\n]*#$1#; 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(PLIST); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $version; 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub loadSettings() 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) package Settings; 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) our $branch = "trunk"; 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) our $nightlyDownloadDirectory = File::Spec->catdir($ENV{HOME}, "Library/Caches/WebKit-Nightlies"); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) our $safariPath = "/Applications/Safari.app"; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $rcfile = File::Spec->catdir($ENV{HOME}, ".bisect-buildsrc"); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return if !-f $rcfile; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $result = do $rcfile; 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Could not parse $rcfile: $@" if $@; 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub makeNightlyList($$$$) 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($useLocalFiles, $localDirectory, $macOSXVersion, $safariVersion) = @_; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @files; 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($useLocalFiles) { 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opendir(DIR, $localDirectory) || die "$!"; 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) foreach my $file (readdir(DIR)) { 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($file =~ /^WebKit-SVN-r([0-9]+)\.dmg$/) { 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) push(@files, +{ rev => $1, file => $file }); 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closedir(DIR); 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open(NIGHTLIES, "curl -s $nightlyBuildsURLBase/all |") || die; 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (my $line = <NIGHTLIES>) { 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chomp $line; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($revision, $timestamp, $url) = split(/,/, $line); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $nightly = basename($url); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) push(@files, +{ rev => $revision, file => $nightly }); 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(NIGHTLIES); 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (eval "v$macOSXVersion" ge v10.5) { 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($safariVersion eq "4 Public Beta") { 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 39682 } @files; 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.2) { 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 37348 } @files; 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.1) { 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 29711 } @files; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.0) { 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 25124 } @files; 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v2.0) { 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 19594 } @files; 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Requires Safari 2.0 or newer"; 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$macOSXVersion" ge v10.4) { 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($safariVersion eq "4 Public Beta") { 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 39682 } @files; 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.2) { 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 37348 } @files; 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.1) { 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 29711 } @files; 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v3.0) { 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 19992 } @files; 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (eval "v$safariVersion" ge v2.0) { 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @files = grep { $_->{rev} >= 11976 } @files; 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Requires Safari 2.0 or newer"; 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Requires Mac OS X 10.4 (Tiger) or 10.5 (Leopard)"; 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $nightlycmp = sub { return $a->{rev} <=> $b->{rev}; }; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return sort $nightlycmp @files; 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub mountAndRunNightly($$$$) 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($filename, $directory, $safari, $tempFile) = @_; 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $mountPath = "/Volumes/WebKit"; 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $webkitApp = File::Spec->catfile($mountPath, "WebKit.app"); 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $diskImage = File::Spec->catfile($directory, $filename); 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $devNull = File::Spec->devnull(); 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $i = 0; 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (-e $mountPath) { 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $i++; 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) usleep 100 if $i > 1; 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) `hdiutil detach '$mountPath' 2> $devNull`; 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Could not unmount $diskImage at $mountPath" if $i > 100; 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Can't mount $diskImage: $mountPath already exists!" if -e $mountPath; 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "Mounting disk image and running WebKit...\n"; 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) `hdiutil attach '$diskImage'`; 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $i = 0; 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (! -e $webkitApp) { 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) usleep 100; 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $i++; 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Could not mount $diskImage at $mountPath" if $i > 100; 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $frameworkPath; 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (-d "/Volumes/WebKit/WebKit.app/Contents/Frameworks") { 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $osXVersion = join('.', (split(/\./, findMacOSXVersion()))[0..1]); 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $frameworkPath = "/Volumes/WebKit/WebKit.app/Contents/Frameworks/$osXVersion"; 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $frameworkPath = "/Volumes/WebKit/WebKit.app/Contents/Resources"; 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $tempFile ||= ""; 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) `DYLD_FRAMEWORK_PATH=$frameworkPath WEBKIT_UNSET_DYLD_FRAMEWORK_PATH=YES $safari $tempFile`; 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) `hdiutil detach '$mountPath' 2> $devNull`; 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub parseRevisions($$;$) 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($optionName, $value, $ignored) = @_; 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($value =~ /^r?([0-9]+|HEAD):?$/i) { 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) push(@revisions, $1); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Too many revision arguments specified" if scalar @revisions > 2; 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif ($value =~ /^r?([0-9]+):?r?([0-9]+|HEAD)$/i) { 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $revisions[0] = $1; 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $revisions[1] = $2; 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Unknown revision '$value': expected 'M' or 'M:N'"; 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub printStatus($$$) 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($startRevision, $endRevision, $isProgression) = @_; 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf "\n%s: r%s %s: r%s\n", 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $isProgression ? "Fails" : "Works", $startRevision, 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $isProgression ? "Works" : "Fails", $endRevision; 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub printTracLink($$) 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($startRevision, $endRevision) = @_; 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("http://trac.webkit.org/log/trunk/?rev=%s&stop_rev=%s\n", $endRevision, $startRevision + 1); 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub promptForTest($) 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($revision) = @_; 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "Did the bug reproduce in r$revision (yes/no/broken)? "; 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $answer = <STDIN>; 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 1 if $answer =~ /^(1|y.*)$/i; 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return -1 if $answer =~ /^(-1|b.*)$/i; # Broken 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 446