コード例 #1
0
        async Task <bool> ReferenceTopLevelPackageAsync(
            InteractivePackage package,
            CancellationToken cancellationToken)
        {
            if (package.AssemblyReferences.Count == 0)
            {
                return(false);
            }

            var references = new List <string> ();

            foreach (var packageAssemblyReference in package.AssemblyReferences)
            {
                var resolvedAssembly = dependencyResolver.ResolveWithoutReferences(packageAssemblyReference);
                if (resolvedAssembly == null)
                {
                    continue;
                }

                if (bannedReferencePrefixes.Any(resolvedAssembly.AssemblyName.Name.StartsWith))
                {
                    continue;
                }

                // Don't add #r for integration assemblies.
                if (HasIntegration(resolvedAssembly))
                {
                    continue;
                }

                references.Add(resolvedAssembly.AssemblyName.Name);
            }

            return(await evaluationService.AddTopLevelReferencesAsync(references, cancellationToken));
        }
コード例 #2
0
 static LibraryDependency ToLibraryDependency(InteractivePackage package)
 => new LibraryDependency
 {
     LibraryRange = new LibraryRange(
         package.Identity.Id,
         package.SupportedVersionRange,
         LibraryDependencyTarget.Package),
 };
コード例 #3
0
 void ReferencePackageInWorkspace(InteractivePackage package)
 {
     foreach (var packageAssemblyReference in package.AssemblyReferences)
     {
         dependencyResolver.AddAssemblySearchPath(
             packageAssemblyReference.ParentDirectory);
     }
 }
コード例 #4
0
 public void AddInstalledPackage(InteractivePackage package)
 {
     if (package == null)
     {
         return;
     }
     InstalledPackages = InstalledPackages
                         .Remove(package)
                         .Add(package);
 }
コード例 #5
0
        public void RemovePackage(InteractivePackage package)
        {
            if (package == null)
            {
                return;
            }

            installedPackages = installedPackages.Remove(package);

            UpdateInstalledPackages();
        }
コード例 #6
0
 internal static InteractivePackageDescription FromInteractivePackage(InteractivePackage package)
 => new InteractivePackageDescription(
     package.Identity.Id,
     package.Identity.HasVersion
             ? package.Identity.Version.ToString()
             : null,
     package.SupportedVersionRange == null
             ? null
             : package.SupportedVersionRange.OriginalString
     ?? package.SupportedVersionRange.ToNormalizedString(),
     package.IsExplicit);
コード例 #7
0
        /// <summary>
        /// Install a NuGet package. Returns all newly installed packages.
        /// </summary>
        public async Task <IReadOnlyCollection <InteractivePackage> > InstallPackageAsync(
            InteractivePackage package,
            SourceRepository sourceRepository,
            CancellationToken cancellationToken)
        {
            if (package == null)
            {
                throw new ArgumentNullException(nameof(package));
            }
            if (!package.Identity.HasVersion)
            {
                throw new ArgumentException("PackageIdentity.Version must be set");
            }

            // TODO: File upstream issue about exception if primary source repo is offline.
            //       Shouldn't secondary source repos kick in? Our current work around is to
            //       pass the source repo from search to install, but that's not perfect.
            sourceRepository = sourceRepository ?? SourceRepositories [0];

            project.ResetInstallationContext();

            // Just need to apply one fixup here
            if (PackageIdComparer.Equals(package.Identity.Id, FixedXamarinFormsPackageIdentity.Id) &&
                package.Identity.Version != FixedXamarinFormsPackageIdentity.Version)
            {
                Log.Warning(
                    TAG,
                    $"Replacing requested Xamarin.Forms version {package.Identity.Version} with " +
                    $"required version {FixedXamarinFormsPackageIdentity.Version}.");
                package = package.WithVersion(
                    FixedXamarinFormsPackageIdentity.Version,
                    overwriteRange: true);
            }

            if (PackageIdComparer.Equals(package.Identity.Id, IntegrationPackageId))
            {
                Log.Warning(TAG, $"Refusing to add integration NuGet package {IntegrationPackageId}.");
                return(Array.Empty <InteractivePackage> ());
            }

            var resolutionContext = new ResolutionContext(
                DependencyBehavior.Lowest, // IDEs only use Highest if upgrading
                includePrelease: true,
                includeUnlisted: true,
                versionConstraints: VersionConstraints.None);

            // Although there is a single repo associated with the package being installed,
            // dependency resolution will also look into the secondary sources. In some cases,
            // this can greatly slow down installation. For the primary case of searching for
            // packages in nuget.org, prevent the package manager from using secondary sources
            // for resolution.
            //
            // It is important to pass an empty enumerable, because if we pass null, the package
            // manager will determine secondary sources based on the NuGet configuration.
            var secondarySources =
                sourceRepository == SourceRepositories [0]
                ? Enumerable.Empty <SourceRepository> ()
                : SourceRepositories.Where(r => r != sourceRepository).ToArray();

            // There does not appear to be a way to hook into or override functionality of the
            // NuGetPackageManager or PackageResolver classes. In order to mess with package
            // resolution, we need to either write a lot of code, proxy the sources, or intercede
            // via preview installation actions.
            //
            // Here we do the latter, though it is not the best general-purpose approach. It works
            // fine for replacing one single package that we know a LOT about. If that package's
            // dependencies continually changed, we'd be better off with another approach.
            var previewInstallActions = await packageManager.PreviewInstallPackageAsync(
                project,
                package.Identity,
                resolutionContext,
                projectContext,
                sourceRepository,
                secondarySources,
                cancellationToken);

            var installActions = new List <NuGetProjectAction> ();

            foreach (var action in previewInstallActions)
            {
                // If the installed package has a dependency on Xamarin.Forms, make sure the version
                // that gets installed is our preferred version. Force it to install from the primary
                // source repository, because we can't assume that version is available everywhere.
                //
                // TODO: Consider adding a search or something to see if we can use the specified source
                //       instead. Could be handy if nuget.org is down or the user is offline and using
                //       a local repo.
                if (action.PackageIdentity.Id == FixedXamarinFormsPackageIdentity.Id)
                {
                    installActions.Add(NuGetProjectAction.CreateInstallProjectAction(
                                           FixedXamarinFormsPackageIdentity,
                                           SourceRepositories [0],
                                           action.Project));
                }
                else
                {
                    installActions.Add(action);
                }
            }

            // We follow the modern behavior of .NET Core and do not actually install packages anywhere.
            // Instead, we ultimately reference them out of the user's global package cache (by default,
            // ~/.nuget/packages). Our NuGetProject implementation simply collects package assembly
            // references (and potentially other necessary files) and populates them back into the
            // InteractiveInstallationContext.
            using (var sourceCacheContext = new SourceCacheContext())
                await packageManager.ExecuteNuGetProjectActionsAsync(
                    project,
                    installActions,
                    projectContext,
                    sourceCacheContext,
                    cancellationToken);

            // Identify which packages were not already noted as installed, or have been upgraded now
            var newlyInstalledPackages = new List <InteractivePackage> ();

            foreach (var newPackage in project.InstallationContext.InstalledPackages)
            {
                InteractivePackage finalNewPackage;
                var foundInstalledMatch = installedPackages.TryGetValue(
                    newPackage,
                    out finalNewPackage);

                if (!foundInstalledMatch ||
                    newPackage.Identity.Version > finalNewPackage.Identity.Version)
                {
                    // Make sure we have a reference to a matching explicit InteractivePackage if it
                    // exists, so that we can persist the original SupportedVersionRange
                    if (!foundInstalledMatch)
                    {
                        finalNewPackage = PackageIdComparer.Equals(package, newPackage)
                            ? package
                            : newPackage;
                    }

                    finalNewPackage = newPackage
                                      .WithIsExplicit(finalNewPackage.IsExplicit)
                                      .WithSupportedVersionRange(finalNewPackage.SupportedVersionRange);

                    newlyInstalledPackages.Add(finalNewPackage);
                    installedPackages = installedPackages
                                        .Remove(finalNewPackage)
                                        .Add(finalNewPackage);
                    UpdateInstalledPackages();
                }
            }

            return(newlyInstalledPackages);
        }
コード例 #8
0
 public FilePath GetPackageInstallPath(InteractivePackage package)
 => project.GetInstalledPath(package.Identity);
コード例 #9
0
        async Task LoadPackageIntegrationsAsync(
            AgentType agentType,
            TargetCompilationConfiguration targetCompilationConfiguration,
            IEvaluationContextManager evaluationContextManager,
            InteractivePackage package,
            CancellationToken cancellationToken)
        {
            // Forms is special-cased because we own it and load the extension from our framework.
            if (PackageIdComparer.Equals(package.Identity.Id, "Xamarin.Forms"))
            {
                await WorkspaceConfiguration.LoadFormsAgentExtensions(
                    package.Identity.Version.Version,
                    targetCompilationConfiguration,
                    evaluationContextManager,
                    dependencyResolver);
            }

            var assembliesToLoadOnAgent = new List <ResolvedAssembly> ();

            // Integration assemblies are not expected to be in a TFM directory—we look for them in
            // the `xamarin.interactive` folder inside the NuGet package.
            var packagePath = packageManager.GetPackageInstallPath(package);

            var interactivePath = packagePath.Combine("xamarin.interactive");

            if (interactivePath.DirectoryExists)
            {
                var interactiveAssemblies = interactivePath.EnumerateFiles("*.dll");
                foreach (var interactiveReference in interactiveAssemblies)
                {
                    var resolvedAssembly = dependencyResolver.ResolveWithoutReferences(interactiveReference);

                    if (HasIntegration(resolvedAssembly))
                    {
                        assembliesToLoadOnAgent.Add(resolvedAssembly);
                    }
                }
            }

            if (assembliesToLoadOnAgent.Count > 0)
            {
                var includePeImage = targetCompilationConfiguration.IncludePEImagesInDependencyResolution;

                var assembliesToLoad = assembliesToLoadOnAgent.Select(dep => {
                    var peImage = includePeImage
                       ? GetFileBytes(dep.Path)
                       : null;
                    var syms = includePeImage
                        ? GetDebugSymbolsFromAssemblyPath(dep.Path)
                        : null;
                    return(new AssemblyDefinition(
                               dep.AssemblyName,
                               dep.Path,
                               peImage: peImage,
                               debugSymbols: syms
                               ));
                }).ToArray();

                await evaluationContextManager.LoadAssembliesAsync(
                    targetCompilationConfiguration.EvaluationContextId,
                    assembliesToLoad,
                    cancellationToken);
            }

            await getAgentConnectionHandler(true, cancellationToken);
        }