public static IEnumerable<Package> SupercedentPackages(this IEnumerable<Package> packageSet, Package package) { // DebugMessage.Invoke.WriteLine(string.Format( "Scanning for package [{0}]", package.Name.SingleItemAsEnumerable())); // anything superceedent in the list of known packages? Registrar.ScanForPackages(package); return packageSet.Where(p => p.Architecture == package.Architecture && p.PublicKeyToken == package.PublicKeyToken && p.Name.Equals(package.Name, StringComparison.CurrentCultureIgnoreCase) && p.PolicyMinimumVersion <= package.Version && p.PolicyMaximumVersion >= package.Version).OrderByDescending(p => p.Version); }
private bool CanSatisfyPackage(Package packageToSatisfy, List<Package> installQueue, List<Package> downloadQueue) { packageToSatisfy.CanSatisfy = false; if (packageToSatisfy.IsInstalled) { return packageToSatisfy.CanSatisfy = true; } if (!packageToSatisfy.DoNotSupercede) { var supercedents = Registrar.InstalledPackages.SupercedentPackages(packageToSatisfy); if (supercedents.Count() > 0) { return true; // a supercedent package is already installed. } } if (!packageToSatisfy.DoNotSupercede) { // if told not to supercede, we won't even perform this check packageToSatisfy.Supercedent = null; var supercedents = Registrar.Packages.SupercedentPackages(packageToSatisfy); if (supercedents.Count() > 0) { if (packageToSatisfy.AllowedToSupercede) { foreach (var supercedent in supercedents) { if (CanSatisfyPackage(supercedent, installQueue, downloadQueue)) { packageToSatisfy.Supercedent = supercedent; break; } } // if we have a supercedent, then this package's dependents are moot.) if (packageToSatisfy.Supercedent != null) { return packageToSatisfy.CanSatisfy = true; } } else { // the user hasn't specifically asked us to supercede, yet we know of // potential supercedents. Let's force the user to make a decision. // throw new PackageHasPotentialUpgradesException(packageToSatisfy, supercedents); PackageManagerMessages.Invoke.PackageHasPotentialUpgrades(packageToSatisfy, supercedents); throw new OperationCompletedBeforeResultException(); } } } if (packageToSatisfy.CouldNotDownload || packageToSatisfy.PackageFailedInstall) { return false; } foreach (var dependentPackage in packageToSatisfy.Dependencies) { if (!CanSatisfyPackage(dependentPackage, installQueue, downloadQueue)) { return false; } } if (!packageToSatisfy.HasLocalFile) { if (downloadQueue != null) { downloadQueue.Add(packageToSatisfy); } } else { if (installQueue != null) { installQueue.Add(packageToSatisfy); } } return packageToSatisfy.CanSatisfy = true; }
/// <summary> /// This generates a list of files that need to be installed to sastisy a given package. /// </summary> /// <param name="package"></param> /// <returns></returns> private IEnumerable<Package> GenerateInstallGraph(Package package, bool hypothetical = false) { if (package.IsInstalled) { if (!package.PackageRequestData.NotifiedClientThisSupercedes) { PackageManagerMessages.Invoke.PackageSatisfiedBy(package, package); package.PackageRequestData.NotifiedClientThisSupercedes = true; } yield break; } var packageData = package.PackageSessionData; if (!package.PackageSessionData.IsPotentiallyInstallable) { yield break; } if (!packageData.DoNotSupercede) { var installedSupercedents = SearchForInstalledPackages(package.Name, null, package.Architecture, package.PublicKeyToken); if( package.PackageSessionData.IsClientSpecified || hypothetical ) { // this means that we're talking about a requested package // and not a dependent package and we can liberally construe supercedent // as anything with a highger version number installedSupercedents = (from p in installedSupercedents where p.Version > package.Version select p).OrderByDescending(p => p.Version).ToArray(); } else { // otherwise, we're installing a dependency, and we need something compatable. installedSupercedents = (from p in installedSupercedents where p.InternalPackageData.PolicyMinimumVersion <= package.Version && p.InternalPackageData.PolicyMaximumVersion >= package.Version select p).OrderByDescending(p => p.Version).ToArray(); } var installedSupercedent = installedSupercedents.FirstOrDefault(); if (installedSupercedent != null ) { if (!installedSupercedent.PackageRequestData.NotifiedClientThisSupercedes) { PackageManagerMessages.Invoke.PackageSatisfiedBy(package, installedSupercedent); installedSupercedent.PackageRequestData.NotifiedClientThisSupercedes = true; } yield break; // a supercedent package is already installed. } // if told not to supercede, we won't even perform this check packageData.Supercedent = null; var supercedents = SearchForPackages(package.Name, null, package.Architecture, package.PublicKeyToken).ToArray(); if( package.PackageSessionData.IsClientSpecified || hypothetical ) { // this means that we're talking about a requested package // and not a dependent package and we can liberally construe supercedent // as anything with a highger version number supercedents = (from p in supercedents where p.Version > package.Version select p).OrderByDescending(p => p.Version).ToArray(); } else { // otherwise, we're installing a dependency, and we need something compatable. supercedents = (from p in supercedents where p.InternalPackageData.PolicyMinimumVersion <= package.Version && p.InternalPackageData.PolicyMaximumVersion >= package.Version select p).OrderByDescending(p => p.Version).ToArray(); } if (supercedents.Any()) { if (packageData.AllowedToSupercede) { foreach (var supercedent in supercedents) { IEnumerable<Package> children; try { children = GenerateInstallGraph(supercedent, true); } catch { // can't be satisfied with that supercedent. // we can quietly move along here. continue; } // we should tell the client that we're making a substitution. if (!supercedent.PackageRequestData.NotifiedClientThisSupercedes) { PackageManagerMessages.Invoke.PackageSatisfiedBy(package, supercedent); supercedent.PackageRequestData.NotifiedClientThisSupercedes = true; } if( supercedent.Name == package.Name ) { supercedent.PackageSessionData.IsClientSpecified = package.PackageSessionData.IsClientSpecified; } // since we got to this spot, we can assume that we can // supercede this package with the results of the successful // GIG call. foreach (var child in children) { yield return child; } // if we have a supercedent, then this package's dependents are moot.) yield break; } } else { // the user hasn't specifically asked us to supercede, yet we know of // potential supercedents. Let's force the user to make a decision. // throw new PackageHasPotentialUpgradesException(packageToSatisfy, supercedents); PackageManagerMessages.Invoke.PackageHasPotentialUpgrades(package, supercedents); throw new OperationCompletedBeforeResultException(); } } } if (packageData.CouldNotDownload) { if (!hypothetical) { PackageManagerMessages.Invoke.UnableToDownloadPackage(package); } throw new OperationCompletedBeforeResultException(); } if (packageData.PackageFailedInstall) { if (!hypothetical) { PackageManagerMessages.Invoke.UnableToInstallPackage(package); } throw new OperationCompletedBeforeResultException(); } var childrenFailed = false; foreach( var d in package.InternalPackageData.Dependencies ) { IEnumerable<Package> children; try { children = GenerateInstallGraph(d); } catch { childrenFailed = true; continue; } foreach (var child in children) yield return child; } if(childrenFailed) { throw new OperationCompletedBeforeResultException(); } yield return package; }
private static void AddPackage( Package package) { lock( _packages ) { _packages.Add(package); } }
internal static IEnumerable<Package> ScanForPackages(Package package) { var feeds = _autoFeedLocations.Union(_sessionFeedLocations).Union(_systemFeedLocations); feeds = DoNotScanLocations.Aggregate(feeds, (current, loc) => (from feed in current where !feed.Location.IsWildcardMatch(loc) select feed)); return feeds.Aggregate(Enumerable.Empty<Package>(), (current, feed) => current.Union(feed.FindPackages(package))); }
internal static Package GetPackage(string packagePath) { Package pkg; Guid pkgGuid; if (packagePath.Contains("*")) { throw new PackageNotFoundException(packagePath); } // supports looking up by productcode/packageID. if( packagePath[0] == '{' && Guid.TryParse(packagePath, out pkgGuid)) { pkg = _packages.Where(package => package.ProductCode == packagePath).FirstOrDefault(); if( pkg == null ) { // where the only thing we know is packageID. pkg = new Package(packagePath); AddPackage(pkg); } return pkg; } // lookup by canonical name. var match = _canonicalFilter.Match(packagePath); if( match.Success ) { return GetPackage(match.Groups[1].Value, match.Groups[2].Value.VersionStringToUInt64(), match.Groups[3].Value, match.Groups[4].Value, string.Empty); } // assuming at this point, it should be a filename? var localPackagePath = Path.GetFullPath(packagePath); if (!File.Exists(localPackagePath)) { // could this be another representation of a package? // not sure we ever ever get here anymore. if (!localPackagePath.EndsWith(".msi")) { Console.WriteLine("Trying package name with .msi appendend. Is this used?"); return GetPackage(localPackagePath + ".msi"); } throw new PackageNotFoundException(localPackagePath); } var lookup = File.GetCreationTime(localPackagePath).Ticks + localPackagePath.GetHashCode(); if (_nonCoAppMSIFiles.Contains(lookup)) { throw new InvalidPackageException(InvalidReason.NotCoAppMSI, localPackagePath); } lock (_packages) { pkg = (_packages.Where( package => package.HasLocalFile && package.LocalPackagePath.ContainsValue(localPackagePath))). FirstOrDefault(); } if (pkg != null) { return pkg; } var localFolder = Path.GetDirectoryName(localPackagePath).ToLower(); // remember this place for finding packages AddAutoFeedLocation(localFolder); try { var pkgDetails = CoAppMSI.GetCoAppPackageFileDetails(localPackagePath); // try via just the package id if (!string.IsNullOrEmpty(pkgDetails.packageId)) { lock (_packages) { pkg = _packages.Where(package => package.ProductCode == pkgDetails.packageId).FirstOrDefault(); } } // try via the cosmetic name fields if (pkg == null) { lock (_packages) { pkg = (_packages.Where(package => package.Architecture == pkgDetails.Architecture && package.Version == pkgDetails.Version && package.PublicKeyToken == pkgDetails.PublicKeyToken && package.Name.Equals(pkgDetails.Name, StringComparison.CurrentCultureIgnoreCase))).FirstOrDefault(); } } if (pkg == null) { pkg = new Package(pkgDetails.Name, pkgDetails.Architecture, pkgDetails.Version, pkgDetails.PublicKeyToken, pkgDetails.packageId); AddPackage(pkg); } if (string.IsNullOrEmpty(pkg.ProductCode)) { pkg.ProductCode = pkgDetails.packageId; } if (pkg.Dependencies.Count == 0) { pkg.Dependencies.AddRange((IEnumerable<Package>) pkgDetails.dependencies); } pkg.LocalPackagePath.Value = localPackagePath; pkg.Assemblies.AddRange((IEnumerable<PackageAssemblyInfo>) pkgDetails.assemblies.Values); pkg.Roles.AddRange((IEnumerable<Tuple<PackageRole, string>>) pkgDetails.roles); pkg.PolicyMinimumVersion = pkgDetails.policy_min_version; pkg.PolicyMaximumVersion = pkgDetails.policy_max_version; // pkgDetails.displayName pkg.FullDescription = pkgDetails.description; pkg.PublishDate = DateTime.Parse(pkgDetails.publishDate); pkg.AuthorVersion = pkgDetails.authorVersion; pkg.CanonicalPackageLocation = pkgDetails.originalLocation; pkg.CanonicalFeedLocation = pkgDetails.feedLocation; pkg.Base64IconData = pkgDetails.icon; pkg.SummaryDescription = pkgDetails.summary; pkg.Publisher.Name = pkgDetails.publisherName; pkg.Publisher.Url = pkgDetails.publisherUrl; pkg.Publisher.Email = pkgDetails.publisherEmail; pkg.packageHandler = new CoAppMSI(); return pkg; } catch (InvalidPackageException ipe) { if (ipe.Reason == InvalidReason.NotCoAppMSI) { _nonCoAppMSIFiles.Add(lookup); } throw; } }
internal static Package GetPackage(string packageName, UInt64 version,string architecture, string publicKeyToken, string packageId) { Package pkg; // try via just the package id if (!string.IsNullOrEmpty(packageId)) { lock (_packages) { pkg = _packages.Where(package => package.ProductCode == packageId).FirstOrDefault(); } if (pkg != null && string.IsNullOrEmpty(pkg.Name)) { pkg.SetPackageProperties(packageName, architecture, version, publicKeyToken); } if (pkg != null) return pkg; } lock (_packages) { pkg = (_packages.Where(package => package.Architecture == architecture && package.Version == version && package.PublicKeyToken == publicKeyToken && package.Name.Equals(packageName, StringComparison.CurrentCultureIgnoreCase))).FirstOrDefault(); } if (pkg == null) { pkg = new Package(packageName, architecture, version, publicKeyToken, packageId); AddPackage(pkg); } if( !string.IsNullOrEmpty(packageId) && string.IsNullOrEmpty(pkg.ProductCode) ) { pkg.ProductCode = packageId; } return pkg; }
internal PackageSessionData(Package package) { _package = package; }
internal InternalPackageData(Package package) { _package = package; Dependencies.CollectionChanged += (x, y) => Changed(); }
internal static Package GetPackage(string packageName, ulong version, string architecture, string publicKeyToken, Guid? productCode) { Package pkg; // try via just the package product code if (productCode != null) { lock (_packages) { pkg = _packages.Where(package => package.ProductCode == productCode).FirstOrDefault(); } if (pkg != null) { // if we *have* this package somewhere, but don't know its name, // we can now fill *that* in. if (string.IsNullOrEmpty(pkg.Name)) { pkg.Name = packageName; pkg.Architecture = architecture; pkg.Version = version; pkg.PublicKeyToken = publicKeyToken; } return pkg; } } lock (_packages) { pkg = (_packages.Where(package => package.Architecture == architecture && package.Version == version && package.PublicKeyToken == publicKeyToken && package.Name.Equals(packageName, StringComparison.CurrentCultureIgnoreCase))).FirstOrDefault(); // we've tried finding it a couple of ways, and got back nothing for our trouble. // we'll create an package with the details we have, and pass that back. if (pkg == null) { pkg = new Package(packageName, architecture, version, publicKeyToken, productCode); _packages.Add(pkg); } } // if we did find a package and its product code was empty, we can fill that in now if we have it. if (productCode !=null && pkg.ProductCode == null) { pkg.ProductCode = productCode; } return pkg; }
internal static Package GetPackageFromCanonicalName(string canonicalName) { lock (_packages) { var packageName = PackageName.Parse(canonicalName); if (packageName.IsFullMatch) { var pkg = _packages.Where(package => package.CanonicalName == canonicalName).FirstOrDefault(); if (pkg == null) { // where the only thing we know is canonical Name. pkg = new Package(packageName.Name, packageName.Arch, packageName.Version.VersionStringToUInt64(), packageName.PublicKeyToken, null); _packages.Add(pkg); } return pkg; } } return null; // only happens if the canonicalName isn't a canonicalName. }
internal static Package GetPackageFromProductCode(Guid? productCode) { if (productCode != null ) { lock (_packages) { var pkg = _packages.Where(package => package.ProductCode == productCode).FirstOrDefault(); if (pkg == null) { // where the only thing we know is product code. pkg = new Package(productCode); _packages.Add(pkg); } return pkg; } } return null; // only happens if the productCode isn't a guid. }
internal PackageRequestData(Package package) { _package = package; }
public CompositionRule(Package package) { _package = package; }
public bool IsAnUpgradeFor(Package olderPackage) { return IsSameFamily(olderPackage) && Version > olderPackage.Version && !(InternalPackageData.PolicyMinimumVersion <= olderPackage.Version && InternalPackageData.PolicyMaximumVersion >= olderPackage.Version); }
public bool IsSameFamily(Package olderPackage) { return Name == olderPackage.Name && Architecture == olderPackage.Architecture && PublicKeyToken == olderPackage.PublicKeyToken; }