Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 36 additions & 99 deletions TortoiseGitToolbar.Shared/Config/Constants/PathConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using EnvDTE80;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.Win32;

namespace MattDavies.TortoiseGitToolbar.Config.Constants
Expand All @@ -14,8 +12,6 @@ public static class PathConfiguration
private const string TortoiseGitx86 = @"C:\Program Files (x86)\TortoiseGit\bin\TortoiseGitProc.exe";
private const string GitBashx86 = @"C:\Program Files (x86)\Git\bin\sh.exe";
private const string GitBashx64 = @"C:\Program Files\Git\bin\sh.exe";
private const string GitExex86 = @"C:\Program Files (x86)\Git\bin\git.exe";
private const string GitExex64 = @"C:\Program Files\Git\bin\git.exe";

private static readonly RegistryKey TortoiseGitProcRegistryRoot = Registry.LocalMachine;
private const string TortoiseGitProcRegistryPath = @"SOFTWARE\TortoiseGit";
Expand Down Expand Up @@ -47,111 +43,62 @@ public static string GetGitBashPath()
: null;
}

public static string GetGitExePath()
public static string GetSolutionFilePath(Solution2 solution)
{
var path = GetGitExePathFromRegistry();
if (path != null)
return path;
return File.Exists(GitExex64) ? GitExex64
: File.Exists(GitExex86) ? GitExex86
: null;
}

public static string GetSolutionPath(Solution2 solution)
{
if (solution != null && solution.IsOpen)
if (solution != null)
{
var solutionPathFromSln = Path.GetDirectoryName(solution.FullName);
Debug.WriteLine("Solution path is: " + solutionPathFromSln);

var repositoryRootPath = GetRepositoryRootGit(solutionPathFromSln);
if (repositoryRootPath == null)
{
Debug.WriteLine("Failed to get root path from git. Trying to filesystem-based approach");
repositoryRootPath = GetRepositoryRootFs(solutionPathFromSln);
if (repositoryRootPath == null)
{
Debug.WriteLine("No parent folder found. Using original path: " + solutionPathFromSln);
return solutionPathFromSln;
}
}

Debug.WriteLine("Using solution path: " + repositoryRootPath);
return repositoryRootPath;
return solution.FullName;
}

return null;
}

/// <summary>
/// Find repository root by calling "git rev-parse --show-toplevel" command
/// </summary>
/// <param name="solutionPath">Path inside repository (working path for git command)</param>
/// <returns> Path to repository root, if found. Otherwise null.</returns>
private static string GetRepositoryRootGit(string solutionPath)
private static string FindGitRepositoryRootPathFromFilePath(string filePath)
{
var gitPath = GetGitExePath();
if (gitPath == null)
{
return null;
}
if (filePath == null) return null;

var procInfo = new ProcessStartInfo
{
FileName = gitPath,
Arguments = "rev-parse --show-toplevel",
UseShellExecute = false,
WorkingDirectory = solutionPath,
RedirectStandardOutput = true,
CreateNoWindow = true,
};
FileInfo fileInfo = new FileInfo(filePath);
DirectoryInfo dirInfo = fileInfo.Directory;

using (var process = Process.Start(procInfo))
while (dirInfo != null && dirInfo.Exists)
{
var stdOut = process.StandardOutput.ReadToEnd();
process.WaitForExit();
var errCode = process.ExitCode;

Debug.WriteLine($"git rev-parse --show-toplevel exited with code {errCode} and stdout: {stdOut}");
if (errCode != 0 || string.IsNullOrWhiteSpace(stdOut))
string gitPath = dirInfo.FullName + "/.git";
// Check for a .git directory
if (Directory.Exists(gitPath))
{
return null;
return dirInfo.FullName;
}

try
// Check for a .git file (sub-module or work tree)
if (File.Exists(gitPath))
{
return Path.GetFullPath(stdOut.Trim());
}
catch (Exception e)
{
Debug.WriteLine($"GetFullPath failed for {stdOut}, with {e} reason: {e.Message}");
return null;
return dirInfo.FullName;
}
// git repo not found, look at the parent level.
dirInfo = dirInfo.Parent;
}

return null;
}

/// <summary>
/// Find repository root basing on filesystem by finding parent directory that contains .git folder
/// </summary>
/// <param name="solutionPath">Directory to start search from.</param>
/// <returns> Path to repository root, if found. Otherwise null.</returns>
private static string GetRepositoryRootFs(string solutionPath)
public static string GetRepositoryRootPath(Solution2 solution)
{
var solutionPathInfo = new DirectoryInfo(solutionPath);

// find parent folder that holds the .git folder
while (!Directory.Exists(Path.Combine(solutionPathInfo.FullName, ".git")))
string selectedFile = GetOpenedFilePath(solution);
if (!String.IsNullOrEmpty(selectedFile))
{
Debug.WriteLine("No .git folder found in solution path.");
if (solutionPathInfo.Parent == null)
var selectedInfo = new FileInfo(selectedFile);
string gitPath = FindGitRepositoryRootPathFromFilePath(selectedFile);
if (!String.IsNullOrEmpty(gitPath))
{
return null;
return gitPath;
}
}

solutionPathInfo = solutionPathInfo.Parent;
string solutionFile = GetSolutionFilePath(solution);
if (!String.IsNullOrEmpty(solutionFile))
{
return FindGitRepositoryRootPathFromFilePath(solutionFile);
}

return solutionPathInfo.FullName;
return null;
}

public static string GetOpenedFilePath(Solution2 solution)
Expand Down Expand Up @@ -213,16 +160,6 @@ public static string GetTortoiseGitPathFromRegistry()
}

public static string GetGitBashPathFromRegistry()
{
return GetGitExecutablePathFromRegisty("sh.exe");
}

public static string GetGitExePathFromRegistry()
{
return GetGitExecutablePathFromRegisty("git.exe");
}

private static string GetGitExecutablePathFromRegisty(string executableName)
{
var path = GetValueFromRegistry(GitBashRegistryRoot, GitBashRegistryPath, GitBashRegistryKeyName);
Debug.WriteLine("Git bash path from registry: " + (path ?? "(null)"));
Expand All @@ -231,11 +168,11 @@ private static string GetGitExecutablePathFromRegisty(string executableName)
{
Debug.WriteLine("Git bash path from registry exists.");

var exePath = Path.Combine(path, executableName);
if (File.Exists(exePath))
var shPath = Path.Combine(path, "sh.exe");
if (File.Exists(shPath))
{
Debug.WriteLine($"Git bash path {executableName} exists: " + exePath);
return exePath;
Debug.WriteLine("Git bash path sh.exe exists: " + shPath);
return shPath;
}
}

Expand Down
93 changes: 57 additions & 36 deletions TortoiseGitToolbar.Shared/Resources/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading