private void WriteLockFile(LockFile previousLockFile, string projectLockFilePath, Runtime.Project project, List <GraphItem> graphItems, PackageRepository repository, IProjectResolver projectResolver, IEnumerable <TargetContext> contexts) { var resolver = new DefaultPackagePathResolver(repository.RepositoryRoot.Root); var previousPackageLibraries = previousLockFile?.PackageLibraries.ToDictionary(l => Tuple.Create(l.Name, l.Version)); var lockFile = new LockFile(); lockFile.Islocked = Lock; // Use empty string as the key of dependencies shared by all frameworks lockFile.ProjectFileDependencyGroups.Add(new ProjectFileDependencyGroup( string.Empty, project.Dependencies.Select(x => x.LibraryRange.ToString()))); foreach (var frameworkInfo in project.GetTargetFrameworks()) { lockFile.ProjectFileDependencyGroups.Add(new ProjectFileDependencyGroup( frameworkInfo.FrameworkName.ToString(), frameworkInfo.Dependencies.Select(x => x.LibraryRange.ToString()))); } // Record all libraries used foreach (var item in graphItems.OrderBy(x => x.Match.Library, new LibraryComparer())) { if (item.Match.LibraryType.Equals(Runtime.LibraryTypes.Implicit)) { continue; } var library = item.Match.Library; if (library.Name == project.Name) { continue; } if (item.Match.LibraryType.Equals(Runtime.LibraryTypes.Project)) { var projectDependency = projectResolver.FindProject(library.Name); var projectLibrary = LockFileUtils.CreateLockFileProjectLibrary(project, projectDependency); lockFile.ProjectLibraries.Add(projectLibrary); } else if (item.Match.LibraryType.Equals(Runtime.LibraryTypes.Package)) { var packageInfo = repository.FindPackagesById(library.Name) .FirstOrDefault(p => p.Version == library.Version); if (packageInfo == null) { throw new InvalidOperationException($"Unresolved package: {library.Name}"); } LockFilePackageLibrary previousLibrary = null; previousPackageLibraries?.TryGetValue(Tuple.Create(library.Name, library.Version), out previousLibrary); var package = packageInfo.Package; // The previousLibrary can't be a project, otherwise exception has been thrown. lockFile.PackageLibraries.Add(LockFileUtils.CreateLockFilePackageLibrary( previousLibrary, resolver, package, correctedPackageName: library.Name)); } else { throw new InvalidOperationException($"Unresolved library: {library.Name}"); } } var packageLibraries = lockFile.PackageLibraries.ToDictionary(lib => Tuple.Create(lib.Name, lib.Version)); // Add the contexts foreach (var context in contexts) { var target = new LockFileTarget(); target.TargetFramework = context.RestoreContext.FrameworkName; target.RuntimeIdentifier = context.RestoreContext.RuntimeName; foreach (var match in context.Matches.OrderBy(x => x.Library, new LibraryComparer())) { if (match.Library.Name == project.Name) { continue; } if (match.LibraryType.Equals(Runtime.LibraryTypes.Project)) { var projectDependency = projectResolver.FindProject(match.Library.Name); var projectTargetLibrary = LockFileUtils.CreateLockFileTargetLibrary(projectDependency, context.RestoreContext); target.Libraries.Add(projectTargetLibrary); } else if (match.LibraryType.Equals(Runtime.LibraryTypes.Package)) { var packageInfo = repository.FindPackagesById(match.Library.Name) .FirstOrDefault(p => p.Version == match.Library.Version); var package = packageInfo.Package; target.Libraries.Add(LockFileUtils.CreateLockFileTargetLibrary( packageLibraries[Tuple.Create(match.Library.Name, match.Library.Version)], package, context.RestoreContext, correctedPackageName: match.Library.Name)); } } lockFile.Targets.Add(target); } var lockFileFormat = new LockFileFormat(); lockFileFormat.Write(projectLockFilePath, lockFile); }
private void PurgeOrphanPackages() { _reports.Verbose.WriteLine("Removing orphaned packages..."); // Find the packages still used by the command scripts var applicationPackagesStillUsed = _commandsRepo.Commands .Select(cmd => _commandsRepo.FindCommandOwner(cmd)) .Distinct(); // Get all the installed packages var packagesRepo = new PackageRepository( _commandsRepo.PackagesRoot, caseSensitivePackagesName: false); // Key = package<id, version>, Value = bool (true if used, false otherwise) var usedPackages = packagesRepo .GetAllPackages() .SelectMany(pack => pack.Value) .ToDictionary( pack => pack, _ => false); var lockFileFormat = new LockFileFormat(); // Mark all the packages still in used by using the dependencies in the lock file foreach (var applicationPackage in applicationPackagesStillUsed) { var appLockFileFullPath = Path.Combine( _commandsRepo.PackagesRoot.Root, _commandsRepo.PathResolver.GetPackageDirectory(applicationPackage.Id, applicationPackage.Version), InstallBuilder.CommandsFolderName, LockFileFormat.LockFileName); if (!File.Exists(appLockFileFullPath)) { _reports.Verbose.WriteLine("Lock file {0} not found. This package will be removed if it is not used by another application", appLockFileFullPath); // The lock file is missing, probably the app is not installed correctly // unless someone else is using it, we'll remove it continue; } var lockFile = lockFileFormat.Read(appLockFileFullPath); foreach (var dependency in lockFile.PackageLibraries) { var dependencyPackage = new NuGet.PackageInfo( _commandsRepo.PackagesRoot, dependency.Name, dependency.Version, null, null); if (usedPackages.ContainsKey(dependencyPackage)) { // Mark the dependency as used usedPackages[dependencyPackage] = true; } } } // Now it's time to remove those unused packages var unusedPackages = usedPackages .Where(pack => !pack.Value) .Select(pack => pack.Key); foreach (var package in unusedPackages) { packagesRepo.RemovePackage(package); _reports.Verbose.WriteLine("Removed orphaned package: {0} {1}", package.Id, package.Version); } }