public class GitHelper()

in tools/mcp/dotnet/AzureSDKDevToolsMCP/Helpers/GitHelper.cs [24:139]


    public class GitHelper(IGitHubService gitHubService, ILogger<GitHelper> logger) : IGitHelper
    {
        readonly ILogger<GitHelper> logger = logger;
        readonly IGitHubService gitHubService = gitHubService;
        readonly static string SPEC_REPO_NAME = "azure-rest-api-specs";
        public IList<string> GetChangedFiles(string repoPath)
        {
            var changedFiles = new List<string>();
            using (var repo = new Repository(repoPath))
            {
                // Get the current branch
                Branch currentBranch = repo.Head;
                logger.LogInformation($"Current branch: {currentBranch.FriendlyName}");
                // Get the changes in the working directory
                var changes = repo.Diff.Compare<TreeChanges>(currentBranch.Tip.Tree, DiffTargets.WorkingDirectory);
                // List changed files
                foreach (var change in changes)
                {
                    changedFiles.Add(change.Path);
                    logger.LogInformation($"Changed file: {change.Path}");
                }
            }
            return changedFiles;
        }

        public string GetBranchName(string repoPath)
        {
            using var repo = new Repository(repoPath);
            var branchName = repo.Head.FriendlyName;
            return branchName;
        }

        private static Uri GetRepoRemoteUri(string path)
        {
            using var repo = new Repository(path);
            var remote = repo.Network?.Remotes["origin"];
            if (remote != null)
            {
                return new Uri(remote.Url);
            }
            throw new InvalidOperationException("Unable to determine remote URL.");
        }

        public string GetRepoName(string path)
        {
            var uri = GetRepoRemoteUri(path);
            var segments = uri.Segments;
            if (segments.Length > 1)
            {
                return segments[^1].TrimEnd(".git".ToCharArray());
            }
            throw new InvalidOperationException("Unable to determine repository name.");
        }

        public async Task<string> GetRepoOwnerName(string path, bool findForkParent = true)
        {
            var uri = GetRepoRemoteUri(path);
            var segments = uri.Segments;
            string repoOwner = string.Empty;
            string repoName = string.Empty;
            if (segments.Length > 2)
            {
                repoOwner = segments[^2].TrimEnd('/');
                repoName = segments[^1].TrimEnd(".git".ToCharArray());
            }

            if(findForkParent) {
                // Check if the repo is a fork and get the parent repo
                var parentRepoUrl = await gitHubService.GetGitHubParentRepoUrl(repoOwner, repoName);
                logger.LogInformation($"Parent repo URL: {parentRepoUrl}");
                if (!string.IsNullOrEmpty(parentRepoUrl))
                {
                    var parentSegments = new Uri(parentRepoUrl).Segments;
                    if (parentSegments.Length > 2)
                    {
                        repoOwner = parentSegments[^2].TrimEnd('/');
                    }
                }
            }

            if (!string.IsNullOrEmpty(repoOwner))
            {
                return repoOwner;
            }

            throw new InvalidOperationException("Unable to determine repository owner.");
        }

        public bool IsRepoPathForPublicSpecRepo(string path)
        {
            // Check if GitHub repo name of cloned path is "azure-rest-api-specs"
            var uri = GetRepoRemoteUri(path);
            return uri.ToString().Contains(SPEC_REPO_NAME);            
        }
        public string GetRepoRootPath(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException("path cannot be null or empty.", nameof(path));
            }

            if (Directory.Exists(Path.Combine(path, "specification")))
            {
                return path;
            }

            // Get absolute path for repo root from given path.
            // Repo root is the parent of "specification" folder.
            var currentDirectory = new DirectoryInfo(path);
            while (currentDirectory != null && !currentDirectory.Name.Equals("specification"))
            {
                currentDirectory = currentDirectory.Parent;
            }
            return currentDirectory?.Parent?.FullName ?? string.Empty;
        }
    }