diff --git a/src/ModuleCore/Database/DatabaseManager.cs b/src/ModuleCore/Database/DatabaseManager.cs index 4aabadd..6f6810d 100644 --- a/src/ModuleCore/Database/DatabaseManager.cs +++ b/src/ModuleCore/Database/DatabaseManager.cs @@ -1,4 +1,6 @@ -namespace ModuleCore.Database; +using SQLite; + +namespace ModuleCore.Database; public class DatabaseManager { @@ -16,8 +18,37 @@ public class DatabaseManager _databaseLocation = new FileInfo(Path.Combine(".", "data", $"{SanitiseFilename(databaseName)}.db")); Directory.CreateDirectory(_databaseLocation.DirectoryName!); - var file = File.Create(_databaseLocation.FullName); - file.Close(); + + if (!File.Exists(_databaseLocation.FullName)) + { + var file = File.Create(_databaseLocation.FullName); + file.Close(); + } + } + + public void InConnection(Action dbAction) + { + using var conn = new SQLiteConnection(_databaseLocation.FullName); + dbAction(conn); + } + + public T InConnection(Func dbAction) + { + using var conn = new SQLiteConnection(_databaseLocation.FullName); + return dbAction(conn); + } + + /// + /// Returns a bool for the given query. Convenience method for . + /// + /// A query starting with SELECT 1, optionally paramaterised with ? + /// Parameter values + /// + public bool Exists(string query, params object[] args) + { + using var conn = new SQLiteConnection(_databaseLocation.FullName); + var exists = conn.ExecuteScalar(query, args); + return exists ?? false; } /// diff --git a/src/ModuleCore/Git/GitManager.cs b/src/ModuleCore/Git/GitManager.cs index 576afd5..a530c4e 100644 --- a/src/ModuleCore/Git/GitManager.cs +++ b/src/ModuleCore/Git/GitManager.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using ModuleCore.Database; using ModuleCore.Git.Models; +using SQLite; namespace ModuleCore.Git; @@ -18,6 +19,11 @@ public class GitManager _registrations = new ConcurrentDictionary(); _db = new DatabaseManager("git.db"); + + _db.InConnection(conn => + { + conn.CreateTable(); + }); } public static GitManager Instance => GitManagerInstance.Value; @@ -40,16 +46,46 @@ public class GitManager ? new DirectoryInfo(absoluteRepositoryLocation).Name : registrationName; - if (_registrations.TryAdd(registrationName, new InternalGitRegistration - { - Name = registrationName, - Location = absoluteRepositoryLocation, - })) + var gitRegistration = new InternalGitRegistration { - return registrationName; - } + Name = registrationName, + Location = absoluteRepositoryLocation, + Id = Guid.CreateVersion7(), + }; - throw new Exception($"Git repo already registered with the name {registrationName}"); + return _db.InConnection(conn => + { + // Query if we already have a registration either by name or location. + // 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. + var registrationExists = _db.Exists( + $""" + SELECT 1 + FROM {InternalGitRegistration.TableName} + WHERE Name = ? OR + Location = ? + """, + gitRegistration.Name, + gitRegistration.Location + ); + + if (registrationExists) + { + throw new Exception($"A Git repo is already registered with the name {registrationName} or location {absoluteRepositoryLocation}"); + } + + // Insert the new record + conn.Insert(gitRegistration); + + if (_registrations.TryAdd(registrationName, gitRegistration)) + { + return registrationName; + } + + // This error case should be unlikely, but if a registration was removed but the registrations wasn't updated + // correctly then we'd unable to re-add a repo with the same name + throw new Exception("An error occured during registration."); + }); } public List ListRepos() @@ -83,12 +119,22 @@ public class GitManager /// /// Used for internal git registration and handles getting the current branch /// + [Table(TableName)] private class InternalGitRegistration { private string _currentBranch = string.Empty; private long _nextCheckTime; - public required string Name { get; set; } - public required string Location { get; set; } + internal const string TableName = "GitRegistration"; + + [PrimaryKey] + public Guid Id { get; set; } + + [Indexed(Unique = true)] + public string Name { get; set; } = null!; + + [Indexed(Unique = true)] + public string Location { get; set; } = null!; + public string CurrentBranch => GetCurrentBranch(); // TODO: not fully decided on if I want this feature or not, but keeping it in for now diff --git a/src/ModuleCore/ModuleCore.csproj b/src/ModuleCore/ModuleCore.csproj index 2f41110..81bd88b 100644 --- a/src/ModuleCore/ModuleCore.csproj +++ b/src/ModuleCore/ModuleCore.csproj @@ -13,4 +13,8 @@ + + + + diff --git a/src/PowershellModule/PostBuild.ps1 b/src/PowershellModule/PostBuild.ps1 index d4c0725..cb7b8de 100644 --- a/src/PowershellModule/PostBuild.ps1 +++ b/src/PowershellModule/PostBuild.ps1 @@ -22,6 +22,7 @@ $allowList = @( "ModuleCore*" "PowershellModule*" "*SQLite*" + "data" ) Write-Host "Removing all non-module required files from '$targetDir'" Get-ChildItem -Path $targetDir -exclude $allowList | Remove-Item -Recurse \ No newline at end of file diff --git a/src/PowershellModule/PowershellModule.csproj b/src/PowershellModule/PowershellModule.csproj index 95ccbdc..56f10c3 100644 --- a/src/PowershellModule/PowershellModule.csproj +++ b/src/PowershellModule/PowershellModule.csproj @@ -12,7 +12,6 @@ All -