public void LoadXml(string inputXmlFile, string baseDirectory = null) { base_directory = baseDirectory ?? Path.GetDirectoryName(inputXmlFile); var doc = XDocument.Load(inputXmlFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo | LoadOptions.SetBaseUri); var rootElement = doc.Element("solution"); var projectsElement = rootElement.Element("projects"); this.projects = new List <ProjectInSolution> (); foreach (var projectElement in projectsElement.Elements("project")) { var projectFile = projectElement.Attribute("file")?.Value; if (projectFile == null) { Console.Error.WriteLine($"WARNING: <project> element '{projectElement.Attribute ("name")}' has no 'file' attribute. Ignoring."); continue; } var projectFileFullPath = Path.Combine(base_directory, projectFile.Replace('\\', Path.DirectorySeparatorChar)); if (!File.Exists(projectFileFullPath)) { Console.Error.WriteLine($"WARNING: <project> file '{projectFileFullPath}' does not exist. Ignoring."); continue; } var project = ProjectRootElement.Open(projectFileFullPath); Func <string, string> chop = s => s?.Substring(1, s.Length - 2); Func <string, string> getGuidProp = name => chop(project.PropertyGroups.SelectMany(g => g.Properties).FirstOrDefault(p => p.Name.Equals(name))?.Value); projects.Add(new ProjectInSolution { Path = projectFile, Name = projectElement.Attribute("name")?.Value ?? Path.GetFileNameWithoutExtension(projectFileFullPath), ProjectGuid = getGuidProp("ProjectGuid") ?? Guid.NewGuid().ToString(), ProjectTypeGuids = getGuidProp("ProjectTypeGuids"), }); } var solutionConfigsElement = rootElement.Element("config-names-for-solution"); this.solution_configuration_platforms = new List <string> (); foreach (var configElement in solutionConfigsElement.Elements("config")) { solution_configuration_platforms.Add(configElement.Attribute("name").Value); } var folders = rootElement.Element("solution-folders"); this.nested_projects = new List <Nest> (); foreach (var folder in folders.Elements("folder")) { string folderName = folder.Attribute("name").Value; // if the solution folder is not part of project list, then add it. if (!projects.Any(p => p.Name.Equals(folderName, StringComparison.OrdinalIgnoreCase))) { projects.Add(new ProjectInSolution { Name = folderName, Path = folderName, ProjectTypeGuids = ProjectTypeGuids.SolutionFolder, ProjectGuid = Guid.NewGuid().ToString() }); } foreach (var item in folder.Elements("project")) { var itemName = item.Attribute("name").Value; nested_projects.Add(new Nest { Item = ProjectNameToGuid(itemName), Parent = ProjectNameToGuid(folderName) }); } } string [] default_properties = { "ActiveCfg", "Build.0" }; var projectConfigsElement = rootElement.Element("project-config-properties"); this.project_configuration_platforms = new List <ProjectConfigurationPlatform> (); foreach (var projectElement in projectConfigsElement.Elements("project")) { var projectName = projectElement.Attribute("name").Value; var projectGuid = ProjectNameToGuid(projectName); var pattern = projectElement.Attribute("pattern")?.Value; switch (pattern) { case "all": foreach (var config in solution_configuration_platforms) { foreach (var prop in default_properties) { int sepidx = config.IndexOf('|'); var cfg = sepidx < 0 ? null : config.Substring(0, sepidx); cfg = cfg != null && cfg.EndsWith("Release") ? "Release" : cfg.EndsWith("Debug") ? "Debug" : cfg; var arch = sepidx < 0 ? null : config.Substring(sepidx + 1); project_configuration_platforms.Add(new ProjectConfigurationPlatform { ProjectGuid = projectGuid, SolutionConfigurationName = config, Property = prop, ConfigurationValue = (cfg != null ? cfg + '|' + arch : config).Replace("AnyCPU", "Any CPU"), }); } } break; case null: foreach (var configPlatformElement in projectElement.Elements("config-platform")) { var config = configPlatformElement.Attribute("config").Value; var prop = configPlatformElement.Attribute("property").Value; var value = configPlatformElement.Attribute("value").Value; project_configuration_platforms.Add(new ProjectConfigurationPlatform { ProjectGuid = projectGuid, SolutionConfigurationName = config, Property = prop, ConfigurationValue = value }); } break; default: throw new ArgumentException("Unexpected pattern value: " + pattern); } } var otherElement = rootElement.Element("other-global-sections"); this.other_global_sections = new List <GlobalSection> (); foreach (var sectionElement in otherElement.Elements("section")) { other_global_sections.Add(new GlobalSection { Name = sectionElement.Attribute("name")?.Value, Type = sectionElement.Attribute("type")?.Value, Value = sectionElement.Value, }); } }
public static MSBuildProject Open(string path) { var root = ProjectRootElement.Open(path); return(root != null ? new MSBuildProject(root) : null); }
/// Simple function to make sure the Api assembly references are configured correctly public static void FixApiHintPath(string projectPath) { var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); bool dirty = false; void AddPropertyIfNotPresent(string name, string condition, string value) { if (root.PropertyGroups .Any(g => g.Condition == string.Empty || g.Condition == condition && g.Properties .Any(p => p.Name == name && p.Value == value && (p.Condition == condition || g.Condition == condition)))) { return; } root.AddProperty(name, value).Condition = condition; dirty = true; } AddPropertyIfNotPresent(name: "ApiConfiguration", condition: " '$(Configuration)' != 'Release' ", value: "Debug"); AddPropertyIfNotPresent(name: "ApiConfiguration", condition: " '$(Configuration)' == 'Release' ", value: "Release"); void SetReferenceHintPath(string referenceName, string condition, string hintPath) { foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition == string.Empty || g.Condition == condition)) { var references = itemGroup.Items.Where(item => item.ItemType == "Reference" && item.Include == referenceName && (item.Condition == condition || itemGroup.Condition == condition)); var referencesWithHintPath = references.Where(reference => reference.Metadata.Any(m => m.Name == "HintPath")); if (referencesWithHintPath.Any(reference => reference.Metadata .Any(m => m.Name == "HintPath" && m.Value == hintPath))) { // Found a Reference item with the right HintPath return; } var referenceWithHintPath = referencesWithHintPath.FirstOrDefault(); if (referenceWithHintPath != null) { // Found a Reference item with a wrong HintPath foreach (var metadata in referenceWithHintPath.Metadata.ToList() .Where(m => m.Name == "HintPath")) { // Safe to remove as we duplicate with ToList() to loop referenceWithHintPath.RemoveChild(metadata); } referenceWithHintPath.AddMetadata("HintPath", hintPath); dirty = true; return; } var referenceWithoutHintPath = references.FirstOrDefault(); if (referenceWithoutHintPath != null) { // Found a Reference item without a HintPath referenceWithoutHintPath.AddMetadata("HintPath", hintPath); dirty = true; return; } } // Found no Reference item at all. Add it. root.AddItem("Reference", referenceName).Condition = condition; dirty = true; } const string coreProjectName = "GodotSharp"; const string editorProjectName = "GodotSharpEditor"; const string coreCondition = ""; const string editorCondition = " '$(Configuration)' == 'Tools' "; var coreHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{coreProjectName}.dll"; var editorHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{editorProjectName}.dll"; SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath); SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath); if (dirty) { root.Save(); } }
int IVsProjectUpgradeViaFactory.UpgradeProject_CheckOnly( string bstrFileName, IVsUpgradeLogger pLogger, out int pUpgradeRequired, out Guid pguidNewProjectFactory, out uint pUpgradeProjectCapabilityFlags ) { pUpgradeRequired = 0; pguidNewProjectFactory = Guid.Empty; if (!File.Exists(bstrFileName)) { pUpgradeProjectCapabilityFlags = 0; return(VSConstants.E_INVALIDARG); } var backupSupport = __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_BACKUPSUPPORTED | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP; var logger = new UpgradeLogger(bstrFileName, pLogger); try { var projectXml = ProjectRootElement.Open(bstrFileName); var userProjectName = bstrFileName + ".user"; var userProjectXml = File.Exists(userProjectName) ? ProjectRootElement.Open(userProjectName) : null; var upgradeRequired = UpgradeProjectCheck( projectXml, userProjectXml, logger.Log, ref pguidNewProjectFactory, ref backupSupport ); if (upgradeRequired != ProjectUpgradeState.NotNeeded) { pUpgradeRequired = 1; } } catch (Exception ex) when(!ExceptionExtensions.IsCriticalException(ex)) { // Log the error and don't attempt to upgrade the project. logger.Log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.UnexpectedUpgradeError, ex.Message)); try { ActivityLog.LogError(GetType().FullName, ex.ToString()); } catch (InvalidOperationException) { // Cannot log to ActivityLog. This may occur if we are // outside of VS right now (for example, unit tests). System.Diagnostics.Trace.TraceError(ex.ToString()); } pUpgradeRequired = 0; } pUpgradeProjectCapabilityFlags = (uint)backupSupport; // If the upgrade checker set the factory GUID to ourselves, we need // to clear it if (pguidNewProjectFactory == GetType().GUID) { pguidNewProjectFactory = Guid.Empty; } return(VSConstants.S_OK); }
private bool ConvertProject(string projectPath, string packagesConfigPath) { try { Log.Info($" Converting project \"{projectPath}\""); PackagesConfigReader packagesConfigReader = new PackagesConfigReader(XDocument.Load(packagesConfigPath)); List <PackageReference> packages = packagesConfigReader.GetPackages(allowDuplicatePackageIds: true).Select(i => new PackageReference(i.PackageIdentity, i.TargetFramework, i.IsUserInstalled, i.IsDevelopmentDependency, i.RequireReinstallation, i.AllowedVersions, PackagePathResolver, VersionFolderPathResolver)).ToList(); DetectMissingTransitiveDependencies(packages, projectPath); ProjectRootElement project = ProjectRootElement.Open(projectPath, _projectCollection, preserveFormatting: true); ProjectItemGroupElement packageReferenceItemGroupElement = null; foreach (ProjectElement element in project.AllChildren) { ProcessElement(element, packages); if (packageReferenceItemGroupElement == null && element is ProjectItemElement itemElement && itemElement.ItemType.Equals("Reference")) { // Find the first Reference item and use it to add PackageReference items to, otherwise a new ItemGroup is added packageReferenceItemGroupElement = element.Parent as ProjectItemGroupElement; } } if (packageReferenceItemGroupElement == null) { packageReferenceItemGroupElement = project.AddItemGroup(); } Log.Info(" Current package references:"); foreach (PackageReference package in packages.Where(i => !i.IsMissingTransitiveDependency)) { Log.Info($" {package.PackageIdentity}"); } foreach (ProjectElement element in packages.Where(i => !i.IsMissingTransitiveDependency).SelectMany(i => i.AllElements)) { Log.Debug($" {element.Location}: Removing element {element.ToXmlString()}"); element.Remove(); } if (this._converterSettings.TrimPackages) { List <NuGetFramework> targetFrameworks = new List <NuGetFramework> { FrameworkConstants.CommonFrameworks.Net45 }; using (SourceCacheContext sourceCacheContext = new SourceCacheContext { IgnoreFailedSources = true, }) { var packageRestoreGraph = GetRestoreTargetGraph(packages, projectPath, targetFrameworks, sourceCacheContext); TrimPackages(packages, projectPath, packageRestoreGraph.Flattened); } } Log.Info(" Converted package references:"); foreach (PackageReference package in packages) { ProjectItemElement packageReferenceItemElement = AddPackageReference(packageReferenceItemGroupElement, package); Log.Info($" {packageReferenceItemElement.ToXmlString()}"); } if (project.HasUnsavedChanges) { Log.Debug($" Saving project \"{project.FullPath}\""); project.Save(); } Log.Debug($" Deleting file \"{packagesConfigPath}\""); File.Delete(packagesConfigPath); Log.Info($" Successfully converted \"{project.FullPath}\""); } catch (Exception e) { Log.Error($"Failed to convert '{projectPath}' : {e}"); return(false); } return(true); }
private async Task <Project> OpenProject(UFile projectPath) { if (msbuildWorkspace == null) { // Only load workspace for C# assemblies (default includes VB but not added as a NuGet package) //var csharpWorkspaceAssemblies = new[] { Assembly.Load("Microsoft.CodeAnalysis.Workspaces"), Assembly.Load("Microsoft.CodeAnalysis.CSharp.Workspaces"), Assembly.Load("Microsoft.CodeAnalysis.Workspaces.Desktop") }; var host = await RoslynHost; msbuildWorkspace = MSBuildWorkspace.Create(ImmutableDictionary <string, string> .Empty, host.HostServices); } msbuildWorkspace.CloseSolution(); // Try up to 10 times (1 second) const int retryCount = 10; for (var i = retryCount - 1; i >= 0; --i) { try { var project = await msbuildWorkspace.OpenProjectAsync(projectPath.ToWindowsPath()); // Change the default CSharp language version to match the supported version for a specific visual studio version or MSBuild version // this is because roslyn will always resolve Default to Latest which might not match the // latest version supported by the build tools installed on the machine var csharpParseOptions = project.ParseOptions as CSharpParseOptions; if (csharpParseOptions != null) { if (csharpParseOptions.SpecifiedLanguageVersion == LanguageVersion.Default || csharpParseOptions.SpecifiedLanguageVersion == LanguageVersion.Latest) { LanguageVersion targetLanguageVersion = csharpParseOptions.SpecifiedLanguageVersion; // Check the visual studio version inside the solution first, which is what visual studio uses to decide which version to open // this should not be confused with the toolsVersion below, since this is the MSBuild version (they might be different) Version visualStudioVersion = session.CurrentProject?.Package.Session.VisualStudioVersion; if (visualStudioVersion != null) { if (visualStudioVersion.Major <= 14) { targetLanguageVersion = LanguageVersion.CSharp6; } } else { // Fallback to checking the tools version on the csproj // this happens when you open an sdpkg instead of a sln file as a project ProjectRootElement xml = ProjectRootElement.Open(projectPath); Version toolsVersion; if (Version.TryParse(xml.ToolsVersion, out toolsVersion)) { if (toolsVersion.Major <= 14) { targetLanguageVersion = LanguageVersion.CSharp6; } } } project = project.WithParseOptions(csharpParseOptions.WithLanguageVersion(targetLanguageVersion)); } } return(project); } catch (IOException) { // FIle might still be locked, let's wait little bit more await Task.Delay(100); if (i == 0) { throw; } } } // Unreachable throw new InvalidOperationException(); }
public ProjectRootElement CsProj() { // Passing new collection to prevent using cached version return(ProjectRootElement.Open(CsProjPath, new ProjectCollection())); }
private Project OpenProject(string filePath) { ProjectRootElement root = ProjectRootElement.Open(filePath, _projectCollection, true); return(new Project(root)); }
public static MsBuildProject OpenProjectForEditing(string projectFilePath, ProjectCollection projectCollection) { var projectRootElement = ProjectRootElement.Open(projectFilePath, projectCollection, preserveFormatting: true); return(new MsBuildProject(projectRootElement)); }
public static IEnumerable <ReferenceInfo> GetDXReferencePaths(string absolutePath, bool includeRoot) { return(GetDXReferencePaths(ProjectRootElement.Open(absolutePath), includeRoot)); }
public static string GetAssemblyNameFromProject(string proj) { return(GetAssemblyNameFromProject(ProjectRootElement.Open(proj))); }
/// <summary> /// Function called after a project file change has been detected which pushes the changes to CPS. The return value indicates the status of the /// reload. /// </summary> public async Task <ProjectReloadResult> ReloadProjectAsync() { // We need a write lock to modify the project file contents. Note that all awaits while holding the lock need // to capture the context as the project lock service has a special execution context which ensures only a single // thread has access. using (var writeAccess = await _projectVsServices.ProjectLockService.WriteLockAsync()) { await writeAccess.CheckoutAsync(_projectVsServices.Project.FullPath).ConfigureAwait(true); var msbuildProject = await writeAccess.GetProjectXmlAsync(_projectVsServices.Project.FullPath, CancellationToken.None).ConfigureAwait(true); if (msbuildProject.HasUnsavedChanges) { // For now force a solution reload. return(ProjectReloadResult.ReloadFailedProjectDirty); } else { // What we need to do is load the one on disk. This accomplishes two things: 1) verifies that at least the msbuild is OK. If it isn't // we want to let the normal solution reload occur so that the user sees the failure, and 2) it allows us to clear the current project // and do a deep copy from the newly loaded one to the original - replacing its contents. Note that the Open call is cached so that if // the project is already in a collection, it will just return the cached one. For this reason, and the fact we don't want the project to // appear in the global project collection, the file is opened in a new collection which we will discard when done. try { ProjectCollection thisCollection = new ProjectCollection(); var newProject = ProjectRootElement.Open(_projectVsServices.Project.FullPath, thisCollection); // First copy to a temp project, so that any failures will not corrupt the users project. ProjectRootElement.Create().DeepCopyFrom(newProject); msbuildProject.RemoveAllChildren(); msbuildProject.DeepCopyFrom(newProject); // There isn't a way to clear the dirty flag on the project xml, so to work around that the project is saved // to a StringWriter. var tw = new StringWriter(); msbuildProject.Save(tw); thisCollection.UnloadAllProjects(); } catch (Microsoft.Build.Exceptions.InvalidProjectFileException) { // Indicate we weren't able to complete the action. We want to do a normal reload return(ProjectReloadResult.ReloadFailed); } catch (Exception ex) { // Any other exception likely mean the msbuildProject is not in a good state. Example, DeepCopyFrom failed. // The only safe thing to do at this point is to reload the project in the solution // TODO: should we have an additional return value here to indicate that the existing project could be in a bad // state and the reload needs to happen without the user being able to block it? System.Diagnostics.Debug.Assert(false, "Replace xml failed with: " + ex.Message); return(ProjectReloadResult.ReloadFailed); } } } // It is important to wait for the new tree to be published to ensure all updates have occurred before the reload manager // releases its hold on the UI thread. This prevents unnecessary race conditions and prevent the user // from interacting with the project until the evaluation has completed. await _projectVsServices.ProjectTree.TreeService.PublishLatestTreeAsync(blockDuringLoadingTree : true).ConfigureAwait(false); return(ProjectReloadResult.ReloadCompleted); }
private void VerifyPackageReferences(string filePath, IReadOnlyDictionary <string, PackageVersionVariable> versionVariables) { ProjectRootElement doc; try { doc = ProjectRootElement.Open(filePath); } catch (InvalidProjectFileException ex) { Log.LogError(null, null, null, filePath, 0, 0, 0, 0, message: "Invalid project file: " + ex.Message); return; } var packageReferences = doc.Items.Where(i => i.ItemType == "PackageReference"); foreach (var pkgRef in packageReferences) { var id = pkgRef.Include; if (string.IsNullOrEmpty(id)) { // this node is an Update or Remove node continue; } var versionMetadata = pkgRef.Metadata.LastOrDefault(m => m.Name == "Version"); var versionRaw = versionMetadata?.Value; if (versionMetadata == null || string.IsNullOrEmpty(versionRaw)) { Log.LogKoreBuildError(pkgRef.Location.File, pkgRef.Location.Line, KoreBuildErrors.PackageReferenceDoesNotHaveVersion, $"PackageReference to {id} does not define a Version"); continue; } var versionIsVariable = versionRaw != null && versionRaw.Length > 3 && versionRaw[0] == '$' && versionRaw[1] == '(' && versionRaw[versionRaw.Length - 1] == ')' && versionRaw.IndexOf(')') == versionRaw.Length - 1; if (!versionIsVariable) { Log.LogKoreBuildError(pkgRef.Location.File, pkgRef.Location.Line, KoreBuildErrors.PackageRefHasLiteralVersion, "PackageReference must use an MSBuild variable to set the version."); continue; } var versionVarName = versionRaw.Substring(2, versionRaw.Length - 3); if (!versionVariables.TryGetValue(versionVarName, out var variable)) { Log.LogKoreBuildError(pkgRef.Location.File, pkgRef.Location.Line, KoreBuildErrors.VariableNotFoundInDependenciesPropsFile, $"The variable {versionRaw} could not be found in {DependenciesFile}"); continue; } var versionValue = variable.Version; if (!VersionRange.TryParse(versionValue, out var nugetVersion)) { Log.LogKoreBuildError(pkgRef.Location.File, pkgRef.Location.Line, KoreBuildErrors.InvalidPackageVersion, $"PackageReference to {id} has an invalid version identifier: '{versionValue}'"); continue; } if (nugetVersion.IsFloating) { Log.LogKoreBuildError(pkgRef.Location.File, pkgRef.Location.Line, KoreBuildErrors.PackageRefHasFloatingVersion, $"PackageReference to {id} uses a floating version: '{versionValue}'"); } } }
public void ConcurrentProjectOpenAndCloseThroughProjectRootElement() { int iterations = 500; string[] paths = ObjectModelHelpers.GetTempFiles(iterations); try { var projects = new ProjectRootElement[iterations]; var collection = new ProjectCollection(); int counter = 0; int remaining = iterations; var done = new ManualResetEvent(false); for (int i = 0; i < iterations; i++) { ThreadPool.QueueUserWorkItem(delegate { var current = Interlocked.Increment(ref counter) - 1; CreatePREWithSubstantialContent().Save(paths[current]); projects[current] = ProjectRootElement.Open(paths[current], collection); if (Interlocked.Decrement(ref remaining) == 0) { done.Set(); } }); } done.WaitOne(); counter = 0; remaining = iterations; done.Reset(); for (int i = 0; i < iterations; i++) { ThreadPool.QueueUserWorkItem(delegate { var current = Interlocked.Increment(ref counter) - 1; collection.UnloadProject(projects[current]); if (Interlocked.Decrement(ref remaining) == 0) { done.Set(); } }); } done.WaitOne(); } finally { for (int i = 0; i < iterations; i++) { File.Delete(paths[i]); } } }
/// <summary> /// Clear out the project's construction model and add a simple SDK-based project to get a baseline. /// We need to use the same name as the original csproj and same path so that all the default that derive /// from name\path get the right values (there are a lot of them). /// </summary> private bool TryCreateSdkBaselineProject(string projectFilePath, IProject project, IProjectRootElement root, ImmutableDictionary <string, ImmutableDictionary <string, string> > configurations, string tfm, bool keepCurrentTFMs, [NotNullWhen(true)] out BaselineProject?baselineProject) { var projectStyle = GetProjectStyle(root); var outputType = GetProjectOutputType(root); var rootElement = ProjectRootElement.Open(projectFilePath); rootElement.RemoveAllChildren(); switch (projectStyle) { case ProjectStyle.Default: case ProjectStyle.DefaultSubset: case ProjectStyle.MSTest: rootElement.Sdk = MSBuildFacts.DefaultSDKAttribute; break; case ProjectStyle.WindowsDesktop: rootElement.Sdk = tfm.ContainsIgnoreCase(MSBuildFacts.Net5) ? MSBuildFacts.DefaultSDKAttribute : DesktopFacts.WinSDKAttribute; // pre-.NET 5 apps need a special SDK attribute. break; case ProjectStyle.Web: rootElement.Sdk = WebFacts.WebSDKAttribute; break; default: baselineProject = null; return(false); } var propGroup = rootElement.AddPropertyGroup(); propGroup.AddProperty(MSBuildFacts.TargetFrameworkNodeName, project.GetTargetFramework()); var outputTypeValue = outputType switch { ProjectOutputType.Exe => MSBuildFacts.ExeOutputType, ProjectOutputType.Library => MSBuildFacts.LibraryOutputType, ProjectOutputType.WinExe => MSBuildFacts.WinExeOutputType, _ => project.GetPropertyValue(MSBuildFacts.OutputTypeNodeName) }; propGroup.AddProperty(MSBuildFacts.OutputTypeNodeName, outputTypeValue ?? throw new InvalidOperationException($"OutputType is not set! '{projectFilePath}'")); if (projectStyle == ProjectStyle.WindowsDesktop) { if (MSBuildHelpers.IsWinForms(root)) { MSBuildHelpers.AddUseWinForms(propGroup); } if (MSBuildHelpers.IsWPF(root)) { MSBuildHelpers.AddUseWPF(propGroup); } // User is referencing WindowsBase only if (MSBuildHelpers.IsDesktop(root) && !MSBuildHelpers.HasWPFOrWinForms(propGroup)) { MSBuildHelpers.AddUseWinForms(propGroup); } } // Create a new collection because a project with this name has already been loaded into the global collection. using var pc = new ProjectCollection(); var newProject = new UnconfiguredProject(configurations); newProject.LoadProjects(pc, rootElement); // If the original project had the TargetFramework property don't touch it during conversion. var propertiesInTheBaseline = ImmutableArray.Create(MSBuildFacts.OutputTypeNodeName); if (project.GetProperty(MSBuildFacts.TargetFrameworkNodeName) is { })
public void GeneratesFile() { var engine = new MockEngine(_output); var task = new GeneratePackageVersionPropsFile { BuildEngine = engine, Packages = new[] { // Order is important. These are intentionally reverse sorted to ensure the generated file sorts properties by prop name new TaskItem("Newtonsoft.Json", new Hashtable { ["Version"] = "10.0.3", ["VariableName"] = "JsonNetVersion" }), new TaskItem("Microsoft.Azure", new Hashtable { ["Version"] = "1.2.0" }), new TaskItem("Another.Package", new Hashtable { ["Version"] = "0.0.1", ["TargetFramework"] = "netstandard1.0" }), }, OutputPath = _tempFile, }; Assert.True(task.Execute(), "Task is expected to pass"); var project = ProjectRootElement.Open(_tempFile); _output.WriteLine(File.ReadAllText(_tempFile)); Assert.Empty(project.Imports); Assert.Empty(project.ImportGroups); var defaultPropGroup = Assert.Single(project.PropertyGroups, pg => string.IsNullOrEmpty(pg.Label)); var allProjectsProp = Assert.Single(defaultPropGroup.Properties); Assert.Equal("MSBuildAllProjects", allProjectsProp.Name); Assert.Empty(allProjectsProp.Condition); Assert.Equal("$(MSBuildAllProjects);$(MSBuildThisFileFullPath)", allProjectsProp.Value); var versions = Assert.Single(project.PropertyGroups, pg => pg.Label == "Package Versions"); // Order is important. These should be sorted. Assert.Collection(versions.Properties, p => { Assert.Equal("AnotherPackagePackageVersion", p.Name); Assert.Equal("Another.Package", p.Label); Assert.Equal("0.0.1", p.Value); Assert.Empty(p.Condition); }, p => { Assert.Equal("JsonNetVersion", p.Name); Assert.Equal("Newtonsoft.Json", p.Label); Assert.Equal("10.0.3", p.Value); Assert.Empty(p.Condition); }, p => { Assert.Equal("MicrosoftAzurePackageVersion", p.Name); Assert.Equal("Microsoft.Azure", p.Label); Assert.Equal("1.2.0", p.Value); Assert.Empty(p.Condition); }); }
private static ExitCodes OnInstallCommand(string versionJsonRoot, string version, IReadOnlyList <string> sources) { if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver)) { Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec."); return(ExitCodes.InvalidVersionSpec); } var options = new VersionOptions { Version = semver, PublicReleaseRefSpec = new string[] { @"^refs/heads/master$", @"^refs/heads/v\d+(?:\.\d+)?$", }, CloudBuild = new VersionOptions.CloudBuildOptions { BuildNumber = new VersionOptions.CloudBuildNumberOptions { Enabled = true, }, }, }; string searchPath = GetSpecifiedOrCurrentDirectoryPath(versionJsonRoot); if (!Directory.Exists(searchPath)) { Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath); return(ExitCodes.NoGitRepo); } using var context = GitContext.Create(searchPath, writable: true); if (!context.IsRepository) { Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath); return(ExitCodes.NoGitRepo); } if (string.IsNullOrEmpty(versionJsonRoot)) { versionJsonRoot = context.WorkingTreePath; } var existingOptions = context.VersionFile.GetVersion(); if (existingOptions != null) { if (!string.IsNullOrEmpty(version)) { var setVersionExitCode = OnSetVersionCommand(versionJsonRoot, version); if (setVersionExitCode != ExitCodes.OK) { return(setVersionExitCode); } } } else { string versionJsonPath = context.VersionFile.SetVersion(versionJsonRoot, options); context.Stage(versionJsonPath); } // Create/update the Directory.Build.props file in the directory of the version.json file to add the NB.GV package. string directoryBuildPropsPath = Path.Combine(versionJsonRoot, "Directory.Build.props"); ProjectRootElement propsFile = File.Exists(directoryBuildPropsPath) ? ProjectRootElement.Open(directoryBuildPropsPath) : ProjectRootElement.Create(directoryBuildPropsPath); const string PackageReferenceItemType = "PackageReference"; if (!propsFile.Items.Any(i => i.ItemType == PackageReferenceItemType && i.Include == PackageId)) { // Validate given sources foreach (var source in sources) { if (!Uri.TryCreate(source, UriKind.Absolute, out var _)) { Console.Error.WriteLine($"\"{source}\" is not a valid NuGet package source."); return(ExitCodes.InvalidNuGetPackageSource); } } string packageVersion = GetLatestPackageVersionAsync(PackageId, versionJsonRoot, sources).GetAwaiter().GetResult(); if (string.IsNullOrEmpty(packageVersion)) { string verifyPhrase = sources.Any() ? "Please verify the given 'source' option(s)." : "Please verify the package sources in the NuGet.Config files."; Console.Error.WriteLine($"Latest stable version of the {PackageId} package could not be determined. " + verifyPhrase); return(ExitCodes.PackageIdNotFound); } var item = propsFile.AddItem( PackageReferenceItemType, PackageId, new Dictionary <string, string> { { "Version", packageVersion }, { "PrivateAssets", "all" }, }); item.Condition = "!Exists('packages.config')"; propsFile.Save(directoryBuildPropsPath); } context.Stage(directoryBuildPropsPath); return(ExitCodes.OK); }
int IVsProjectUpgradeViaFactory.UpgradeProject_CheckOnly( string bstrFileName, IVsUpgradeLogger pLogger, out int pUpgradeRequired, out Guid pguidNewProjectFactory, out uint pUpgradeProjectCapabilityFlags ) { pUpgradeRequired = 0; pguidNewProjectFactory = Guid.Empty; if (!File.Exists(bstrFileName)) { pUpgradeProjectCapabilityFlags = 0; return(VSConstants.E_INVALIDARG); } var backupSupport = __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_BACKUPSUPPORTED | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP; var logger = new UpgradeLogger(bstrFileName, pLogger); try { var projectXml = ProjectRootElement.Open(bstrFileName); var userProjectName = bstrFileName + ".user"; var userProjectXml = File.Exists(userProjectName) ? ProjectRootElement.Open(userProjectName) : null; var upgradeRequired = UpgradeProjectCheck( projectXml, userProjectXml, logger.Log, ref pguidNewProjectFactory, ref backupSupport ); if (upgradeRequired != ProjectUpgradeState.NotNeeded) { pUpgradeRequired = 1; } } catch (Exception ex) { if (ex.IsCriticalException()) { throw; } // Log the error and don't attempt to upgrade the project. logger.Log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.UnexpectedUpgradeError, ex.Message)); CommonUtils.ActivityLogError(GetType().FullName, ex.ToString()); pUpgradeRequired = 0; } pUpgradeProjectCapabilityFlags = (uint)backupSupport; // If the upgrade checker set the factory GUID to ourselves, we need // to clear it if (pguidNewProjectFactory == GetType().GUID) { pguidNewProjectFactory = Guid.Empty; } return(VSConstants.S_OK); }
public static string[] GetIncludeFiles(string projectPath, string itemType) { var result = new List <string>(); var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs"); var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); if (root.AreDefaultCompileItemsEnabled()) { var excluded = new List <string>(); result.AddRange(existingFiles); foreach (var item in root.Items) { if (string.IsNullOrEmpty(item.Condition)) { continue; } if (item.ItemType != itemType) { continue; } string normalizedRemove = item.Remove.NormalizePath(); var glob = MSBuildGlob.Parse(normalizedRemove); excluded.AddRange(result.Where(includedFile => glob.IsMatch(includedFile))); } result.RemoveAll(f => excluded.Contains(f)); } foreach (var itemGroup in root.ItemGroups) { if (itemGroup.Condition.Length != 0) { continue; } foreach (var item in itemGroup.Items) { if (item.ItemType != itemType) { continue; } string normalizedInclude = item.Include.NormalizePath(); var glob = MSBuildGlob.Parse(normalizedInclude); foreach (var existingFile in existingFiles) { if (glob.IsMatch(existingFile)) { result.Add(existingFile); } } } } return(result.ToArray()); }
public override bool Execute() { var vstemplate = XDocument.Load(VsTemplateShell); var workingTemplate = XDocument.Load(VsTemplateShell); // var workingTemplate = XDocument.Parse(@"<VSTemplate Version=""3.0.0"" xmlns=""http://schemas.microsoft.com/developer/vstemplate/2005"" Type=""Project"" />"); if (vstemplate.Root == null || workingTemplate.Root == null) { return(false); } // var templateData = new XElement(XName.Get("TemplateData", VsTemplateSchema)); // workingTemplate.Root.Add(templateData); // MergeTemplateData(templateData, vstemplate.Root.Element(XName.Get("TemplateData", VsTemplateSchema))); var project = ProjectRootElement.Open(GetProjectFile(vstemplate)); var realProjectFile = Path.GetFileName(project.FullPath); if (realProjectFile == null) { return(false); } var projectExtension = Path.GetExtension(project.FullPath); if (projectExtension == null) { return(false); } var templateContentElement = vstemplate.Root.Element(XName.Get("TemplateContent", VsTemplateSchema)); XElement projectElement = null; if (templateContentElement != null) { var element = templateContentElement.Element(XName.Get("Project", VsTemplateSchema)); if (element != null) { projectElement = XElement.Parse(element.ToString()); } templateContentElement.Remove(); } var tcToRemove = workingTemplate.Root.Element(XName.Get("TemplateContent", VsTemplateSchema)); if (tcToRemove != null) { tcToRemove.Remove(); } templateContentElement = new XElement(XName.Get("TemplateContent", VsTemplateSchema)); templateContentElement.Add(projectElement); if (projectElement == null) { projectElement = new XElement(XName.Get("Project", VsTemplateSchema)); templateContentElement.Add(projectElement); } //else { // projectElement.RemoveAttributes(); //} // instead of calling RemoveAttribute and then Add we can just call SetAttributeValue below so that we don't // remove any attributes we are not aware of if (UpdateProjectElement) { projectElement.SetAttributeValue(XName.Get("TargetFileName"), "$safeprojectname$" + projectExtension); projectElement.SetAttributeValue(XName.Get("File"), realProjectFile); projectElement.SetAttributeValue(XName.Get("ReplaceParameters"), true); } // projectElement.Add(new XAttribute(XName.Get("TargetFileName"), "$safeprojectname$" + projectExtension)); // projectElement.Add(new XAttribute(XName.Get("File"), realProjectFile)); // projectElement.Add(new XAttribute(XName.Get("ReplaceParameters"), true)); workingTemplate.Root.Add(templateContentElement); var sourceFileNames = new HashSet <string>(); var targetFileNames = new HashSet <string>(); List <string> filesToExclude = GetFilesToExlucudeAsList(); RecurseItems(projectElement, sourceFileNames, targetFileNames); _filesToCopy = new List <string>(); var itemsToMerge = new List <string>(); foreach (var item in project.Items) { if (!IsPotentialSourceFile(item)) { continue; } var name = item.Include; var lowerName = name.ToLower(); if (targetFileNames.Contains(lowerName)) { continue; } if (filesToExclude.Contains(lowerName)) { continue; } if (item.ItemType != "Folder") { _filesToCopy.Add(name); } if (!sourceFileNames.Contains(lowerName)) { itemsToMerge.Add(name); } } //Copy all non-mutated sections var mutatedTemplateSections = new[] { "TemplateContent", "TemplateData" }; // In commit f668a11df0f403520ae1457d3fd5a872ace2107d the entire file is copied first, // so this should no longer be needed. // var elementsToCopyDirectly = vstemplate.Root.Elements().Where(x => !mutatedTemplateSections.Contains(x.Name.LocalName)); //foreach (var element in elementsToCopyDirectly) { // var clonedElement = XElement.Parse(element.ToString()); // workingTemplate.Root.Add(clonedElement); //} Merge(projectElement, itemsToMerge); workingTemplate.Save(DestinationTemplateLocation); FilesToCopy = new ITaskItem[_filesToCopy.Count]; for (int i = 0; i < FilesToCopy.Length; i++) { FilesToCopy[i] = new TaskItem(_filesToCopy[i]); } return(true); }
int IVsProjectUpgradeViaFactory.UpgradeProject( string bstrFileName, uint fUpgradeFlag, string bstrCopyLocation, out string pbstrUpgradedFullyQualifiedFileName, IVsUpgradeLogger pLogger, out int pUpgradeRequired, out Guid pguidNewProjectFactory ) { pbstrUpgradedFullyQualifiedFileName = null; // We first run (or re-run) the upgrade check and bail out early if // there is actually no need to upgrade. var hr = ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly( bstrFileName, pLogger, out pUpgradeRequired, out pguidNewProjectFactory, out var dummy ); if (!ErrorHandler.Succeeded(hr)) { return(hr); } var logger = new UpgradeLogger(bstrFileName, pLogger); var backup = (__VSPPROJECTUPGRADEVIAFACTORYFLAGS)fUpgradeFlag; bool anyBackup, sxsBackup, copyBackup; anyBackup = backup.HasFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_BACKUPSUPPORTED); if (anyBackup) { sxsBackup = backup.HasFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP); copyBackup = !sxsBackup && backup.HasFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP); } else { sxsBackup = copyBackup = false; } if (copyBackup) { throw new NotSupportedException("PUVFF_COPYBACKUP is not supported"); } pbstrUpgradedFullyQualifiedFileName = bstrFileName; if (pUpgradeRequired == 0 && !copyBackup) { // No upgrade required, and no backup required. logger.Log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradeNotRequired)); return(VSConstants.S_OK); } try { UpgradeLogger logger2 = null; var userFileName = bstrFileName + ".user"; if (File.Exists(userFileName)) { logger2 = new UpgradeLogger(userFileName, pLogger); } else { userFileName = null; } if (sxsBackup) { // For SxS backups we want to put the old project file alongside // the current one. bstrCopyLocation = Path.GetDirectoryName(bstrFileName); } if (anyBackup) { var namePart = Path.GetFileNameWithoutExtension(bstrFileName); var extPart = Path.GetExtension(bstrFileName) + (sxsBackup ? ".old" : ""); var projectFileBackup = Path.Combine(bstrCopyLocation, namePart + extPart); for (var i = 1; File.Exists(projectFileBackup); ++i) { projectFileBackup = Path.Combine( bstrCopyLocation, string.Format("{0}{1}{2}", namePart, i, extPart) ); } File.Copy(bstrFileName, projectFileBackup); // Back up the .user file if there is one if (userFileName != null) { if (sxsBackup) { File.Copy( userFileName, Path.ChangeExtension(projectFileBackup, ".user.old") ); } else { File.Copy(userFileName, projectFileBackup + ".old"); } } // TODO: Implement support for backing up all files //if (copyBackup) { // - Open the project // - Inspect all Items // - Copy those items that are referenced relative to the // project file into bstrCopyLocation //} } if (this.site.GetService(typeof(SVsQueryEditQuerySave)) is IVsQueryEditQuerySave2 queryEdit) { var tagVSQueryEditFlags_QEF_AllowUnopenedProjects = (tagVSQueryEditFlags)0x80; ErrorHandler.ThrowOnFailure(queryEdit.QueryEditFiles( (uint)(tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting | tagVSQueryEditFlags.QEF_DisallowInMemoryEdits | tagVSQueryEditFlags_QEF_AllowUnopenedProjects), 1, new[] { bstrFileName }, null, null, out var editVerdict, out var queryEditMoreInfo )); if (editVerdict != (uint)tagVSQueryEditResult.QER_EditOK) { logger.Log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.UpgradeCannotCheckOutProject)); return(VSConstants.E_FAIL); } // File may have been updated during checkout, so check // again whether we need to upgrade. if ((queryEditMoreInfo & (uint)tagVSQueryEditResultFlags.QER_MaybeChanged) != 0) { hr = ((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly( bstrFileName, pLogger, out pUpgradeRequired, out pguidNewProjectFactory, out dummy ); if (!ErrorHandler.Succeeded(hr)) { return(hr); } if (pUpgradeRequired == 0) { logger.Log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradeNotRequired)); return(VSConstants.S_OK); } } } // Load the project file and user file into MSBuild as plain // XML to make it easier for subclasses. var projectXml = ProjectRootElement.Open(bstrFileName); if (projectXml == null) { throw new Exception(SR.GetString(SR.UpgradeCannotLoadProject)); } var userXml = userFileName != null?ProjectRootElement.Open(userFileName) : null; // Invoke our virtual UpgradeProject function. If it fails, it // will throw and we will log the exception. UpgradeProject(ref projectXml, ref userXml, logger.Log); // Get the SCC info from the project file. if (projectXml != null) { this._cachedSccProject = bstrFileName; this._cachedSccProjectName = string.Empty; this._cachedSccAuxPath = string.Empty; this._cachedSccLocalPath = string.Empty; this._cachedSccProvider = string.Empty; foreach (var property in projectXml.Properties) { switch (property.Name) { case ProjectFileConstants.SccProjectName: this._cachedSccProjectName = property.Value; break; case ProjectFileConstants.SccAuxPath: this._cachedSccAuxPath = property.Value; break; case ProjectFileConstants.SccLocalPath: this._cachedSccLocalPath = property.Value; break; case ProjectFileConstants.SccProvider: this._cachedSccProvider = property.Value; break; default: break; } } } // Save the updated files. if (projectXml != null) { projectXml.Save(); } if (userXml != null) { userXml.Save(); } // Need to add "Converted" (unlocalized) to the report because // the XSLT refers to it. logger.Log(__VSUL_ERRORLEVEL.VSUL_STATUSMSG, "Converted"); return(VSConstants.S_OK); } catch (Exception ex) when(!ExceptionExtensions.IsCriticalException(ex)) { logger.Log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.UnexpectedUpgradeError, ex.Message)); try { ActivityLog.LogError(GetType().FullName, ex.ToString()); } catch (InvalidOperationException) { // Cannot log to ActivityLog. This may occur if we are // outside of VS right now (for example, unit tests). System.Diagnostics.Trace.TraceError(ex.ToString()); } return(VSConstants.E_FAIL); } }
public static void MigrateFromOldConfigNames(string projectPath) { var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); bool dirty = false; bool hasGodotProjectGeneratorVersion = false; bool foundOldConfiguration = false; foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition == string.Empty)) { if (!hasGodotProjectGeneratorVersion && propertyGroup.Properties.Any(p => p.Name == "GodotProjectGeneratorVersion")) { hasGodotProjectGeneratorVersion = true; } foreach (var configItem in propertyGroup.Properties .Where(p => p.Condition.Trim() == "'$(Configuration)' == ''" && p.Value == "Tools")) { configItem.Value = "Debug"; foundOldConfiguration = true; dirty = true; } } if (!hasGodotProjectGeneratorVersion) { root.PropertyGroups.First(g => g.Condition == string.Empty)? .AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString()); dirty = true; } if (!foundOldConfiguration) { var toolsConditions = new[] { "'$(Configuration)|$(Platform)' == 'Tools|AnyCPU'", "'$(Configuration)|$(Platform)' != 'Tools|AnyCPU'", "'$(Configuration)' == 'Tools'", "'$(Configuration)' != 'Tools'" }; foundOldConfiguration = root.PropertyGroups .Any(g => toolsConditions.Any(c => c == g.Condition.Trim())); } if (foundOldConfiguration) { void MigrateConfigurationConditions(string oldConfiguration, string newConfiguration) { void MigrateConditions(string oldCondition, string newCondition) { foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition)) { propertyGroup.Condition = " " + newCondition + " "; dirty = true; } foreach (var propertyGroup in root.PropertyGroups) { foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition)) { prop.Condition = " " + newCondition + " "; dirty = true; } } foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition)) { itemGroup.Condition = " " + newCondition + " "; dirty = true; } foreach (var itemGroup in root.ItemGroups) { foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition)) { item.Condition = " " + newCondition + " "; dirty = true; } } } foreach (var op in new[] { "==", "!=" }) { MigrateConditions($"'$(Configuration)|$(Platform)' {op} '{oldConfiguration}|AnyCPU'", $"'$(Configuration)|$(Platform)' {op} '{newConfiguration}|AnyCPU'"); MigrateConditions($"'$(Configuration)' {op} '{oldConfiguration}'", $"'$(Configuration)' {op} '{newConfiguration}'"); } } MigrateConfigurationConditions("Debug", "ExportDebug"); MigrateConfigurationConditions("Release", "ExportRelease"); MigrateConfigurationConditions("Tools", "Debug"); // Must be last } if (dirty) { root.Save(); } }
void IVsProjectUpgradeViaFactory4.UpgradeProject_CheckOnly( string bstrFileName, IVsUpgradeLogger pLogger, out uint pUpgradeRequired, out Guid pguidNewProjectFactory, out uint pUpgradeProjectCapabilityFlags ) { pguidNewProjectFactory = Guid.Empty; if (!File.Exists(bstrFileName)) { pUpgradeRequired = 0; pUpgradeProjectCapabilityFlags = 0; return; } var backupSupport = __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_BACKUPSUPPORTED | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP; var logger = new UpgradeLogger(bstrFileName, pLogger); try { var projectXml = ProjectRootElement.Open(bstrFileName); var userProjectName = bstrFileName + ".user"; var userProjectXml = File.Exists(userProjectName) ? ProjectRootElement.Open(userProjectName) : null; var upgradeRequired = UpgradeProjectCheck( projectXml, userProjectXml, logger.Log, ref pguidNewProjectFactory, ref backupSupport ); switch (upgradeRequired) { case ProjectUpgradeState.SafeRepair: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_SAFEREPAIR; break; case ProjectUpgradeState.UnsafeRepair: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_UNSAFEREPAIR; break; case ProjectUpgradeState.OneWayUpgrade: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_ONEWAYUPGRADE; break; case ProjectUpgradeState.Incompatible: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_INCOMPATIBLE; break; case ProjectUpgradeState.Deprecated: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_DEPRECATED; break; default: case ProjectUpgradeState.NotNeeded: pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_NOREPAIR; break; } } catch (Exception ex) when(!ExceptionExtensions.IsCriticalException(ex)) { // Log the error and don't attempt to upgrade the project. logger.Log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.UnexpectedUpgradeError, ex.Message)); try { ActivityLog.LogError(GetType().FullName, ex.ToString()); } catch (InvalidOperationException) { // Cannot log to ActivityLog. This may occur if we are // outside of VS right now (for example, unit tests). System.Diagnostics.Trace.TraceError(ex.ToString()); } pUpgradeRequired = (uint)__VSPPROJECTUPGRADEVIAFACTORYREPAIRFLAGS.VSPUVF_PROJECT_NOREPAIR; } pUpgradeProjectCapabilityFlags = (uint)backupSupport; // If the upgrade checker set the factory GUID to ourselves, we need // to clear it if (pguidNewProjectFactory == GetType().GUID) { pguidNewProjectFactory = Guid.Empty; } }
public static DependencyVersionsFile Load(string sourceFile) { var project = ProjectRootElement.Open(sourceFile, ProjectCollection.GlobalProjectCollection, preserveFormatting: true); return(Load(project)); }
public override bool Execute() { var collection = new ProjectCollection(); var xml = new ConcurrentDictionary <string, XDocument>(StringComparer.OrdinalIgnoreCase); var root = ProjectRootElement.Open(HelpProject, collection); var eval = new Project(root, null, null, collection); var logical = eval.GetLogicalProject().ToArray(); var allProps = logical .OfType <ProjectPropertyElement>() // Add the local props first .Where(x => x.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase)) .Concat(logical .OfType <ProjectPropertyElement>() .Where(x => !x.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase))) .ToArray(); var allTargets = logical .OfType <ProjectTargetElement>() // Add the local props first .Where(x => x.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase)) .Concat(logical .OfType <ProjectTargetElement>() .Where(x => !x.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase))) .ToArray(); var includeExpr = new Regex(HelpInclude, RegexOptions.IgnoreCase); var excludeExpr = new Regex(HelpExclude, RegexOptions.IgnoreCase); var searchExpr = new Regex(HelpSearch, RegexOptions.IgnoreCase); // Should exclude it if it doesn't match the include or matches the exclude bool ShouldExclude(string value) => (!includeExpr.IsMatch(value) || excludeExpr.IsMatch(value)); bool SatisfiesSearch(string value) => string.IsNullOrWhiteSpace(HelpSearch) || searchExpr.IsMatch(value); var helpProperties = bool.Parse(HelpProperties); var helpTargets = bool.Parse(HelpTargets); var helpImports = bool.Parse(HelpImports); var metaHelp = new StringBuilder(); metaHelp.Append("Help: properties to customize what 'Help' reports"); var help = new StringBuilder(); var standard = allTargets.Any(t => t.Name == "Configure") && allTargets.Any(t => t.Name == "Build") && allTargets.Any(t => t.Name == "Test"); if (standard) { help.AppendLine(UseColors ? "Standard: {YES:LawnGreen} √ (Configure, Build and Test targets supported)" : "Standard: YES √ (Configure, Build and Test targets supported)").AppendLine(); } else { help.AppendLine(UseColors ? "Standard: {NO:Tomato} x (Missing Configure, Build, Test or Run targets. Lean more at http://corebuild.io" : "Standard: NO x (Missing Configure, Build, Test or Run targets. Lean more at http://corebuild.io").AppendLine(); Log.LogWarning(null, "CB01", null, null, 0, 0, 0, 0, "This project is NOT CoreBuild Standard compatible. Please provide Configure, Build and Test targets. Lean more at http://corebuild.io"); } var hasProps = false; if (helpProperties) { var propsHelp = new StringBuilder(); propsHelp.Append("Properties:"); var processed = new HashSet <string>(); var alwaysInclude = new HashSet <string>(HelpProperty.Select(x => x.ItemSpec)); foreach (var prop in allProps .Where(x => x != null && !x.Name.StartsWith("_")) .OrderBy(x => x.Name)) { // First property to make it to the list wins. // Target project source is loaded first, followed by imported properties. if (processed.Contains(prop.Name)) { continue; } var isMeta = Path.GetFileName(prop.Location.File) == "CoreBuild.Help.targets"; var builder = isMeta ? metaHelp : propsHelp; if (!alwaysInclude.Contains(prop.Name)) { // Skip non-meta props that should be excluded if (!isMeta && ShouldExclude(prop.Name)) { processed.Add(prop.Name); continue; } var isLocal = prop.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase); // Skip non-meta props that are from imports as needed if (!isMeta && !helpImports && !isLocal) { processed.Add(prop.Name); continue; } } var candidate = new CandidateElement(prop.Name, allProps.Where(x => x.Name == prop.Name), xml); if (candidate.IsHidden) { processed.Add(prop.Name); continue; } if (isMeta || alwaysInclude.Contains(prop.Name) || SatisfiesSearch(prop.Name) || SatisfiesSearch(candidate.Comment)) { // We got a prop. Flag if non-meta if (!isMeta) { hasProps = true; } if (isMeta) { builder.AppendLine().Append($"\t- {prop.Name}"); } else { builder.AppendLine().Append(UseColors ? $"\t- {{{prop.Name}:Aqua}}" : $"\t- {prop.Name}"); } if (!string.IsNullOrWhiteSpace(candidate.Comment)) { AppendComment(builder, prop.Name, candidate.Comment); } processed.Add(prop.Name); } } if (hasProps) { help.Append(propsHelp.ToString()); } } if (helpTargets) { var hasTargets = false; var targetsHelp = new StringBuilder(); if (hasProps) { targetsHelp.AppendLine().AppendLine(); } targetsHelp.Append("Targets:"); var processed = new HashSet <string>(); var alwaysInclude = new HashSet <string>(HelpTarget.Select(x => x.ItemSpec)); foreach (var target in allTargets .Where(x => x.Name != "Help" && !x.Name.StartsWith("_")) .OrderBy(x => x.Name)) { // First target to make it to the list wins. // Target project source is loaded first, followed by imported targets. if (processed.Contains(target.Name)) { continue; } if (!alwaysInclude.Contains(target.Name)) { var isLocal = target.Location.File.Equals(HelpProject, StringComparison.OrdinalIgnoreCase); // Skip targets that should be excluded if (ShouldExclude(target.Name) || // Skip targets that are from imports as needed (!helpImports && !isLocal)) { processed.Add(target.Name); continue; } } var candidate = new CandidateElement(target.Name, allTargets.Where(x => x.Name == target.Name), xml); if (candidate.IsHidden) { processed.Add(target.Name); continue; } if (alwaysInclude.Contains(target.Name) || SatisfiesSearch(target.Name) || SatisfiesSearch(candidate.Comment)) { hasTargets = true; targetsHelp.AppendLine().Append(UseColors ? $"\t- {{{target.Name}:Yellow}}" : $"\t- {target.Name}"); if (!string.IsNullOrWhiteSpace(candidate.Comment)) { AppendComment(targetsHelp, target.Name, candidate.Comment); } } } if (hasTargets) { help.Append(targetsHelp.ToString()); } } help.AppendLine(); metaHelp.AppendLine(); Log.LogMessage(MessageImportance.High, help.ToString()); Log.LogMessage(MessageImportance.Normal, metaHelp.ToString()); return(true); }
static void Main(string[] args) { var sdkRootPath = args[0]; var beforeCommonSdkTargetsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.BeforeCommon.targets"); var commonSdkTargetsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.Common.targets"); var sdkTargetsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.targets"); var sdkPropsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.props"); var csharpTargetsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.CSharp.targets"); var csharpPropsFilePath = Path.Combine(sdkRootPath, "src", "Tasks", "Microsoft.NET.Build.Tasks", "build", "Microsoft.NET.Sdk.CSharp.props"); var beforeCommonSdkTargetsFile = ProjectRootElement.Open(beforeCommonSdkTargetsFilePath); var commonSdkTargetsFile = ProjectRootElement.Open(commonSdkTargetsFilePath); var sdkTargetsFile = ProjectRootElement.Open(sdkTargetsFilePath); var sdkPropsFile = ProjectRootElement.Open(sdkPropsFilePath); var csharpPropsFile = ProjectRootElement.Open(csharpPropsFilePath); var csharpTargetsFile = ProjectRootElement.Open(csharpTargetsFilePath); var allProperties = new List <DefaultProjectPropertyInfo>(); var allItems = new List <DefaultProjectItemInfo>(); AddPropertyDefault(allProperties, sdkPropsFile, "OutputType"); AddPropertyDefault(allProperties, sdkPropsFile, "Configuration", ignoreConditions: true); AddPropertyDefault(allProperties, sdkPropsFile, "Platform"); AddPropertyDefault(allProperties, sdkPropsFile, "FileAlignment"); AddPropertyDefault(allProperties, sdkPropsFile, "PlatformTarget"); AddPropertyDefault(allProperties, sdkPropsFile, "ErrorReport"); AddPropertyDefault(allProperties, sdkPropsFile, "AssemblyName"); AddPropertyDefault(allProperties, sdkPropsFile, "RootNamespace"); AddPropertyDefault(allProperties, sdkPropsFile, "Deterministic"); AddPropertyDefault(allProperties, csharpPropsFile, "WarningLevel"); AddPropertyDefault(allProperties, csharpPropsFile, "NoWarn"); AddHardcodedPropertyDefault(allProperties, "PackageRequireLicenseAcceptance", "false"); AddConfigurationPropertyDefaults(allProperties, sdkPropsFile, "Debug"); AddConfigurationPropertyDefaults(allProperties, sdkPropsFile, "Release"); AddConfigurationPropertyDefaults(allProperties, csharpPropsFile, "Debug"); AddConfigurationPropertyDefaults(allProperties, csharpPropsFile, "Release"); AddPropertyDefault(allProperties, commonSdkTargetsFile, "VersionPrefix", ignoreConditions: true); AddPropertyDefault(allProperties, commonSdkTargetsFile, "AssemblyTitle", ignoreConditions: true); AddPropertyDefault(allProperties, commonSdkTargetsFile, "Product", ignoreConditions: true); AddPropertyDefault(allProperties, commonSdkTargetsFile, "NeutralLanguage", ignoreConditions: true); AddPropertyDefault(allProperties, beforeCommonSdkTargetsFile, "AutoUnifyAssemblyReferences", ignoreConditions: true); AddPropertyDefault(allProperties, beforeCommonSdkTargetsFile, "DesignTimeAutoUnify", ignoreConditions: true); AddPropertyDefault(allProperties, beforeCommonSdkTargetsFile, "TargetExt", ignoreConditions: true); AddCompileAndEmbeddedResourceDefaults(allItems, sdkTargetsFile); var wrapper = new SerializableMigrationDefaultsInfo() { Items = allItems, Properties = allProperties }; var output = Path.Combine(Directory.GetCurrentDirectory(), "sdkdefaults.json"); string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented); File.WriteAllText(output, json); }
List <CustomBuildEval> EvaluateCustomBuild() { var eval = new List <CustomBuildEval>(); var evaluateTarget = new XElement(ns + "Target", new XAttribute("Name", "EvaluateCustomBuild"), new XElement(ns + "PropertyGroup", new XElement(ns + "CustomBuildEval", "@(CustomBuild->'" + "{%(Identity)}" + "{%(AdditionalInputs)}" + "{%(Outputs)}" + "{%(Message)}" + "{%(Command)}')"))); this[Files.Project].xml.Root.Add(evaluateTarget); var tempProjFile = Path.Combine( Path.GetDirectoryName(this[Files.Project].filePath), Path.GetRandomFileName()); if (File.Exists(tempProjFile)) { File.Delete(tempProjFile); } this[Files.Project].xml.Save(tempProjFile); var projRoot = ProjectRootElement.Open(tempProjFile); var pattern = new Regex(@"{([^}]+)}{([^}]+)}{([^}]+)}{([^}]+)}{([^}]+)}"); var projConfigs = this[Files.Project].xml .Elements(ns + "Project") .Elements(ns + "ItemGroup") .Elements(ns + "ProjectConfiguration"); foreach (var projConfig in projConfigs) { string configName = (string)projConfig.Attribute("Include"); var properties = new Dictionary <string, string>(); foreach (var configProp in projConfig.Elements()) { properties.Add(configProp.Name.LocalName, (string)configProp); } var projInst = new ProjectInstance(projRoot, properties, null, new ProjectCollection()); var buildRequest = new BuildRequestData( projInst, new string[] { "EvaluateCustomBuild" }, null, BuildRequestDataFlags.ProvideProjectStateAfterBuild); var buildResult = BuildManager.DefaultBuildManager.Build( new BuildParameters(), buildRequest); string customBuildEval = buildResult.ProjectStateAfterBuild .GetPropertyValue("CustomBuildEval"); foreach (Match cbEval in pattern.Matches(customBuildEval)) { eval.Add(new CustomBuildEval { ProjectConfig = configName, Identity = cbEval.Groups[1].Value, AdditionalInputs = cbEval.Groups[2].Value, Outputs = cbEval.Groups[3].Value, Message = cbEval.Groups[4].Value, Command = cbEval.Groups[5].Value, }); } } evaluateTarget.Remove(); File.Delete(tempProjFile); return(eval); }
public ProjectRootPathNode(string filePath) { _filePath = filePath; _element = ProjectRootElement.Open(_filePath); }
public static void AddProject(this SlnFile slnFile, string fullProjectPath, IList <string> solutionFolders) { if (string.IsNullOrEmpty(fullProjectPath)) { throw new ArgumentException(); } var relativeProjectPath = Path.GetRelativePath( PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory), fullProjectPath); if (slnFile.Projects.Any((p) => string.Equals(p.FilePath, relativeProjectPath, StringComparison.OrdinalIgnoreCase))) { Reporter.Output.WriteLine(string.Format( CommonLocalizableStrings.SolutionAlreadyContainsProject, slnFile.FullPath, relativeProjectPath)); } else { ProjectRootElement rootElement = null; ProjectInstance projectInstance = null; try { rootElement = ProjectRootElement.Open(fullProjectPath); projectInstance = new ProjectInstance(rootElement); } catch (InvalidProjectFileException e) { Reporter.Error.WriteLine(string.Format( CommonLocalizableStrings.InvalidProjectWithExceptionMessage, fullProjectPath, e.Message)); return; } var slnProject = new SlnProject { Id = projectInstance.GetProjectId(), TypeGuid = rootElement.GetProjectTypeGuid() ?? projectInstance.GetDefaultProjectTypeGuid(), Name = Path.GetFileNameWithoutExtension(relativeProjectPath), FilePath = relativeProjectPath }; if (string.IsNullOrEmpty(slnProject.TypeGuid)) { Reporter.Error.WriteLine( string.Format( CommonLocalizableStrings.UnsupportedProjectType, projectInstance.FullPath)); return; } // NOTE: The order you create the sections determines the order they are written to the sln // file. In the case of an empty sln file, in order to make sure the solution configurations // section comes first we need to add it first. This doesn't affect correctness but does // stop VS from re-ordering things later on. Since we are keeping the SlnFile class low-level // it shouldn't care about the VS implementation details. That's why we handle this here. slnFile.AddDefaultBuildConfigurations(); slnFile.MapSolutionConfigurationsToProject( projectInstance, slnFile.ProjectConfigurationsSection.GetOrCreatePropertySet(slnProject.Id)); if (solutionFolders != null) { slnFile.AddSolutionFolders(slnProject, solutionFolders); } slnFile.Projects.Add(slnProject); Reporter.Output.WriteLine( string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, relativeProjectPath)); } }
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); }