Ejemplo n.º 1
0
        private async Task <DependencyVersionsFile> TryDownloadLineupDepsFile()
        {
            if (string.IsNullOrEmpty(LineupDependenciesFile))
            {
                return(null);
            }

            var    path = LineupDependenciesFile;
            string text;

            if (path.StartsWith("http"))
            {
                using (var client = new HttpClient())
                {
                    text = await client.GetStringAsync(path);
                }
            }
            else
            {
                text = File.ReadAllText(path);
            }


            using (var stringReader = new StringReader(text))
                using (var reader = new XmlTextReader(stringReader))
                {
                    var project = new Project(ProjectRootElement.Create(reader));
                    return(DependencyVersionsFile.LoadFromProject(project));
                }
        }
Ejemplo n.º 2
0
        public async Task <bool> ExecuteAsync()
        {
            if (!DependencyVersionsFile.TryLoad(DependenciesFile, out var localVersionsFile))
            {
                Log.LogError($"Could not load file from {DependenciesFile}");
                return(false);
            }

            if (!localVersionsFile.HasVersionsPropertyGroup())
            {
                Log.LogKoreBuildWarning(KoreBuildErrors.PackageRefPropertyGroupNotFound, $"No PropertyGroup with Label=\"{DependencyVersionsFile.PackageVersionsLabel}\" could be found in {DependenciesFile}");
            }

            if (localVersionsFile.VersionVariables.Count == 0)
            {
                Log.LogMessage(MessageImportance.High, $"No version variables could be found in {DependenciesFile}");
                return(true);
            }


            var tmpNupkgPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var logger       = new MSBuildLogger(Log);

            try
            {
                var remoteDepsVersionFile = await TryDownloadLineupDepsFile() ?? await TryDownloadLineupPackage(logger, tmpNupkgPath);

                if (remoteDepsVersionFile == null)
                {
                    return(false);
                }

                var updateCount = UpdateDependencies(localVersionsFile, remoteDepsVersionFile);

                if (updateCount > 0)
                {
                    Log.LogMessage($"Finished updating {updateCount} version variables in {DependenciesFile}");
                    localVersionsFile.Save(DependenciesFile);
                }
                else
                {
                    Log.LogMessage($"Versions in {DependenciesFile} are already up to date");
                }

                return(!Log.HasLoggedErrors);
            }
            finally
            {
                if (File.Exists(tmpNupkgPath))
                {
                    File.Delete(tmpNupkgPath);
                }
            }
        }
        private async Task <DependencyVersionsFile> TryDownloadLineupPackage(MSBuildLogger logger, string tmpNupkgPath)
        {
            VersionRange versionRange;

            if (string.IsNullOrEmpty(LineupPackageVersion))
            {
                versionRange = VersionRange.AllFloating;
            }
            else if (!VersionRange.TryParse(LineupPackageVersion, out versionRange))
            {
                Log.LogError($"{LineupPackageVersion} is not a valid NuGet package version");
                return(null);
            }

            var packageVersion = await GetPackageVersion(versionRange);

            if (packageVersion == null)
            {
                Log.LogError($"Could not find a version of {LineupPackageId} in the version range {versionRange}.");
                return(null);
            }

            var packageId = new PackageIdentity(LineupPackageId, packageVersion);

            var request = new PackageDownloadRequest
            {
                Identity   = packageId,
                OutputPath = tmpNupkgPath,
                Sources    = new[] { LineupPackageRestoreSource },
            };

            var result = await new PackageDownloader(logger).DownloadPackagesAsync(new[] { request }, TimeSpan.FromSeconds(60), _cts.Token);

            if (!result)
            {
                Log.LogError("Could not download the lineup package");
                return(null);
            }

            using (var nupkgReader = new PackageArchiveReader(tmpNupkgPath))
            {
                using (var stream = nupkgReader.GetStream("build/dependencies.props"))
                {
                    using (var reader = new XmlTextReader(stream))
                    {
                        var projectRoot = ProjectRootElement.Create(reader);
                        return(DependencyVersionsFile.Load(projectRoot));
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public override bool Execute()
        {
            if (Projects == null || Projects.Length == 0)
            {
                Log.LogMessage(MessageImportance.Low, "No projects or solutions were found. Skipping PackageReference validation.");
                return(true);
            }

            if (!File.Exists(DependenciesFile))
            {
                Log.LogKoreBuildError(KoreBuildErrors.DependenciesFileDoesNotExist, $"Expected the dependencies file to exist at {DependenciesFile}");
                return(false);
            }

            if (!DependencyVersionsFile.TryLoad(DependenciesFile, out var depsFile))
            {
                Log.LogError($"Could not load the dependencies file from {DependenciesFile}");
                return(false);
            }

            if (!depsFile.HasVersionsPropertyGroup())
            {
                Log.LogKoreBuildWarning(KoreBuildErrors.PackageRefPropertyGroupNotFound, $"No PropertyGroup with Label=\"{DependencyVersionsFile.PackageVersionsLabel}\" could be found in {DependenciesFile}");
            }

            foreach (var proj in Projects)
            {
                var ext = Path.GetExtension(proj.ItemSpec);
                if (ext == ".sln")
                {
                    var solutionProps = MSBuildListSplitter.GetNamedProperties(Properties);
                    var projectFiles  = Projects.SelectMany(p => SolutionInfoFactory.GetProjects(p, solutionProps)).Distinct();
                    foreach (var project in projectFiles)
                    {
                        VerifyPackageReferences(project, depsFile.VersionVariables);
                    }
                }
                else
                {
                    VerifyPackageReferences(proj.ItemSpec, depsFile.VersionVariables);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public void AdditionalImportsAreAdded_WithOverrideImportFalse()
        {
            // Arrange
            var path     = "obj/test.props";
            var depsFile = DependencyVersionsFile.Create(addOverrideImport: false, additionalImports: new[] { path });

            depsFile.Save(_tempFile);

            // Act
            var project = ProjectRootElement.Open(_tempFile);

            _output.WriteLine(File.ReadAllText(_tempFile));

            // Assert
            var import = Assert.Single(project.Imports);

            Assert.Equal(path, import.Project);
        }
        public void SetIsCaseInsensitive()
        {
            var depsFile = DependencyVersionsFile.Create(addOverrideImport: true);

            depsFile.Set("XunitRunnerVisualStudioVersion", "2.3.0");
            depsFile.Set("XunitRunnerVisualstudioVersion", "2.4.0");
            depsFile.Save(_tempFile);

            var project = ProjectRootElement.Open(_tempFile);

            _output.WriteLine(File.ReadAllText(_tempFile));

            var versions = Assert.Single(project.PropertyGroups, p => !string.IsNullOrEmpty(p.Label));
            var prop     = Assert.Single(versions.Properties);

            Assert.Equal("XunitRunnerVisualStudioVersion", prop.Name);
            Assert.Equal("2.4.0", prop.Value);
        }
        public void ItSortsVariablesAlphabetically()
        {
            var depsFile = DependencyVersionsFile.Create(addOverrideImport: true);

            depsFile.Set("XyzPackageVersion", "123");
            depsFile.Set("AbcPackageVersion", "456");
            depsFile.Save(_tempFile);

            var project = ProjectRootElement.Open(_tempFile);

            _output.WriteLine(File.ReadAllText(_tempFile));

            var versions = Assert.Single(project.PropertyGroups, p => !string.IsNullOrEmpty(p.Label));

            Assert.Collection(versions.Properties,
                              v => Assert.Equal("AbcPackageVersion", v.Name),
                              v => Assert.Equal("XyzPackageVersion", v.Name));
        }
        public void AdditionalImportsAreAdded_WithOverrideImportTrue()
        {
            // Arrange
            var path     = "obj/external.props";
            var depsFile = DependencyVersionsFile.Create(addOverrideImport: true, additionalImports: new[] { path });

            depsFile.Save(_tempFile);

            // Act
            var project = ProjectRootElement.Open(_tempFile);

            _output.WriteLine(File.ReadAllText(_tempFile));

            // Assert
            Assert.Collection(
                project.Imports,
                import => Assert.Equal(path, import.Project),
                import => Assert.Equal("$(DotNetPackageVersionPropsPath)", import.Project));
        }
Ejemplo n.º 9
0
        private string CreateProjectDepsFile(string depsFilePath, params VersionVariable[] variables)
        {
            var proj             = ProjectRootElement.Create(NewProjectFileOptions.None);
            var originalDepsFile = DependencyVersionsFile.Load(proj);

            foreach (var item in variables)
            {
                if (item.IsReadOnly)
                {
                    originalDepsFile.AddPinnedVariable(item.Name, item.Version);
                }
                else
                {
                    originalDepsFile.Update(item.Name, item.Version);
                }
            }
            originalDepsFile.Save(depsFilePath);
            return(depsFilePath);
        }
        public async Task ModifiesVariableValueUsingDepsFile()
        {
            // arrange
            var depsFilePath        = CreateProjectDepsFile(("PackageVersionVar", "1.0.0"));
            var updatedDepsFilePath = CreateProjectDepsFile(Path.Combine(_tempDir, "dependencies.props"), ("PackageVersionVar", "2.0.0"));

            // act
            var task = new UpgradeDependencies
            {
                BuildEngine            = new MockEngine(_output),
                DependenciesFile       = depsFilePath,
                LineupDependenciesFile = updatedDepsFilePath
            };

            // assert
            Assert.True(await task.ExecuteAsync(), "Task is expected to pass");
            var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath);

            Assert.Equal("2.0.0", modifiedDepsFile.VersionVariables["PackageVersionVar"]);
        }
        public async Task ModifiesVariableValue()
        {
            // arrange
            var packageId         = new PackageIdentity("Lineup", NuGetVersion.Parse("1.0.0"));
            var lineupPackagePath = CreateLineup(packageId, ("PackageVersionVar", "2.0.0"));
            var depsFilePath      = CreateProjectDepsFile(("PackageVersionVar", "1.0.0"));

            // act
            var task = new UpgradeDependencies
            {
                BuildEngine                = new MockEngine(_output),
                DependenciesFile           = depsFilePath,
                LineupPackageId            = packageId.Id,
                LineupPackageRestoreSource = _tempDir,
            };

            // assert
            Assert.True(await task.ExecuteAsync(), "Task is expected to pass");
            var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath);

            Assert.Equal("2.0.0", modifiedDepsFile.VersionVariables["PackageVersionVar"]);
        }
        private int UpdateDependencies(DependencyVersionsFile localVersionsFile, DependencyVersionsFile remoteDepsVersionFile)
        {
            var updateCount = 0;

            foreach (var localVariable in localVersionsFile.VersionVariables.Values.Where(v => !v.IsReadOnly))
            {
                string remoteVariableVersion;

                // special case any package bundled in ThunderBuild
                if (!string.IsNullOrEmpty(ThunderBuildVersion.Current) && localVariable.Name == "InternalAspNetCoreSdkPackageVersion")
                {
                    remoteVariableVersion = ThunderBuildVersion.Current;
                    Log.LogMessage(MessageImportance.Low, "Setting InternalAspNetCoreSdkPackageVersion to the current version of ThunderBuild");
                }
                else
                {
                    if (remoteDepsVersionFile.VersionVariables.TryGetValue(localVariable.Name, out var remoteVariable))
                    {
                        remoteVariableVersion = remoteVariable.Version;
                    }
                    else
                    {
                        Log.LogThunderBuildWarning(
                            DependenciesFile,
                            ThunderBuildErrors.PackageVersionNotFoundInLineup,
                            $"A new version variable for {localVariable.Name} could not be found in {LineupPackageId}. This might be an unsupported external dependency.");
                        continue;
                    }
                }

                if (remoteVariableVersion != localVariable.Version)
                {
                    updateCount++;
                    localVersionsFile.Update(localVariable.Name, remoteVariableVersion);
                }
            }

            return(updateCount);
        }
Ejemplo n.º 13
0
        public async Task SnapsInternalAspNetCoreSdkToBuildTools()
        {
            // arrange
            var packageId         = new PackageIdentity("Lineup", NuGetVersion.Parse("1.0.0"));
            var lineupPackagePath = CreateLineup(packageId, new VersionVariable("InternalAspNetCoreSdkPackageVersion", "2.0.0"));
            var depsFilePath      = CreateProjectDepsFile(new VersionVariable("InternalAspNetCoreSdkPackageVersion", "1.0.0"));

            // act
            var task = new UpgradeDependencies
            {
                BuildEngine                = new MockEngine(_output),
                DependenciesFile           = depsFilePath,
                LineupPackageId            = packageId.Id,
                LineupPackageRestoreSource = _tempDir,
            };

            // assert
            Assert.True(await task.ExecuteAsync(), "Task is expected to pass");
            var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath);

            Assert.Equal(KoreBuildVersion.Current, modifiedDepsFile.VersionVariables["InternalAspNetCoreSdkPackageVersion"].Version);
        }
 public void GeneratesVariableName(string id, string varName)
 {
     Assert.Equal(varName, DependencyVersionsFile.GetVariableName(id));
 }
Ejemplo n.º 15
0
        public override bool Execute()
        {
            OutputPath = OutputPath.Replace('\\', '/');
            Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));

            DependencyVersionsFile depsFile;

            if (File.Exists(OutputPath))
            {
                if (!DependencyVersionsFile.TryLoad(OutputPath, out depsFile))
                {
                    depsFile = DependencyVersionsFile.Create(AddOverrideImport, AdditionalImports);
                    Log.LogWarning($"Could not load the existing deps file from {OutputPath}. This file will be overwritten.");
                }
            }
            else
            {
                depsFile = DependencyVersionsFile.Create(AddOverrideImport, AdditionalImports);
            }

            var varNames = new HashSet <string>();

            foreach (var pkg in Packages)
            {
                var packageVersion = pkg.GetMetadata("Version");

                if (string.IsNullOrEmpty(packageVersion))
                {
                    Log.LogError("Package {0} is missing the Version metadata", pkg.ItemSpec);
                    continue;
                }

                string packageVarName;
                if (!string.IsNullOrEmpty(pkg.GetMetadata("VariableName")))
                {
                    packageVarName = pkg.GetMetadata("VariableName");
                    if (!packageVarName.EndsWith("Version", StringComparison.Ordinal))
                    {
                        Log.LogError("VariableName for {0} must end in 'Version'", pkg.ItemSpec);
                        continue;
                    }
                }
                else
                {
                    packageVarName = DependencyVersionsFile.GetVariableName(pkg.ItemSpec);
                }

                if (varNames.Contains(packageVarName))
                {
                    Log.LogError("Multiple packages would produce {0} in the generated dependencies.props file. Set VariableName to differentiate the packages manually", packageVarName);
                    continue;
                }

                var item = depsFile.Update(packageVarName, packageVersion);
                if (!SuppressVariableLabels)
                {
                    item.SetLabel(pkg.ItemSpec);
                }
            }

            depsFile.Save(OutputPath);
            Log.LogMessage(MessageImportance.Normal, $"Generated {OutputPath}");
            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var unifiedPackageList = new Dictionary <string, PackageReferenceInfo>(StringComparer.OrdinalIgnoreCase);

            var projects    = new ProjectInfoFactory(Log).CreateMany(Projects, Properties, false, _cts.Token);
            var packageRefs = projects.SelectMany(p => p.Frameworks).SelectMany(f => f.Dependencies);

            foreach (var packageRef in packageRefs)
            {
                if (packageRef.Value.IsImplicitlyDefined)
                {
                    // skip PackageReferences added by the SDK
                    continue;
                }

                if (packageRef.Value.NoWarn.Contains(KoreBuildErrors.Prefix + KoreBuildErrors.ConflictingPackageReferenceVersions))
                {
                    // Make it possible to suppress version conflicts while generating this file.
                    continue;
                }

                if (unifiedPackageList.TryGetValue(packageRef.Value.Id, out var other))
                {
                    if (other.Version != packageRef.Value.Version)
                    {
                        Log.LogKoreBuildError(KoreBuildErrors.ConflictingPackageReferenceVersions, $"Conflicting dependency versions for {packageRef.Value.Id}: {other.Project.FileName} references '{other.Version}' but {packageRef.Value.Project.FileName} references '{packageRef.Value.Version}'");
                    }
                }
                else
                {
                    unifiedPackageList.Add(packageRef.Value.Id, packageRef.Value);
                    Log.LogMessage(MessageImportance.Low, $"Found {packageRef.Value.Id} = {packageRef.Value.Version}");
                }
            }

            if (Log.HasLoggedErrors)
            {
                return(false);
            }

            var items = unifiedPackageList.Values.Select(p => new TaskItem(p.Id, new Hashtable {
                ["Version"] = p.Version
            })).ToArray();

            var task = new GeneratePackageVersionPropsFile
            {
                AddOverrideImport      = true,
                SuppressVariableLabels = true,
                Packages    = items,
                BuildEngine = BuildEngine,
                HostObject  = HostObject,
                OutputPath  = DependenciesFile,
            };

            if (!task.Execute())
            {
                return(false);
            }

            var otherImports = OtherImports != null
                ? OtherImports.Select(p => p.ItemSpec)
                : Array.Empty <string>();

            foreach (var proj in projects.Select(p => p.FullPath).Concat(otherImports))
            {
                var project = ProjectRootElement.Open(proj, ProjectCollection.GlobalProjectCollection, preserveFormatting: true);
                var changed = false;
                foreach (var item in project.Items.Where(i => i.ItemType == "PackageReference"))
                {
                    var noWarn = item.Metadata.FirstOrDefault(m => m.Name == "NoWarn");
                    if (noWarn != null && noWarn.Value.Contains(KoreBuildErrors.Prefix + KoreBuildErrors.ConflictingPackageReferenceVersions))
                    {
                        continue;
                    }

                    var versionMetadata = item.Metadata.LastOrDefault(p => p.Name == "Version");
                    if (versionMetadata != null && versionMetadata.Value.StartsWith("$("))
                    {
                        continue;
                    }
                    changed = true;

                    var varName = $"$({DependencyVersionsFile.GetVariableName(item.Include)})";
                    if (versionMetadata == null)
                    {
                        item.AddMetadata("Version", varName, expressAsAttribute: true);
                    }
                    else
                    {
                        versionMetadata.Value = varName;
                    }
                }

                if (changed)
                {
                    Log.LogMessage(MessageImportance.High, $"Updated {proj}");
                    project.Save(proj);
                }
                else
                {
                    Log.LogMessage(MessageImportance.Normal, $"Skipping {proj}. Already up to date.");
                }
            }

            return(!Log.HasLoggedErrors);
        }