← Back to Files
GitService.cs
using System.Diagnostics;
namespace KaiChat.Services;
public class GitService : IGitService
{
private readonly string _repoPath;
private readonly ILogger<GitService> _logger;
public GitService(IConfiguration config, ILogger<GitService> logger)
{
_repoPath = config.GetValue<string>("KaiChat:BaseFolder")
?? throw new InvalidOperationException("KaiChat:BaseFolder must be set");
_logger = logger;
}
public string RepoPath => _repoPath;
public async Task<GitResult> StageAllAsync()
{
return await RunGitAsync("add -A");
}
public async Task<GitResult> StagePathAsync(string repoRelativePath)
{
return await RunGitAsync($"add -A -- \"{repoRelativePath.Replace("\"", "\\\"")}\"");
}
public async Task<GitResult> CommitAsync(string message, string? body = null)
{
var args = new List<string> { "commit", "-m", message };
if (!string.IsNullOrWhiteSpace(body))
{
args.Add("-m");
args.Add(body);
}
return await RunGitAsync(args);
}
public async Task<GitResult> StatusAsync()
{
return await RunGitAsync("status --short");
}
public async Task<GitResult> AutoCommitAsync(string summary, string? filePath = null)
{
var stage = filePath != null
? await StagePathAsync(filePath)
: await StageAllAsync();
if (!stage.Success)
return stage;
var status = await StatusAsync();
if (string.IsNullOrWhiteSpace(status.Output))
return new GitResult { Success = true, Output = "Nothing to commit." };
return await CommitAsync($"KaiChat: {summary}");
}
private async Task<GitResult> RunGitAsync(string arguments)
{
try
{
var psi = new ProcessStartInfo("git")
{
Arguments = arguments,
WorkingDirectory = _repoPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = new Process { StartInfo = psi };
process.Start();
var output = await process.StandardOutput.ReadToEndAsync();
var error = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync();
return new GitResult
{
Success = process.ExitCode == 0,
Output = output.Trim(),
Error = error.Trim()
};
}
catch (Exception ex)
{
_logger.LogError(ex, "Git command failed: git {Args}", arguments);
return new GitResult { Success = false, Error = ex.Message };
}
}
private async Task<GitResult> RunGitAsync(IReadOnlyList<string> arguments)
{
try
{
var psi = new ProcessStartInfo("git")
{
WorkingDirectory = _repoPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
foreach (var argument in arguments)
psi.ArgumentList.Add(argument);
using var process = new Process { StartInfo = psi };
process.Start();
var output = await process.StandardOutput.ReadToEndAsync();
var error = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync();
return new GitResult
{
Success = process.ExitCode == 0,
Output = output.Trim(),
Error = error.Trim()
};
}
catch (Exception ex)
{
_logger.LogError(ex, "Git command failed: git {Args}", string.Join(" ", arguments));
return new GitResult { Success = false, Error = ex.Message };
}
}
}