You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
recyclarr/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepositoryFactory.cs

57 lines
1.7 KiB

using System.IO.Abstractions;
namespace Recyclarr.TrashLib.Repo.VersionControl;
public class GitRepositoryFactory : IGitRepositoryFactory
{
private readonly ILogger _log;
private readonly IGitPath _gitPath;
// A few hand-picked files that should exist in a .git directory.
private static readonly string[] ValidGitPaths =
{
".git/config",
".git/index",
".git/HEAD"
};
public GitRepositoryFactory(ILogger log, IGitPath gitPath)
{
_log = log;
_gitPath = gitPath;
}
public async Task<IGitRepository> CreateAndCloneIfNeeded(
Uri repoUrl,
IDirectoryInfo repoPath,
string branch,
CancellationToken token)
{
var repo = new GitRepository(_log, _gitPath, repoPath);
if (!repoPath.Exists)
{
_log.Information("Cloning...");
await repo.Clone(token, repoUrl, branch, 1);
}
else
{
// First check if the `.git` directory is present and intact. We used to just do a `git status` here, but
// this sometimes has a false positive if our repo directory is inside another repository.
if (ValidGitPaths.Select(repoPath.File).Any(x => !x.Exists))
{
throw new InvalidGitRepoException("A `.git` directory or its files are missing");
}
// Run just to check repository health. If unhealthy, an exception will
// be thrown. That exception will propagate up and result in a re-clone.
await repo.Status(token);
}
await repo.SetRemote(token, "origin", repoUrl);
_log.Debug("Remote 'origin' set to {Url}", repoUrl);
return repo;
}
}