internal static async Task InstallFromStream(Stream stream, Library library, string packagesDirectory, SHA512 sha512) { var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNuspec = packagePathResolver.GetManifestFilePath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var hashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock => { // If this is the first process trying to install the target nupkg, go ahead // After this process successfully installs the package, all other processes // waiting on this lock don't need to install it again if (createdNewLock) { Directory.CreateDirectory(targetPath); using (var nupkgStream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) { await stream.CopyToAsync(nupkgStream); nupkgStream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, nupkgStream); } // Fixup the casing of the nuspec on disk to match what we expect var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single(); if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal)) { Manifest manifest = null; using (var nuspecStream = File.OpenRead(nuspecFile)) { manifest = Manifest.ReadFrom(nuspecStream, validateSchema: false); manifest.Metadata.Id = library.Name; } // Delete the previous nuspec file File.Delete(nuspecFile); // Write the new manifest using (var targetNuspecStream = File.OpenWrite(targetNuspec)) { manifest.Save(targetNuspecStream); } } stream.Seek(0, SeekOrigin.Begin); var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(stream)); File.WriteAllText(hashPath, nupkgSHA); } return 0; }); }
public void Emit(PackRoot root) { var package = _nugetDependencyResolver.FindCandidate( _libraryDescription.Identity.Name, _libraryDescription.Identity.Version); Console.WriteLine("Packing nupkg dependency {0} {1}", package.Id, package.Version); var resolver = new DefaultPackagePathResolver(root.PackagesPath); TargetPath = resolver.GetInstallPath(package.Id, package.Version); if (Directory.Exists(TargetPath)) { if (root.Overwrite) { root.Operations.Delete(TargetPath); } else { Console.WriteLine(" {0} already exists.", TargetPath); return; } } Console.WriteLine(" Target {0}", TargetPath); var targetNupkgPath = resolver.GetPackageFilePath(package.Id, package.Version); var hashPath = resolver.GetHashPath(package.Id, package.Version); using (var sourceStream = package.GetStream()) { using (var archive = new ZipArchive(sourceStream, ZipArchiveMode.Read)) { root.Operations.ExtractNupkg(archive, TargetPath); } } using (var sourceStream = package.GetStream()) { using (var targetStream = new FileStream(targetNupkgPath, FileMode.Create, FileAccess.Write, FileShare.None)) { sourceStream.CopyTo(targetStream); } sourceStream.Seek(0, SeekOrigin.Begin); var sha512Bytes = SHA512.Create().ComputeHash(sourceStream); File.WriteAllText(hashPath, Convert.ToBase64String(sha512Bytes)); } }
internal static async Task InstallFromStream( Stream stream, LibraryIdentity library, string packagesDirectory, IReport information, string packageHash = null) { var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNuspec = packagePathResolver.GetManifestFilePath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var targetHashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, action: async _ => { if (string.IsNullOrEmpty(packageHash)) { using (var sha512 = SHA512.Create()) { packageHash = Convert.ToBase64String(sha512.ComputeHash(stream)); } } var actionName = "Installing"; var installedPackageHash = string.Empty; if (File.Exists(targetHashPath) && File.Exists(targetNuspec)) { installedPackageHash = File.ReadAllText(targetHashPath); actionName = "Overwriting"; } if (string.Equals(packageHash, installedPackageHash, StringComparison.Ordinal)) { information.WriteLine($"{library.Name}.{library.Version} already exists"); } else { information.WriteLine($"{actionName} {library.Name}.{library.Version}"); Directory.CreateDirectory(targetPath); using (var nupkgStream = new FileStream( targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, bufferSize: 4096, useAsync: true)) { stream.Seek(0, SeekOrigin.Begin); await stream.CopyToAsync(nupkgStream); nupkgStream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, nupkgStream); } // Fixup the casing of the nuspec on disk to match what we expect var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single(); Manifest manifest = null; using (var nuspecStream = File.OpenRead(nuspecFile)) { manifest = Manifest.ReadFrom(nuspecStream, validateSchema: false); manifest.Metadata.Id = library.Name; manifest.Metadata.Version = library.Version; } // Delete the previous nuspec file File.Delete(nuspecFile); // Write the new manifest using (var targetNuspecStream = File.OpenWrite(targetNuspec)) { manifest.Save(targetNuspecStream); } // Note: PackageRepository relies on the hash file being written out as the final operation as part of a package install // to assume a package was fully installed. File.WriteAllText(targetHashPath, packageHash); } return 0; }); }
private bool EmitNupkg(PublishRoot root) { root.Reports.Quiet.WriteLine(" Packing nupkg from {0} dependency {1}", _libraryDescription.Type, _libraryDescription.Identity.Name); IsPackage = true; var project = GetCurrentProject(); var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); var targetNupkg = resolver.GetPackageFileName(project.Name, project.Version); TargetPath = resolver.GetInstallPath(project.Name, project.Version); root.Reports.Quiet.WriteLine(" Source {0}", _libraryDescription.Path.Bold()); root.Reports.Quiet.WriteLine(" Target {0}", TargetPath); if (Directory.Exists(TargetPath)) { root.Operations.Delete(TargetPath); } // Generate nupkg from this project dependency var buildOptions = new BuildOptions(); buildOptions.ProjectDir = project.ProjectDirectory; buildOptions.OutputDir = Path.Combine(project.ProjectDirectory, "bin"); buildOptions.Configurations.Add(root.Configuration); buildOptions.Reports = root.Reports; buildOptions.GeneratePackages = true; var buildManager = new BuildManager(root.HostServices, buildOptions); if (!buildManager.Build()) { return false; } // Extract the generated nupkg to target path var srcNupkgPath = Path.Combine(buildOptions.OutputDir, root.Configuration, targetNupkg); var targetNupkgPath = resolver.GetPackageFilePath(project.Name, project.Version); var hashFile = resolver.GetHashPath(project.Name, project.Version); using (var sourceStream = new FileStream(srcNupkgPath, FileMode.Open, FileAccess.Read)) { using (var archive = new ZipArchive(sourceStream, ZipArchiveMode.Read)) { root.Operations.ExtractNupkg(archive, TargetPath); } } using (var sourceStream = new FileStream(srcNupkgPath, FileMode.Open, FileAccess.Read)) { using (var targetStream = new FileStream(targetNupkgPath, FileMode.Create, FileAccess.Write, FileShare.None)) { sourceStream.CopyTo(targetStream); } sourceStream.Seek(0, SeekOrigin.Begin); var sha512Bytes = SHA512.Create().ComputeHash(sourceStream); File.WriteAllText(hashFile, Convert.ToBase64String(sha512Bytes)); } // Copy content files (e.g. html, js and images) of main project into "root" folder of the exported package var rootFolderPath = Path.Combine(TargetPath, "root"); var rootProjectJson = Path.Combine(rootFolderPath, Runtime.Project.ProjectFileName); root.Operations.Delete(rootFolderPath); CopyProject(root, project, rootFolderPath, includeSource: false); UpdateWebRoot(root, rootFolderPath); UpdateJson(rootProjectJson, jsonObj => { // Update the project entrypoint jsonObj["entryPoint"] = _libraryDescription.Identity.Name; // Set mark this as non loadable jsonObj["loadable"] = false; // Update the dependencies node to reference the main project var deps = new JObject(); jsonObj["dependencies"] = deps; deps[_libraryDescription.Identity.Name] = _libraryDescription.Identity.Version.ToString(); }); _applicationBase = Path.Combine("..", PublishRoot.AppRootName, "packages", resolver.GetPackageDirectory(_libraryDescription.Identity.Name, _libraryDescription.Identity.Version), "root"); root.Reports.Quiet.WriteLine("Removing {0}", srcNupkgPath); File.Delete(srcNupkgPath); srcNupkgPath = Path.ChangeExtension(srcNupkgPath, "symbols.nupkg"); root.Reports.Quiet.WriteLine("Removing {0}", srcNupkgPath); File.Delete(srcNupkgPath); return true; }
private void PrunePackages(PublishRoot root) { if (root.MainProjectLockFile == null) { return; } var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName)); root.PublishedLockFile = new LockFileFormat().Read(lockFilePath); var filesToKeep = new HashSet<string>(); var filesToRemove = new HashSet<string>(); foreach (var target in root.PublishedLockFile.Targets) { foreach (var library in target.Libraries) { var packageDir = resolver.GetInstallPath(library.Name, library.Version); if (library.Name != root.MainProjectName && string.Equals(library.Type, Runtime.LibraryTypes.Package, StringComparison.OrdinalIgnoreCase)) { filesToRemove.Add(resolver.GetHashPath(library.Name, library.Version)); filesToRemove.Add(resolver.GetPackageFilePath(library.Name, library.Version)); filesToRemove.AddRange(Directory.EnumerateFiles(packageDir, $"{library.Name}.xml", SearchOption.AllDirectories)); } foreach (var path in library.RuntimeAssemblies) { filesToKeep.Add(Path.Combine(packageDir, path)); } foreach (var path in library.CompileTimeAssemblies) { filesToKeep.Add(Path.Combine(packageDir, path)); } foreach (var path in library.NativeLibraries) { filesToKeep.Add(Path.Combine(packageDir, path)); } foreach (var path in library.ResourceAssemblies) { filesToKeep.Add(Path.Combine(packageDir, path)); } } } foreach (var target in root.MainProjectLockFile.Targets.Where(projectTarget => string.IsNullOrEmpty(projectTarget.RuntimeIdentifier) && !root.PublishedLockFile.Targets.Any(publishTarget => projectTarget.TargetFramework == publishTarget.TargetFramework))) { foreach (var library in target.Libraries) { var packageDir = resolver.GetInstallPath(library.Name, library.Version); if (Directory.Exists(packageDir)) { foreach (var path in library.RuntimeAssemblies) { filesToRemove.Add(Path.Combine(packageDir, path)); } foreach (var path in library.CompileTimeAssemblies) { filesToRemove.Add(Path.Combine(packageDir, path)); } foreach (var path in library.NativeLibraries) { filesToRemove.Add(Path.Combine(packageDir, path)); } foreach (var path in library.ResourceAssemblies) { filesToRemove.Add(Path.Combine(packageDir, path)); } } } } foreach (var file in filesToRemove.Except(filesToKeep)) { File.Delete(file); } if (Directory.Exists(root.TargetPackagesPath)) { root.Operations.DeleteEmptyFolders(root.TargetPackagesPath); } return; }
private async Task<bool> RestoreForProject(LocalPackageRepository localRepository, string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); Project project; if (!Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } Func<string, string> getVariable = key => { return null; }; ScriptExecutor.Execute(project, "prerestore", getVariable); var projectDirectory = project.ProjectDirectory; var restoreOperations = new RestoreOperations { Report = Reports.Information }; var projectProviders = new List<IWalkProvider>(); var localProviders = new List<IWalkProvider>(); var remoteProviders = new List<IWalkProvider>(); var contexts = new List<RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( new ProjectResolver( projectDirectory, rootDirectory)))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory, new EmptyFrameworkResolver()))); var allSources = SourceProvider.LoadPackageSources(); var enabledSources = Sources.Any() ? Enumerable.Empty<PackageSource>() : allSources.Where(s => s.IsEnabled); var addedSources = Sources.Concat(FallbackSources).Select( value => allSources.FirstOrDefault(source => CorrectName(value, source)) ?? new PackageSource(value)); var effectiveSources = enabledSources.Concat(addedSources).Distinct().ToList(); foreach (var source in effectiveSources) { if (new Uri(source.Source).IsFile) { remoteProviders.Add( new RemoteWalkProvider( new PackageFolder( source.Source, Reports.Verbose))); } else { remoteProviders.Add( new RemoteWalkProvider( new PackageFeed( source.Source, source.UserName, source.Password, NoCache, Reports.Verbose))); } } foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.TargetFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } var tasks = new List<Task<GraphNode>>(); foreach (var context in contexts) { tasks.Add(restoreOperations.CreateGraphNode(context, new Library { Name = project.Name, Version = project.Version }, _ => true)); } var graphs = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List<GraphItem>(); var missingItems = new List<Library>(); ForEach(graphs, node => { if (node == null || node.Library == null) { return; } if (node.Item == null || node.Item.Match == null) { if (node.Library.Version != null && !missingItems.Contains(node.Library)) { missingItems.Add(node.Library); Reports.Information.WriteLine(string.Format("Unable to locate {0} >= {1}", node.Library.Name.Red().Bold(), node.Library.Version)); success = false; } return; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isAdded = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isAdded && isRemote) { installItems.Add(node.Item); } }); var dependencies = new Dictionary<Library, string>(); // If there is a global.json file specified, we should do SHA value verification var globalJsonFileSpecified = !string.IsNullOrEmpty(GlobalJsonFile); JToken dependenciesNode = null; if (globalJsonFileSpecified) { var globalJson = JObject.Parse(File.ReadAllText(GlobalJsonFile)); dependenciesNode = globalJson["dependencies"]; if (dependenciesNode != null) { dependencies = dependenciesNode .OfType<JProperty>() .ToDictionary(d => new Library() { Name = d.Name, Version = SemanticVersion.Parse(d.Value.Value<string>("version")) }, d => d.Value.Value<string>("sha")); } } var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); using (var sha512 = SHA512.Create()) { foreach (var item in installItems) { var library = item.Match.Library; var memStream = new MemoryStream(); await item.Match.Provider.CopyToAsync(item.Match, memStream); memStream.Seek(0, SeekOrigin.Begin); var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(memStream)); string expectedSHA; if (dependencies.TryGetValue(library, out expectedSHA)) { if (!string.Equals(expectedSHA, nupkgSHA, StringComparison.Ordinal)) { Reports.Information.WriteLine( string.Format("SHA of downloaded package {0} doesn't match expected value.".Red().Bold(), library.ToString())); success = false; continue; } } else { // Report warnings only when given global.json contains "dependencies" if (globalJsonFileSpecified && dependenciesNode != null) { Reports.Information.WriteLine( string.Format("Expected SHA of package {0} doesn't exist in given global.json file.".Yellow().Bold(), library.ToString())); } } Reports.Information.WriteLine(string.Format("Installing {0} {1}", library.Name.Bold(), library.Version)); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var hashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock => { // If this is the first process trying to install the target nupkg, go ahead // After this process successfully installs the package, all other processes // waiting on this lock don't need to install it again if (createdNewLock) { Directory.CreateDirectory(targetPath); using (var stream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) { await item.Match.Provider.CopyToAsync(item.Match, stream); stream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, stream); } File.WriteAllText(hashPath, nupkgSHA); } return 0; }); } } ScriptExecutor.Execute(project, "postrestore", getVariable); ScriptExecutor.Execute(project, "prepare", getVariable); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); // Print the dependency graph if (success) { var graphNum = contexts.Count; for (int i = 0; i < graphNum; i++) { PrintDependencyGraph(graphs[i], contexts[i].FrameworkName); } } return success; }
private void WriteGlobalJson() { var rootDirectory = ProjectResolver.ResolveRootDirectory(_project.ProjectDirectory); var projectResolver = new ProjectResolver(_project.ProjectDirectory, rootDirectory); var packagesDir = NuGetDependencyResolver.ResolveRepositoryPath(rootDirectory); var pathResolver = new DefaultPackagePathResolver(packagesDir); var dependenciesObj = new JObject(); // Generate SHAs for all package dependencies foreach (var deploymentPackage in Packages) { var library = deploymentPackage.Library; var shaFilePath = pathResolver.GetHashPath(library.Name, library.Version); if (!File.Exists(shaFilePath)) { throw new FileNotFoundException("Expected SHA file doesn't exist", shaFilePath); } var sha = File.ReadAllText(shaFilePath); var shaObj = new JObject(); shaObj["version"] = library.Version.ToString(); shaObj["sha"] = sha; dependenciesObj[library.Name] = shaObj; } // If "--no-source" is specified, project dependencies are packed to packages // So we also generate SHAs for them in this case foreach (var deploymentProject in Projects) { Runtime.Project project; if (!projectResolver.TryResolveProject(deploymentProject.Name, out project)) { throw new Exception("TODO: unable to resolve project named " + deploymentProject.Name); } var shaFilePath = pathResolver.GetHashPath(project.Name, project.Version); if (!File.Exists(shaFilePath)) { // This project is not packed to a package continue; } var sha = File.ReadAllText(shaFilePath); var shaObj = new JObject(); shaObj.Add(new JProperty("version", project.Version.ToString())); shaObj.Add(new JProperty("sha", sha)); dependenciesObj.Add(new JProperty(project.Name, shaObj)); } var rootObject = default(JObject); if (GlobalSettings.HasGlobalFile(rootDirectory)) { rootObject = JObject.Parse(File.ReadAllText(Path.Combine( rootDirectory, GlobalSettings.GlobalFileName))); } else { rootObject = new JObject(); } var applicationRoot = Path.Combine(OutputPath, BundleRoot.AppRootName); rootObject["dependencies"] = dependenciesObj; rootObject["packages"] = PathUtility.GetRelativePath( PathUtility.EnsureTrailingForwardSlash(applicationRoot), TargetPackagesPath, separator: '/'); File.WriteAllText(Path.Combine(applicationRoot, GlobalSettings.GlobalFileName), rootObject.ToString()); }
internal static async Task InstallFromStream(Stream stream, Library library, string packagesDirectory, SHA512 sha512, bool performingParallelInstalls = false) { var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNuspec = packagePathResolver.GetManifestFilePath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var hashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock => { // If this is the first process trying to install the target nupkg, go ahead // After this process successfully installs the package, all other processes // waiting on this lock don't need to install it again. if (createdNewLock && !File.Exists(targetNupkg)) { var extractPath = targetPath; if (performingParallelInstalls) { // Extracting to the {id}/{version} has an issue with concurrent installs - when a package has been partially // extracted, the Restore Operation can inadvertly conclude the package is available locally and proceed to read // partially written package contents. To avoid this we'll extract the package to a sibling directory and Move it // to the target path. extractPath = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetRandomFileName()); targetNupkg = Path.Combine(extractPath, Path.GetFileName(targetNupkg)); } var extractDirectory = Directory.CreateDirectory(extractPath); using (var nupkgStream = new FileStream( targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, bufferSize: 4096, useAsync: true)) { await stream.CopyToAsync(nupkgStream); nupkgStream.Seek(0, SeekOrigin.Begin); ExtractPackage(extractPath, nupkgStream); } // Fixup the casing of the nuspec on disk to match what we expect var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single(); if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal)) { Manifest manifest = null; using (var nuspecStream = File.OpenRead(nuspecFile)) { manifest = Manifest.ReadFrom(nuspecStream, validateSchema: false); manifest.Metadata.Id = library.Name; } // Delete the previous nuspec file File.Delete(nuspecFile); // Write the new manifest using (var targetNuspecStream = File.OpenWrite(targetNuspec)) { manifest.Save(targetNuspecStream); } } stream.Seek(0, SeekOrigin.Begin); var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(stream)); File.WriteAllText(hashPath, nupkgSHA); if (performingParallelInstalls) { extractDirectory.MoveTo(targetPath); } } return 0; }); }