/// <summary> /// Sorts the specified list of packages according to their dependencies, guaranteeing that no package /// is listed before its dependencies. Use this to determine the order of batch updates and installs /// to prevent conflicts from having different versions of the same packages. /// </summary> public void OrderByDependencies(IList <LocalPackage> packages) { // Map each list entry to its PackageInfo PackageInfo[] localInfo = packages .Select(p => p.Info ?? this.GetPackage(p.Name)) .NotNull() .ToArray(); // Sort the mapped list this.OrderByDependencies(localInfo); // Now sort the original list to match the sorted mapped list LocalPackage[] originalPackages = packages.ToArray(); int nonSortedCount = 0; for (int i = 0; i < originalPackages.Length; i++) { LocalPackage localPackage = originalPackages[i]; int newIndex = localInfo.IndexOfFirst(p => p.Id == localPackage.Id && p.Version == localPackage.Version); if (newIndex == -1) { newIndex = localInfo.IndexOfFirst(p => p.Id == localPackage.Id); } // Unresolved packages are always last in the sorted list if (newIndex == -1) { newIndex = packages.Count - nonSortedCount - 1; nonSortedCount++; } packages[newIndex] = localPackage; } }
/// <summary> /// Determines whether all installed pacakges are forward compatible to <paramref name="target"/>. /// </summary> /// <param name="target"></param> /// <returns></returns> public PackageCompatibility GetForwardCompatibility(PackageInfo target) { LocalPackage current = this.localPackages.FirstOrDefault(p => p.Id == target.Id); if (current == null) { return(PackageCompatibility.Definite); } Version currentVersion = current.Version; Version targetVersion = target.Version; // ToDo: Implement a more sophisticated algorithm if (currentVersion.Major != targetVersion.Major) { return(PackageCompatibility.Unlikely); } else if (currentVersion.Minor != targetVersion.Minor) { return(PackageCompatibility.Likely); } else { return(PackageCompatibility.Definite); } }
public void UpdatePackage(LocalPackage package) { this.uninstallQueue = null; PackageInfo newVersion = this.QueryPackageInfo(package.Id); this.manager.UpdatePackage(newVersion.Id, new SemanticVersion(newVersion.Version), true, false); this.uninstallQueue = new List <LocalPackage>(); }
public void UpdatePackage(LocalPackage package, Version specificVersion = null) { // Due to a bug in NuGet 2.8.2, specific-version downgrades are limited to the package itself, // without updating its dependencies. Otherwise, some of them might be uninstalled without // being reinstalled properly. this.uninstallQueue = null; bool isDowngrade = specificVersion != null && specificVersion < package.Version; NuGet.IPackage newPackage = this.FindPackageInfo(new PackageName(package.Id, specificVersion), false); this.manager.UpdatePackage(newPackage, !isDowngrade, false); this.uninstallQueue = new List <LocalPackage>(); }
public void UpdatePackage(LocalPackage package) { NuGet.IPackage newPackage = this.FindPackageInfo(new PackageName(package.Id)); // Check license terms if (!this.CheckDeepLicenseAgreements(newPackage)) { return; } this.uninstallQueue = null; this.manager.UpdatePackage(newPackage, true, false); this.uninstallQueue = new List <LocalPackage>(); }
public bool CanUninstallPackage(LocalPackage package) { bool allowed = true; this.manager.WhatIf = true; try { this.manager.UninstallPackage(package.Id, new SemanticVersion(package.Version), false, true); } catch (Exception) { allowed = false; } this.manager.WhatIf = false; return(allowed); }
public void OrderByDependencies(IList <LocalPackage> packages) { // Map each list entry to its PackageInfo PackageInfo[] localInfo = packages.Select(p => p.Info ?? this.QueryPackageInfo(p.PackageName)).ToArray(); // Sort the mapped list this.OrderByDependencies(localInfo); // Now sort the original list to match the sorted mapped list LocalPackage[] originalPackages = packages.ToArray(); for (int i = 0; i < originalPackages.Length; i++) { LocalPackage localPackage = originalPackages[i]; int newIndex = localInfo.IndexOfFirst(p => p.Id == localPackage.Id && p.Version == localPackage.Version); packages[newIndex] = localPackage; } }
/// <summary> /// Installs the specified package if it wasn't installed yet and synchronizes /// the registered Duality package version number with the one that is present /// in the local cache. /// </summary> /// <param name="localPackage"></param> public void VerifyPackage(LocalPackage localPackage) { Version oldPackageVersion = localPackage.Version; // Determine the exact version that will be installed PackageInfo packageInfo = this.GetPackage(localPackage.Name); if (packageInfo == null) { throw new Exception(string.Format( "Can't resolve version of package '{0}'. There seems to be no compatible version available.", localPackage.Id)); } // Prepare a listener to determine whether we actually installed something EventHandler <PackageOperationEventArgs> installListener = null; bool packageInstalled = false; installListener = delegate(object sender, PackageOperationEventArgs args) { if (args.Package.Id == localPackage.Id) { packageInstalled = true; } }; // Install the package. Won't do anything if the package is already installed. this.manager.PackageInstalled += installListener; this.InstallPackage(localPackage.Name, true); this.manager.PackageInstalled -= installListener; // If we didn't install anything, that package was already in the local repo. // Update the local setup to match its specific version. if (!packageInstalled && oldPackageVersion == null) { // Add the explicit version to the PackageConfig file this.setup.Packages.RemoveAll(p => p.Id == packageInfo.Id); this.setup.Packages.Add(new LocalPackage(packageInfo)); } // In case we've just retrieved an explicit version for the first time, save the config file. if (oldPackageVersion == null) { this.setup.Save(this.env.ConfigFilePath); } }
public bool CanUpdatePackage(LocalPackage package) { bool allowed = true; this.manager.WhatIf = true; try { Version version = this.QueryPackageInfo(package.PackageName.VersionInvariant).Version; this.manager.UpdatePackage(package.Id, new SemanticVersion(version), true, false); } catch (Exception) { allowed = false; } this.manager.WhatIf = false; return(allowed); }
/// <summary> /// Determines compatibility between the current package installs and the specified target package. /// Works for both updates and new installs. /// </summary> /// <param name="target"></param> /// <returns></returns> public PackageCompatibility GetCompatibilityLevel(PackageInfo target) { // If the target package is already installed in the matching version, assume compatibility if (this.localPackages.Any(local => local.Id == target.Id && local.Version == target.Version)) { return(PackageCompatibility.Definite); } // Determine all packages that might be updated or installed PackageInfo[] touchedPackages = this.GetDeepDependencies(new[] { target }).ToArray(); // Generate a mapping to already installed packages Dictionary <PackageInfo, LocalPackage> localMap = new Dictionary <PackageInfo, LocalPackage>(); foreach (PackageInfo package in touchedPackages) { LocalPackage local = this.localPackages.FirstOrDefault(p => p.Id == package.Id); if (local == null) { continue; } localMap.Add(package, local); } // Determine the maximum version difference between target and installed PackageCompatibility compatibility = PackageCompatibility.Definite; foreach (var pair in localMap) { Version targetVersion = pair.Key.Version; Version localVersion = pair.Value.Version; if (localVersion.Major != targetVersion.Major) { compatibility = compatibility.Combine(PackageCompatibility.Unlikely); } else if (localVersion.Minor != targetVersion.Minor) { compatibility = compatibility.Combine(PackageCompatibility.Likely); } } return(compatibility); }
public void VerifyPackage(LocalPackage package) { Version oldPackageVersion = package.Version; // Determine the exact version that will be downloaded PackageInfo packageInfo = this.QueryPackageInfo(package.Id, package.Version); if (packageInfo == null) { throw new ApplicationException(string.Format( "Can't resolve version of package '{0}'. There seems to be no compatible version available.", package.Id)); } // Prepare a listener to determine whether we actually installed something EventHandler <PackageOperationEventArgs> installListener = null; bool packageInstalled = false; installListener = delegate(object sender, PackageOperationEventArgs args) { if (args.Package.Id == package.Id) { packageInstalled = true; } }; // Install the package. Won't do anything if the package is already installed. this.manager.PackageInstalled += installListener; this.InstallPackage(packageInfo); this.manager.PackageInstalled -= installListener; // If we didn't install anything, that package was already present in the local cache, but not in the PackageConfig file if (!packageInstalled && oldPackageVersion == null) { // Add the explicit version to the PackageConfig file this.localPackages.RemoveAll(p => p.Id == packageInfo.Id); this.localPackages.Add(new LocalPackage(packageInfo)); } // In case we've just retrieved an explicit version for the first time, save the config file. if (oldPackageVersion == null) { this.SaveConfig(); } }
public bool CanUpdatePackage(LocalPackage package, Version specificVersion = null) { bool allowed = true; this.manager.WhatIf = true; try { bool isSpecific = specificVersion != null; if (specificVersion == null) { specificVersion = this.QueryPackageInfo(package.PackageName.VersionInvariant).Version; } this.manager.UpdatePackage(package.Id, new SemanticVersion(specificVersion), !isSpecific, false); } catch (Exception) { allowed = false; } this.manager.WhatIf = false; return(allowed); }
public void VerifyPackage(LocalPackage package) { Version oldPackageVersion = package.Version; // Determine the exact version that will be downloaded PackageInfo packageInfo = this.QueryPackageInfo(package.Id, package.Version); if (packageInfo == null) { throw new ApplicationException(string.Format( "Can't resolve version of package '{0}'. There seems to be no compatible version available.", package.Id)); } // Install the package. Won't do anything if the package is already installed. this.InstallPackage(packageInfo); // In case we've just retrieved an explicit version for the first time, save the config file. if (oldPackageVersion == null) { this.SaveConfig(); } }
public LocalPackageItem(LocalPackage package, BaseItem parent) : base(package.Info, parent) {}
/// <summary> /// Determines the number of deep dependencies for the specified package. /// </summary> /// <param name="package"></param> /// <param name="deepCount"></param> /// <param name="resolver"></param> /// <returns></returns> private int GetDeepDependencyCount(PackageInfo package, Dictionary <PackageInfo, int> deepCount, Dictionary <PackageName, PackageInfo> resolveCache) { int count; if (!deepCount.TryGetValue(package, out count)) { // Use the count of direct dependencies as starting value count = package.Dependencies.Count(); // Prevent endless recursion on cyclic dependency graphs by registering early deepCount[package] = count; // Iterate over dependencies and count theirs as well foreach (PackageName dependencyName in package.Dependencies) { // Try to resolve the dependency name to get a hold on the actual info PackageInfo dependency; if (!resolveCache.TryGetValue(dependencyName, out dependency)) { // Try the exact name locally and online dependency = this.QueryPackageInfo(dependencyName); // If nothing turns up, see if we have a similar package locally and try that as well if (dependency == null) { LocalPackage localDependency = this.localPackages.FirstOrDefault(p => p.Id == dependencyName.Id); if (localDependency != null) { if (localDependency.Info != null) { dependency = localDependency.Info; } else { dependency = this.QueryPackageInfo(localDependency.PackageName); } } } // If we still have nothing, try a general search for the newest package with that Id if (dependency == null) { dependency = this.QueryPackageInfo(dependencyName.VersionInvariant); } // Cache the results for later resolveCache[dependencyName] = dependency; } if (dependency == null) { continue; } // Add secondary dependencies count += GetDeepDependencyCount(dependency, deepCount, resolveCache); } // Update the registered value deepCount[package] = count; } return(count); }
public void UninstallPackage(LocalPackage package) { this.manager.UninstallPackage(package.Id, new SemanticVersion(package.Version), false, true); }
/// <summary> /// Determines compatibility between the current package installs and the specified target package. /// Works for both updates and new installs. /// </summary> /// <param name="target"></param> /// <returns></returns> public PackageCompatibility GetCompatibilityLevel(PackageInfo target) { // If the target package is already installed in the matching version, assume compatibility if (this.setup.GetPackage(target.Id, target.Version) != null) { return(PackageCompatibility.Definite); } // Determine all packages that might be updated or installed this.dependencyWalker.Clear(); this.dependencyWalker.WalkGraph(target); List <PackageInfo> touchedPackages = this.dependencyWalker.VisitedPackages.ToList(); // Verify properly specified dependencies for Duality packages if (target.IsDualityPackage) { // If none of the targets deep dependencies is anyhow related to Duality, assume they're incomplete and potentially incompatible bool anyDualityDependency = false; foreach (PackageInfo package in touchedPackages) { if (DualityPackageNames.Any(name => string.Equals(name, package.Id))) { anyDualityDependency = true; break; } } if (!anyDualityDependency) { return(PackageCompatibility.None); } } // Generate a mapping to already installed packages Dictionary <PackageInfo, LocalPackage> localMap = new Dictionary <PackageInfo, LocalPackage>(); foreach (PackageInfo package in touchedPackages) { LocalPackage local = this.setup.GetPackage(package.Id); if (local == null) { continue; } localMap.Add(package, local); } // Determine the maximum version difference between target and installed PackageCompatibility compatibility = PackageCompatibility.Definite; foreach (var pair in localMap) { Version targetVersion = pair.Key.Version; Version localVersion = pair.Value.Version; if (localVersion.Major != targetVersion.Major) { compatibility = compatibility.Combine(PackageCompatibility.Unlikely); } else if (localVersion.Minor != targetVersion.Minor) { compatibility = compatibility.Combine(PackageCompatibility.Likely); } } return(compatibility); }
public void UninstallPackage(LocalPackage package) { this.uninstallQueue.Add(package); this.manager.UninstallPackage(package.Id, new SemanticVersion(package.Version), false, true); this.uninstallQueue.Clear(); }