Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c48549117f | |||
| 7b59b90572 | |||
| 164df4ecf4 | |||
| cf336da271 |
2 changed files with 74 additions and 27 deletions
|
|
@ -10,20 +10,16 @@ namespace ModuleCore.Git;
|
||||||
public class GitManager
|
public class GitManager
|
||||||
{
|
{
|
||||||
private static readonly Lazy<GitManager> GitManagerInstance = new(() => new GitManager());
|
private static readonly Lazy<GitManager> GitManagerInstance = new(() => new GitManager());
|
||||||
private readonly ConcurrentDictionary<string, InternalGitRegistration> _registrations;
|
private static Action<string>? _debugWriterDelegate;
|
||||||
private readonly DatabaseManager _db;
|
private readonly DatabaseManager _db;
|
||||||
|
private readonly ConcurrentDictionary<string, InternalGitRegistration> _registrations;
|
||||||
|
|
||||||
private GitManager()
|
private GitManager()
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"{nameof(GitManager)} init");
|
|
||||||
|
|
||||||
_registrations = new ConcurrentDictionary<string, InternalGitRegistration>();
|
_registrations = new ConcurrentDictionary<string, InternalGitRegistration>();
|
||||||
_db = new DatabaseManager("git.db");
|
_db = new DatabaseManager("git.db");
|
||||||
|
|
||||||
_db.InConnection(conn =>
|
InitialiseRegistrations();
|
||||||
{
|
|
||||||
conn.CreateTable<InternalGitRegistration>();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GitManager Instance => GitManagerInstance.Value;
|
public static GitManager Instance => GitManagerInstance.Value;
|
||||||
|
|
@ -33,6 +29,40 @@ public class GitManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static GitManager InternalFreshInstance => new();
|
internal static GitManager InternalFreshInstance => new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates up any database tables and loads all previously saved git registrations.
|
||||||
|
/// </summary>
|
||||||
|
private void InitialiseRegistrations()
|
||||||
|
{
|
||||||
|
_debugWriterDelegate?.Invoke("Initialising GitManager from first run - this should only happen once.");
|
||||||
|
|
||||||
|
_db.InConnection(conn =>
|
||||||
|
{
|
||||||
|
var createTableResult = conn.CreateTable<InternalGitRegistration>();
|
||||||
|
|
||||||
|
if (createTableResult == CreateTableResult.Created)
|
||||||
|
{
|
||||||
|
_debugWriterDelegate?.Invoke($"Created table {InternalGitRegistration.TableName}.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_debugWriterDelegate?.Invoke("Loading previous registrations from database.");
|
||||||
|
|
||||||
|
var registrations = _db.InConnection<List<InternalGitRegistration>>(conn =>
|
||||||
|
conn.Table<InternalGitRegistration>()
|
||||||
|
.ToList()
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (var internalGitRegistration in registrations)
|
||||||
|
{
|
||||||
|
_debugWriterDelegate?.Invoke($"Loading {internalGitRegistration.Name} ({internalGitRegistration.Id}) from database...");
|
||||||
|
if (!_registrations.TryAdd(internalGitRegistration.Name, internalGitRegistration))
|
||||||
|
{
|
||||||
|
_debugWriterDelegate?.Invoke("...failed to restore - potential duplicate name.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a git repository based on an absolute location. If <paramref name="registrationName" /> is null or empty,
|
/// Registers a git repository based on an absolute location. If <paramref name="registrationName" /> is null or empty,
|
||||||
/// the registration will use the folder name for the git repo at the top level.
|
/// the registration will use the folder name for the git repo at the top level.
|
||||||
|
|
@ -55,23 +85,22 @@ public class GitManager
|
||||||
|
|
||||||
return _db.InConnection<string>(conn =>
|
return _db.InConnection<string>(conn =>
|
||||||
{
|
{
|
||||||
// Query if we already have a registration either by name or location.
|
// Query if we already have a registration either by name. Previously we also checked by location, but I
|
||||||
|
// decided to stick with constraining to the name only, same as the key used for the dictionary.
|
||||||
// tbh this is a bit of a janky way to do exists when I have to pass the query in anyway, but I just didn't
|
// tbh this is a bit of a janky way to do exists when I have to pass the query in anyway, but I just didn't
|
||||||
// want to do null checks and a truthy check so I wrap it in a barely-valuable method.
|
// want to do null checks and a truthy check so I wrap it in a barely-valuable method.
|
||||||
var registrationExists = _db.Exists(
|
var registrationExists = _db.Exists(
|
||||||
$"""
|
$"""
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM {InternalGitRegistration.TableName}
|
FROM {InternalGitRegistration.TableName}
|
||||||
WHERE Name = ? OR
|
WHERE Name = ?
|
||||||
Location = ?
|
|
||||||
""",
|
""",
|
||||||
gitRegistration.Name,
|
gitRegistration.Name
|
||||||
gitRegistration.Location
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (registrationExists)
|
if (registrationExists)
|
||||||
{
|
{
|
||||||
throw new Exception($"A Git repo is already registered with the name {registrationName} or location {absoluteRepositoryLocation}");
|
throw new Exception($"A Git repo is already registered with the name {registrationName}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the new record
|
// Insert the new record
|
||||||
|
|
@ -116,15 +145,33 @@ public class GitManager
|
||||||
throw new Exception($"No git repo has been registered with the name {registeredName}");
|
throw new Exception($"No git repo has been registered with the name {registeredName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an output for debug output. <see cref="ClearDebugWriter" /> should be called as soon as the need for output
|
||||||
|
/// is no longer needed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="commandRuntime"></param>
|
||||||
|
public static void SetDebugWriter(Action<string> commandRuntime)
|
||||||
|
{
|
||||||
|
_debugWriterDelegate = commandRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears any output previously registered with <see cref="SetDebugWriter" />
|
||||||
|
/// </summary>
|
||||||
|
public static void ClearDebugWriter()
|
||||||
|
{
|
||||||
|
_debugWriterDelegate = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for internal git registration and handles getting the current branch
|
/// Used for internal git registration and handles getting the current branch
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Table(TableName)]
|
[Table(TableName)]
|
||||||
private class InternalGitRegistration
|
private class InternalGitRegistration
|
||||||
{
|
{
|
||||||
|
internal const string TableName = "GitRegistration";
|
||||||
private string _currentBranch = string.Empty;
|
private string _currentBranch = string.Empty;
|
||||||
private long _nextCheckTime;
|
private long _nextCheckTime;
|
||||||
internal const string TableName = "GitRegistration";
|
|
||||||
|
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
@ -132,7 +179,6 @@ public class GitManager
|
||||||
[Indexed(Unique = true)]
|
[Indexed(Unique = true)]
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
[Indexed(Unique = true)]
|
|
||||||
public string Location { get; set; } = null!;
|
public string Location { get; set; } = null!;
|
||||||
|
|
||||||
public string CurrentBranch => GetCurrentBranch();
|
public string CurrentBranch => GetCurrentBranch();
|
||||||
|
|
@ -184,7 +230,8 @@ public class GitManager
|
||||||
// Set the next check to be in the future so we don't hold up any list commands every time.
|
// Set the next check to be in the future so we don't hold up any list commands every time.
|
||||||
_nextCheckTime = now.AddMinutes(15).Ticks;
|
_nextCheckTime = now.AddMinutes(15).Ticks;
|
||||||
|
|
||||||
return _currentBranch;
|
// The branch name could (will) have a newline character at the end, so we trim that off
|
||||||
|
return _currentBranch.Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,20 +15,15 @@ public sealed class NewGitRepoCommand : PSCmdlet
|
||||||
HelpMessage = "Reference name for the repo")]
|
HelpMessage = "Reference name for the repo")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
public NewGitRepoCommand()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void BeginProcessing()
|
protected override void BeginProcessing()
|
||||||
{
|
{
|
||||||
var pwd = this.SessionState.Path.CurrentLocation.Path;
|
GitManager.SetDebugWriter(WriteDebug);
|
||||||
WriteDebug("Checking if current directory is a git repository...");
|
|
||||||
|
|
||||||
var repoFolfder = IsGitRepo(pwd);
|
var repoFolder = IsGitRepo(SessionState.Path.CurrentLocation.Path);
|
||||||
|
|
||||||
if (repoFolfder is not null)
|
if (repoFolder is not null)
|
||||||
{
|
{
|
||||||
GitManager.Instance.RegisterRepo(repoFolfder.Directory, Name ?? repoFolfder.Folder);
|
GitManager.Instance.RegisterRepo(repoFolder.Directory, Name ?? repoFolder.Folder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -43,17 +38,20 @@ public sealed class NewGitRepoCommand : PSCmdlet
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GitManager.ClearDebugWriter();
|
||||||
|
|
||||||
base.BeginProcessing();
|
base.BeginProcessing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParsedGitFolderDetails? IsGitRepo(string path)
|
private ParsedGitFolderDetails? IsGitRepo(string path)
|
||||||
{
|
{
|
||||||
|
WriteDebug("Checking if current directory is a git repository...");
|
||||||
|
|
||||||
var ps = new ProcessStartInfo("git",
|
var ps = new ProcessStartInfo("git",
|
||||||
["rev-parse", "--show-toplevel"])
|
["-C", path, "rev-parse", "--show-toplevel"])
|
||||||
{
|
{
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
WorkingDirectory = path
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the user doesn't have git on their path, this will throw an exception that I don't have to do anything
|
// If the user doesn't have git on their path, this will throw an exception that I don't have to do anything
|
||||||
|
|
@ -75,6 +73,8 @@ public sealed class NewGitRepoCommand : PSCmdlet
|
||||||
// Gotta trim what we get as it might already have a newline character at the end
|
// Gotta trim what we get as it might already have a newline character at the end
|
||||||
var dirInfo = new DirectoryInfo(directory.Trim());
|
var dirInfo = new DirectoryInfo(directory.Trim());
|
||||||
|
|
||||||
|
WriteDebug("...location is a git repo (duh).");
|
||||||
|
|
||||||
var repoFolderInfo = new ParsedGitFolderDetails
|
var repoFolderInfo = new ParsedGitFolderDetails
|
||||||
{
|
{
|
||||||
Directory = dirInfo.FullName,
|
Directory = dirInfo.FullName,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue