Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        internal static List <PackageDef> GatherPackagesAndDependencyDefs(Installation installation, PackageSpecifier[] pkgRefs, string[] packageNames, string Version, CpuArchitecture arch, string OS, List <IPackageRepository> repositories, bool force, bool includeDependencies, bool askToIncludeDependencies, bool noDowngrade)
        {
            List <PackageDef> gatheredPackages = new List <PackageDef>();

            List <PackageSpecifier> packages = new List <PackageSpecifier>();

            if (pkgRefs != null)
            {
                packages = pkgRefs.ToList();
            }
            else
            {
                if (packageNames == null)
                {
                    throw new Exception("No packages specified.");
                }
                foreach (string packageName in packageNames)
                {
                    var version = Version;
                    if (Path.GetExtension(packageName).ToLower().EndsWith("tappackages"))
                    {
                        var tempDir          = Path.GetTempPath();
                        var bundleFiles      = PluginInstaller.UnpackPackage(packageName, tempDir);
                        var packagesInBundle = bundleFiles.Select(PackageDef.FromPackage);

                        // A packages file may contain the several variants of the same package, try to select one based on OS and Architecture
                        foreach (IGrouping <string, PackageDef> grp in packagesInBundle.GroupBy(p => p.Name))
                        {
                            var selected = grp.ToList();
                            if (selected.Count == 1)
                            {
                                gatheredPackages.Add(selected.First());
                                continue;
                            }
                            if (!string.IsNullOrEmpty(OS))
                            {
                                selected = selected.Where(p => p.OS.ToLower().Split(',').Any(OS.ToLower().Contains)).ToList();
                                if (selected.Count == 1)
                                {
                                    gatheredPackages.Add(selected.First());
                                    log.Debug("TapPackages file contains packages for several operating systems. Picking only the one for {0}.", OS);
                                    continue;
                                }
                            }
                            if (arch != CpuArchitecture.Unspecified)
                            {
                                selected = selected.Where(p => ArchitectureHelper.CompatibleWith(arch, p.Architecture)).ToList();
                                if (selected.Count == 1)
                                {
                                    gatheredPackages.Add(selected.First());
                                    log.Debug("TapPackages file contains packages for several CPU architectures. Picking only the one for {0}.", arch);
                                    continue;
                                }
                            }
                            throw new Exception("TapPackages file contains multiple variants of the same package. Unable to autoselect a suitable one.");
                        }
                    }
                    else if (string.IsNullOrWhiteSpace(packageName) == false)
                    {
                        packages.Add(new PackageSpecifier(packageName, VersionSpecifier.Parse(version ?? ""), arch, OS));
                    }
                }
            }

            foreach (var packageReference in packages)
            {
                var       installedPackages = installation.GetPackages();
                Stopwatch timer             = Stopwatch.StartNew();
                if (File.Exists(packageReference.Name))
                {
                    var package = PackageDef.FromPackage(packageReference.Name);

                    if (noDowngrade)
                    {
                        var installedPackage = installedPackages.FirstOrDefault(p => p.Name == package.Name);
                        if (installedPackage != null && installedPackage.Version.CompareTo(package.Version) >= 0)
                        {
                            log.Info($"The same or a newer version of package '{package.Name}' in already installed.");
                            continue;
                        }
                    }

                    gatheredPackages.Add(package);
                    log.Debug(timer, "Found package {0} locally.", packageReference.Name);
                }
                else
                {
                    PackageDef package = PackageActionHelpers.FindPackage(packageReference, force, installation, repositories);

                    if (noDowngrade)
                    {
                        var installedPackage = installedPackages.FirstOrDefault(p => p.Name == package.Name);
                        if (installedPackage != null && installedPackage.Version.CompareTo(package.Version) >= 0)
                        {
                            log.Info($"The same or a newer version of package '{package.Name}' in already installed.");
                            continue;
                        }
                    }

                    if (PackageCacheHelper.PackageIsFromCache(package))
                    {
                        log.Debug(timer, "Found package {0} version {1} in local cache", package.Name, package.Version);
                    }
                    else
                    {
                        log.Debug(timer, "Found package {0} version {1}", package.Name, package.Version);
                    }

                    gatheredPackages.Add(package);
                }
            }

            if (gatheredPackages.All(p => p.IsBundle()))
            {
                // If we are just installing bundles, we can assume that dependencies should also be installed
                includeDependencies = true;
            }

            log.Debug("Resolving dependencies.");
            var resolver = new DependencyResolver(installation, gatheredPackages, repositories);

            if (resolver.UnknownDependencies.Any())
            {
                foreach (var dep in resolver.UnknownDependencies)
                {
                    string message = string.Format("A package dependency named '{0}' with a version compatible with {1} could not be found in any repository.", dep.Name, dep.Version);

                    if (force)
                    {
                        log.Warning(message);
                        log.Warning("Continuing without downloading dependencies. Plugins will likely not work as expected.", dep.Name);
                    }
                    else
                    {
                        log.Error(message);
                    }
                }
                if (!force)
                {
                    log.Info("To download package dependencies despite the conflicts, use the --force option.");
                    return(null);
                }
            }
            else if (resolver.MissingDependencies.Any())
            {
                string dependencyArgsHint = "";
                if (!includeDependencies)
                {
                    dependencyArgsHint = $" (use --dependencies to also get these)";
                }
                if (resolver.MissingDependencies.Count > 1)
                {
                    log.Info("{0} required dependencies are currently not installed{1}.", resolver.MissingDependencies.Count, dependencyArgsHint);
                }
                else
                {
                    log.Info("A required dependency is currently not installed{0}.", dependencyArgsHint);
                }


                if (includeDependencies)
                {
                    //log.Debug($"Currently set to download dependencies quietly.");
                    foreach (var package in resolver.MissingDependencies)
                    {
                        log.Debug("Adding dependency {0} {1}", package.Name, package.Version);
                        gatheredPackages.Insert(0, package);
                    }
                }
                else if (askToIncludeDependencies)
                {
                    var pkgs = new List <DepRequest>();

                    foreach (var package in resolver.MissingDependencies)
                    {
                        // Handle each package at a time.
                        DepRequest req = null;
                        pkgs.Add(req = new DepRequest {
                            PackageName = package.Name, message = string.Format("Add dependency {0} {1} ?", package.Name, package.Version), Response = DepResponse.Add
                        });
                        UserInput.Request(req, true);
                    }

                    foreach (var pkg in resolver.MissingDependencies)
                    {
                        var res = pkgs.FirstOrDefault(r => r.PackageName == pkg.Name);

                        if ((res != null) && res.Response == DepResponse.Add)
                        {
                            gatheredPackages.Insert(0, pkg);
                        }
                    }
                }
            }

            return(gatheredPackages);
        }