/// <summary> /// Figures out what project to build. /// Throws if it cannot figure it out. /// </summary> /// <param name="parameters"></param> /// <returns>The project filename/path.</returns> /// Internal for testing purposes internal static string ProcessProjectSwitch ( string[] parameters, string[] projectsExtensionsToIgnore, DirectoryGetFiles getFiles ) { ErrorUtilities.VerifyThrow(parameters.Length <= 1, "It should not be possible to specify more than 1 project at a time."); string projectFile = null; // We need to look in the current directory for a project file... if (parameters.Length == 0) { // Get all files in the current directory that have a proj-like extension string[] potentialProjectFiles = getFiles(".", "*.*proj"); // Get all files in the current directory that have a sln extension string[] potentialSolutionFiles = getFiles(".", "*.sln"); List<string> extensionsToIgnore = new List<string>(); if (projectsExtensionsToIgnore != null) { extensionsToIgnore.AddRange(projectsExtensionsToIgnore); } if (potentialProjectFiles != null) { foreach (string s in potentialProjectFiles) { if (s.EndsWith("~", true, CultureInfo.CurrentCulture)) { extensionsToIgnore.Add(Path.GetExtension(s)); } } } if (potentialSolutionFiles != null) { foreach (string s in potentialSolutionFiles) { if (!FileUtilities.IsSolutionFilename(s)) { extensionsToIgnore.Add(Path.GetExtension(s)); } } } Dictionary<string, object> extensionsToIgnoreDictionary = ValidateExtensions(extensionsToIgnore.ToArray()); // Remove projects that are in the projectExtensionsToIgnore List // If we have no extensions to ignore we can skip removing any extensions if (extensionsToIgnoreDictionary.Count > 0) { // No point removing extensions if we have no project files if (potentialProjectFiles != null && potentialProjectFiles.Length > 0) { potentialProjectFiles = RemoveFilesWithExtensionsToIgnore(potentialProjectFiles, extensionsToIgnoreDictionary); } // No point removing extensions if we have no solutions if (potentialSolutionFiles != null && potentialSolutionFiles.Length > 0) { potentialSolutionFiles = RemoveFilesWithExtensionsToIgnore(potentialSolutionFiles, extensionsToIgnoreDictionary); } } // If there is exactly 1 project file and exactly 1 solution file if ((potentialProjectFiles.Length == 1) && (potentialSolutionFiles.Length == 1)) { // Grab the name of both project and solution without extensions string solutionName = Path.GetFileNameWithoutExtension(potentialSolutionFiles[0]); string projectName = Path.GetFileNameWithoutExtension(potentialProjectFiles[0]); // Compare the names and error if they are not identical InitializationException.VerifyThrow(String.Compare(solutionName, projectName, StringComparison.OrdinalIgnoreCase) == 0, "AmbiguousProjectError"); } // If there is more than one solution file in the current directory we have no idea which one to use else if (potentialSolutionFiles.Length > 1) { InitializationException.VerifyThrow(false, "AmbiguousProjectError"); } // If there is more than one project file in the current directory we may be able to figure it out else if (potentialProjectFiles.Length > 1) { // We have more than one project, it is ambiguous at the moment bool isAmbiguousProject = true; // If there are exactly two projects and one of them is a .proj use that one and ignore the other if (potentialProjectFiles.Length == 2) { string firstPotentialProjectExtension = Path.GetExtension(potentialProjectFiles[0]); string secondPotentialProjectExtension = Path.GetExtension(potentialProjectFiles[1]); // If the two projects have the same extension we can't decide which one to pick if (String.Compare(firstPotentialProjectExtension, secondPotentialProjectExtension, StringComparison.OrdinalIgnoreCase) != 0) { // Check to see if the first project is the proj, if it is use it if (String.Compare(firstPotentialProjectExtension, ".proj", StringComparison.OrdinalIgnoreCase) == 0) { potentialProjectFiles = new string[] { potentialProjectFiles[0] }; // We have made a decision isAmbiguousProject = false; } // If the first project is not the proj check to see if the second one is the proj, if so use it else if (String.Compare(secondPotentialProjectExtension, ".proj", StringComparison.OrdinalIgnoreCase) == 0) { potentialProjectFiles = new string[] { potentialProjectFiles[1] }; // We have made a decision isAmbiguousProject = false; } } } InitializationException.VerifyThrow(!isAmbiguousProject, "AmbiguousProjectError"); } // if there are no project or solution files in the directory, we can't build else if ((potentialProjectFiles.Length == 0) && (potentialSolutionFiles.Length == 0)) { InitializationException.VerifyThrow(false, "MissingProjectError"); } // We are down to only one project or solution. // If only 1 solution build the solution. If only 1 project build the project // If 1 solution and 1 project and they are of the same name build the solution projectFile = (potentialSolutionFiles.Length == 1) ? potentialSolutionFiles[0] : potentialProjectFiles[0]; } else { InitializationException.VerifyThrow(File.Exists(parameters[0]), "ProjectNotFoundError", parameters[0]); projectFile = parameters[0]; } return projectFile; }
/// <summary> /// Additional constructor to make unit testing the TaskRegistry support easier /// </summary> /// <remarks> /// Internal for unit test purposes only. /// </remarks> /// <param name="toolsVersion">Name of the toolset</param> /// <param name="toolsPath">Path to this toolset's tasks and targets</param> /// <param name="buildProperties"> /// Properties that should be associated with the Toolset. /// May be null, in which case an empty property group will be used. /// </param> /// <param name="projectCollection">The project collection.</param> /// <param name="getFiles">A delegate to intercept GetFiles calls. For unit testing.</param> /// <param name="loadXmlFromPath">A delegate to intercept Xml load calls. For unit testing.</param> internal Toolset(string toolsVersion, string toolsPath, PropertyDictionary<ProjectPropertyInstance> buildProperties, ProjectCollection projectCollection, DirectoryGetFiles getFiles, LoadXmlFromPath loadXmlFromPath, string msbuildOverrideTasksPath, DirectoryExists directoryExists) : this(toolsVersion, toolsPath, buildProperties, projectCollection.EnvironmentProperties, projectCollection.GlobalPropertiesCollection, null, msbuildOverrideTasksPath, null) { ErrorUtilities.VerifyThrowInternalNull(getFiles, "getFiles"); ErrorUtilities.VerifyThrowInternalNull(loadXmlFromPath, "loadXmlFromPath"); _directoryExists = directoryExists; _getFiles = getFiles; _loadXmlFromPath = loadXmlFromPath; }
/// <summary> /// Given a search path and a task pattern get a list of task or override task files. /// </summary> internal static string[] GetTaskFiles(DirectoryGetFiles getFiles, ILoggingService loggingServices, BuildEventContext buildEventContext, string taskPattern, string searchPath, string taskFileWarning) { string[] defaultTasksFiles = { }; try { if (null != getFiles) { defaultTasksFiles = getFiles(searchPath, taskPattern); } else { // The order of the returned file names is not guaranteed per msdn defaultTasksFiles = Directory.GetFiles(searchPath, taskPattern); } if (defaultTasksFiles.Length == 0) { loggingServices.LogWarning ( buildEventContext, null, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty), taskFileWarning, taskPattern, searchPath, String.Empty ); } } catch (Exception e) { // handle problems when reading the default tasks files if (ExceptionHandling.NotExpectedException(e)) { // Catching Exception, but rethrowing unless it's an IO related exception. throw; } loggingServices.LogWarning ( buildEventContext, null, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty), taskFileWarning, taskPattern, searchPath, e.Message ); } // Sort the file names to give a deterministic order Array.Sort<string>(defaultTasksFiles, StringComparer.OrdinalIgnoreCase); return defaultTasksFiles; }
internal static string ProcessProjectSwitch ( string[] parameters, string[] projectsExtensionsToIgnore, DirectoryGetFiles getFiles ) { ErrorUtilities.VerifyThrow(parameters.Length <= 1, "It should not be possible to specify more than 1 project at a time."); string projectFile = null; string projectDirectory = null; if (parameters.Length == 1) { projectFile = FileUtilities.FixFilePath(parameters[0]); if (Directory.Exists(projectFile)) { // If the project file is actually a directory then change the directory to be searched // and null out the project file projectDirectory = projectFile; projectFile = null; } else { InitializationException.VerifyThrow(File.Exists(projectFile), "ProjectNotFoundError", projectFile); } } // We need to look in a directory for a project file... if (projectFile == null) { // Get all files in the current directory that have a proj-like extension string[] potentialProjectFiles = getFiles(projectDirectory ?? ".", "*.*proj"); // Get all files in the current directory that have a sln extension string[] potentialSolutionFiles = getFiles(projectDirectory ?? ".", "*.sln"); List <string> extensionsToIgnore = new List <string>(); if (projectsExtensionsToIgnore != null) { extensionsToIgnore.AddRange(projectsExtensionsToIgnore); } if (potentialProjectFiles != null) { foreach (string s in potentialProjectFiles) { if (s.EndsWith("~", StringComparison.CurrentCultureIgnoreCase)) { extensionsToIgnore.Add(Path.GetExtension(s)); } } } if (potentialSolutionFiles != null) { foreach (string s in potentialSolutionFiles) { if (!FileUtilities.IsSolutionFilename(s)) { extensionsToIgnore.Add(Path.GetExtension(s)); } } } Dictionary <string, object> extensionsToIgnoreDictionary = ValidateExtensions(extensionsToIgnore.ToArray()); // Remove projects that are in the projectExtensionsToIgnore List // If we have no extensions to ignore we can skip removing any extensions if (extensionsToIgnoreDictionary.Count > 0) { // No point removing extensions if we have no project files if (potentialProjectFiles != null && potentialProjectFiles.Length > 0) { potentialProjectFiles = RemoveFilesWithExtensionsToIgnore(potentialProjectFiles, extensionsToIgnoreDictionary); } // No point removing extensions if we have no solutions if (potentialSolutionFiles != null && potentialSolutionFiles.Length > 0) { potentialSolutionFiles = RemoveFilesWithExtensionsToIgnore(potentialSolutionFiles, extensionsToIgnoreDictionary); } } // If there is exactly 1 project file and exactly 1 solution file if ((potentialProjectFiles.Length == 1) && (potentialSolutionFiles.Length == 1)) { // Grab the name of both project and solution without extensions string solutionName = Path.GetFileNameWithoutExtension(potentialSolutionFiles[0]); string projectName = Path.GetFileNameWithoutExtension(potentialProjectFiles[0]); // Compare the names and error if they are not identical InitializationException.VerifyThrow(String.Compare(solutionName, projectName, StringComparison.OrdinalIgnoreCase) == 0, projectDirectory == null ? "AmbiguousProjectError" : "AmbiguousProjectDirectoryError", null, projectDirectory); } // If there is more than one solution file in the current directory we have no idea which one to use else if (potentialSolutionFiles.Length > 1) { InitializationException.VerifyThrow(false, projectDirectory == null ? "AmbiguousProjectError" : "AmbiguousProjectDirectoryError", null, projectDirectory); } // If there is more than one project file in the current directory we may be able to figure it out else if (potentialProjectFiles.Length > 1) { // We have more than one project, it is ambiguous at the moment bool isAmbiguousProject = true; // If there are exactly two projects and one of them is a .proj use that one and ignore the other if (potentialProjectFiles.Length == 2) { string firstPotentialProjectExtension = Path.GetExtension(potentialProjectFiles[0]); string secondPotentialProjectExtension = Path.GetExtension(potentialProjectFiles[1]); // If the two projects have the same extension we can't decide which one to pick if (String.Compare(firstPotentialProjectExtension, secondPotentialProjectExtension, StringComparison.OrdinalIgnoreCase) != 0) { // Check to see if the first project is the proj, if it is use it if (String.Compare(firstPotentialProjectExtension, ".proj", StringComparison.OrdinalIgnoreCase) == 0) { potentialProjectFiles = new string[] { potentialProjectFiles[0] }; // We have made a decision isAmbiguousProject = false; } // If the first project is not the proj check to see if the second one is the proj, if so use it else if (String.Compare(secondPotentialProjectExtension, ".proj", StringComparison.OrdinalIgnoreCase) == 0) { potentialProjectFiles = new string[] { potentialProjectFiles[1] }; // We have made a decision isAmbiguousProject = false; } } } InitializationException.VerifyThrow(!isAmbiguousProject, projectDirectory == null ? "AmbiguousProjectError" : "AmbiguousProjectDirectoryError", null, projectDirectory); } // if there are no project or solution files in the directory, we can't build else if ((potentialProjectFiles.Length == 0) && (potentialSolutionFiles.Length == 0)) { InitializationException.VerifyThrow(false, "MissingProjectError"); } // We are down to only one project or solution. // If only 1 solution build the solution. If only 1 project build the project // If 1 solution and 1 project and they are of the same name build the solution projectFile = (potentialSolutionFiles.Length == 1) ? potentialSolutionFiles[0] : potentialProjectFiles[0]; } return(projectFile); }