MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.Refacto.../GitRefactoringManager.cs

395 lines
11 KiB
C#
Executable File

using MarketAlly.AIPlugin;
using LibGit2Sharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace MarketAlly.AIPlugin.Refactoring.Plugins
{
public class GitConfiguration
{
public string AuthorName { get; set; } = "MarketAlly Refactoring Tool";
public string AuthorEmail { get; set; } = "refactor@localhost";
}
// Corrected Git integration manager with proper LibGit2Sharp API usage
public class GitRefactoringManager
{
private readonly string _repositoryPath;
private readonly GitConfiguration _gitConfig;
public bool IsGitRepository { get; private set; }
public GitRefactoringManager(string repositoryPath, GitConfiguration gitConfig = null)
{
_repositoryPath = repositoryPath;
_gitConfig = gitConfig ?? new GitConfiguration();
IsGitRepository = Repository.IsValid(repositoryPath);
}
public async Task<GitRefactoringInfo> CreateRefactoringBranch(string branchName, bool applyChanges)
{
if (!IsGitRepository)
return null;
var gitInfo = new GitRefactoringInfo
{
RepositoryPath = _repositoryPath,
NewBranchName = branchName,
CreatedAt = DateTime.UtcNow
};
try
{
using (var repo = new Repository(_repositoryPath))
{
gitInfo.OriginalBranch = repo.Head.FriendlyName;
gitInfo.OriginalCommit = repo.Head.Tip.Sha;
// Check if working directory is clean
var status = repo.RetrieveStatus();
if (status.IsDirty)
{
gitInfo.Success = false;
gitInfo.Error = "Working directory has uncommitted changes. Please commit or stash changes before refactoring.";
return gitInfo;
}
if (applyChanges)
{
// Check if branch already exists
var existingBranch = repo.Branches[branchName];
if (existingBranch != null)
{
// Generate unique branch name
var timestamp = DateTime.Now.ToString("HHmmss");
branchName = $"{branchName}-{timestamp}";
gitInfo.NewBranchName = branchName;
}
// Create and checkout new branch using Commands.Checkout
var newBranch = repo.CreateBranch(branchName);
Commands.Checkout(repo, newBranch);
gitInfo.BranchCreated = true;
}
gitInfo.Success = true;
}
}
catch (Exception ex)
{
gitInfo.Success = false;
gitInfo.Error = ex.Message;
}
return await Task.FromResult(gitInfo);
}
public async Task<bool> CommitChanges(string message, List<string> operationsPerformed)
{
if (!IsGitRepository)
return false;
try
{
using (var repo = new Repository(_repositoryPath))
{
// Get repository status
var status = repo.RetrieveStatus();
if (!status.IsDirty)
{
Console.WriteLine("No changes to commit.");
return await Task.FromResult(false);
}
// Stage all modified files
foreach (var modified in status.Modified)
{
repo.Index.Add(modified.FilePath);
}
// Stage all new files
foreach (var untracked in status.Untracked)
{
repo.Index.Add(untracked.FilePath);
}
// Stage all renamed files
foreach (var renamed in status.RenamedInIndex)
{
repo.Index.Add(renamed.FilePath);
}
// Write the index changes
repo.Index.Write();
// Create commit if there are staged changes
var indexStatus = repo.RetrieveStatus();
if (indexStatus.Added.Any() || indexStatus.Modified.Any() || indexStatus.Staged.Any())
{
var signature = new Signature(_gitConfig.AuthorName, _gitConfig.AuthorEmail, DateTimeOffset.Now);
// Enhanced commit message with operation details
var enhancedMessage = $"{message}\n\nOperations performed:\n{string.Join("\n", operationsPerformed.Select(op => $"- {op}"))}";
var commit = repo.Commit(enhancedMessage, signature, signature);
Console.WriteLine($"Created commit: {commit.Sha[..8]} - {message}");
return await Task.FromResult(true);
}
return await Task.FromResult(false);
}
}
catch (Exception ex)
{
Console.WriteLine($"Git commit failed: {ex.Message}");
return await Task.FromResult(false);
}
}
public async Task<GitStatusInfo> GetRepositoryStatus()
{
if (!IsGitRepository)
return null;
try
{
using (var repo = new Repository(_repositoryPath))
{
var status = repo.RetrieveStatus();
return await Task.FromResult(new GitStatusInfo
{
IsClean = !status.IsDirty,
CurrentBranch = repo.Head.FriendlyName,
LatestCommitSha = repo.Head.Tip.Sha,
LatestCommitMessage = repo.Head.Tip.MessageShort,
LatestCommitAuthor = repo.Head.Tip.Author.Name,
LatestCommitDate = repo.Head.Tip.Author.When,
ModifiedFiles = status.Modified.Select(f => f.FilePath).ToList(),
AddedFiles = status.Added.Select(f => f.FilePath).ToList(),
DeletedFiles = status.Removed.Select(f => f.FilePath).ToList(),
UntrackedFiles = status.Untracked.Select(f => f.FilePath).ToList(),
StagedFiles = status.Staged.Select(f => f.FilePath).ToList()
});
}
}
catch (Exception ex)
{
return new GitStatusInfo
{
IsClean = false,
Error = ex.Message
};
}
}
public async Task<bool> SwitchToBranch(string branchName)
{
if (!IsGitRepository)
return false;
try
{
using (var repo = new Repository(_repositoryPath))
{
var branch = repo.Branches[branchName];
if (branch == null)
{
Console.WriteLine($"Branch '{branchName}' not found.");
return false;
}
Commands.Checkout(repo, branch);
Console.WriteLine($"Switched to branch '{branchName}'");
return await Task.FromResult(true);
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to switch to branch '{branchName}': {ex.Message}");
return await Task.FromResult(false);
}
}
public async Task<bool> DeleteBranch(string branchName, bool force = false)
{
if (!IsGitRepository)
return false;
try
{
using (var repo = new Repository(_repositoryPath))
{
var branch = repo.Branches[branchName];
if (branch == null)
{
Console.WriteLine($"Branch '{branchName}' not found.");
return false;
}
if (branch.IsCurrentRepositoryHead)
{
Console.WriteLine($"Cannot delete current branch '{branchName}'. Switch to another branch first.");
return false;
}
repo.Branches.Remove(branch);
Console.WriteLine($"Deleted branch '{branchName}'");
return await Task.FromResult(true);
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to delete branch '{branchName}': {ex.Message}");
return await Task.FromResult(false);
}
}
public async Task<List<string>> GetBranches()
{
if (!IsGitRepository)
return new List<string>();
try
{
using (var repo = new Repository(_repositoryPath))
{
return await Task.FromResult(repo.Branches.Select(b => b.FriendlyName).ToList());
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to get branches: {ex.Message}");
return new List<string>();
}
}
public async Task<bool> HasUncommittedChanges()
{
if (!IsGitRepository)
return false;
try
{
using (var repo = new Repository(_repositoryPath))
{
var status = repo.RetrieveStatus();
return await Task.FromResult(status.IsDirty);
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to check repository status: {ex.Message}");
return false;
}
}
public async Task<string> GetCurrentBranch()
{
if (!IsGitRepository)
return "Not a Git repository";
try
{
using (var repo = new Repository(_repositoryPath))
{
return await Task.FromResult(repo.Head.FriendlyName);
}
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
}
}
// Enhanced Git status information
public class GitStatusInfo
{
public bool IsClean { get; set; }
public string CurrentBranch { get; set; } = string.Empty;
public string LatestCommitSha { get; set; } = string.Empty;
public string LatestCommitMessage { get; set; } = string.Empty;
public string LatestCommitAuthor { get; set; } = string.Empty;
public DateTimeOffset LatestCommitDate { get; set; }
public List<string> ModifiedFiles { get; set; } = new List<string>();
public List<string> AddedFiles { get; set; } = new List<string>();
public List<string> DeletedFiles { get; set; } = new List<string>();
public List<string> UntrackedFiles { get; set; } = new List<string>();
public List<string> StagedFiles { get; set; } = new List<string>();
public string Error { get; set; } = string.Empty;
}
// Enhanced commands for the solution plugin
public static class GitCommands
{
public static List<string> GenerateReviewCommands(GitRefactoringInfo gitInfo)
{
var commands = new List<string>();
if (gitInfo?.NewBranchName != null)
{
commands.Add("# Review the refactoring changes:");
commands.Add($"git log --oneline -5 # See recent commits");
commands.Add($"git diff {gitInfo.OriginalBranch}..{gitInfo.NewBranchName} --stat # See file changes summary");
commands.Add($"git diff {gitInfo.OriginalBranch}..{gitInfo.NewBranchName} # See detailed changes");
commands.Add("");
}
return commands;
}
public static List<string> GenerateMergeCommands(GitRefactoringInfo gitInfo)
{
var commands = new List<string>();
if (gitInfo?.NewBranchName != null && gitInfo?.OriginalBranch != null)
{
commands.Add("# To merge the refactoring back to main:");
commands.Add($"git checkout {gitInfo.OriginalBranch}");
commands.Add($"git merge {gitInfo.NewBranchName}");
commands.Add($"git branch -d {gitInfo.NewBranchName} # Delete the refactor branch");
commands.Add("");
}
return commands;
}
public static List<string> GenerateRollbackCommands(GitRefactoringInfo gitInfo)
{
var commands = new List<string>();
if (gitInfo?.NewBranchName != null && gitInfo?.OriginalBranch != null)
{
commands.Add("# To discard all refactoring changes:");
commands.Add($"git checkout {gitInfo.OriginalBranch}");
commands.Add($"git branch -D {gitInfo.NewBranchName} # Force delete the refactor branch");
commands.Add("# Your original code is completely restored!");
commands.Add("");
}
return commands;
}
public static List<string> GenerateCommitCommands(GitRefactoringInfo gitInfo, List<string> operations)
{
var commands = new List<string>();
if (gitInfo?.NewBranchName != null)
{
var operationsSummary = string.Join(", ", operations);
commands.Add("# To commit the refactoring changes:");
commands.Add("git add .");
commands.Add($"git commit -m \"Automated refactoring: {operationsSummary}\"");
commands.Add("");
}
return commands;
}
}
}