Skip to content

Commit

Permalink
Add option to preserve relative folder structure between .sln files
Browse files Browse the repository at this point in the history
  • Loading branch information
jnm2 committed Apr 18, 2021
1 parent 308ba8f commit d1b4801
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Now also available on NuGet:
3. Pass a path to an .sln file or a .csproj file (or multiple paths separated by spaces) to create an index for them
4. Pass /out:<path> to HtmlGenerator.exe to configure where to generate the website to. This path will be used in step 6 as your "physicalPath".
5. Pass /in:<path> to pass a file with a list of full paths to projects and solutions to include in the index
6. Set SourceIndexServer project as startup and run/debug the website.
6. Pass /root:<path> if you want to preserve relative .sln folders rather than merging all solutions. This folder must contain all specified .sln or .csproj paths.
7. Set SourceIndexServer project as startup and run/debug the website.

**Note:** Visual Studio 2019 is required to build Source Browser.

Expand Down
40 changes: 36 additions & 4 deletions src/HtmlGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ private static void Main(string[] args)
var federations = new HashSet<string>();
var serverPathMappings = new Dictionary<string, string>();
var pluginBlacklist = new List<string>();
var rootPath = (string)null;

foreach (var arg in args)
{
Expand Down Expand Up @@ -162,6 +163,12 @@ private static void Main(string[] args)
continue;
}

if (arg.StartsWith("/root:", StringComparison.Ordinal))
{
rootPath = Path.GetFullPath(arg.Substring("/root:".Length).StripQuotes());
continue;
}

try
{
AddProject(projects, arg);
Expand All @@ -178,6 +185,18 @@ private static void Main(string[] args)
return;
}

if (rootPath is object)
{
foreach (var project in projects)
{
if (!Paths.IsOrContains(rootPath, project))
{
Log.Exception("If /root is specified, it must be an ancestor folder of all specified projects.", isSevere: true);
return;
}
}
}

AssertTraceListener.Register();
AppDomain.CurrentDomain.FirstChanceException += FirstChanceExceptionHandler.HandleFirstChanceException;

Expand Down Expand Up @@ -218,7 +237,7 @@ private static void Main(string[] args)
federation.AddFederation(entry.Key, entry.Value);
}

IndexSolutions(projects, properties, federation, serverPathMappings, pluginBlacklist, doNotIncludeReferencedProjects);
IndexSolutions(projects, properties, federation, serverPathMappings, pluginBlacklist, doNotIncludeReferencedProjects, rootPath);
FinalizeProjects(emitAssemblyList, federation);
WebsiteFinalizer.Finalize(websiteDestination, emitAssemblyList, federation);
}
Expand Down Expand Up @@ -263,6 +282,7 @@ private static void PrintUsage()
+ "[/noplugins] "
+ "[/noplugin:Git] "
+ "<pathtosolution1.csproj|vbproj|sln|binlog|buildlog|dll|exe> [more solutions/projects..] "
+ "[/root:<root folder to enable relative .sln folders>] "
+ "[/in:<filecontaingprojectlist>] "
+ "[/nobuiltinfederations] "
+ "[/offlinefederation:server=assemblyListFile] "
Expand Down Expand Up @@ -292,7 +312,8 @@ private static void IndexSolutions(
Federation federation,
Dictionary<string, string> serverPathMappings,
IEnumerable<string> pluginBlacklist,
bool doNotIncludeReferencedProjects = false)
bool doNotIncludeReferencedProjects = false,
string rootPath = null)
{
var assemblyNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

Expand All @@ -311,6 +332,17 @@ private static void IndexSolutions(

foreach (var path in solutionFilePaths)
{
var solutionFolder = mergedSolutionExplorerRoot;

if (rootPath is object)
{
var relativePath = Paths.MakeRelativeToFolder(Path.GetDirectoryName(path), rootPath);
var segments = relativePath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);

foreach (var segment in segments)
solutionFolder = solutionFolder.GetOrCreateFolder(segment);
}

using (Disposable.Timing("Generating " + path))
{
if (path.EndsWith(".binlog", StringComparison.OrdinalIgnoreCase) ||
Expand All @@ -324,7 +356,7 @@ private static void IndexSolutions(
serverPathMappings,
processedAssemblyList,
assemblyNames,
mergedSolutionExplorerRoot);
solutionFolder);
}

continue;
Expand All @@ -340,7 +372,7 @@ private static void IndexSolutions(
doNotIncludeReferencedProjects: doNotIncludeReferencedProjects))
{
solutionGenerator.GlobalAssemblyList = assemblyNames;
solutionGenerator.Generate(processedAssemblyList, mergedSolutionExplorerRoot);
solutionGenerator.Generate(processedAssemblyList, solutionFolder);
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/HtmlGenerator/Utilities/Paths.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ public static void PrepareDestinationFolder(bool forceOverwrite = false)
Directory.CreateDirectory(SolutionDestinationFolder);
}

public static bool IsOrContains(string path, string possibleDescendent)
{
return EnsureTrailingSlash(possibleDescendent).StartsWith(EnsureTrailingSlash(path), StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Returns a path to <paramref name="filePath"/> if you start in a folder where the file
/// <paramref name="relativeToPath"/> is located.
Expand Down Expand Up @@ -134,7 +139,7 @@ public static string MakeRelativeToFolder(string filePath, string relativeToPath
}

StringBuilder result = new StringBuilder();
while (!EnsureTrailingSlash(filePath).StartsWith(EnsureTrailingSlash(relativeToPath), StringComparison.OrdinalIgnoreCase))
while (!IsOrContains(relativeToPath, filePath))
{
result.Append(@"..\");
relativeToPath = Path.GetDirectoryName(relativeToPath);
Expand Down

0 comments on commit d1b4801

Please sign in to comment.