/// <summary> Copies and links a List of Projects into the <c> destinationFolder </c>. /// <para> File is Linked from the first <c> projectsToLink </c> for each if there is more than 1 source. </para> </summary> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null or empty. </exception> /// <param name="projectsToLink"> a List of projects to Link. </param> /// <param name="destinationFolder"> Pathname of the destination folder. Empty string throws <c>ArgumentNullException</c></param> /// <param name="createSubFolders"> True (default) if you want each now project in its own subfolder. </param> internal static void NewProject(List<ProjectToLink> projectsToLink, string destinationFolder, bool createSubFolders = true) { if (projectsToLink == null) throw new ArgumentNullException(nameof(projectsToLink)); if (string.IsNullOrEmpty(destinationFolder)) throw new ArgumentNullException(nameof(destinationFolder)); var destinationProjects = new HashSet<string>(projectsToLink.Select(p => p.DestinationProjectName)); Log.WriteLine("Recycling " + destinationProjects.Count + " Project(s) to " + destinationFolder); foreach (string destinationProject in destinationProjects) { string destinationProjPath = createSubFolders ? Path.Combine(destinationFolder + "\\" + Path.GetFileNameWithoutExtension(destinationProject), destinationProject) : Path.Combine(destinationFolder, destinationProject); if (File.Exists(destinationProjPath)) { bool overwriteExisting = YesOrNo.Ask(destinationProjPath + Environment.NewLine + "already exists!" + Environment.NewLine + "Overwrite it ?"); if (!overwriteExisting) continue; } List<string> sources = projectsToLink .Where(d => d.DestinationProjectName == destinationProject) .Select(s => s.SourceProject).ToList(); if (sources.Count != 1) { string message = destinationProject + "has " + sources.Count + " source Projects." + Environment.NewLine; for (var index = 0; index < sources.Count; index++) { string source = sources[index]; message += index + 1 + ". " + source + Environment.NewLine; } message += "Continue (Y) or skip (N) " + destinationProject + " or Cancel Everything?"; bool? carryOn = YesOrNo.OrCancel(message); if (carryOn == null) { Log.WriteLine("User aborted All Recycling. " + message); return; // bail out of everything } if (carryOn == false) { Log.WriteLine("User skipped one Linked Project. " + message); continue; // skip just this Destination Project } } if (sources.Any()) { Log.WriteLine("Recycling to :" + destinationProjPath); Directory.CreateDirectory(Path.GetDirectoryName(destinationProjPath)); // safe. Doesn't care if it already exists. File.Copy(sources[0], destinationProjPath, true); var destinationProjXml = new DestinationProjXml(destinationProjPath); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.ClearStartPlaceholderContent(); destinationProjXml.AddExclusion("app.config"); Log.WriteLine("...because a linked App.config will cause problems when you change build settings."); destinationProjXml.AddExclusion("packages.config"); Log.WriteLine("...because nuget's packages.config will cause problems when you change build settings."); destinationProjXml.ClearAllExistingCodeExceptExplicitlyLinked(); foreach (string source in sources) { if (File.Exists(source)) destinationProjXml.AddSource(PathMaker.MakeRelativePath(destinationProjPath, source)); else Log.WriteLine("Bad Source in: " + destinationProjPath + Environment.NewLine + " Source: " + source + Environment.NewLine); } destinationProjXml.Save(); App.ParseCommands(new[] {destinationProjPath}); } } }
/// <summary> Links the source code from the source <c> sourceProj </c> file to the destination <c> destProj </c> file. /// <para> Tweaks relative file paths so the project can find them. </para> /// Adds a <c> <Link> </c> for the destination project Solution Explorer. </summary> internal void LinkCode() { string oldXml = destProjXml.ReadLinkedXml(); destProjXml.ClearOldLinkedCode(); var totalCodezLinked = 0; List <string> alreadyIncluded = (from sourceItemGroup in destProjXml.ItemGroups from sourceItem in sourceItemGroup.Elements() where !Settings.ItemElementsToSkip.Contains(sourceItem.Name.LocalName.ToLower()) select sourceItem.Attribute("Include") ?? sourceItem.Attribute("Exclude") into attrib where attrib != null select attrib.Value.ToLower()).ToList(); if (alreadyIncluded.Count > 1) { Log.WriteLine("These are already include so will not be linked...", ConsoleColor.White, ConsoleColor.DarkGray); Log.WriteLine(alreadyIncluded, ConsoleColor.Gray); } foreach (string sourcePath in SourceProjList) { var codezLinked = 0; try { string sourceProjAbsolutePath = PathMaker.IsAbsolutePath(sourcePath) ? sourcePath : Path.Combine(DestProjDirectory, sourcePath); string sourceProjDirectory = Path.GetDirectoryName(sourceProjAbsolutePath); string destDirectoryForRelativePath = DestProjDirectory.EndsWith("\\") ? DestProjDirectory : DestProjDirectory + "\\"; string linkRelativeSource = PathMaker.MakeRelativePath(destDirectoryForRelativePath, sourceProjAbsolutePath); var sourceProjParser = new SourceProjParser(sourceProjAbsolutePath); destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("Linked from " + linkRelativeSource)); Log.WriteLine("Recycling from: " + sourceProjAbsolutePath + Environment.NewLine + " to: " + DestProjAbsolutePath + Environment.NewLine, ConsoleColor.Cyan); foreach (XElement sourceItemGroup in sourceProjParser.ItemGroups) { var newLinkedItemGroup = new XElement(Settings.MSBuild + "ItemGroup"); foreach (XElement sourceItem in sourceItemGroup.Elements()) { string sourceElementName = sourceItem.Name.LocalName; if (Settings.ItemElementsToSkip.Contains(sourceElementName.ToLower())) { continue; } XAttribute attrib = sourceItem.Attribute("Include") ?? sourceItem.Attribute("Exclude"); if (attrib != null) { string originalSourcePath = attrib.Value; string trimmedOriginalSourcePath = originalSourcePath.Trim().ToLower(); if (alreadyIncluded.IndexOf(trimmedOriginalSourcePath) > -1) { Log.WriteLine("Skipped: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because there is a file with the same path in the destination project." + Environment.NewLine, ConsoleColor.Gray); continue; } List <string> include = InclusionsList.Where(i => Operators.LikeString(trimmedOriginalSourcePath, i, CompareMethod.Text)).ToList(); // OW my eyes! if (!InclusionsList.Any() || include.Any()) { if (!PathMaker.IsAbsolutePath(originalSourcePath)) { var sourcePathFromDestination = ""; try { string sourceFileName = Path.GetFileName(originalSourcePath); // wildcards blow up Path.GetFullPath() string originalFolder = originalSourcePath; List <string> excludedFiles = ExclusionsList.Where(x => x.Contains(sourceFileName.ToLower())).ToList(); // ExclusionsList.Where(x => Operators.LikeString(trimmedOriginalSourcePath, x, CompareMethod.Text)).ToList(); // OW my eyes! var excludedPaths = ExclusionsList.Where(x => x.Contains(originalSourcePath.ToLower())).ToArray(); if (excludedPaths?.Any() ?? false) { excludedFiles.AddRange(excludedPaths); } if (excludedFiles.Any()) { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because you said to Exclude: " + excludedFiles.FirstOrDefault(), ConsoleColor.White, ConsoleColor.DarkRed); continue; } if (!string.IsNullOrEmpty(sourceFileName)) { originalFolder = originalSourcePath.Replace(sourceFileName, ""); } string sourceAbsolutePath = Path.GetFullPath(sourceProjDirectory + "\\" + originalFolder) + sourceFileName; sourcePathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", sourceAbsolutePath); } catch (ArgumentException badArg) { if (badArg.Message.Contains("Illegal characters in path")) { if (Regex.IsMatch(originalSourcePath, @"^[a-zA-Z]:\\")) // is already an absolute path { sourcePathFromDestination = originalSourcePath; } else if (Regex.IsMatch(originalSourcePath, @"\*\*")) // it is **\*.* or something awkward like that. { string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", sourceProjDirectory); sourcePathFromDestination = relativeFolderPathFromDestination + "\\" + originalSourcePath; var linkElement = new XElement(Settings.MSBuild + "Link", @"%(RecursiveDir)%(Filename)%(Extension)"); sourceItem.Add(linkElement); } else { try { string originalFolder = originalSourcePath.Substring(0, originalSourcePath.LastIndexOf("\\")); string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", originalFolder); sourcePathFromDestination = relativeFolderPathFromDestination + originalSourcePath.Substring(originalSourcePath.LastIndexOf("\\")); } catch (Exception e) { App.Crash(e, "Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } } } else { try { string originalFolder = originalSourcePath.Substring(0, originalSourcePath.LastIndexOf("\\")); string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", originalFolder); sourcePathFromDestination = relativeFolderPathFromDestination + originalSourcePath.Substring(originalSourcePath.LastIndexOf("\\")); } catch (Exception e) { App.Crash(e, "Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } } } catch (Exception e) { App.Crash(e, "Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } if (!Settings.ItemElementsDoNotMakeRelativePath.Contains(sourceElementName.ToLower())) { attrib.Value = sourcePathFromDestination; } } XElement[] links = sourceItem.Descendants(Settings.MSBuild + "Link").ToArray(); // Folders, mostly if (!(links.Any() || Settings.ItemElementsDoNotBreakLink.Contains(sourceElementName.ToLower()))) { var linkElement = new XElement(Settings.MSBuild + "Link", _linkPrefix + originalSourcePath); sourceItem.Add(linkElement); } foreach (XElement link in links) { link.Value = _linkPrefix + link.Value; } var dependentOn = sourceItem.Descendants(Settings.MSBuild + "DependentUpon").ToArray(); /*foreach (XElement dependent in dependentOn) * { * dependent.Value = _linkPrefix + dependent.Value; * sourceItem.Add(dependent); * }*/ newLinkedItemGroup.Add(sourceItem); codezLinked++; alreadyIncluded.Add(originalSourcePath); } else { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because it did not match anything on the Include: list " + Environment.NewLine, ConsoleColor.Gray, ConsoleColor.DarkRed); } } } if (newLinkedItemGroup.HasElements) { destProjXml.EndPlaceHolder.AddBeforeSelf(newLinkedItemGroup); } } destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End Link from " + linkRelativeSource + Environment.NewLine + "Linked " + codezLinked + " codez.")); totalCodezLinked += codezLinked; // so we don't link things twice... destProjXml.Keepers.RemoveAll(k => k.Attribute("Include").Value.Contains(sourceProjDirectory)); // copy Source project Resources so *.resx files don't break. Warning: Last one wins so weird race condition lives here string sourceResources = sourceProjDirectory + "\\Resources"; if (Directory.Exists(sourceResources)) { string destResourcesPath = DestProjDirectory + "\\Resources"; Log.WriteLine($"Copying all Files from {sourceResources} to {destResourcesPath}.", ConsoleColor.Green); if (!Directory.Exists(destResourcesPath)) { Directory.CreateDirectory(destResourcesPath); } foreach (string sourceFile in Directory.GetFiles(sourceResources)) { string destFile = destResourcesPath + "\\" + Path.GetFileName(sourceFile); if (File.Exists(destFile)) { long sourceSize = new FileInfo(sourceFile).Length; long destSize = new FileInfo(destFile).Length; if (sourceSize != destSize) // ie. it is probably a different file. { Log.WriteLine($"WARNING: Overwriting {destFile}", ConsoleColor.Red); Log.WriteLine($"Source: {sourceSize} bytes, Dest: {destSize} Bytes.", ConsoleColor.Yellow); } } File.Copy(sourceFile, Path.Combine(destResourcesPath, Path.GetFileName(sourceFile)), true); Log.WriteLine($"Copied {sourceFile}", ConsoleColor.Green); } Log.WriteLine($"Copied all Files from {sourceResources} to {destResourcesPath}." + Environment.NewLine, ConsoleColor.Green); } } catch (Exception e) { App.Crash(e, "Recycling " + sourcePath + " to " + DestProjAbsolutePath); } } // end foreach source project destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End of Linked Code" + Environment.NewLine + "See CodeLinkerLog.txt for details. CodeLinker by " + Settings.SourceCodeUrl + " ")); if (oldXml != destProjXml.ReadLinkedXml()) { destProjXml.Save(); Log.WriteLine("Linked " + totalCodezLinked + " codez from " + SourceProjList.Count + " source Project(s).", ConsoleColor.Green); } else { Log.WriteLine("No changes, didn't save.", ConsoleColor.Cyan, ConsoleColor.DarkBlue); } Log.WriteLine("-------------------------------------------------------", ConsoleColor.DarkGray); Log.WriteLine(); }
/// <summary> Links the source code from the source <c> sourceProj </c> file to the destination <c> destProj </c> file. /// <para> Tweaks relative file paths so the project can find them. </para> /// Adds a <c> <Link> </c> for the destination project Solution Explorer. </summary> internal void LinkCode() { string oldXml = destProjXml.ReadLinkedXml(); destProjXml.ClearOldLinkedCode(); var totalCodezLinked = 0; if (!SourceProjList?.Any() ?? true) { Log.WriteLine("[Warning] No Source Projects found. done.", ConsoleColor.Cyan); return; } foreach (string sourcePath in SourceProjList) { var codezLinked = 0; try { string sourceProjAbsolutePath = PathMaker.IsAbsolutePath(sourcePath) ? sourcePath : Path.Combine(DestProjDirectory, sourcePath); string sourceProjDirectory = Path.GetDirectoryName(sourceProjAbsolutePath); string destDirectoryForRelativePath = DestProjDirectory.EndsWith("\\", StringComparison.Ordinal) ? DestProjDirectory : DestProjDirectory + "\\"; string linkRelativeSource = PathMaker.MakeRelativePath(destDirectoryForRelativePath, sourceProjAbsolutePath); var sourceProjParser = new SourceProjLoader(sourceProjAbsolutePath); destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("Linked from " + linkRelativeSource)); Log.WriteLine("Recycling from: " + sourceProjAbsolutePath + Environment.NewLine + " to: " + DestProjAbsolutePath + Environment.NewLine, ConsoleColor.Cyan); List <string> alreadyIncluded = (from sourceItemsGroup in destProjXml.ItemGroups from sourceItems in sourceItemsGroup.Elements() where !Settings.ItemElementsToSkip?.Contains(sourceItems.Name.LocalName.ToLower()) ?? false select sourceItems.Attribute("Include") ?? sourceItems.Attribute("Exclude") into attribute where attribute != null select attribute.Value.ToLower()).ToList(); foreach (XElement sourceItemGroup in sourceProjParser.ItemGroups) { var newLinkedItemGroup = new XElement(Settings.MSBuild + "ItemGroup"); foreach (XElement sourceItem in sourceItemGroup.Elements()) { string sourceElementName = sourceItem.Name.LocalName; if (Settings.ItemElementsToSkip.Contains(sourceElementName.ToLower())) { continue; } XAttribute attrib = sourceItem.Attribute("Include") ?? sourceItem.Attribute("Exclude"); if (attrib == null) { continue; // these are not the droids } string originalSourcePath = attrib.Value; string trimmedOriginalSourcePath = originalSourcePath.Trim(); if (alreadyIncluded.Contains(trimmedOriginalSourcePath, StringComparer.OrdinalIgnoreCase)) { Log.WriteLine("Skipped: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because there is a file with the same path in the destination project." + Environment.NewLine, ConsoleColor.Gray); continue; } List <string> include = InclusionsList.Where(i => Operators.LikeString(trimmedOriginalSourcePath, i, CompareMethod.Text)).ToList(); // OW my eyes! string sourceFileName = Path.GetFileName(trimmedOriginalSourcePath); // wildcards blow up Path.GetFullPath() string originalFolder = Path.GetDirectoryName(originalSourcePath); List <string> exclusions = ExclusionsList.Where(x => x != null && (x.Contains(sourceFileName?.ToLower()) || x.Contains(originalSourcePath?.ToLower()) || x.Contains(sourceFileName) || x.Contains(originalSourcePath))).ToList(); if (exclusions.Any()) { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because you said to Exclude: " + exclusions.FirstOrDefault(), ConsoleColor.DarkYellow); continue; } if (!InclusionsList.Any() || include.Any()) // empty inclusions list means include everything unless explicity excluded { if (!PathMaker.IsAbsolutePath(originalSourcePath)) { string sourcePathFromDestination = ""; try { string sourceAbsolutePath = Path.GetFullPath(sourceProjDirectory + "\\" + originalFolder) + "\\" + sourceFileName; sourcePathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory.Trim('\\') + "\\", sourceAbsolutePath); /* * Log.WriteLine($"dest proj directory .... {DestProjDirectory}"); * Log.WriteLine($"original source path.... {originalSourcePath}"); * Log.WriteLine($"original folder ........ {originalFolder}"); * Log.WriteLine($"source proj directory.. {sourceProjDirectory}"); * Log.WriteLine($"sourceFileName ......... {sourceFileName}"); * Log.WriteLine($"sourceAbsolutePath ..... {sourceAbsolutePath}"); * Log.WriteLine($"source path ........ {sourcePathFromDestination}"); */ } catch (ArgumentException badArg) { // Log.WriteException(badArg); if (badArg.Message.Contains("Illegal characters in path")) { if (Regex.IsMatch(originalSourcePath, @"^[a-zA-Z]:\\")) // is already an absolute path { sourcePathFromDestination = originalSourcePath; } else if (Regex.IsMatch(originalSourcePath, @"\*\*")) // it is **\*.* or something awkward like that. { string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", sourceProjDirectory); sourcePathFromDestination = relativeFolderPathFromDestination + "\\" + originalSourcePath; var linkElement = new XElement(Settings.MSBuild + "Link", @"%(RecursiveDir)%(Filename)%(Extension)"); sourceItem.Add(linkElement); } // wtf: I bet that's a bug else { try { string originalFolderrr = originalSourcePath.Substring(0, originalSourcePath.LastIndexOf("\\", StringComparison.Ordinal)); string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", originalFolderrr); sourcePathFromDestination = relativeFolderPathFromDestination + originalSourcePath.Substring(originalSourcePath.LastIndexOf("\\", StringComparison.Ordinal)); } catch (Exception e) { App.Crash(e, "FAILed Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } } } else { try { string originalFolderr = originalSourcePath.Substring(0, originalSourcePath.LastIndexOf("\\")); string relativeFolderPathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", originalFolderr); sourcePathFromDestination = relativeFolderPathFromDestination + originalSourcePath.Substring(originalSourcePath.LastIndexOf("\\")); } catch (Exception e) { App.Crash(e, "FAILed Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } } } catch (Exception e) { App.Crash(e, "FAILed Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } if (!Settings.ItemElementsDoNotMakeRelativePath.Contains(sourceElementName.ToLower())) { attrib.Value = sourcePathFromDestination; } } XElement[] links = sourceItem.Descendants(Settings.MSBuild + "Link").ToArray(); // Folders, mostly if (!(links.Any() || Settings.ItemElementsDoNotBreakLink.Contains(sourceElementName.ToLower()))) { var linkElement = new XElement(Settings.MSBuild + "Link", originalSourcePath); sourceItem.Add(linkElement); Log.WriteLine($"linking {originalSourcePath}", ConsoleColor.DarkGreen, ConsoleColor.Black); } newLinkedItemGroup.Add(sourceItem); codezLinked++; alreadyIncluded.Add(originalSourcePath); } else { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because it did not match anything on the Include: list " + Environment.NewLine, ConsoleColor.Gray, ConsoleColor.DarkRed); } } if (newLinkedItemGroup.HasElements) { destProjXml.EndPlaceHolder.AddBeforeSelf(newLinkedItemGroup); } } destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End Link from " + linkRelativeSource + Environment.NewLine + "Linked " + codezLinked + " codez.")); totalCodezLinked += codezLinked; // so we don't link things twice... destProjXml.Keepers.RemoveAll(k => k.Attribute("Include").Value.Contains(sourceProjDirectory)); // copy Source project Resources so *.resx files don't break. Warning: Last one wins so weird race condition lives here string sourceResources = sourceProjDirectory + "\\Resources"; if (Directory.Exists(sourceResources)) { string destResourcesPath = DestProjDirectory + "\\Resources"; Log.WriteLine($"Copying all Resource Files from {sourceResources} to {destResourcesPath}.", ConsoleColor.Green); if (!Directory.Exists(destResourcesPath)) { Directory.CreateDirectory(destResourcesPath); } foreach (string sourceFile in Directory.GetFiles(sourceResources)) { string excluded = ExclusionsList.FirstOrDefault(e => e == sourceFile.ToLower() || e == sourceFile); if (excluded != null) { Log.WriteLine($"Excluded: {sourceFile}{Environment.NewLine}" + $"from: Resources in Destination Project{Environment.NewLine}" + $"because you said to Exclude:{excluded} ", ConsoleColor.White, ConsoleColor.DarkRed); } string destFile = destResourcesPath + "\\" + Path.GetFileName(sourceFile); if (File.Exists(destFile)) { long sourceSize = new FileInfo(sourceFile).Length; long destSize = new FileInfo(destFile).Length; if (sourceSize != destSize) // ie. it is probably a different file. { Log.WriteLine($"[Warning] Overwriting {destFile}", ConsoleColor.Red); Log.WriteLine($"Source: {sourceSize} bytes, Dest: {destSize} Bytes.", ConsoleColor.Yellow); } } File.Copy(sourceFile, Path.Combine(destResourcesPath, Path.GetFileName(sourceFile)), true); Log.WriteLine($"Copied {sourceFile}", ConsoleColor.Green); } Log.WriteLine($"Copied all Files from {sourceResources} to {destResourcesPath}." + Environment.NewLine, ConsoleColor.Green); } } catch (Exception e) { App.Crash(e, "Recycling " + sourcePath + " to " + DestProjAbsolutePath); } } // end foreach source project destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End of Linked Code" /*+ DateTime.Now.ToString("U") */ + Environment.NewLine + "See CodeLinkerLog.txt for details. CodeLinker by " + Settings.SourceCodeUrl)); bool hasChanged = oldXml != destProjXml.ReadLinkedXml(); destProjXml.PreserveKeepersAndReport(ExclusionsList); if (hasChanged) { destProjXml.Save(); Log.WriteLine("Linked " + totalCodezLinked + " codez from " + SourceProjList.Count + " source Project(s).", ConsoleColor.Green); } else { Log.WriteLine("No changes, didn't save.", ConsoleColor.Cyan, ConsoleColor.DarkBlue); } Log.WriteLine("-------------------------------------------------------", ConsoleColor.DarkGray); Log.WriteLine(); }
public static void ParseCommands(string[] args) { linkers.Clear(); // System.Diagnostics.Debugger.Launch(); // to find teh bugs load this in Visual Studio and uncomment the start of this line. int argsCount = args.Length; if (argsCount == 0) { Log.WriteLine("No Args given so Help Text Displayed."); Log.WriteLine(); Help.Write(); Finish(); } List<string> argsList = args.Select(a => a.Replace(@"""", "")).ToList(); if (argsList.Contains("/?")) { Help.Write(); Log.WriteLine("User asked For Help. Hope I helped."); Finish(); } bool doSubDirectories = argsList.Contains("/s", StringComparer.CurrentCultureIgnoreCase); bool createSubDirectories = !argsList.Contains("/nosub", StringComparer.CurrentCultureIgnoreCase); Log.WriteToConsole = !argsList.Contains("/stfu", StringComparer.CurrentCultureIgnoreCase); NoConfirm = argsList.Contains("/noconfirm", StringComparer.CurrentCultureIgnoreCase); if (!string.IsNullOrEmpty(argsList[0])) { if (argsList[0].IsaCsOrVbProjFile()) { if (argsCount > 1 && args[1].IsaCsOrVbProjFile()) { Log.WriteLine("Queueing Code Link from: " + argsList[0] + " to " + argsList[1]); linkers.Add(new DestinationProjLinker(argsList[0], argsList[1])); } else { Log.WriteLine("Queueing Code Link to: " + argsList[0] + ". Source TBA."); linkers.Add(new DestinationProjLinker(argsList[0])); } } else if (argsList[0].ToLower() == "strip") { if (argsCount > 1) { if (args[1].IsaCsOrVbProjFile()) { var destinationProjXml = new DestinationProjXml(args[1]); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.Save(); Finish("Stripped all code from " + args[1]); } else { try { List<string> destProjFiles = GetProjectsFromFolders(argsList[1], doSubDirectories); foreach (string destProjFile in destProjFiles) { Log.WriteLine("Stripping Code from: " + destProjFile + ". "); var destinationProjXml = new DestinationProjXml(destProjFile); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.Save(); } } catch (Exception e) { Crash(e, "Stripping Code from Folder: " + args[1] + " didn't work. Bad name?"); } Finish("Stripped all code"); } } } else if (argsList[0].ToLower() == "new") { if (argsCount > 2) { if (args[1].IsaCsOrVbProjFile()) { string sourcePath = PathMaker.MakeAbsolutePathFromPossibleRelativePathOrDieTrying(null, args[1]); try { ProjectMaker.NewProject(sourcePath, args[2], createSubDirectories); } catch (Exception e) { Crash(e, "Linking " + args[1] + " to " + args[2] + " didn't work. Bad name?"); } Finish("Linked " + " from " + args[1] + " to " + args[2]); } else { try { List<string> sourceProjFiles = GetProjectsFromFolders(argsList[1], doSubDirectories); foreach (string sourceProjFile in sourceProjFiles) { if (sourceProjFile.IsaCsOrVbProjFile()) { string sourcePath = PathMaker.MakeAbsolutePathFromPossibleRelativePathOrDieTrying(null, sourceProjFile); try { ProjectMaker.NewProject(sourcePath, args[2], createSubDirectories); } catch (Exception e) { Crash(e, "Linking " + sourceProjFile + " to " + args[2] + " didn't work. Bad name?"); } Log.WriteLine("Linked " + " from " + sourceProjFile + " to " + args[2]); } else Log.WriteLine("ERROR: " + sourceProjFile + " is not a project file. Cannot Link it."); } } catch (Exception e) { Crash(e, "Linking Projects from Folder: " + args[1] + " didn't work. Bad name?"); } Finish("Linked Projects"); } } } // /NewProject else // vanilla Link command with a folder { try { List<string> destProjFiles = GetProjectsFromFolders(argsList[0], doSubDirectories); foreach (string destProjFile in destProjFiles) { Log.WriteLine("Queueing Code Link to: " + destProjFile + ". Source TBA."); linkers.Add(new DestinationProjLinker(destProjFile)); } } catch (Exception e) { Crash(e, "Queueing Code Link didn't work. Bad file name?"); } } if (!linkers.Any()) { string errorMessage = "I got nuthin. Your Args made no sense to me." + Environment.NewLine; foreach (string arg in args) { errorMessage += arg + Environment.NewLine; } Crash(errorMessage); } foreach (DestinationProjLinker destinationProjLinker in linkers) { destinationProjLinker.LinkCode(); } } }
/// <summary> Copies and links a List of Projects into the <c>destinationFolder</c>. /// <para> File is Linked from the first <c>projectsToLink</c> for each if there is more than 1 source.</para></summary> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null or empty. </exception> /// <param name="projectsToLink"> The projects to Link. </param> /// <param name="destinationFolder"> Pathname of the destination folder. Empty string throws <c>ArgumentNullException</c></param> internal static void NewProject(List <ProjectToLink> projectsToLink, string destinationFolder) { if (projectsToLink == null) { throw new ArgumentNullException(nameof(projectsToLink)); } if (string.IsNullOrEmpty(destinationFolder)) { throw new ArgumentNullException(nameof(destinationFolder)); } HashSet <string> destinationProjects = new HashSet <string>(projectsToLink.Select(p => p.DestinationProjectName)); Log.WriteLine("Recycling " + destinationProjects.Count + " Project(s) to " + destinationFolder); foreach (string destinationProject in destinationProjects) { string destinationProjPath = Path.Combine(destinationFolder, destinationProject); if (File.Exists(destinationProjPath)) { bool overwriteExisting = YesOrNo.Ask(destinationProjPath + Environment.NewLine + "already exists!" + Environment.NewLine + "Overwrite it ?"); if (!overwriteExisting) { continue; } } List <string> sources = projectsToLink.Where(d => d.DestinationProjectName == destinationProject).Select(s => s.SourceProject).ToList(); if (sources.Count != 1) { string message = destinationProject + "has " + sources.Count + " source Projects." + Environment.NewLine; for (int index = 0; index < sources.Count; index++) { string source = sources[index]; message += (index + 1).ToString() + ". " + source + Environment.NewLine; } message += "Continue (Y) or skip (N) " + destinationProject + " or Cancel Everything?"; bool?carryOn = YesOrNo.OrCancel(message); if (carryOn == null) { Log.WriteLine("User aborted All Recycling. " + message); return; // bail out of everything } if (carryOn == false) { Log.WriteLine("User skipped one Linked Project. " + message); continue; // skip just this Destination Project } } if (sources.Any()) { Log.WriteLine("Recycling to :" + destinationProjPath); File.Copy(sources[0], destinationProjPath, overwrite: true); DestinationProjXml destinationProjXml = new DestinationProjXml(destinationProjPath); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.ClearStartPlaceholderContent(); destinationProjXml.AddExclusion("app.config"); Log.WriteLine("...because a linked App.config will cause problems when you change build settings."); destinationProjXml.ClearAllExistingCodeExceptExplicitlyLinked(); foreach (string source in sources) { if (File.Exists(source)) { destinationProjXml.AddSource(PathMaker.MakeRelativePath(destinationProjPath, source)); } else { Log.WriteLine("Bad Source in: " + destinationProjPath + Environment.NewLine + " Source: " + source + Environment.NewLine); } } destinationProjXml.Save(); App.ParseCommands(new[] { destinationProjPath }); } } }
public static void ParseCommands(string[] args) { linkers.Clear(); // System.Diagnostics.Debugger.Launch(); // to find teh bugs load this in Visual Studio and uncomment the start of this line. int argsCount = args.Length; if (argsCount == 0) { Log.WriteLine("No Args given so Help Text Displayed.", ConsoleColor.Red); Log.WriteLine(); Help.Write(); Finish(); } List <string> argsList = args.Select(a => a.Replace(@"""", "")).ToList(); if (argsList.Contains("/?")) { Help.Write(); Log.WriteLine("User asked For Help. Hope I helped.", ConsoleColor.Green); Finish(); } bool doSubDirectories = argsList.Contains("/s", StringComparer.CurrentCultureIgnoreCase); bool createSubDirectories = !argsList.Contains("/nosub", StringComparer.CurrentCultureIgnoreCase); Log.WriteToConsole = !argsList.Contains("/stfu", StringComparer.CurrentCultureIgnoreCase); NoConfirm = argsList.Contains("/noconfirm", StringComparer.CurrentCultureIgnoreCase); if (argsList.Contains("/abs", StringComparer.CurrentCultureIgnoreCase)) { PathMaker.UseRelativePaths = false; } string prefixArg = args.FirstOrDefault(arg => arg.StartsWith("/prefix:", StringComparison.OrdinalIgnoreCase)); if (prefixArg?.Any() ?? false) { string prefix = prefixArg.Substring(8).Replace("\"", ""); DestinationProjLinker.LinkPrefix = prefix; } if (!string.IsNullOrEmpty(argsList[0])) { if (argsList[0].IsaCsOrVbProjFile()) { if (argsCount > 1 && args[1].IsaCsOrVbProjFile()) { Log.WriteLine("Queueing Code Link from: " + argsList[0], ConsoleColor.Cyan); Log.WriteLine(" to: " + argsList[1], ConsoleColor.Cyan); Log.WriteLine(); linkers.Add(new DestinationProjLinker(argsList[0], argsList[1])); } else { Log.WriteLine("Queueing Code Link to: " + argsList[0] + ". Source TBA.", ConsoleColor.Cyan); linkers.Add(new DestinationProjLinker(argsList[0])); } } else if (argsList[0].ToLower() == "strip") { if (argsCount > 1) { if (args[1].IsaCsOrVbProjFile()) { var destinationProjXml = new DestinationProjXml(args[1]); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.Save(); Finish("Stripped all code from " + args[1]); } else { try { List <string> destProjFiles = GetProjectsFromFolders(argsList[1], doSubDirectories); foreach (string destProjFile in destProjFiles) { Log.WriteLine("Stripping Code from: " + destProjFile + ". ", ConsoleColor.Yellow); var destinationProjXml = new DestinationProjXml(destProjFile); destinationProjXml.ClearOldLinkedCode(); destinationProjXml.Save(); } } catch (Exception e) { Crash(e, "Stripping Code from Folder: " + args[1] + " didn't work. Bad name?"); } Finish("Stripped all code"); } } } else if (argsList[0].ToLower() == "new") { if (argsCount > 2) { if (args[1].IsaCsOrVbProjFile()) { string sourcePath = PathMaker.MakeAbsolutePathFromPossibleRelativePathOrDieTrying(null, args[1]); try { ProjectMaker.NewProject(sourcePath, args[2], createSubDirectories); } catch (Exception e) { Crash(e, "Linking " + args[1] + " to " + args[2] + " didn't work. Bad name?"); } Finish("Linked " + " from " + args[1] + " to " + args[2]); } else { try { List <string> sourceProjFiles = GetProjectsFromFolders(argsList[1], doSubDirectories); foreach (string sourceProjFile in sourceProjFiles) { if (sourceProjFile.IsaCsOrVbProjFile()) { string sourcePath = PathMaker.MakeAbsolutePathFromPossibleRelativePathOrDieTrying(null, sourceProjFile); try { ProjectMaker.NewProject(sourcePath, args[2], createSubDirectories); } catch (Exception e) { Crash(e, "Linking " + sourceProjFile + " to " + args[2] + " didn't work. Bad name?"); } Log.WriteLine("Linked " + " from " + sourceProjFile + " to " + args[2], ConsoleColor.Green); } else { Log.WriteLine("ERROR: " + sourceProjFile + " is not a project file. Cannot Link it.", ConsoleColor.Green); } } } catch (Exception e) { Crash(e, "Linking Projects from Folder: " + args[1] + " didn't work. Bad name?"); } Finish("Linked Projects"); } } } // /NewProject else // vanilla Link command with a folder { try { List <string> destProjFiles = GetProjectsFromFolders(argsList[0], doSubDirectories); foreach (string destProjFile in destProjFiles) { Log.WriteLine("Queueing Code Link to: " + destProjFile + ". Source TBA.", ConsoleColor.Cyan); linkers.Add(new DestinationProjLinker(destProjFile)); } } catch (Exception e) { Crash(e, "Queueing Code Link didn't work. Bad file name?"); } } if (!linkers.Any()) { string errorMessage = "I got nuthin. Your Args made no sense to me." + Environment.NewLine; foreach (string arg in args) { errorMessage += arg + Environment.NewLine; } Crash(errorMessage); } foreach (DestinationProjLinker destinationProjLinker in linkers) { destinationProjLinker.LinkCode(); } } }
/// <summary> Links the source code from the source <c>sourceProj</c> file to the destination <c>destProj</c> file. /// <para> Tweaks relative file paths so the project can find them. </para> /// Adds a <c><Link></c> for the destination project Solution Explorer.</summary> internal void LinkCode() { string oldXml = destProjXml.ReadLinkedXml(); destProjXml.ClearOldLinkedCode(); int totalCodezLinked = 0; foreach (string sourcePath in SourceProjList) { int codezLinked = 0; try { string sourceProjAbsolutePath = (PathMaker.IsAbsolutePath(sourcePath)) ? sourcePath : Path.Combine(DestProjDirectory, sourcePath); string sourceProjDirectory = Path.GetDirectoryName(sourceProjAbsolutePath); string destDirectoryForRelativePath = DestProjDirectory.EndsWith("\\") ? DestProjDirectory : DestProjDirectory + "\\"; string linkRelativeSource = PathMaker.MakeRelativePath(destDirectoryForRelativePath, sourceProjAbsolutePath); SourceProjParser sourceProjParser = new SourceProjParser(sourceProjAbsolutePath); destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("Linked from " + linkRelativeSource)); Log.WriteLine("Recycling from: " + sourceProjAbsolutePath + Environment.NewLine + " to: " + DestProjAbsolutePath + Environment.NewLine); foreach (XElement sourceItemGroup in sourceProjParser.ItemGroups) { XElement newLinkedItemGroup = new XElement(Settings.MSBuild + "ItemGroup"); foreach (XElement sourceItem in sourceItemGroup.Elements()) { string sourceElementName = sourceItem.Name.LocalName; if (Settings.ItemElementsToSkip.Contains(sourceElementName.ToLower())) { continue; } XAttribute attrib = sourceItem.Attribute("Include") ?? sourceItem.Attribute("Exclude"); if (attrib != null) { string originalSourcePath = attrib.Value; string trimmedOriginalSourcePath = originalSourcePath.Trim().ToLower(); IEnumerable <string> exclude = ExclusionsList.Where(x => Operators.LikeString(trimmedOriginalSourcePath, x, CompareMethod.Text)).ToList(); // OW my eyes! if (exclude.Any()) { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because you said to Exclude: " + exclude.FirstOrDefault() + Environment.NewLine); continue; } List <string> include = InclusionsList.Where(i => Operators.LikeString(trimmedOriginalSourcePath, i, CompareMethod.Text)).ToList(); // OW my eyes! if (!InclusionsList.Any() || include.Any()) { if (!PathMaker.IsAbsolutePath(originalSourcePath)) { string sourceAbsolutePath = ""; try { string sourceFileName = Path.GetFileName(originalSourcePath); // wildcards blow up Path.GetFullPath() string originalFolder = originalSourcePath; if (!string.IsNullOrEmpty(sourceFileName)) { originalFolder = originalSourcePath.Replace(sourceFileName, ""); } sourceAbsolutePath = Path.GetFullPath(sourceProjDirectory + "\\" + originalFolder) + sourceFileName; } catch (Exception e) { App.Crash(e, "Recycling. GetFullPath: " + sourceProjDirectory + "\\" + originalSourcePath); } string relativePathFromDestination = PathMaker.MakeRelativePath(DestProjDirectory + "\\", sourceAbsolutePath); if (!Settings.ItemElementsDoNotMakeRelativePath.Contains(sourceElementName.ToLower())) { attrib.Value = relativePathFromDestination; } } IEnumerable <XElement> links = sourceItem.Descendants(Settings.MSBuild + "Link"); if (!(links.Any() || Settings.ItemElementsDoNotBreakLink.Contains(sourceElementName.ToLower()))) // Folders, mostly { XElement linkElement = new XElement(Settings.MSBuild + "Link", originalSourcePath); sourceItem.Add(linkElement); } newLinkedItemGroup.Add(sourceItem); codezLinked++; } else { Log.WriteLine("Excluded: " + originalSourcePath + Environment.NewLine + " from: " + sourceProjAbsolutePath + Environment.NewLine + "because it did not match anything on the Include: list " + Environment.NewLine); } } } if (newLinkedItemGroup.HasElements) { destProjXml.EndPlaceHolder.AddBeforeSelf(newLinkedItemGroup); } } destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End Link from " + linkRelativeSource + Environment.NewLine + "Linked " + codezLinked + " codez.")); totalCodezLinked += codezLinked; destProjXml.Keepers.RemoveAll(k => k.Attribute("Include").Value.Contains(sourceProjDirectory)); } catch (Exception e) { App.Crash(e, "Recycling " + sourcePath + " to " + DestProjAbsolutePath); } } destProjXml.EndPlaceHolder.AddBeforeSelf(new XComment("End of Linked Code" + Environment.NewLine + "See CodeLinkerLog.txt for details. CodeLinker by " + Settings.SourceCodeUrl + " ")); if (oldXml != destProjXml.ReadLinkedXml()) { destProjXml.Save(); Log.WriteLine("Linked " + totalCodezLinked + " codez from " + SourceProjList.Count + " source Project(s)."); } else { Log.WriteLine("No changes, didn't save."); } Log.WriteLine("----------------------------"); Log.WriteLine(); }