Example #1
0
 protected static function detectDownloadConflicts($packages, $reg)
 {
     // check conflicts with packages already installed
     $checked = $conflicts = array();
     foreach ($packages as $package) {
         $fullPackageName = $package->channel . '/' . $package->name;
         if (isset($checked[$fullPackageName])) {
             continue;
         }
         $checked[$fullPackageName] = 1;
         $conflict = $reg->detectFileConflicts($package);
         if (!count($conflict)) {
             continue;
         }
         $conflicts[$fullPackageName] = $conflict;
     }
     // check conflicts with other downloaded packages
     $dupes = $checked = $filelist = array();
     foreach ($packages as $package) {
         $fullPackageName = $package->channel . '/' . $package->name;
         if (isset($checked[$fullPackageName])) {
             continue;
         }
         $checked[$fullPackageName] = 1;
         foreach ($package->installcontents as $file) {
             // TODO: Ignore file conflicts when force is applied?
             // TODO: Add more error checking i think
             $role = Installer\Role::factory($package->getPackageType(), $file->role);
             list(, $path) = $role->getRelativeLocation($package, $file, true);
             if (isset($filelist[$file->role][$path])) {
                 $dupes[$path] = $file->role;
             }
             $filelist[$file->role][$path][] = $fullPackageName;
         }
     }
     foreach ($dupes as $path => $role) {
         $conflicted = array_shift($filelist[$role][$path]);
         foreach ($filelist[$role][$path] as $package) {
             $conflicts[$conflicted][] = array($path => $package);
         }
     }
     if (count($conflicts)) {
         $message = "File conflicts detected:\n";
         foreach ($conflicts as $package => $files) {
             $message .= " Package {$package}:\n";
             foreach ($files as $info) {
                 foreach ($info as $path => $conflict) {
                     $message .= '  ' . $path . ' (conflicts with package ' . $conflict . ")\n";
                 }
             }
         }
         AtomicFileTransaction::rollback();
         throw new Installer\Exception($message);
     }
 }
Example #2
0
    /**
     * Install packages slated for installation during transaction
     */
    static function commit()
    {
        if (self::$inTransaction === false) {
            return false;
        }

        $installer = new Uninstaller;
        // validate dependencies
        $errs = new \PEAR2\MultiErrors;
        $reg = Config::current()->registry;
        try {
            foreach (self::$uninstallPackages as $package) {
                $package->validateUninstallDependencies(self::$uninstallPackages, $errs);
            }

            if (count($errs->E_ERROR)) {
                throw new Installer\Exception('Dependency validation failed ' .
                    'for some installed packages, installation aborted', $errs);
            }

            // create dependency connections and load them into the directed graph
            $graph = new DirectedGraph;
            foreach (self::$uninstallPackages as $package) {
                $package->makeUninstallConnections($graph, self::$uninstallPackages);
            }

            // topologically sort packages and install them via iterating over the graph
            $actual = array();
            foreach ($graph as $package) {
                $actual[] = $package;
            }

            // easy reverse topological sort
            array_reverse($actual);

            AtomicFileTransaction::begin();
            $reg->begin();
            try {
                foreach ($actual as $package) {
                    $installer->uninstall($package, $reg);
                    self::$uninstalledPackages[] = $package;
                }

                $dirtrees = array();
                foreach (self::$uninstalledPackages as $package) {
                    $dirtrees[] = $reg->info($package->name, $package->channel, 'dirtree');
                    $previous   = $reg->toPackageFile($package->name, $package->channel, true);
                    self::$registeredPackages[] = array($package, $previous);
                    $reg->uninstall($package->name, $package->channel);
                }

                AtomicFileTransaction::rmEmptyDirs($dirtrees);
                AtomicFileTransaction::commit();
                $reg->commit();
                AtomicFileTransaction::removeBackups();
            } catch (\Exception $e) {
                if (AtomicFileTransaction::inTransaction()) {
                    AtomicFileTransaction::rollback();
                }

                $reg->rollback();
                throw $e;
            }

            self::$uninstallPackages = array();
            Config::current()->saveConfig();
            if (isset(Main::$options['install-plugins'])) {
                Config::setCurrent(self::$lastCurrent->path);
            }
        } catch (\Exception $e) {
            self::rollback();
            throw $e;
        }
    }