/// <summary> /// Do the actual leg-work of removing a package. Optionally make it /// a forceful removal (used during a failed system install, or possibly /// a future system un-install). A forceful removal means that dependency /// checks are ignored and an error while deleting the database record /// is ignored (since the table may no longer exist). /// </summary> /// <param name="packageName">The name of the package to remove.</param> /// <param name="forceRemove">Wether or not to force the removal.</param> private void RemovePackage(String packageName, Boolean forceRemove) { PackageInstaller installer = new PackageInstaller(this); Database db; Package package; Migration mig; Boolean LocalTransaction = false; // // Check if the package is installed. // package = GetInstalledPackage(packageName); if (package == null) { throw new PackageNotInstalledException(String.Format("The package {0} is not currently installed.", packageName)); } // // Check if there are any packages that depend on the package // we are about to remove. // if (forceRemove == false) { if (PackagesRequiring(packageName).Count > 0) { throw new PackageDependencyException(String.Format("The package {0} as dependencies and cannot be removed.", packageName)); } } // // Begin the SQL Transaction. // if (Command.Transaction == null) { Command.Transaction = Connection.BeginTransaction(); LocalTransaction = true; } db = new Database(Command); // // Begin the actual removal process. // try { // // Unconfigure all packages that recommend this one. // try { foreach (String name in PackagesRecommending(packageName)) { mig = installer.MigrationForPackage(GetInstalledPackage(name)); if (mig != null) { mig.Unconfigure(db, null, packageName); } } } catch (Exception e) { throw new DatabaseMigrationException("Unable to re-configure dependent packages.", e); } // // Unconfigure this package. // try { // // Load the migration object from the package. // mig = installer.MigrationForPackage(package); if (mig != null) { // // Unconfigure this package from its recommendations. // foreach (PackageRecommendation pkg in package.Info.Recommends) { mig.Unconfigure(db, null, pkg.Name); } // // Unconfigure this package from its requirements. // foreach (PackageRequirement pkg in package.Info.Requires) { mig.Unconfigure(db, null, pkg.Name); } // // Do a general unconfigure of this package. // mig.Unconfigure(db, null, null); } } catch (Exception e) { throw new DatabaseMigrationException("Unable to unconfigure package.", e); } // // Remove all the new files, pages, modules, etc. // try { installer.RemovePackagePages(package); installer.RemovePackageModules(package); installer.RemovePackageFiles(package); } catch (IOException) { throw; } catch (Exception) { throw; } // // Migrate the database to a completely non-existant state. // if (mig != null) { try { mig.Downgrade(db, null); } catch (Exception e) { throw new DatabaseMigrationException("Error while trying to migrate database.", e); } } // // Remove the package from the database. // try { Command.CommandType = CommandType.Text; Command.CommandText = "DELETE FROM [cust_rc_packager_packages] WHERE [name] = @Name"; Command.Parameters.Clear(); Command.Parameters.Add(new SqlParameter("@Name", package.Info.PackageName)); Command.ExecuteNonQuery(); } catch { if (forceRemove == false) { throw; } } // // Commit database changes, we are all done. // if (LocalTransaction) { Command.Transaction.Commit(); Command.Transaction = null; db.Command.Transaction = null; } } catch (Exception) { // // Rollback file system changes. // try { installer.RevertFileChanges(); } catch { } // // Rollback database changes. // if (LocalTransaction) { Command.Transaction.Rollback(); Command.Transaction = null; db.Command.Transaction = null; } // // Throw the exception again. // throw; } }