diff --git a/TGS.Server/Instance/Administration.cs b/TGS.Server/Instance/Administration.cs index 7c795857c1..fa11d6afba 100644 --- a/TGS.Server/Instance/Administration.cs +++ b/TGS.Server/Instance/Administration.cs @@ -150,8 +150,12 @@ namespace TGS.Server public string RecreateStaticFolder() { - if (!Monitor.TryEnter(RepoLock)) - return "Repo locked!"; + lock (RepoLock) + { + if (RepoBusy) + return "Repo locked!"; + RepoBusy = true; + } try { if (!Monitor.TryEnter(watchdogLock)) @@ -183,7 +187,8 @@ namespace TGS.Server } finally { - Monitor.Exit(RepoLock); + lock (RepoLock) + RepoBusy = false; } return null; } diff --git a/TGS.Server/Instance/Compiler.cs b/TGS.Server/Instance/Compiler.cs index 3ce9971504..19d1ce2237 100644 --- a/TGS.Server/Instance/Compiler.cs +++ b/TGS.Server/Instance/Compiler.cs @@ -309,16 +309,13 @@ namespace TGS.Server } string resurrectee; bool repobusy_check = false; - if (!Monitor.TryEnter(RepoLock)) - repobusy_check = true; - if (!repobusy_check) + lock (RepoLock) { if (RepoBusy) repobusy_check = true; else RepoBusy = true; - Monitor.Exit(RepoLock); } if (repobusy_check) @@ -331,6 +328,7 @@ namespace TGS.Server return; } } + string CurrentSha; try { @@ -344,7 +342,7 @@ namespace TGS.Server if (!silent) SendMessage("DM: Compiling...", MessageType.DeveloperInfo); - resurrectee = GetStagingDir(); //non-relative + resurrectee = GetStagingDir(); //non-relative var Config = GetCachedRepoConfig(); var deleteExcludeList = new List { BridgeDLLName }; @@ -386,9 +384,7 @@ namespace TGS.Server finally { lock (RepoLock) - { RepoBusy = false; - } } var res = CreateBackup(); diff --git a/TGS.Server/Instance/Repository.cs b/TGS.Server/Instance/Repository.cs index 78c6db44af..3f93681b5b 100644 --- a/TGS.Server/Instance/Repository.cs +++ b/TGS.Server/Instance/Repository.cs @@ -69,11 +69,11 @@ namespace TGS.Server /// object RepoLock = new object(); /// - /// Used in conjunction with for multithreading safety + /// Used for multithreading safety. You may not use the repo if this is not locked or . Either old the lock while you do work or set to then release it, do your work, reaquire it, and set back to /// bool RepoBusy = false; /// - /// Whether or not a git clone operation is in progress + /// Whether or not a git operation is in progress. See /// bool Cloning = false; @@ -118,10 +118,8 @@ namespace TGS.Server //this should never be called while the repo is busy RepoConfig I = null; lock (RepoLock) - { if (!RepoBusy && LoadRepo() == null) I = new RepoConfig(RelativePath(RepoTGS3SettingsPath)); - } if (I == null) throw new Exception("Unable to load TGS3.json from repo!"); var J = GetCachedRepoConfig(); @@ -141,9 +139,7 @@ namespace TGS.Server public bool OperationInProgress() { lock (RepoLock) - { return RepoBusy; - } } /// @@ -189,9 +185,7 @@ namespace TGS.Server public bool Exists() { lock (RepoLock) - { return !Cloning && Repository.IsValid(RelativePath(RepoPath)); - } } /// @@ -419,6 +413,11 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + { + error = "Repo is busy!"; + return null; + } var result = LoadRepo(); if (result != null) { @@ -502,6 +501,8 @@ namespace TGS.Server return "I'm sorry Dave, I'm afraid I can't do that..."; lock (RepoLock) { + if (RepoBusy) + return "Repo is busy!"; var result = LoadRepo(); if (result != null) return result; @@ -645,6 +646,8 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + return "Repo is busy!"; var result = LoadRepo(); if (result != null) return result; @@ -741,6 +744,8 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + return "Repo is busy!"; var res = LoadRepo(); if (res != null) return res; @@ -780,6 +785,11 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + { + error = "Repo is busy!"; + return null; + } error = LoadRepo(); if (error != null) return null; @@ -803,6 +813,8 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + return "Repo is busy!"; var res = LoadRepo() ?? ResetNoLock(trackedBranch ? (Repo.Head.TrackedBranch ?? Repo.Head) : Repo.Head); if (res == null) { @@ -869,6 +881,8 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + return "Repo is busy!"; var result = LoadRepo(); if (result != null) return result; @@ -995,6 +1009,11 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + { + error = "Repo is busy!"; + return null; + } var result = LoadRepo(); if (result != null) { @@ -1021,48 +1040,44 @@ namespace TGS.Server /// public string GetCommitterName() { - lock (RepoLock) - { - return Config.CommitterName; - } + return Config.CommitterName; } /// public void SetCommitterName(string newName) { - lock (RepoLock) - { - Config.CommitterName = newName; - } + Config.CommitterName = newName; } /// public string GetCommitterEmail() { - lock (RepoLock) - { - return Config.CommitterEmail; - } + return Config.CommitterEmail; } /// public void SetCommitterEmail(string newEmail) { - lock (RepoLock) - { - Config.CommitterEmail = newEmail; - } + Config.CommitterEmail = newEmail; } /// public string SynchronizePush() { - var Config = GetCachedRepoConfig(); - if (Config == null) - return "Error reading changelog configuration"; - if(!Config.ChangelogSupport || !SSHAuth()) - return null; - return LocalIsRemote() ? Commit(Config) ?? Push() : "Can't push changelog: HEAD does not match tracked remote branch"; + lock (RepoLock) + { + if (RepoBusy) + return "Repo is busy!"; + var Config = GetCachedRepoConfig(); + if (Config == null) + return "Error reading changelog configuration"; + if (!Config.ChangelogSupport || !SSHAuth()) + return null; + var res = LoadRepo(); + if (res != null) + return res; + return LocalIsRemote() ? Commit(Config) ?? Push() : "Can't push changelog: HEAD does not match tracked remote branch"; + } } /// @@ -1107,6 +1122,8 @@ namespace TGS.Server { lock (RepoLock) { + if (RepoBusy) + return false; if (LoadRepo() != null) return false; if (Fetch() != null) @@ -1123,70 +1140,56 @@ namespace TGS.Server } /// - /// Create a commit based on a + /// Create a commit based on a . Requires and /// /// A with /// on success, error message on failure string Commit(RepoConfig Config) { - lock (RepoLock) + try { - var result = LoadRepo(); - if (result != null) - return result; - try - { - // Stage the file - foreach(var I in Config.PathsToStage) - Commands.Stage(Repo, I); + // Stage the file + foreach (var I in Config.PathsToStage) + Commands.Stage(Repo, I); - if (Repo.RetrieveStatus().Staged.Count() == 0) //nothing to commit - return null; - - // Create the committer's signature and commit - var authorandcommitter = MakeSig(); - - // Commit to the repository - WriteInfo(String.Format("Commit {0} created from changelogs", Repo.Commit(CommitMessage, authorandcommitter, authorandcommitter)), EventID.RepoCommit); - DeletePRList(); + if (Repo.RetrieveStatus().Staged.Count() == 0) //nothing to commit return null; - } - catch (Exception e) - { - WriteWarning("Repo commit failed: " + e.ToString(), EventID.RepoCommitFail); - return e.ToString(); - } + + // Create the committer's signature and commit + var authorandcommitter = MakeSig(); + + // Commit to the repository + WriteInfo(String.Format("Commit {0} created from changelogs", Repo.Commit(CommitMessage, authorandcommitter, authorandcommitter)), EventID.RepoCommit); + DeletePRList(); + return null; + } + catch (Exception e) + { + WriteWarning("Repo commit failed: " + e.ToString(), EventID.RepoCommitFail); + return e.ToString(); } } - /// + /// + /// Push HEAD to . Requires repo be locked, , , and + /// + /// on success, error message on failure string Push() { - if (LocalIsRemote()) //nothing to push - return null; - lock (RepoLock) + try { - var result = LoadRepo(); - if (result != null) - return result; - try + var options = new PushOptions() { - if (!SSHAuth()) - return String.Format("Either {0} or {1} is missing from the server directory. Unable to push!", PrivateKeyPath, PublicKeyPath); - - var options = new PushOptions() - { - CredentialsProvider = GenerateGitCredentials, - }; - Repo.Network.Push(Repo.Network.Remotes[SSHPushRemote], Repo.Head.CanonicalName, options); - WriteInfo("Repo pushed up to commit: " + Repo.Head.Tip.Sha, EventID.RepoPush); - return null; - } - catch (Exception e) - { - WriteWarning("Repo push failed: " + e.ToString(), EventID.RepoPushFail); - return e.ToString(); - } + CredentialsProvider = GenerateGitCredentials, + }; + Repo.Network.Push(Repo.Network.Remotes[SSHPushRemote], Repo.Head.CanonicalName, options); + WriteInfo("Repo pushed up to commit: " + Repo.Head.Tip.Sha, EventID.RepoPush); + return null; + } + catch (Exception e) + { + WriteWarning("Repo push failed: " + e.ToString(), EventID.RepoPushFail); + return e.ToString(); } }