private PackageDef GetPackageDefFromRepo(List <IPackageRepository> repositories, string name, VersionSpecifier version) { if (name.ToLower().EndsWith(".tappackage")) { name = Path.GetFileNameWithoutExtension(name); } var specifier = new PackageSpecifier(name, version, CpuArchitecture.Unspecified, OperatingSystem.Current.ToString()); var packages = PackageRepositoryHelpers.GetPackagesFromAllRepos(repositories, specifier, InstalledPackages.Values.ToArray()); if (packages.Any() == false) { packages = PackageRepositoryHelpers.GetPackagesFromAllRepos(repositories, specifier); if (packages.Any()) { log.Warning($"Unable to find a version of '{name}' package compatible with currently installed packages. Some installed packages may be upgraded."); } } return(packages.OrderByDescending(pkg => pkg.Version).FirstOrDefault(pkg => ArchitectureHelper.PluginsCompatible(pkg.Architecture, ArchitectureHelper.HostArchitecture))); }
protected override int LockedExecute(CancellationToken cancellationToken) { if (OutputPaths.Length > Packages.Length) { throw new Exception("More OutputPaths specified than packages. Exiting."); } string destinationDir = Target ?? Directory.GetCurrentDirectory(); Installation destinationInstallation = new Installation(destinationDir); List <IPackageRepository> repositories = new List <IPackageRepository>(); if (Repository == null) { repositories.AddRange(PackageManagerSettings.Current.Repositories.Where(p => p.IsEnabled).Select(s => s.Manager).ToList()); } else { repositories.AddRange(Repository.Select(s => PackageRepositoryHelpers.DetermineRepositoryType(s))); } List <PackageDef> PackagesToDownload = PackageActionHelpers.GatherPackagesAndDependencyDefs(destinationInstallation, PackageReferences, Packages, Version, Architecture, OS, repositories, ForceInstall, InstallDependencies, false, false); if (PackagesToDownload == null) { return(2); } if (!DryRun) { // If OutputPaths are specified, download the specified packages to those locations before downloading the remaining files // Place the remaining files in the same location as the last named location for (int i = 0; i < OutputPaths.Length; i++) { var outputPath = OutputPaths[i]; var packageName = Packages[i]; var package = PackagesToDownload.First(p => p.Name == packageName || (p.PackageSource is FilePackageDefSource s && s.PackageFilePath == Path.GetFullPath(packageName))); string filename = null; // Treat path as a directory if it ends with '/' if (outputPath.EndsWith("/") || outputPath.EndsWith(Path.DirectorySeparatorChar.ToString())) { Directory.CreateDirectory(outputPath); } if (Directory.Exists(outputPath)) { destinationDir = outputPath; } // Otherwise, treat it as a full path else { var file = new FileInfo(outputPath); destinationDir = file.DirectoryName; Directory.CreateDirectory(destinationDir); filename = file.FullName; } PackageActionHelpers.DownloadPackages(destinationDir, new List <PackageDef>() { package }, new List <string>() { filename }); PackagesToDownload.Remove(package); } // Download the remaining packages PackageActionHelpers.DownloadPackages(destinationDir, PackagesToDownload); } else { log.Info("Dry run completed. Specified packages are available."); } DownloadedPackages = PackagesToDownload; return(0); }
protected override int LockedExecute(CancellationToken cancellationToken) { if (OS == null) { switch (Environment.OSVersion.Platform) { case PlatformID.MacOSX: OS = "OSX"; break; case PlatformID.Unix: OS = "Linux"; break; default: OS = "Windows"; break; } } List <IPackageRepository> repositories = new List <IPackageRepository>(); if (Installed == false) { if (Repository == null) { repositories.AddRange(PackageManagerSettings.Current.Repositories.Where(p => p.IsEnabled).Select(s => s.Manager)); } else { repositories.AddRange(Repository.Select(s => PackageRepositoryHelpers.DetermineRepositoryType(s))); } } if (Target == null) { Target = FileSystemHelper.GetCurrentInstallationDirectory(); } HashSet <PackageDef> installed = new Installation(Target).GetPackages().ToHashSet(); VersionSpecifier versionSpec = VersionSpecifier.Parse("^"); if (!String.IsNullOrWhiteSpace(Version)) { versionSpec = VersionSpecifier.Parse(Version); } if (string.IsNullOrEmpty(Name)) { var packages = installed.ToList(); packages.AddRange(PackageRepositoryHelpers.GetPackageNameAndVersionFromAllRepos(repositories, new PackageSpecifier("", versionSpec, Architecture, OS))); if (Installed) { packages = packages.Where(p => installed.Any(i => i.Name == p.Name)).ToList(); } PrintReadable(packages, installed); } else { IPackageIdentifier package = installed.FirstOrDefault(p => p.Name == Name); if (Installed) { if (package is null) { log.Info($"{Name} is not installed"); return(-1); } log.Info(package.Version.ToString()); return(0); } List <PackageVersion> versions = null; if (All) { versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name).Distinct().ToList(); var versionsCount = versions.Count; if (versionsCount == 0) // No versions { log.Info($"No versions of '{Name}'."); return(0); } if (Version != null) // Version is specified by user { versions = versions.Where(v => versionSpec.IsCompatible(v.Version)).ToList(); } if (versions.Any() == false && versionsCount > 0) { log.Info($"Package '{Name}' does not exists with version '{Version}'."); log.Info($"Package '{Name}' exists in {versionsCount} other versions, please specify a different version."); return(0); } } else { var opentap = new Installation(Target).GetOpenTapPackage(); versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name, opentap).Distinct().ToList(); versions = versions.Where(s => s.IsPlatformCompatible(Architecture, OS)).ToList(); if (versions.Any() == false) // No compatible versions { versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name).ToList(); if (versions.Any()) { log.Warning($"There are no compatible versions of '{Name}'."); log.Info($"There are {versions.Count} incompatible versions available. Use '--all' to show these."); } else { log.Warning($"Package '{Name}' could not be found in any repository."); } return(0); } versions = versions.Where(v => versionSpec.IsCompatible(v.Version)).ToList(); if (versions.Any() == false) // No versions that are compatible { if (string.IsNullOrEmpty(Version)) { log.Warning($"There are no released versions of '{Name}'."); } else { log.Warning($"Package '{Name}' does not exists with version '{Version}'."); } var anyPrereleaseSpecifier = new VersionSpecifier(versionSpec.Major, versionSpec.Minor, versionSpec.Patch, versionSpec.PreRelease, versionSpec.BuildMetadata, VersionMatchBehavior.AnyPrerelease | versionSpec.MatchBehavior); versions = versions.Where(v => anyPrereleaseSpecifier.IsCompatible(v.Version)).ToList(); if (versions.Any()) { log.Info($"There are {versions.Count} pre-released versions available. Use '--version <pre-release>' (e.g. '--version rc') or '--all' to show these."); } return(0); } } PrintVersionsReadable(package, versions); } return(0); }
internal static PackageDef FindPackage(PackageSpecifier packageReference, bool force, Installation installation, List <IPackageRepository> repositories) { IPackageIdentifier[] compatibleWith; if (!force) { var tapPackage = installation.GetOpenTapPackage(); if (tapPackage != null) { compatibleWith = new[] { installation.GetOpenTapPackage() } } ; else { compatibleWith = new[] { new PackageIdentifier("OpenTAP", PluginManager.GetOpenTapAssembly().SemanticVersion.ToString(), CpuArchitecture.Unspecified, "") } }; } else { compatibleWith = Array.Empty <IPackageIdentifier>(); } var compatiblePackages = PackageRepositoryHelpers.GetPackagesFromAllRepos(repositories, packageReference, compatibleWith); // Of the compatible packages, pick the one with the highest version number. If that package is available from several repositories, pick the one with the lowest index in the list in PackageManagerSettings PackageDef package = null; if (compatiblePackages.Any()) { package = compatiblePackages.GroupBy(p => p.Version).OrderByDescending(g => g.Key).FirstOrDefault() .OrderBy(p => repositories.IndexWhen(e => NormalizeRepoUrl(e.Url) == NormalizeRepoUrl((p.PackageSource as IRepositoryPackageDefSource)?.RepositoryUrl))).FirstOrDefault(); } // If no package was found, try to figure out why if (package == null) { var compatibleVersions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, packageReference.Name, compatibleWith); var versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, packageReference.Name); // Any packages compatible with opentap and platform var filteredVersions = compatibleVersions.Where(v => v.IsPlatformCompatible(packageReference.Architecture, packageReference.OS)).ToList(); if (filteredVersions.Any()) { // if the specified version exist, don't say it could not be found. if (versions.Any(v => packageReference.Version.IsCompatible(v.Version))) { throw new ExitCodeException(1, $"Package '{packageReference.Name}' matching version '{packageReference.Version}' is not compatible. Latest compatible version is '{filteredVersions.FirstOrDefault().Version}'."); } else { throw new ExitCodeException(1, $"Package '{packageReference.Name}' matching version '{packageReference.Version}' could not be found. Latest compatible version is '{filteredVersions.FirstOrDefault().Version}'."); } } // Any compatible with platform but not opentap filteredVersions = versions.Where(v => v.IsPlatformCompatible(packageReference.Architecture, packageReference.OS)).ToList(); if (filteredVersions.Any() && compatibleWith.Any()) { var opentapPackage = compatibleWith.First(); throw new ExitCodeException(1, $"Package '{packageReference.Name}' does not exist in a version compatible with '{opentapPackage.Name}' version '{opentapPackage.Version}'."); } // Any compatible with opentap but not platform if (compatibleVersions.Any()) { if (packageReference.Version != VersionSpecifier.Any || packageReference.OS != null || packageReference.Architecture != CpuArchitecture.Unspecified) { throw new ExitCodeException(1, string.Format("No '{0}' package {1} was found.", packageReference.Name, string.Join(" and ", new string[] { packageReference.Version != VersionSpecifier.Any ? $"compatible with version '{packageReference.Version}'": null, packageReference.OS != null ? $"compatible with '{packageReference.OS}' operating system" : null, packageReference.Architecture != CpuArchitecture.Unspecified ? $"with '{packageReference.Architecture}' architecture" : null }.Where(x => x != null).ToArray()))); } else { throw new ExitCodeException(1, $"Package '{packageReference.Name}' does not exist in a version compatible with this OS and architecture."); } } // Any version if (versions.Any()) { var opentapPackage = compatibleWith.FirstOrDefault(); if (opentapPackage != null) { throw new ExitCodeException(1, $"Package '{packageReference.Name}' does not exist in a version compatible with this OS, architecture and '{opentapPackage.Name}' version '{opentapPackage.Version}'."); } else { throw new ExitCodeException(1, $"Package '{packageReference.Name}' does not exist in a version compatible with this OS and architecture."); } } throw new ExitCodeException(1, $"Package '{packageReference.Name}' could not be found in any repository."); } return(package); }
internal static List <string> DownloadPackages(string destinationDir, List <PackageDef> PackagesToDownload, List <string> filenames = null) { List <string> downloadedPackages = new List <string>(); for (int i = 0; i < PackagesToDownload.Count; i++) { Stopwatch timer = Stopwatch.StartNew(); var pkg = PackagesToDownload[i]; string filename = filenames?.ElementAtOrDefault(i) ?? Path.Combine(destinationDir, GetQualifiedFileName(pkg)); TapThread.ThrowIfAborted(); try { PackageDef existingPkg = null; try { // If the package we are installing is from a file, we should always use that file instead of a cached package. // During development a package might not change version but still have different content. if (pkg.PackageSource is FilePackageDefSource == false && File.Exists(filename)) { existingPkg = PackageDef.FromPackage(filename); } } catch (Exception e) { log.Warning("Could not open OpenTAP Package. Redownloading package.", e); File.Delete(filename); } if (existingPkg != null) { if (existingPkg.Version == pkg.Version && existingPkg.OS == pkg.OS && existingPkg.Architecture == pkg.Architecture) { if (!PackageCacheHelper.PackageIsFromCache(existingPkg)) { log.Info("Package '{0}' already exists in '{1}'.", pkg.Name, destinationDir); } else { log.Info("Package '{0}' already exists in cache '{1}'.", pkg.Name, destinationDir); } } else { throw new Exception($"A package already exists but it is not the same as the package that is being downloaded."); } } else { string source = (pkg.PackageSource as IRepositoryPackageDefSource)?.RepositoryUrl; if (source == null && pkg.PackageSource is FilePackageDefSource fileSource) { source = fileSource.PackageFilePath; } IPackageRepository rm = PackageRepositoryHelpers.DetermineRepositoryType(source); if (PackageCacheHelper.PackageIsFromCache(pkg)) { rm.DownloadPackage(pkg, filename); log.Info(timer, "Found package '{0}' in cache. Copied to '{1}'.", pkg.Name, Path.GetFullPath(filename)); } else { log.Debug("Downloading '{0}' version '{1}' from '{2}'", pkg.Name, pkg.Version, source); rm.DownloadPackage(pkg, filename); log.Info(timer, "Downloaded '{0}' to '{1}'.", pkg.Name, Path.GetFullPath(filename)); PackageCacheHelper.CachePackage(filename); } } } catch (Exception ex) { log.Error("Failed to download OpenTAP package."); throw ex; } downloadedPackages.Add(filename); } return(downloadedPackages); }