private void UpdateTemplateListFromCache(TemplateCache cache, ISet <ITemplateInfo> templates) { using (Timing.Over(_environmentSettings.Host, "Enumerate infos")) templates.UnionWith(cache.TemplateInfo); }
public static void InstallPackage(IReadOnlyList <string> packages, bool quiet) { Init(); RemoteWalkContext context = new RemoteWalkContext(); ILogger logger = new NullLogger(); SourceCacheContext cacheContext = new SourceCacheContext { IgnoreFailedSources = true }; foreach (SourceRepository repo in Repos) { if (!repo.PackageSource.IsLocal) { context.RemoteLibraryProviders.Add(new SourceRepositoryDependencyProvider(repo, logger, cacheContext)); } else { context.LocalLibraryProviders.Add(new SourceRepositoryDependencyProvider(repo, logger, cacheContext)); } } Paths.User.Content.CreateDirectory(); RemoteDependencyWalker walker = new RemoteDependencyWalker(context); HashSet <Package> remainingPackages = new HashSet <Package>(packages.Select(x => new Package(x, VersionRange.All))); HashSet <Package> encounteredPackages = new HashSet <Package>(); List <string> templateRoots = new List <string>(); List <KeyValuePair <string, string> > componentRoots = new List <KeyValuePair <string, string> >(); while (remainingPackages.Count > 0) { HashSet <Package> nextRound = new HashSet <Package>(); foreach (Package package in remainingPackages) { string name = package.PackageId; GraphNode <RemoteResolveResult> result = walker.WalkAsync(new LibraryRange(name, package.Version, LibraryDependencyTarget.All), NuGetFramework.AnyFramework, "", RuntimeGraph.Empty, true).Result; RemoteMatch match = result.Item.Data.Match; PackageIdentity packageIdentity = new PackageIdentity(match.Library.Name, match.Library.Version); nextRound.UnionWith(result.Item.Data.Dependencies.Select(x => new Package(x.Name, x.LibraryRange.VersionRange))); VersionFolderPathContext versionFolderPathContext = new VersionFolderPathContext( packageIdentity, Paths.User.PackageCache, new NullLogger(), packageSaveMode: PackageSaveMode.Defaultv3, xmlDocFileSaveMode: XmlDocFileSaveMode.Skip, fixNuspecIdCasing: true, normalizeFileNames: true); if (match.Library.Version == null) { if (!quiet) { throw new Exception($"Package '{package.PackageId}' version {package.Version} could not be located."); } else { continue; } } string source = Path.Combine(Paths.User.PackageCache, match.Library.Name, match.Library.Version.ToString()); if (!source.Exists() && match.Provider != null) { PackageExtractor.InstallFromSourceAsync( stream => match.Provider.CopyToAsync(match.Library, stream, CancellationToken.None), versionFolderPathContext, CancellationToken.None).Wait(); string target = Path.Combine(Paths.User.Content, match.Library.Name); target.CreateDirectory(); target = Path.Combine(target, match.Library.Version.ToString()); target.CreateDirectory(); Paths.Copy(source, target); target.Delete("*.nupkg", "*.nupkg.*"); string nuspec = target.EnumerateFiles("*.nuspec").FirstOrDefault(); //If there's a nuspec, figure out whether this package is a template and walk the dependency graph if (nuspec?.Exists() ?? false) { XDocument doc = XDocument.Load(nuspec); IReadOnlyList <PackageType> types = NuspecUtility.GetPackageTypes(doc.Root.Element(XName.Get("metadata", "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd")), false); //If the thing we got is a template... if (types.Any(x => string.Equals(x.Name, "template", StringComparison.OrdinalIgnoreCase))) { templateRoots.Add(target); } else { componentRoots.Add(new KeyValuePair <string, string>(match.Library.Name, match.Library.Version.ToString())); } } } } encounteredPackages.UnionWith(remainingPackages); nextRound.ExceptWith(encounteredPackages); remainingPackages = nextRound; } foreach (KeyValuePair <string, string> package in componentRoots) { foreach (string path in Path.Combine(Paths.User.Content, package.Key, package.Value).EnumerateFiles($"{package.Key}.dll", SearchOption.AllDirectories)) { if (path.IndexOf($"{Path.DirectorySeparatorChar}lib{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase) < 0 || (path.IndexOf($"{Path.DirectorySeparatorChar}netstandard1.", StringComparison.OrdinalIgnoreCase) < 0 && path.IndexOf($"{Path.DirectorySeparatorChar}netcoreapp1.", StringComparison.OrdinalIgnoreCase) < 0)) { continue; } #if !NET451 Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); #else Assembly asm = Assembly.LoadFile(path); #endif foreach (Type type in asm.GetTypes()) { SettingsLoader.Components.Register(type); } } } TemplateCache.Scan(templateRoots); }
public SettingsLoader(IEngineEnvironmentSettings environmentSettings) { _environmentSettings = environmentSettings; _paths = new Paths(environmentSettings); _userTemplateCache = new TemplateCache(environmentSettings); }
private static void LoadTemplates(TemplateCache cache, ISet <ITemplateInfo> templates) { using (Timing.Over("Enumerate infos")) templates.UnionWith(cache.TemplateInfo); }
private async Task <TemplateCache> UpdateTemplateCacheAsync(bool needsRebuild) { // Kick off gathering template packages, so parsing cache can happen in parallel. Task <IReadOnlyList <ITemplatePackage> > getTemplatePackagesTask = _templatePackagesManager.GetTemplatePackagesAsync(needsRebuild); if (!(_userTemplateCache is TemplateCache cache)) { cache = new TemplateCache(JObject.Parse(_paths.ReadAllText(_paths.TemplateCacheFile, "{}"))); } if (cache.Version == null) { // Null version means, parsing cache failed. needsRebuild = true; } if (!needsRebuild && cache.Version != TemplateInfo.CurrentVersion) { _environmentSettings.Host.LogDiagnosticMessage( $"Template cache file version is {cache.Version}, but template engine is {TemplateInfo.CurrentVersion}, rebuilding cache.", "Debug"); needsRebuild = true; } if (!needsRebuild && cache.Locale != CultureInfo.CurrentUICulture.Name) { _environmentSettings.Host.LogDiagnosticMessage( $"Template cache locale is {cache.Locale}, but CurrentUICulture is {CultureInfo.CurrentUICulture.Name}, rebuilding cache.", "Debug"); needsRebuild = true; } var allTemplatePackages = await getTemplatePackagesTask.ConfigureAwait(false); var mountPoints = new Dictionary <string, DateTime>(); foreach (var package in allTemplatePackages) { mountPoints[package.MountPointUri] = package.LastChangeTime; // We can stop comparing, but we need to keep looping to fill mountPoints if (!needsRebuild) { if (cache.MountPointsInfo.TryGetValue(package.MountPointUri, out var cachedLastChangeTime)) { if (package.LastChangeTime > cachedLastChangeTime) { needsRebuild = true; } } else { needsRebuild = true; } } } // Check that some mountpoint wasn't removed... if (!needsRebuild && mountPoints.Keys.Count != cache.MountPointsInfo.Count) { needsRebuild = true; } // Cool, looks like everything is up to date, exit if (!needsRebuild) { return(cache); } var scanResults = new List <(ITemplatePackage Package, ScanResult ScanResult)>(); Parallel.ForEach(allTemplatePackages, (package) => { try { var scanResult = _installScanner.Scan(package.MountPointUri); lock (scanResults) { scanResults.Add((package, scanResult)); } } catch (Exception ex) { _environmentSettings.Host.OnNonCriticalError(null, $"Failed to scan \"{package.MountPointUri}\":{Environment.NewLine}{ex}", null, 0); } }); cache = new TemplateCache( scanResults.OrderBy((p) => (p.Package.Provider.Factory as IPrioritizedComponent)?.Priority ?? 0).Select((pair) => pair.ScanResult), mountPoints ); JObject serialized = JObject.FromObject(cache); _paths.WriteAllText(_paths.TemplateCacheFile, serialized.ToString()); return(_userTemplateCache = cache); }