#!/bin/php
<?php
echo "Calling emerge_with_fixes.php...\r\n";

$callarr=$argv;
unset($callarr[0]);
$callstr=join(" ",$callarr);
$env="";
if(isset($_SERVER["USE"])){
    $env="USE=\"".$_SERVER["USE"]."\"";
}

echo "Call basic call... ";
$basecall=$env." emerge -pv ".$callstr;
echo $basecall."\r\n\r\n";
$p = popen($basecall." 2>&1","r");
$output="";
while(!feof($p)){
    $get = fgets($p,1024);
    $output.=$get;
    $get = trim($get);
    echo "EMERGE-STDOUT: ".$get."\r\n";
}
pclose($p);

// now we know what happened
$fix_applied=false;
$force_retry=false; // if true, we push retcode=2, if the next cycle call could have different results and other fixes!
if(stripos($output,"It might be possible to break this cycle")!==false){
    // We must break dependencies
    echo "[EMERGE_WITH_FIXES.PHP] Try solution A:\r\n";
    $fixes=array();
    $pos = stripos($output,"It might be possible to break this cycle");
    $suboutput = substr($output,$pos);
    $suboutput = explode("Note that this change can be reverted, once the package has been installed",$suboutput);
    $reloutput = $suboutput[0];
    $reloutput = explode("\n",$reloutput);
    foreach($reloutput as $line){
	$line = trim($line);
	if(substr($line,0,2)=="- "){
	    $exp = explode("(Change USE:",$line);
	    $pkg=trim(substr($exp[0],2));
	    $use=trim($exp[1]);
	    if(substr($use,-1)==")") $use=substr($use,0,-1);
	    echo "Find fix: remerge package ".$pkg." with useflags: ".$use."\r\n";
	    $useflags="";
	    if(isset($_SERVER["USE"])){
		$useflags=$_SERVER["USE"];
	    }
	    $useflags.=" ".$use;
	    $fixes[]="USE=\"".$useflags."\" emerge --oneshot =".$pkg;
	}
    }

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
	echo "Calling ".$cmd."\r\n";
	passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
}
if(stripos($output,"Error: circular dependencies:")!==false && stripos($output,"(media-libs/harfbuzz-")!==false && stripos($output,"(media-libs/freetype-")!==false){
    // We break circle    
    echo "[EMERGE_WITH_FIXES.PHP] Try solution D:\r\n";
    if(!isset($_SERVER["USE"])){
        $_SERVER["USE"]="";
    }
    // This command solves the circle
    $env="USE=\"".$_SERVER["USE"]." -harfbuzz\"";
    $fixes[]=$env." emerge --oneshot --ignore-world media-libs/freetype";

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
	echo "Calling ".$cmd."\r\n";
	passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(stripos($output,"Error: circular dependencies:")!==false && stripos($output,"(sys-libs/gpm-")!==false && stripos($output,"(sys-libs/ncurses-")!==false){
    // We break circle   
    echo "[EMERGE_WITH_FIXES.PHP] Try solution E:\r\n";
    if(!isset($_SERVER["USE"])){
        $_SERVER["USE"]="";
    }
    // This command solves the circle
    $env="USE=\"".$_SERVER["USE"]." -gpm\"";
    $fixes[]=$env." emerge --oneshot --ignore-world sys-libs/ncurses";

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(stripos($output,"Error: circular dependencies:")!==false && stripos($output,"(app-emulation/qemu-")!==false && stripos($output,"(app-emulation/spice-")!==false){
    // We break circle
    echo "[EMERGE_WITH_FIXES.PHP] Try solution G:\r\n";
    if(!isset($_SERVER["USE"])){
        $_SERVER["USE"]="";
    }
    // This command solves the circle
    $env="USE=\"".$_SERVER["USE"]."\"";
    $fixes[]=$env." emerge --oneshot --ignore-world app-emulation/spice";
    $env="USE=\"".$_SERVER["USE"]." -spice\"";
    $fixes[]=$env." emerge --oneshot --ignore-world app-emulation/qemu";

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(
        (stripos($output,"] sys-devel/gcc-")!==false && stripos($output,"graphite*")!==false && stripos($output,"] media-gfx/darktable-")!==false)
        ||  (stripos($output,"sys-devel/gcc-")!==false && stripos($output,"[graphite]")!==false && stripos($output,"media-gfx/darktable-")!==false)
        ||  (stripos($output,"Please switch to a version of sys-devel/gcc built with USE=graphite")!==false)
){
    // darktable needs gcc with graphite
    echo "[EMERGE_WITH_FIXES.PHP] Try solution F:\r\n";
    if(!isset($_SERVER["USE"])){
        $_SERVER["USE"]="";
    }
    // This command solves the circle
    $env="USE=\"".$_SERVER["USE"]." graphite\"";
    $fixes[]=$env." emerge --oneshot --ignore-world sys-devel/gcc";
    $fixes[]="gcc-config \"\$(gcc-config -l | awk -F'[][]' '/^[[:space:]]*\[[0-9]+\]/{print \$2}' | sort -V | tail -n1)\"";  // switch to highest compiler, best effort for the last installed compiler

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(stripos($output,"] sys-libs/libxcrypt")!==false && stripos($output,"] <sys-apps/man-pages")!==false && stripos($output,"Error: The above package list contains packages which cannot be")!==false){
    // unmerge man-pages
    echo "[EMERGE_WITH_FIXES.PHP] Try solution K:\r\n";
    $fixes[]=$env." emerge --unmerge sys-apps/man-pages";

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(stripos($output,"The following REQUIRED_USE flag")!==false && stripos($output,"exactly-one-of")!==false && stripos($output,"llvm_slot")!==false){
    // llvm-slot wrong throug parent use-flag definition!
    if(stripos($output,"llvm-core/libclc")!==false) {
        echo "[EMERGE_WITH_FIXES.PHP] Try solution H1:\r\n";
        // This command solves the wrong llvm-slot
        $fixes[] = "USE=\"llvm_slot_18\" emerge --oneshot --ignore-world llvm-core/libclc";
        $fixes[] = "emerge --oneshot --ignore-world " . $callstr;
    }
    else{
        echo "[EMERGE_WITH_FIXES.PHP] Try solution HZ:\r\n";
        // This command solves the wrong llvm-slot
        $fixes[] = "emerge --oneshot --ignore-world " . $callstr;
    }

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(stripos($output,"WARNING: One or more repositories have missing repo_name entries")!==false){
    echo "[EMERGE_WITH_FIXES.PHP] Try solution I:\r\n";
    // some repo is missing!
    $exec = shell_exec("svn info /var/db/repos/gentoo/");
    $exec = explode("\n", $exec);
    $crev=-1;
    foreach($exec as $execline){
        $execline=trim($execline);
        if(str_starts_with($execline,"Revision:")){
            $exp = explode(": ",$execline);
            $crev=(int)$exp[1];
        }
    }
    if($crev>1){
        echo "Current revision is: ".$crev."\r\n";
    }
    else{
        echo "Cant findout current rev :(\r\n";
        print_r($exec);
        exit(1);
    }
    echo "Calling \"emerge --sync\"...\r\n";
    passthru("emerge --sync");
    echo "Calling \"emergesync.php ".$crev." downgrade_allowed\"...\r\n";
    passthru("emergesync.php ".$crev." downgrade_allowed");

    $fixes[]=$env." emerge --oneshot ".$callstr;
    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(!$fix_applied && stripos($output,"Multiple package instances within a single package slot have been pulled")!==false && stripos($output,"installed at the same time on the same system")!==false && stripos($output,"x11-libs/libdrm")!==false && stripos($output,"(Change USE: +video_cards_vmware)")!==false){
    echo "[EMERGE_WITH_FIXES.PHP] Try solution J:\r\n";
    // remove irrelevant packages

    // This command solves the circle
    $fixes[]="emerge --oneshot x11-base/xorg-drivers";
    $fixes[]="emerge --unmerge x11-drivers/xf86-video-vmware";

    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        echo "Calling ".$cmd."\r\n";
        passthru($cmd);
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
    $force_retry=true;
}
if(!$fix_applied && (stripos($output,"Multiple package instances within a single package slot have been pulled")!==false || stripos($output,"installed at the same time on the same system")!==false)){
    // We must cleanup
    if(isset($_SERVER["CALLED_BY_FIXES"])) {
        echo "[EMERGE_WITH_FIXES.PHP] Try solution B (a):\r\n";
        $fixes[] = "update_maintain_deps.php";
        $fixes[] = "emerge --autounmask --autounmask-continue --backtrack=100 --rebuilt-binaries --update --deep --newuse world";
        $fixes[] = "fixpackages";
        $fixes[] = "emerge --depclean --with-bdeps=n --dynamic-deps=n";
    }
    else{
        echo "[EMERGE_WITH_FIXES.PHP] Try solution B (b):\r\n";
        $retcode=-1;
        echo "calling emerge --autounmask --autounmask-continue --backtrack=100 --rebuilt-binaries --update --deep --newuse world...\r\n";
        passthru("emerge --autounmask --autounmask-continue --backtrack=100 --rebuilt-binaries --update --deep --newuse world",$retcode);
        if($retcode==1) {
            echo "[EMERGE_WITH_FIXES.PHP] Try solution B (b) not worked - go to B (a):\r\n";
            $fixes[] = "CALLED_BY_FIXES=\"CALLED_BY_FIXES\" emerge_with_fixes.php --autounmask --autounmask-continue --backtrack=100 --rebuilt-binaries --update --deep --newuse world";
            $fixes[] = "emerge --depclean --with-bdeps=n --dynamic-deps=n";
        }
        else{
            echo "[EMERGE_WITH_FIXES.PHP] Try solution B (b) worked - update and quit:\r\n";
            $fixes[] = "update_maintain_deps.php";
        }
    }
    echo "Apply ".count($fixes)." commands...\r\n";
    foreach($fixes as $cmd){
        if(strpos($cmd,"depclean")!==false){
            echo "Calling ".$cmd." -pv\r\n";
            $execed = shell_exec($cmd." -pv");
            if(stripos($execed,"app-portage/pw-cfg-portage")!==false){
                echo "Cant Calling ".$cmd." - would remove pw-cfg-portage-systemandprofile\r\n";
            }
            else{
                echo "Calling ".$cmd." (depclean safe!)\r\n";
                passthru($cmd);
            }
        }
        else {
            echo "Calling " . $cmd . "\r\n";
            passthru($cmd);
        }
    }
    echo "Command applied! DONE!\r\n";
    $fix_applied=true;
}

if(!$fix_applied){
    echo "\r\nThere is no fix applied :(\r\n";
    exit(1);
}
else{
	if($force_retry){
		exit(2);
	}
	else{
		exit(3);
	}
}
exit(0);

