Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.
Merged
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
47 changes: 47 additions & 0 deletions common/TelemetryEvents/GitExtension/GitDetectEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.GitExtension;

// How git.exe was located
public enum GitDetectStatus
{
// git.exe was not found on the system
NotFound,

// In the PATH environment variable
PathEnvironmentVariable,

// Probed well-known registry keys to find a Git install location
RegistryProbe,

// Probed well-known folders under Program Files [(x86)]
ProgramFiles,
}

[EventData]
public class GitDetectEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServicePerformance;

public string Status { get; }

public string Version { get; }

public GitDetectEvent(GitDetectStatus status, string version)
{
Status = status.ToString();
Version = version;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// This event so far has no sensitive strings
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using DevHome.Common.TelemetryEvents.GitExtension;
using DevHome.Common.TelemetryEvents.SourceControlIntegration;
using DevHome.Telemetry;
using Microsoft.Win32;
using Microsoft.Windows.DevHome.SDK;
using Serilog;
Expand All @@ -13,26 +16,34 @@ public class GitDetect

private readonly ILogger _log = Log.ForContext<GitDetect>();

private struct DetectInfo
{
public bool Found;
public string Version;
}

public GitDetect()
{
GitConfiguration = new GitConfiguration(null);
}

public bool DetectGit()
{
var gitExeFound = false;
var detect = new DetectInfo { Found = false, Version = string.Empty };
var status = GitDetectStatus.NotFound;

if (!gitExeFound)
if (!detect.Found)
{
// Check if git.exe is present in PATH environment variable
gitExeFound = ValidateGitConfigurationPath("git.exe");
if (gitExeFound)
detect = ValidateGitConfigurationPath("git.exe");
if (detect.Found)
{
status = GitDetectStatus.PathEnvironmentVariable;
GitConfiguration.StoreGitExeInstallPath("git.exe");
}
}

if (!gitExeFound)
if (!detect.Found)
{
// Check execution of git.exe by finding install location in registry keys
string[] registryPaths = { "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" };
Expand All @@ -43,25 +54,31 @@ public bool DetectGit()
if (!string.IsNullOrEmpty(gitPath))
{
var paths = FindSubdirectories(gitPath);
gitExeFound = CheckForExeInPaths(paths);
if (gitExeFound)
detect = CheckForExeInPaths(paths);
if (detect.Found)
{
status = GitDetectStatus.RegistryProbe;
break;
}
}
}
}

if (!gitExeFound)
if (!detect.Found)
{
// Search for git.exe in common file paths
var programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
var programFilesX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
string[] possiblePaths = { $"{programFiles}\\Git\\bin", $"{programFilesX86}\\Git\\bin", $"{programFiles}\\Git\\cmd", $"{programFilesX86}\\Git\\cmd" };
gitExeFound = CheckForExeInPaths(possiblePaths);
detect = CheckForExeInPaths(possiblePaths);
if (detect.Found)
{
status = GitDetectStatus.ProgramFiles;
}
}

return gitExeFound;
TelemetryFactory.Get<ITelemetry>().Log("GitDetect_Event", LogLevel.Critical, new GitDetectEvent(status, detect.Version));
return detect.Found;
}

private string[] FindSubdirectories(string installLocation)
Expand All @@ -85,35 +102,35 @@ private string[] FindSubdirectories(string installLocation)
}
}

private bool CheckForExeInPaths(string[] possiblePaths)
private DetectInfo CheckForExeInPaths(string[] possiblePaths)
{
// Iterate through the possible paths to find the git.exe file
foreach (var path in possiblePaths.Where(x => !string.IsNullOrEmpty(x)))
{
var gitPath = Path.Combine(path, "git.exe");
var isValid = ValidateGitConfigurationPath(gitPath);
var detect = ValidateGitConfigurationPath(gitPath);

// If the git.exe file is found, store the install path and log the information
if (isValid)
if (detect.Found)
{
GitConfiguration.StoreGitExeInstallPath(gitPath);
_log.Information("Git Exe Install Path found");
return true;
return detect;
}
}

_log.Debug("Git.exe not found in paths examined");
return false;
return new DetectInfo { Found = false, Version = string.Empty };
}

public bool ValidateGitConfigurationPath(string path)
private DetectInfo ValidateGitConfigurationPath(string path)
{
var result = GitExecute.ExecuteGitCommand(path, string.Empty, "--version");
if (result.Status == ProviderOperationStatus.Success && result.Output != null && result.Output.Contains("git version"))
{
return true;
return new DetectInfo { Found = true, Version = result.Output.Replace("git version", string.Empty).TrimEnd() };
}

return false;
return new DetectInfo { Found = false, Version = string.Empty };
}
}