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)); }
static LibraryDependency ToLibraryDependency(InteractivePackage package) => new LibraryDependency { LibraryRange = new LibraryRange( package.Identity.Id, package.SupportedVersionRange, LibraryDependencyTarget.Package), };
void ReferencePackageInWorkspace(InteractivePackage package) { foreach (var packageAssemblyReference in package.AssemblyReferences) { dependencyResolver.AddAssemblySearchPath( packageAssemblyReference.ParentDirectory); } }
public void AddInstalledPackage(InteractivePackage package) { if (package == null) { return; } InstalledPackages = InstalledPackages .Remove(package) .Add(package); }
public void RemovePackage(InteractivePackage package) { if (package == null) { return; } installedPackages = installedPackages.Remove(package); UpdateInstalledPackages(); }
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);
/// <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); }
public FilePath GetPackageInstallPath(InteractivePackage package) => project.GetInstalledPath(package.Identity);
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); }