bool AbstractRepository::includesRemoveItself( const QList<InstallOperation *> &install_) { bool res = false; QString exeDir = WPMUtils::getExeDir(); for (int i = 0; i < install_.count(); i++) { InstallOperation* op = install_.at(i); if (!op->install) { QString err; PackageVersion* pv = this->findPackageVersion_( op->package, op->version, &err); if (err.isEmpty() && pv) { QString path = pv->getPath(); delete pv; if (WPMUtils::pathEquals(exeDir, path) || WPMUtils::isUnder(exeDir, path)) { res = true; break; } } } } return res; }
QString AbstractRepository::planUpdates(const QList<Package*> packages, QList<Dependency*> ranges, QList<InstallOperation*>& ops, bool keepDirectories, bool install, const QString &where_) { QString err; QList<PackageVersion*> installed = getInstalled_(&err); QList<PackageVersion*> newest, newesti; QList<bool> used; // packages first if (err.isEmpty()) { for (int i = 0; i < packages.count(); i++) { Package* p = packages.at(i); PackageVersion* a = findNewestInstallablePackageVersion_(p->name, &err); if (!err.isEmpty()) break; if (a == 0) { err = QString(QObject::tr("No installable version found for the package %1")). arg(p->title); break; } PackageVersion* b = findNewestInstalledPackageVersion_(p->name, &err); if (!err.isEmpty()) { err = QString(QObject::tr("Cannot find the newest installed version for %1: %2")). arg(p->title).arg(err); break; } if (b == 0) { if (!install) { err = QString(QObject::tr("No installed version found for the package %1")). arg(p->title); break; } } if (b == 0 || a->version.compare(b->version) > 0) { newest.append(a); newesti.append(b); used.append(false); } } } // version ranges second if (err.isEmpty()) { for (int i = 0; i < ranges.count(); i++) { Dependency* d = ranges.at(i); QScopedPointer<Package> p(findPackage_(d->package)); if (!p.data()) { err = QString(QObject::tr("Cannot find the package %1")). arg(d->package); break; } PackageVersion* a = findBestMatchToInstall(*d, QList<PackageVersion*>(), &err); if (!err.isEmpty()) break; if (a == 0) { err = QString(QObject::tr("No installable version found for the package %1")). arg(p->title); break; } InstalledPackageVersion* ipv = findHighestInstalledMatch(*d); PackageVersion* b = 0; if (ipv) { b = findPackageVersion_(ipv->package, ipv->version, &err); if (!err.isEmpty()) { err = QString(QObject::tr("Cannot find the newest installed version for %1: %2")). arg(p->title).arg(err); break; } } if (b == 0) { if (!install) { err = QString(QObject::tr("No installed version found for the package %1")). arg(p->title); break; } } if (b == 0 || a->version.compare(b->version) > 0) { newest.append(a); newesti.append(b); used.append(false); } } } if (err.isEmpty()) { // many packages cannot be installed side-by-side and overwrite for // example // the shortcuts of the old version in the start menu. We try to find // those packages where the old version can be uninstalled first and // then // the new version installed. This is the reversed order for an update. // If this is possible and does not affect other packages, we do this // first. for (int i = 0; i < newest.count(); i++) { QList<PackageVersion*> avoid; QList<InstallOperation*> ops2; QList<PackageVersion*> installedCopy = installed; PackageVersion* b = newesti.at(i); if (b) { QString err = b->planUninstallation( installedCopy, ops2); if (err.isEmpty()) { QString where; if (i == 0 && !where_.isEmpty()) where = where_; else if (keepDirectories) where = b->getPath(); err = newest.at(i)->planInstallation(installedCopy, ops2, avoid, where); if (err.isEmpty()) { if (ops2.count() == 2) { used[i] = true; installed = installedCopy; ops.append(ops2[0]); ops.append(ops2[1]); ops2.clear(); } } } } qDeleteAll(ops2); } } if (err.isEmpty()) { for (int i = 0; i < newest.count(); i++) { if (!used[i]) { QString where; PackageVersion* b = newesti.at(i); if (keepDirectories && b) where = b->getPath(); QList<PackageVersion*> avoid; err = newest.at(i)->planInstallation(installed, ops, avoid, where); if (!err.isEmpty()) break; } } } if (err.isEmpty()) { for (int i = 0; i < newesti.count(); i++) { if (!used[i]) { PackageVersion* b = newesti.at(i); if (b) { err = b->planUninstallation(installed, ops); if (!err.isEmpty()) break; } } } } if (err.isEmpty()) { InstallOperation::simplify(ops); } qDeleteAll(installed); qDeleteAll(newest); qDeleteAll(newesti); return err; }