Deploy code docs to GitHub Pages for workflow run 233

Commit: aec2124051
This commit is contained in:
tgstation-server
2020-09-07 16:31:16 +00:00
parent b50d54d03d
commit 90fc835a3b
2 changed files with 379 additions and 333 deletions
+191 -168
View File
@@ -762,175 +762,198 @@ $(function() {
<div class="line"><a name="l00742"></a><span class="lineno"> 742</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> search)</div>
<div class="line"><a name="l00743"></a><span class="lineno"> 743</span>&#160; {</div>
<div class="line"><a name="l00744"></a><span class="lineno"> 744</span>&#160; revInfoWereLookingFor = dbPull</div>
<div class="line"><a name="l00745"></a><span class="lineno"> 745</span>&#160; .Where(x =&gt; model.NewTestMerges.Any(z =&gt;</div>
<div class="line"><a name="l00746"></a><span class="lineno"> 746</span>&#160; x.PrimaryTestMerge.Number == z.Number</div>
<div class="line"><a name="l00747"></a><span class="lineno"> 747</span>&#160; &amp;&amp; x.PrimaryTestMerge.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)</div>
<div class="line"><a name="l00748"></a><span class="lineno"> 748</span>&#160; &amp;&amp; (x.PrimaryTestMerge.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == <span class="keyword">null</span>))</div>
<div class="line"><a name="l00749"></a><span class="lineno"> 749</span>&#160; &amp;&amp; x.ActiveTestMerges.Select(y =&gt; y.TestMerge).All(y =&gt; appliedTestMergeIds.Contains(y.Id)))</div>
<div class="line"><a name="l00750"></a><span class="lineno"> 750</span>&#160; .FirstOrDefault();</div>
<div class="line"><a name="l00751"></a><span class="lineno"> 751</span>&#160; </div>
<div class="line"><a name="l00752"></a><span class="lineno"> 752</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00753"></a><span class="lineno"> 753</span>&#160; {</div>
<div class="line"><a name="l00754"></a><span class="lineno"> 754</span>&#160; lastGoodRevInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00755"></a><span class="lineno"> 755</span>&#160; appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);</div>
<div class="line"><a name="l00756"></a><span class="lineno"> 756</span>&#160; search.Remove(I);</div>
<div class="line"><a name="l00757"></a><span class="lineno"> 757</span>&#160; <span class="keywordflow">break</span>;</div>
<div class="line"><a name="l00758"></a><span class="lineno"> 758</span>&#160; }</div>
<div class="line"><a name="l00759"></a><span class="lineno"> 759</span>&#160; }</div>
<div class="line"><a name="l00760"></a><span class="lineno"> 760</span>&#160; }</div>
<div class="line"><a name="l00761"></a><span class="lineno"> 761</span>&#160; <span class="keywordflow">while</span> (revInfoWereLookingFor != <span class="keyword">null</span> &amp;&amp; search.Count &gt; 0);</div>
<div class="line"><a name="l00745"></a><span class="lineno"> 745</span>&#160; .Where(testRevInfo =&gt;</div>
<div class="line"><a name="l00746"></a><span class="lineno"> 746</span>&#160; {</div>
<div class="line"><a name="l00747"></a><span class="lineno"> 747</span>&#160; var testMergeMatch = model.NewTestMerges.Any(testTestMerge =&gt;</div>
<div class="line"><a name="l00748"></a><span class="lineno"> 748</span>&#160; {</div>
<div class="line"><a name="l00749"></a><span class="lineno"> 749</span>&#160; var numberMatch = testRevInfo.PrimaryTestMerge.Number == testTestMerge.Number;</div>
<div class="line"><a name="l00750"></a><span class="lineno"> 750</span>&#160; <span class="keywordflow">if</span> (!numberMatch)</div>
<div class="line"><a name="l00751"></a><span class="lineno"> 751</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00752"></a><span class="lineno"> 752</span>&#160; </div>
<div class="line"><a name="l00753"></a><span class="lineno"> 753</span>&#160; var shaMatch = testRevInfo.PrimaryTestMerge.PullRequestRevision.StartsWith(</div>
<div class="line"><a name="l00754"></a><span class="lineno"> 754</span>&#160; testTestMerge.PullRequestRevision,</div>
<div class="line"><a name="l00755"></a><span class="lineno"> 755</span>&#160; StringComparison.Ordinal);</div>
<div class="line"><a name="l00756"></a><span class="lineno"> 756</span>&#160; if (!shaMatch)</div>
<div class="line"><a name="l00757"></a><span class="lineno"> 757</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00758"></a><span class="lineno"> 758</span>&#160; </div>
<div class="line"><a name="l00759"></a><span class="lineno"> 759</span>&#160; var commentMatch = testRevInfo.PrimaryTestMerge.Comment == testTestMerge.Comment;</div>
<div class="line"><a name="l00760"></a><span class="lineno"> 760</span>&#160; <span class="keywordflow">return</span> commentMatch;</div>
<div class="line"><a name="l00761"></a><span class="lineno"> 761</span>&#160; });</div>
<div class="line"><a name="l00762"></a><span class="lineno"> 762</span>&#160; </div>
<div class="line"><a name="l00763"></a><span class="lineno"> 763</span>&#160; revInfoWereLookingFor = lastGoodRevInfo;</div>
<div class="line"><a name="l00764"></a><span class="lineno"> 764</span>&#160; needToApplyRemainingPrs = search.Count != 0;</div>
<div class="line"><a name="l00765"></a><span class="lineno"> 765</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00766"></a><span class="lineno"> 766</span>&#160; model.NewTestMerges = search;</div>
<div class="line"><a name="l00767"></a><span class="lineno"> 767</span>&#160; }</div>
<div class="line"><a name="l00768"></a><span class="lineno"> 768</span>&#160; <span class="keywordflow">else</span> <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00769"></a><span class="lineno"> 769</span>&#160; needToApplyRemainingPrs = <span class="keyword">false</span>;</div>
<div class="line"><a name="l00770"></a><span class="lineno"> 770</span>&#160; }</div>
<div class="line"><a name="l00771"></a><span class="lineno"> 771</span>&#160; }</div>
<div class="line"><a name="l00772"></a><span class="lineno"> 772</span>&#160; </div>
<div class="line"><a name="l00773"></a><span class="lineno"> 773</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00774"></a><span class="lineno"> 774</span>&#160; {</div>
<div class="line"><a name="l00775"></a><span class="lineno"> 775</span>&#160; <span class="comment">// goteem</span></div>
<div class="line"><a name="l00776"></a><span class="lineno"> 776</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogDebug(<span class="stringliteral">&quot;Reusing existing SHA {0}...&quot;</span>, revInfoWereLookingFor.CommitSha);</div>
<div class="line"><a name="l00777"></a><span class="lineno"> 777</span>&#160; await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00778"></a><span class="lineno"> 778</span>&#160; lastRevisionInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00779"></a><span class="lineno"> 779</span>&#160; }</div>
<div class="line"><a name="l00780"></a><span class="lineno"> 780</span>&#160; </div>
<div class="line"><a name="l00781"></a><span class="lineno"> 781</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00782"></a><span class="lineno"> 782</span>&#160; {</div>
<div class="line"><a name="l00783"></a><span class="lineno"> 783</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> model.NewTestMerges)</div>
<div class="line"><a name="l00784"></a><span class="lineno"> 784</span>&#160; {</div>
<div class="line"><a name="l00785"></a><span class="lineno"> 785</span>&#160; Octokit.PullRequest pr = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00786"></a><span class="lineno"> 786</span>&#160; <span class="keywordtype">string</span> errorMessage = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00787"></a><span class="lineno"> 787</span>&#160; </div>
<div class="line"><a name="l00788"></a><span class="lineno"> 788</span>&#160; <span class="keywordflow">if</span> (lastRevisionInfo.ActiveTestMerges.Any(x =&gt; x.TestMerge.Number == I.Number))</div>
<div class="line"><a name="l00789"></a><span class="lineno"> 789</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoDuplicateTestMerge);</div>
<div class="line"><a name="l00790"></a><span class="lineno"> 790</span>&#160; </div>
<div class="line"><a name="l00791"></a><span class="lineno"> 791</span>&#160; Exception exception = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00792"></a><span class="lineno"> 792</span>&#160; <span class="keywordflow">try</span></div>
<div class="line"><a name="l00793"></a><span class="lineno"> 793</span>&#160; {</div>
<div class="line"><a name="l00794"></a><span class="lineno"> 794</span>&#160; <span class="comment">// load from cache if possible</span></div>
<div class="line"><a name="l00795"></a><span class="lineno"> 795</span>&#160; <span class="keywordflow">if</span> (prMap == <span class="keyword">null</span> || !prMap.TryGetValue(I.Number, out pr))</div>
<div class="line"><a name="l00796"></a><span class="lineno"> 796</span>&#160; pr = await gitHubClient</div>
<div class="line"><a name="l00797"></a><span class="lineno"> 797</span>&#160; .PullRequest</div>
<div class="line"><a name="l00798"></a><span class="lineno"> 798</span>&#160; .Get(repoOwner, repoName, I.Number)</div>
<div class="line"><a name="l00799"></a><span class="lineno"> 799</span>&#160; .WithToken(ct)</div>
<div class="line"><a name="l00800"></a><span class="lineno"> 800</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00801"></a><span class="lineno"> 801</span>&#160; }</div>
<div class="line"><a name="l00802"></a><span class="lineno"> 802</span>&#160; <span class="keywordflow">catch</span> (Octokit.RateLimitExceededException ex)</div>
<div class="line"><a name="l00803"></a><span class="lineno"> 803</span>&#160; {</div>
<div class="line"><a name="l00804"></a><span class="lineno"> 804</span>&#160; <span class="comment">// you look at your anonymous access and sigh</span></div>
<div class="line"><a name="l00805"></a><span class="lineno"> 805</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: RATE LIMITED&quot;</span>;</div>
<div class="line"><a name="l00806"></a><span class="lineno"> 806</span>&#160; exception = ex;</div>
<div class="line"><a name="l00807"></a><span class="lineno"> 807</span>&#160; }</div>
<div class="line"><a name="l00808"></a><span class="lineno"> 808</span>&#160; <span class="keywordflow">catch</span> (Octokit.AuthorizationException ex)</div>
<div class="line"><a name="l00809"></a><span class="lineno"> 809</span>&#160; {</div>
<div class="line"><a name="l00810"></a><span class="lineno"> 810</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: BAD CREDENTIALS&quot;</span>;</div>
<div class="line"><a name="l00811"></a><span class="lineno"> 811</span>&#160; exception = ex;</div>
<div class="line"><a name="l00812"></a><span class="lineno"> 812</span>&#160; }</div>
<div class="line"><a name="l00813"></a><span class="lineno"> 813</span>&#160; <span class="keywordflow">catch</span> (Octokit.NotFoundException ex)</div>
<div class="line"><a name="l00814"></a><span class="lineno"> 814</span>&#160; {</div>
<div class="line"><a name="l00815"></a><span class="lineno"> 815</span>&#160; <span class="comment">// you look at your shithub and sigh</span></div>
<div class="line"><a name="l00816"></a><span class="lineno"> 816</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: PULL REQUEST NOT FOUND&quot;</span>;</div>
<div class="line"><a name="l00817"></a><span class="lineno"> 817</span>&#160; exception = ex;</div>
<div class="line"><a name="l00818"></a><span class="lineno"> 818</span>&#160; }</div>
<div class="line"><a name="l00819"></a><span class="lineno"> 819</span>&#160; </div>
<div class="line"><a name="l00820"></a><span class="lineno"> 820</span>&#160; <span class="keywordflow">if</span> (exception != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00821"></a><span class="lineno"> 821</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogWarning(exception, <span class="stringliteral">&quot;Error retrieving pull request metadata!&quot;</span>);</div>
<div class="line"><a name="l00822"></a><span class="lineno"> 822</span>&#160; </div>
<div class="line"><a name="l00823"></a><span class="lineno"> 823</span>&#160; <span class="comment">// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it</span></div>
<div class="line"><a name="l00824"></a><span class="lineno"> 824</span>&#160; <span class="keywordflow">if</span> (I.PullRequestRevision == <span class="keyword">null</span> &amp;&amp; pr != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00825"></a><span class="lineno"> 825</span>&#160; I.PullRequestRevision = pr.Head.Sha;</div>
<div class="line"><a name="l00826"></a><span class="lineno"> 826</span>&#160; </div>
<div class="line"><a name="l00827"></a><span class="lineno"> 827</span>&#160; var mergeResult = await repo.AddTestMerge(</div>
<div class="line"><a name="l00828"></a><span class="lineno"> 828</span>&#160; I,</div>
<div class="line"><a name="l00829"></a><span class="lineno"> 829</span>&#160; committerName,</div>
<div class="line"><a name="l00830"></a><span class="lineno"> 830</span>&#160; currentModel.CommitterEmail,</div>
<div class="line"><a name="l00831"></a><span class="lineno"> 831</span>&#160; currentModel.AccessUser,</div>
<div class="line"><a name="l00832"></a><span class="lineno"> 832</span>&#160; currentModel.AccessToken,</div>
<div class="line"><a name="l00833"></a><span class="lineno"> 833</span>&#160; NextProgressReporter(),</div>
<div class="line"><a name="l00834"></a><span class="lineno"> 834</span>&#160; ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00835"></a><span class="lineno"> 835</span>&#160; </div>
<div class="line"><a name="l00836"></a><span class="lineno"> 836</span>&#160; <span class="keywordflow">if</span> (!mergeResult.HasValue)</div>
<div class="line"><a name="l00837"></a><span class="lineno"> 837</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00838"></a><span class="lineno"> 838</span>&#160; <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoTestMergeConflict,</div>
<div class="line"><a name="l00839"></a><span class="lineno"> 839</span>&#160; <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00840"></a><span class="lineno"> 840</span>&#160; $<span class="stringliteral">&quot;Merge of PR #{I.Number} at {I.PullRequestRevision.Substring(0, 7)} conflicted!&quot;</span>));</div>
<div class="line"><a name="l00841"></a><span class="lineno"> 841</span>&#160; </div>
<div class="line"><a name="l00842"></a><span class="lineno"> 842</span>&#160; ++doneSteps;</div>
<div class="line"><a name="l00843"></a><span class="lineno"> 843</span>&#160; </div>
<div class="line"><a name="l00844"></a><span class="lineno"> 844</span>&#160; <span class="comment">// MergedBy will be set later</span></div>
<div class="line"><a name="l00845"></a><span class="lineno"> 845</span>&#160; var tm = <span class="keyword">new</span> Models.TestMerge</div>
<div class="line"><a name="l00846"></a><span class="lineno"> 846</span>&#160; {</div>
<div class="line"><a name="l00847"></a><span class="lineno"> 847</span>&#160; Author = pr?.User.Login ?? errorMessage,</div>
<div class="line"><a name="l00848"></a><span class="lineno"> 848</span>&#160; BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00849"></a><span class="lineno"> 849</span>&#160; MergedAt = DateTimeOffset.Now,</div>
<div class="line"><a name="l00850"></a><span class="lineno"> 850</span>&#160; TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00851"></a><span class="lineno"> 851</span>&#160; Comment = I.Comment,</div>
<div class="line"><a name="l00852"></a><span class="lineno"> 852</span>&#160; Number = I.Number,</div>
<div class="line"><a name="l00853"></a><span class="lineno"> 853</span>&#160; PullRequestRevision = I.PullRequestRevision,</div>
<div class="line"><a name="l00854"></a><span class="lineno"> 854</span>&#160; Url = pr?.HtmlUrl ?? errorMessage</div>
<div class="line"><a name="l00855"></a><span class="lineno"> 855</span>&#160; };</div>
<div class="line"><a name="l00856"></a><span class="lineno"> 856</span>&#160; </div>
<div class="line"><a name="l00857"></a><span class="lineno"> 857</span>&#160; await UpdateRevInfo(tm).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00858"></a><span class="lineno"> 858</span>&#160; }</div>
<div class="line"><a name="l00859"></a><span class="lineno"> 859</span>&#160; }</div>
<div class="line"><a name="l00860"></a><span class="lineno"> 860</span>&#160; }</div>
<div class="line"><a name="l00861"></a><span class="lineno"> 861</span>&#160; </div>
<div class="line"><a name="l00862"></a><span class="lineno"> 862</span>&#160; var currentHead = repo.Head;</div>
<div class="line"><a name="l00863"></a><span class="lineno"> 863</span>&#160; <span class="keywordflow">if</span> (startSha != currentHead || (postUpdateSha != <span class="keyword">null</span> &amp;&amp; postUpdateSha != currentHead))</div>
<div class="line"><a name="l00864"></a><span class="lineno"> 864</span>&#160; {</div>
<div class="line"><a name="l00865"></a><span class="lineno"> 865</span>&#160; await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), <span class="keyword">false</span>, ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00866"></a><span class="lineno"> 866</span>&#160; await UpdateRevInfo().ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00867"></a><span class="lineno"> 867</span>&#160; }</div>
<div class="line"><a name="l00868"></a><span class="lineno"> 868</span>&#160; </div>
<div class="line"><a name="l00869"></a><span class="lineno"> 869</span>&#160; <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a name="l00870"></a><span class="lineno"> 870</span>&#160; }</div>
<div class="line"><a name="l00871"></a><span class="lineno"> 871</span>&#160; <span class="keywordflow">catch</span></div>
<div class="line"><a name="l00872"></a><span class="lineno"> 872</span>&#160; {</div>
<div class="line"><a name="l00873"></a><span class="lineno"> 873</span>&#160; doneSteps = 0;</div>
<div class="line"><a name="l00874"></a><span class="lineno"> 874</span>&#160; numSteps = 2;</div>
<div class="line"><a name="l00875"></a><span class="lineno"> 875</span>&#160; </div>
<div class="line"><a name="l00876"></a><span class="lineno"> 876</span>&#160; <span class="comment">// Forget what we&#39;ve done and abort</span></div>
<div class="line"><a name="l00877"></a><span class="lineno"> 877</span>&#160; <span class="comment">// DCTx2: Cancellation token is for job, operations should always run</span></div>
<div class="line"><a name="l00878"></a><span class="lineno"> 878</span>&#160; await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00879"></a><span class="lineno"> 879</span>&#160; <span class="keywordflow">if</span> (startReference != <span class="keyword">null</span> &amp;&amp; repo.Head != startSha)</div>
<div class="line"><a name="l00880"></a><span class="lineno"> 880</span>&#160; await repo.ResetToSha(startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00881"></a><span class="lineno"> 881</span>&#160; <span class="keywordflow">else</span></div>
<div class="line"><a name="l00882"></a><span class="lineno"> 882</span>&#160; progressReporter(100);</div>
<div class="line"><a name="l00883"></a><span class="lineno"> 883</span>&#160; <span class="keywordflow">throw</span>;</div>
<div class="line"><a name="l00884"></a><span class="lineno"> 884</span>&#160; }</div>
<div class="line"><a name="l00885"></a><span class="lineno"> 885</span>&#160; }</div>
<div class="line"><a name="l00886"></a><span class="lineno"> 886</span>&#160; </div>
<div class="line"><a name="l00887"></a><span class="lineno"> 887</span>&#160; var job = <span class="keyword">new</span> Models.Job</div>
<div class="line"><a name="l00888"></a><span class="lineno"> 888</span>&#160; {</div>
<div class="line"><a name="l00889"></a><span class="lineno"> 889</span>&#160; Description = description,</div>
<div class="line"><a name="l00890"></a><span class="lineno"> 890</span>&#160; StartedBy = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html">AuthenticationContext</a>.<a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html#a0846ac9679599a99923987863edb0d5c">User</a>,</div>
<div class="line"><a name="l00891"></a><span class="lineno"> 891</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html">Instance</a> = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#a19f89ec03ffd6f2bf5cab5214d5e6bb8">Instance</a>,</div>
<div class="line"><a name="l00892"></a><span class="lineno"> 892</span>&#160; CancelRightsType = <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a7b02c8c3dadd90810a9eaa24712a0a20">RightsType</a>.Repository,</div>
<div class="line"><a name="l00893"></a><span class="lineno"> 893</span>&#160; CancelRight = (ulong)<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a95336db3db40dbae9701ef6e51240f39">RepositoryRights</a>.CancelPendingChanges,</div>
<div class="line"><a name="l00894"></a><span class="lineno"> 894</span>&#160; };</div>
<div class="line"><a name="l00895"></a><span class="lineno"> 895</span>&#160; </div>
<div class="line"><a name="l00896"></a><span class="lineno"> 896</span>&#160; <span class="comment">// Time to access git, do it in a job</span></div>
<div class="line"><a name="l00897"></a><span class="lineno"> 897</span>&#160; await <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_repository_controller.html#ad15c0217bf9e5ce926a198191d0a04c4">jobManager</a>.<a class="code" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html#a21be789f798adf9985f2432d3499b4cd">RegisterOperation</a>(</div>
<div class="line"><a name="l00898"></a><span class="lineno"> 898</span>&#160; job,</div>
<div class="line"><a name="l00899"></a><span class="lineno"> 899</span>&#160; (core, databaseContextFactory, paramJob, progressReporter, ct) =&gt;</div>
<div class="line"><a name="l00900"></a><span class="lineno"> 900</span>&#160; UpdateCallbackThatDesperatelyNeedsRefactoring(</div>
<div class="line"><a name="l00901"></a><span class="lineno"> 901</span>&#160; core,</div>
<div class="line"><a name="l00902"></a><span class="lineno"> 902</span>&#160; databaseContextFactory,</div>
<div class="line"><a name="l00903"></a><span class="lineno"> 903</span>&#160; progressReporter,</div>
<div class="line"><a name="l00904"></a><span class="lineno"> 904</span>&#160; ct),</div>
<div class="line"><a name="l00905"></a><span class="lineno"> 905</span>&#160; cancellationToken)</div>
<div class="line"><a name="l00906"></a><span class="lineno"> 906</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00907"></a><span class="lineno"> 907</span>&#160; </div>
<div class="line"><a name="l00908"></a><span class="lineno"> 908</span>&#160; api.ActiveJob = job.ToApi();</div>
<div class="line"><a name="l00909"></a><span class="lineno"> 909</span>&#160; <span class="keywordflow">return</span> Accepted(api);</div>
<div class="line"><a name="l00910"></a><span class="lineno"> 910</span>&#160; }</div>
<div class="line"><a name="l00911"></a><span class="lineno"> 911</span>&#160;<span class="preprocessor"> #pragma warning restore CA1502, CA1505</span></div>
<div class="line"><a name="l00912"></a><span class="lineno"> 912</span>&#160; }</div>
<div class="line"><a name="l00913"></a><span class="lineno"> 913</span>&#160;}</div>
<div class="line"><a name="l00763"></a><span class="lineno"> 763</span>&#160; <span class="keywordflow">if</span> (!testMergeMatch)</div>
<div class="line"><a name="l00764"></a><span class="lineno"> 764</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00765"></a><span class="lineno"> 765</span>&#160; </div>
<div class="line"><a name="l00766"></a><span class="lineno"> 766</span>&#160; var previousTestMergesMatch = testRevInfo</div>
<div class="line"><a name="l00767"></a><span class="lineno"> 767</span>&#160; .ActiveTestMerges</div>
<div class="line"><a name="l00768"></a><span class="lineno"> 768</span>&#160; .Select(previousRevInfoTestMerge =&gt; previousRevInfoTestMerge.TestMerge)</div>
<div class="line"><a name="l00769"></a><span class="lineno"> 769</span>&#160; .All(previousTestMerge =&gt; appliedTestMergeIds.Contains(previousTestMerge.Id));</div>
<div class="line"><a name="l00770"></a><span class="lineno"> 770</span>&#160; </div>
<div class="line"><a name="l00771"></a><span class="lineno"> 771</span>&#160; <span class="keywordflow">return</span> previousTestMergesMatch;</div>
<div class="line"><a name="l00772"></a><span class="lineno"> 772</span>&#160; })</div>
<div class="line"><a name="l00773"></a><span class="lineno"> 773</span>&#160; .FirstOrDefault();</div>
<div class="line"><a name="l00774"></a><span class="lineno"> 774</span>&#160; </div>
<div class="line"><a name="l00775"></a><span class="lineno"> 775</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00776"></a><span class="lineno"> 776</span>&#160; {</div>
<div class="line"><a name="l00777"></a><span class="lineno"> 777</span>&#160; lastGoodRevInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00778"></a><span class="lineno"> 778</span>&#160; appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);</div>
<div class="line"><a name="l00779"></a><span class="lineno"> 779</span>&#160; search.Remove(I);</div>
<div class="line"><a name="l00780"></a><span class="lineno"> 780</span>&#160; <span class="keywordflow">break</span>;</div>
<div class="line"><a name="l00781"></a><span class="lineno"> 781</span>&#160; }</div>
<div class="line"><a name="l00782"></a><span class="lineno"> 782</span>&#160; }</div>
<div class="line"><a name="l00783"></a><span class="lineno"> 783</span>&#160; }</div>
<div class="line"><a name="l00784"></a><span class="lineno"> 784</span>&#160; <span class="keywordflow">while</span> (revInfoWereLookingFor != <span class="keyword">null</span> &amp;&amp; search.Count &gt; 0);</div>
<div class="line"><a name="l00785"></a><span class="lineno"> 785</span>&#160; </div>
<div class="line"><a name="l00786"></a><span class="lineno"> 786</span>&#160; revInfoWereLookingFor = lastGoodRevInfo;</div>
<div class="line"><a name="l00787"></a><span class="lineno"> 787</span>&#160; needToApplyRemainingPrs = search.Count != 0;</div>
<div class="line"><a name="l00788"></a><span class="lineno"> 788</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00789"></a><span class="lineno"> 789</span>&#160; model.NewTestMerges = search;</div>
<div class="line"><a name="l00790"></a><span class="lineno"> 790</span>&#160; }</div>
<div class="line"><a name="l00791"></a><span class="lineno"> 791</span>&#160; <span class="keywordflow">else</span> <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00792"></a><span class="lineno"> 792</span>&#160; needToApplyRemainingPrs = <span class="keyword">false</span>;</div>
<div class="line"><a name="l00793"></a><span class="lineno"> 793</span>&#160; }</div>
<div class="line"><a name="l00794"></a><span class="lineno"> 794</span>&#160; }</div>
<div class="line"><a name="l00795"></a><span class="lineno"> 795</span>&#160; </div>
<div class="line"><a name="l00796"></a><span class="lineno"> 796</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00797"></a><span class="lineno"> 797</span>&#160; {</div>
<div class="line"><a name="l00798"></a><span class="lineno"> 798</span>&#160; <span class="comment">// goteem</span></div>
<div class="line"><a name="l00799"></a><span class="lineno"> 799</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogDebug(<span class="stringliteral">&quot;Reusing existing SHA {0}...&quot;</span>, revInfoWereLookingFor.CommitSha);</div>
<div class="line"><a name="l00800"></a><span class="lineno"> 800</span>&#160; await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00801"></a><span class="lineno"> 801</span>&#160; lastRevisionInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00802"></a><span class="lineno"> 802</span>&#160; }</div>
<div class="line"><a name="l00803"></a><span class="lineno"> 803</span>&#160; </div>
<div class="line"><a name="l00804"></a><span class="lineno"> 804</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00805"></a><span class="lineno"> 805</span>&#160; {</div>
<div class="line"><a name="l00806"></a><span class="lineno"> 806</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> model.NewTestMerges)</div>
<div class="line"><a name="l00807"></a><span class="lineno"> 807</span>&#160; {</div>
<div class="line"><a name="l00808"></a><span class="lineno"> 808</span>&#160; Octokit.PullRequest pr = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00809"></a><span class="lineno"> 809</span>&#160; <span class="keywordtype">string</span> errorMessage = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00810"></a><span class="lineno"> 810</span>&#160; </div>
<div class="line"><a name="l00811"></a><span class="lineno"> 811</span>&#160; <span class="keywordflow">if</span> (lastRevisionInfo.ActiveTestMerges.Any(x =&gt; x.TestMerge.Number == I.Number))</div>
<div class="line"><a name="l00812"></a><span class="lineno"> 812</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoDuplicateTestMerge);</div>
<div class="line"><a name="l00813"></a><span class="lineno"> 813</span>&#160; </div>
<div class="line"><a name="l00814"></a><span class="lineno"> 814</span>&#160; Exception exception = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00815"></a><span class="lineno"> 815</span>&#160; <span class="keywordflow">try</span></div>
<div class="line"><a name="l00816"></a><span class="lineno"> 816</span>&#160; {</div>
<div class="line"><a name="l00817"></a><span class="lineno"> 817</span>&#160; <span class="comment">// load from cache if possible</span></div>
<div class="line"><a name="l00818"></a><span class="lineno"> 818</span>&#160; <span class="keywordflow">if</span> (prMap == <span class="keyword">null</span> || !prMap.TryGetValue(I.Number, out pr))</div>
<div class="line"><a name="l00819"></a><span class="lineno"> 819</span>&#160; pr = await gitHubClient</div>
<div class="line"><a name="l00820"></a><span class="lineno"> 820</span>&#160; .PullRequest</div>
<div class="line"><a name="l00821"></a><span class="lineno"> 821</span>&#160; .Get(repoOwner, repoName, I.Number)</div>
<div class="line"><a name="l00822"></a><span class="lineno"> 822</span>&#160; .WithToken(ct)</div>
<div class="line"><a name="l00823"></a><span class="lineno"> 823</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00824"></a><span class="lineno"> 824</span>&#160; }</div>
<div class="line"><a name="l00825"></a><span class="lineno"> 825</span>&#160; <span class="keywordflow">catch</span> (Octokit.RateLimitExceededException ex)</div>
<div class="line"><a name="l00826"></a><span class="lineno"> 826</span>&#160; {</div>
<div class="line"><a name="l00827"></a><span class="lineno"> 827</span>&#160; <span class="comment">// you look at your anonymous access and sigh</span></div>
<div class="line"><a name="l00828"></a><span class="lineno"> 828</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: RATE LIMITED&quot;</span>;</div>
<div class="line"><a name="l00829"></a><span class="lineno"> 829</span>&#160; exception = ex;</div>
<div class="line"><a name="l00830"></a><span class="lineno"> 830</span>&#160; }</div>
<div class="line"><a name="l00831"></a><span class="lineno"> 831</span>&#160; <span class="keywordflow">catch</span> (Octokit.AuthorizationException ex)</div>
<div class="line"><a name="l00832"></a><span class="lineno"> 832</span>&#160; {</div>
<div class="line"><a name="l00833"></a><span class="lineno"> 833</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: BAD CREDENTIALS&quot;</span>;</div>
<div class="line"><a name="l00834"></a><span class="lineno"> 834</span>&#160; exception = ex;</div>
<div class="line"><a name="l00835"></a><span class="lineno"> 835</span>&#160; }</div>
<div class="line"><a name="l00836"></a><span class="lineno"> 836</span>&#160; <span class="keywordflow">catch</span> (Octokit.NotFoundException ex)</div>
<div class="line"><a name="l00837"></a><span class="lineno"> 837</span>&#160; {</div>
<div class="line"><a name="l00838"></a><span class="lineno"> 838</span>&#160; <span class="comment">// you look at your shithub and sigh</span></div>
<div class="line"><a name="l00839"></a><span class="lineno"> 839</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: PULL REQUEST NOT FOUND&quot;</span>;</div>
<div class="line"><a name="l00840"></a><span class="lineno"> 840</span>&#160; exception = ex;</div>
<div class="line"><a name="l00841"></a><span class="lineno"> 841</span>&#160; }</div>
<div class="line"><a name="l00842"></a><span class="lineno"> 842</span>&#160; </div>
<div class="line"><a name="l00843"></a><span class="lineno"> 843</span>&#160; <span class="keywordflow">if</span> (exception != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00844"></a><span class="lineno"> 844</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogWarning(exception, <span class="stringliteral">&quot;Error retrieving pull request metadata!&quot;</span>);</div>
<div class="line"><a name="l00845"></a><span class="lineno"> 845</span>&#160; </div>
<div class="line"><a name="l00846"></a><span class="lineno"> 846</span>&#160; <span class="comment">// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it</span></div>
<div class="line"><a name="l00847"></a><span class="lineno"> 847</span>&#160; <span class="keywordflow">if</span> (I.PullRequestRevision == <span class="keyword">null</span> &amp;&amp; pr != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00848"></a><span class="lineno"> 848</span>&#160; I.PullRequestRevision = pr.Head.Sha;</div>
<div class="line"><a name="l00849"></a><span class="lineno"> 849</span>&#160; </div>
<div class="line"><a name="l00850"></a><span class="lineno"> 850</span>&#160; var mergeResult = await repo.AddTestMerge(</div>
<div class="line"><a name="l00851"></a><span class="lineno"> 851</span>&#160; I,</div>
<div class="line"><a name="l00852"></a><span class="lineno"> 852</span>&#160; committerName,</div>
<div class="line"><a name="l00853"></a><span class="lineno"> 853</span>&#160; currentModel.CommitterEmail,</div>
<div class="line"><a name="l00854"></a><span class="lineno"> 854</span>&#160; currentModel.AccessUser,</div>
<div class="line"><a name="l00855"></a><span class="lineno"> 855</span>&#160; currentModel.AccessToken,</div>
<div class="line"><a name="l00856"></a><span class="lineno"> 856</span>&#160; NextProgressReporter(),</div>
<div class="line"><a name="l00857"></a><span class="lineno"> 857</span>&#160; ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00858"></a><span class="lineno"> 858</span>&#160; </div>
<div class="line"><a name="l00859"></a><span class="lineno"> 859</span>&#160; <span class="keywordflow">if</span> (!mergeResult.HasValue)</div>
<div class="line"><a name="l00860"></a><span class="lineno"> 860</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00861"></a><span class="lineno"> 861</span>&#160; <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoTestMergeConflict,</div>
<div class="line"><a name="l00862"></a><span class="lineno"> 862</span>&#160; <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00863"></a><span class="lineno"> 863</span>&#160; $<span class="stringliteral">&quot;Merge of PR #{I.Number} at {I.PullRequestRevision.Substring(0, 7)} conflicted!&quot;</span>));</div>
<div class="line"><a name="l00864"></a><span class="lineno"> 864</span>&#160; </div>
<div class="line"><a name="l00865"></a><span class="lineno"> 865</span>&#160; ++doneSteps;</div>
<div class="line"><a name="l00866"></a><span class="lineno"> 866</span>&#160; </div>
<div class="line"><a name="l00867"></a><span class="lineno"> 867</span>&#160; <span class="comment">// MergedBy will be set later</span></div>
<div class="line"><a name="l00868"></a><span class="lineno"> 868</span>&#160; var tm = <span class="keyword">new</span> Models.TestMerge</div>
<div class="line"><a name="l00869"></a><span class="lineno"> 869</span>&#160; {</div>
<div class="line"><a name="l00870"></a><span class="lineno"> 870</span>&#160; Author = pr?.User.Login ?? errorMessage,</div>
<div class="line"><a name="l00871"></a><span class="lineno"> 871</span>&#160; BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00872"></a><span class="lineno"> 872</span>&#160; MergedAt = DateTimeOffset.Now,</div>
<div class="line"><a name="l00873"></a><span class="lineno"> 873</span>&#160; TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00874"></a><span class="lineno"> 874</span>&#160; Comment = I.Comment,</div>
<div class="line"><a name="l00875"></a><span class="lineno"> 875</span>&#160; Number = I.Number,</div>
<div class="line"><a name="l00876"></a><span class="lineno"> 876</span>&#160; PullRequestRevision = I.PullRequestRevision,</div>
<div class="line"><a name="l00877"></a><span class="lineno"> 877</span>&#160; Url = pr?.HtmlUrl ?? errorMessage</div>
<div class="line"><a name="l00878"></a><span class="lineno"> 878</span>&#160; };</div>
<div class="line"><a name="l00879"></a><span class="lineno"> 879</span>&#160; </div>
<div class="line"><a name="l00880"></a><span class="lineno"> 880</span>&#160; await UpdateRevInfo(tm).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00881"></a><span class="lineno"> 881</span>&#160; }</div>
<div class="line"><a name="l00882"></a><span class="lineno"> 882</span>&#160; }</div>
<div class="line"><a name="l00883"></a><span class="lineno"> 883</span>&#160; }</div>
<div class="line"><a name="l00884"></a><span class="lineno"> 884</span>&#160; </div>
<div class="line"><a name="l00885"></a><span class="lineno"> 885</span>&#160; var currentHead = repo.Head;</div>
<div class="line"><a name="l00886"></a><span class="lineno"> 886</span>&#160; <span class="keywordflow">if</span> (startSha != currentHead || (postUpdateSha != <span class="keyword">null</span> &amp;&amp; postUpdateSha != currentHead))</div>
<div class="line"><a name="l00887"></a><span class="lineno"> 887</span>&#160; {</div>
<div class="line"><a name="l00888"></a><span class="lineno"> 888</span>&#160; await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), <span class="keyword">false</span>, ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00889"></a><span class="lineno"> 889</span>&#160; await UpdateRevInfo().ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00890"></a><span class="lineno"> 890</span>&#160; }</div>
<div class="line"><a name="l00891"></a><span class="lineno"> 891</span>&#160; </div>
<div class="line"><a name="l00892"></a><span class="lineno"> 892</span>&#160; <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a name="l00893"></a><span class="lineno"> 893</span>&#160; }</div>
<div class="line"><a name="l00894"></a><span class="lineno"> 894</span>&#160; <span class="keywordflow">catch</span></div>
<div class="line"><a name="l00895"></a><span class="lineno"> 895</span>&#160; {</div>
<div class="line"><a name="l00896"></a><span class="lineno"> 896</span>&#160; doneSteps = 0;</div>
<div class="line"><a name="l00897"></a><span class="lineno"> 897</span>&#160; numSteps = 2;</div>
<div class="line"><a name="l00898"></a><span class="lineno"> 898</span>&#160; </div>
<div class="line"><a name="l00899"></a><span class="lineno"> 899</span>&#160; <span class="comment">// Forget what we&#39;ve done and abort</span></div>
<div class="line"><a name="l00900"></a><span class="lineno"> 900</span>&#160; <span class="comment">// DCTx2: Cancellation token is for job, operations should always run</span></div>
<div class="line"><a name="l00901"></a><span class="lineno"> 901</span>&#160; await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00902"></a><span class="lineno"> 902</span>&#160; <span class="keywordflow">if</span> (startReference != <span class="keyword">null</span> &amp;&amp; repo.Head != startSha)</div>
<div class="line"><a name="l00903"></a><span class="lineno"> 903</span>&#160; await repo.ResetToSha(startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00904"></a><span class="lineno"> 904</span>&#160; <span class="keywordflow">else</span></div>
<div class="line"><a name="l00905"></a><span class="lineno"> 905</span>&#160; progressReporter(100);</div>
<div class="line"><a name="l00906"></a><span class="lineno"> 906</span>&#160; <span class="keywordflow">throw</span>;</div>
<div class="line"><a name="l00907"></a><span class="lineno"> 907</span>&#160; }</div>
<div class="line"><a name="l00908"></a><span class="lineno"> 908</span>&#160; }</div>
<div class="line"><a name="l00909"></a><span class="lineno"> 909</span>&#160; </div>
<div class="line"><a name="l00910"></a><span class="lineno"> 910</span>&#160; var job = <span class="keyword">new</span> Models.Job</div>
<div class="line"><a name="l00911"></a><span class="lineno"> 911</span>&#160; {</div>
<div class="line"><a name="l00912"></a><span class="lineno"> 912</span>&#160; Description = description,</div>
<div class="line"><a name="l00913"></a><span class="lineno"> 913</span>&#160; StartedBy = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html">AuthenticationContext</a>.<a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html#a0846ac9679599a99923987863edb0d5c">User</a>,</div>
<div class="line"><a name="l00914"></a><span class="lineno"> 914</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html">Instance</a> = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#a19f89ec03ffd6f2bf5cab5214d5e6bb8">Instance</a>,</div>
<div class="line"><a name="l00915"></a><span class="lineno"> 915</span>&#160; CancelRightsType = <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a7b02c8c3dadd90810a9eaa24712a0a20">RightsType</a>.Repository,</div>
<div class="line"><a name="l00916"></a><span class="lineno"> 916</span>&#160; CancelRight = (ulong)<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a95336db3db40dbae9701ef6e51240f39">RepositoryRights</a>.CancelPendingChanges,</div>
<div class="line"><a name="l00917"></a><span class="lineno"> 917</span>&#160; };</div>
<div class="line"><a name="l00918"></a><span class="lineno"> 918</span>&#160; </div>
<div class="line"><a name="l00919"></a><span class="lineno"> 919</span>&#160; <span class="comment">// Time to access git, do it in a job</span></div>
<div class="line"><a name="l00920"></a><span class="lineno"> 920</span>&#160; await <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_repository_controller.html#ad15c0217bf9e5ce926a198191d0a04c4">jobManager</a>.<a class="code" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html#a21be789f798adf9985f2432d3499b4cd">RegisterOperation</a>(</div>
<div class="line"><a name="l00921"></a><span class="lineno"> 921</span>&#160; job,</div>
<div class="line"><a name="l00922"></a><span class="lineno"> 922</span>&#160; (core, databaseContextFactory, paramJob, progressReporter, ct) =&gt;</div>
<div class="line"><a name="l00923"></a><span class="lineno"> 923</span>&#160; UpdateCallbackThatDesperatelyNeedsRefactoring(</div>
<div class="line"><a name="l00924"></a><span class="lineno"> 924</span>&#160; core,</div>
<div class="line"><a name="l00925"></a><span class="lineno"> 925</span>&#160; databaseContextFactory,</div>
<div class="line"><a name="l00926"></a><span class="lineno"> 926</span>&#160; progressReporter,</div>
<div class="line"><a name="l00927"></a><span class="lineno"> 927</span>&#160; ct),</div>
<div class="line"><a name="l00928"></a><span class="lineno"> 928</span>&#160; cancellationToken)</div>
<div class="line"><a name="l00929"></a><span class="lineno"> 929</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00930"></a><span class="lineno"> 930</span>&#160; </div>
<div class="line"><a name="l00931"></a><span class="lineno"> 931</span>&#160; api.ActiveJob = job.ToApi();</div>
<div class="line"><a name="l00932"></a><span class="lineno"> 932</span>&#160; <span class="keywordflow">return</span> Accepted(api);</div>
<div class="line"><a name="l00933"></a><span class="lineno"> 933</span>&#160; }</div>
<div class="line"><a name="l00934"></a><span class="lineno"> 934</span>&#160;<span class="preprocessor"> #pragma warning restore CA1502, CA1505</span></div>
<div class="line"><a name="l00935"></a><span class="lineno"> 935</span>&#160; }</div>
<div class="line"><a name="l00936"></a><span class="lineno"> 936</span>&#160;}</div>
</div><!-- fragment --></div><!-- contents -->
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_instance_required_controller_html_a1f3dffb9da170f16374e58f333ece5a7"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_instance_required_controller.html#a1f3dffb9da170f16374e58f333ece5a7">Tgstation.Server.Host.Controllers.InstanceRequiredController.instanceManager</a></div><div class="ttdeci">readonly IInstanceManager instanceManager</div><div class="ttdoc">The IInstanceManager for the InstanceRequiredController.</div><div class="ttdef"><b>Definition:</b> <a href="_instance_required_controller_8cs_source.html#l00022">InstanceRequiredController.cs:22</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html">Tgstation.Server.Api.Models.Repository</a></div><div class="ttdoc">Represents a git repository</div><div class="ttdef"><b>Definition:</b> <a href="_tgstation_8_server_8_api_2_models_2_repository_8cs_source.html#l00009">Repository.cs:10</a></div></div>
@@ -1261,172 +1261,195 @@ Here is the call graph for this function:</div>
<div class="line"><a name="l00742"></a><span class="lineno"> 742</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> search)</div>
<div class="line"><a name="l00743"></a><span class="lineno"> 743</span>&#160; {</div>
<div class="line"><a name="l00744"></a><span class="lineno"> 744</span>&#160; revInfoWereLookingFor = dbPull</div>
<div class="line"><a name="l00745"></a><span class="lineno"> 745</span>&#160; .Where(x =&gt; model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a>.Any(z =&gt;</div>
<div class="line"><a name="l00746"></a><span class="lineno"> 746</span>&#160; x.PrimaryTestMerge.Number == z.Number</div>
<div class="line"><a name="l00747"></a><span class="lineno"> 747</span>&#160; &amp;&amp; x.PrimaryTestMerge.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)</div>
<div class="line"><a name="l00748"></a><span class="lineno"> 748</span>&#160; &amp;&amp; (x.PrimaryTestMerge.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == <span class="keyword">null</span>))</div>
<div class="line"><a name="l00749"></a><span class="lineno"> 749</span>&#160; &amp;&amp; x.ActiveTestMerges.Select(y =&gt; y.TestMerge).All(y =&gt; appliedTestMergeIds.Contains(y.Id)))</div>
<div class="line"><a name="l00750"></a><span class="lineno"> 750</span>&#160; .FirstOrDefault();</div>
<div class="line"><a name="l00751"></a><span class="lineno"> 751</span>&#160; </div>
<div class="line"><a name="l00752"></a><span class="lineno"> 752</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00753"></a><span class="lineno"> 753</span>&#160; {</div>
<div class="line"><a name="l00754"></a><span class="lineno"> 754</span>&#160; lastGoodRevInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00755"></a><span class="lineno"> 755</span>&#160; appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);</div>
<div class="line"><a name="l00756"></a><span class="lineno"> 756</span>&#160; search.Remove(I);</div>
<div class="line"><a name="l00757"></a><span class="lineno"> 757</span>&#160; <span class="keywordflow">break</span>;</div>
<div class="line"><a name="l00758"></a><span class="lineno"> 758</span>&#160; }</div>
<div class="line"><a name="l00759"></a><span class="lineno"> 759</span>&#160; }</div>
<div class="line"><a name="l00760"></a><span class="lineno"> 760</span>&#160; }</div>
<div class="line"><a name="l00761"></a><span class="lineno"> 761</span>&#160; <span class="keywordflow">while</span> (revInfoWereLookingFor != <span class="keyword">null</span> &amp;&amp; search.Count &gt; 0);</div>
<div class="line"><a name="l00745"></a><span class="lineno"> 745</span>&#160; .Where(testRevInfo =&gt;</div>
<div class="line"><a name="l00746"></a><span class="lineno"> 746</span>&#160; {</div>
<div class="line"><a name="l00747"></a><span class="lineno"> 747</span>&#160; var testMergeMatch = model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a>.Any(testTestMerge =&gt;</div>
<div class="line"><a name="l00748"></a><span class="lineno"> 748</span>&#160; {</div>
<div class="line"><a name="l00749"></a><span class="lineno"> 749</span>&#160; var numberMatch = testRevInfo.PrimaryTestMerge.Number == testTestMerge.Number;</div>
<div class="line"><a name="l00750"></a><span class="lineno"> 750</span>&#160; <span class="keywordflow">if</span> (!numberMatch)</div>
<div class="line"><a name="l00751"></a><span class="lineno"> 751</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00752"></a><span class="lineno"> 752</span>&#160; </div>
<div class="line"><a name="l00753"></a><span class="lineno"> 753</span>&#160; var shaMatch = testRevInfo.PrimaryTestMerge.PullRequestRevision.StartsWith(</div>
<div class="line"><a name="l00754"></a><span class="lineno"> 754</span>&#160; testTestMerge.PullRequestRevision,</div>
<div class="line"><a name="l00755"></a><span class="lineno"> 755</span>&#160; StringComparison.Ordinal);</div>
<div class="line"><a name="l00756"></a><span class="lineno"> 756</span>&#160; if (!shaMatch)</div>
<div class="line"><a name="l00757"></a><span class="lineno"> 757</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00758"></a><span class="lineno"> 758</span>&#160; </div>
<div class="line"><a name="l00759"></a><span class="lineno"> 759</span>&#160; var commentMatch = testRevInfo.PrimaryTestMerge.Comment == testTestMerge.Comment;</div>
<div class="line"><a name="l00760"></a><span class="lineno"> 760</span>&#160; <span class="keywordflow">return</span> commentMatch;</div>
<div class="line"><a name="l00761"></a><span class="lineno"> 761</span>&#160; });</div>
<div class="line"><a name="l00762"></a><span class="lineno"> 762</span>&#160; </div>
<div class="line"><a name="l00763"></a><span class="lineno"> 763</span>&#160; revInfoWereLookingFor = lastGoodRevInfo;</div>
<div class="line"><a name="l00764"></a><span class="lineno"> 764</span>&#160; needToApplyRemainingPrs = search.Count != 0;</div>
<div class="line"><a name="l00765"></a><span class="lineno"> 765</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00766"></a><span class="lineno"> 766</span>&#160; model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a> = search;</div>
<div class="line"><a name="l00767"></a><span class="lineno"> 767</span>&#160; }</div>
<div class="line"><a name="l00768"></a><span class="lineno"> 768</span>&#160; <span class="keywordflow">else</span> <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00769"></a><span class="lineno"> 769</span>&#160; needToApplyRemainingPrs = <span class="keyword">false</span>;</div>
<div class="line"><a name="l00770"></a><span class="lineno"> 770</span>&#160; }</div>
<div class="line"><a name="l00771"></a><span class="lineno"> 771</span>&#160; }</div>
<div class="line"><a name="l00772"></a><span class="lineno"> 772</span>&#160; </div>
<div class="line"><a name="l00773"></a><span class="lineno"> 773</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00774"></a><span class="lineno"> 774</span>&#160; {</div>
<div class="line"><a name="l00775"></a><span class="lineno"> 775</span>&#160; <span class="comment">// goteem</span></div>
<div class="line"><a name="l00776"></a><span class="lineno"> 776</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogDebug(<span class="stringliteral">&quot;Reusing existing SHA {0}...&quot;</span>, revInfoWereLookingFor.CommitSha);</div>
<div class="line"><a name="l00777"></a><span class="lineno"> 777</span>&#160; await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00778"></a><span class="lineno"> 778</span>&#160; lastRevisionInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00779"></a><span class="lineno"> 779</span>&#160; }</div>
<div class="line"><a name="l00780"></a><span class="lineno"> 780</span>&#160; </div>
<div class="line"><a name="l00781"></a><span class="lineno"> 781</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00782"></a><span class="lineno"> 782</span>&#160; {</div>
<div class="line"><a name="l00783"></a><span class="lineno"> 783</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a>)</div>
<div class="line"><a name="l00784"></a><span class="lineno"> 784</span>&#160; {</div>
<div class="line"><a name="l00785"></a><span class="lineno"> 785</span>&#160; Octokit.PullRequest pr = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00786"></a><span class="lineno"> 786</span>&#160; <span class="keywordtype">string</span> errorMessage = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00787"></a><span class="lineno"> 787</span>&#160; </div>
<div class="line"><a name="l00788"></a><span class="lineno"> 788</span>&#160; <span class="keywordflow">if</span> (lastRevisionInfo.ActiveTestMerges.Any(x =&gt; x.TestMerge.Number == I.Number))</div>
<div class="line"><a name="l00789"></a><span class="lineno"> 789</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoDuplicateTestMerge);</div>
<div class="line"><a name="l00790"></a><span class="lineno"> 790</span>&#160; </div>
<div class="line"><a name="l00791"></a><span class="lineno"> 791</span>&#160; Exception exception = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00792"></a><span class="lineno"> 792</span>&#160; <span class="keywordflow">try</span></div>
<div class="line"><a name="l00793"></a><span class="lineno"> 793</span>&#160; {</div>
<div class="line"><a name="l00794"></a><span class="lineno"> 794</span>&#160; <span class="comment">// load from cache if possible</span></div>
<div class="line"><a name="l00795"></a><span class="lineno"> 795</span>&#160; <span class="keywordflow">if</span> (prMap == <span class="keyword">null</span> || !prMap.TryGetValue(I.Number, out pr))</div>
<div class="line"><a name="l00796"></a><span class="lineno"> 796</span>&#160; pr = await gitHubClient</div>
<div class="line"><a name="l00797"></a><span class="lineno"> 797</span>&#160; .PullRequest</div>
<div class="line"><a name="l00798"></a><span class="lineno"> 798</span>&#160; .Get(repoOwner, repoName, I.Number)</div>
<div class="line"><a name="l00799"></a><span class="lineno"> 799</span>&#160; .WithToken(ct)</div>
<div class="line"><a name="l00800"></a><span class="lineno"> 800</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00801"></a><span class="lineno"> 801</span>&#160; }</div>
<div class="line"><a name="l00802"></a><span class="lineno"> 802</span>&#160; <span class="keywordflow">catch</span> (Octokit.RateLimitExceededException ex)</div>
<div class="line"><a name="l00803"></a><span class="lineno"> 803</span>&#160; {</div>
<div class="line"><a name="l00804"></a><span class="lineno"> 804</span>&#160; <span class="comment">// you look at your anonymous access and sigh</span></div>
<div class="line"><a name="l00805"></a><span class="lineno"> 805</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: RATE LIMITED&quot;</span>;</div>
<div class="line"><a name="l00806"></a><span class="lineno"> 806</span>&#160; exception = ex;</div>
<div class="line"><a name="l00807"></a><span class="lineno"> 807</span>&#160; }</div>
<div class="line"><a name="l00808"></a><span class="lineno"> 808</span>&#160; <span class="keywordflow">catch</span> (Octokit.AuthorizationException ex)</div>
<div class="line"><a name="l00809"></a><span class="lineno"> 809</span>&#160; {</div>
<div class="line"><a name="l00810"></a><span class="lineno"> 810</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: BAD CREDENTIALS&quot;</span>;</div>
<div class="line"><a name="l00811"></a><span class="lineno"> 811</span>&#160; exception = ex;</div>
<div class="line"><a name="l00812"></a><span class="lineno"> 812</span>&#160; }</div>
<div class="line"><a name="l00813"></a><span class="lineno"> 813</span>&#160; <span class="keywordflow">catch</span> (Octokit.NotFoundException ex)</div>
<div class="line"><a name="l00814"></a><span class="lineno"> 814</span>&#160; {</div>
<div class="line"><a name="l00815"></a><span class="lineno"> 815</span>&#160; <span class="comment">// you look at your shithub and sigh</span></div>
<div class="line"><a name="l00816"></a><span class="lineno"> 816</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: PULL REQUEST NOT FOUND&quot;</span>;</div>
<div class="line"><a name="l00817"></a><span class="lineno"> 817</span>&#160; exception = ex;</div>
<div class="line"><a name="l00818"></a><span class="lineno"> 818</span>&#160; }</div>
<div class="line"><a name="l00819"></a><span class="lineno"> 819</span>&#160; </div>
<div class="line"><a name="l00820"></a><span class="lineno"> 820</span>&#160; <span class="keywordflow">if</span> (exception != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00821"></a><span class="lineno"> 821</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogWarning(exception, <span class="stringliteral">&quot;Error retrieving pull request metadata!&quot;</span>);</div>
<div class="line"><a name="l00822"></a><span class="lineno"> 822</span>&#160; </div>
<div class="line"><a name="l00823"></a><span class="lineno"> 823</span>&#160; <span class="comment">// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it</span></div>
<div class="line"><a name="l00824"></a><span class="lineno"> 824</span>&#160; <span class="keywordflow">if</span> (I.PullRequestRevision == <span class="keyword">null</span> &amp;&amp; pr != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00825"></a><span class="lineno"> 825</span>&#160; I.PullRequestRevision = pr.Head.Sha;</div>
<div class="line"><a name="l00826"></a><span class="lineno"> 826</span>&#160; </div>
<div class="line"><a name="l00827"></a><span class="lineno"> 827</span>&#160; var mergeResult = await repo.AddTestMerge(</div>
<div class="line"><a name="l00828"></a><span class="lineno"> 828</span>&#160; I,</div>
<div class="line"><a name="l00829"></a><span class="lineno"> 829</span>&#160; committerName,</div>
<div class="line"><a name="l00830"></a><span class="lineno"> 830</span>&#160; currentModel.CommitterEmail,</div>
<div class="line"><a name="l00831"></a><span class="lineno"> 831</span>&#160; currentModel.AccessUser,</div>
<div class="line"><a name="l00832"></a><span class="lineno"> 832</span>&#160; currentModel.AccessToken,</div>
<div class="line"><a name="l00833"></a><span class="lineno"> 833</span>&#160; NextProgressReporter(),</div>
<div class="line"><a name="l00834"></a><span class="lineno"> 834</span>&#160; ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00835"></a><span class="lineno"> 835</span>&#160; </div>
<div class="line"><a name="l00836"></a><span class="lineno"> 836</span>&#160; <span class="keywordflow">if</span> (!mergeResult.HasValue)</div>
<div class="line"><a name="l00837"></a><span class="lineno"> 837</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00838"></a><span class="lineno"> 838</span>&#160; <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoTestMergeConflict,</div>
<div class="line"><a name="l00839"></a><span class="lineno"> 839</span>&#160; <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00840"></a><span class="lineno"> 840</span>&#160; $<span class="stringliteral">&quot;Merge of PR #{I.Number} at {I.PullRequestRevision.Substring(0, 7)} conflicted!&quot;</span>));</div>
<div class="line"><a name="l00841"></a><span class="lineno"> 841</span>&#160; </div>
<div class="line"><a name="l00842"></a><span class="lineno"> 842</span>&#160; ++doneSteps;</div>
<div class="line"><a name="l00843"></a><span class="lineno"> 843</span>&#160; </div>
<div class="line"><a name="l00844"></a><span class="lineno"> 844</span>&#160; <span class="comment">// MergedBy will be set later</span></div>
<div class="line"><a name="l00845"></a><span class="lineno"> 845</span>&#160; var tm = <span class="keyword">new</span> Models.TestMerge</div>
<div class="line"><a name="l00846"></a><span class="lineno"> 846</span>&#160; {</div>
<div class="line"><a name="l00847"></a><span class="lineno"> 847</span>&#160; Author = pr?.User.Login ?? errorMessage,</div>
<div class="line"><a name="l00848"></a><span class="lineno"> 848</span>&#160; BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00849"></a><span class="lineno"> 849</span>&#160; MergedAt = DateTimeOffset.Now,</div>
<div class="line"><a name="l00850"></a><span class="lineno"> 850</span>&#160; TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00851"></a><span class="lineno"> 851</span>&#160; Comment = I.Comment,</div>
<div class="line"><a name="l00852"></a><span class="lineno"> 852</span>&#160; Number = I.Number,</div>
<div class="line"><a name="l00853"></a><span class="lineno"> 853</span>&#160; PullRequestRevision = I.PullRequestRevision,</div>
<div class="line"><a name="l00854"></a><span class="lineno"> 854</span>&#160; Url = pr?.HtmlUrl ?? errorMessage</div>
<div class="line"><a name="l00855"></a><span class="lineno"> 855</span>&#160; };</div>
<div class="line"><a name="l00856"></a><span class="lineno"> 856</span>&#160; </div>
<div class="line"><a name="l00857"></a><span class="lineno"> 857</span>&#160; await UpdateRevInfo(tm).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00858"></a><span class="lineno"> 858</span>&#160; }</div>
<div class="line"><a name="l00859"></a><span class="lineno"> 859</span>&#160; }</div>
<div class="line"><a name="l00860"></a><span class="lineno"> 860</span>&#160; }</div>
<div class="line"><a name="l00861"></a><span class="lineno"> 861</span>&#160; </div>
<div class="line"><a name="l00862"></a><span class="lineno"> 862</span>&#160; var currentHead = repo.Head;</div>
<div class="line"><a name="l00863"></a><span class="lineno"> 863</span>&#160; <span class="keywordflow">if</span> (startSha != currentHead || (postUpdateSha != <span class="keyword">null</span> &amp;&amp; postUpdateSha != currentHead))</div>
<div class="line"><a name="l00864"></a><span class="lineno"> 864</span>&#160; {</div>
<div class="line"><a name="l00865"></a><span class="lineno"> 865</span>&#160; await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), <span class="keyword">false</span>, ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00866"></a><span class="lineno"> 866</span>&#160; await UpdateRevInfo().ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00867"></a><span class="lineno"> 867</span>&#160; }</div>
<div class="line"><a name="l00868"></a><span class="lineno"> 868</span>&#160; </div>
<div class="line"><a name="l00869"></a><span class="lineno"> 869</span>&#160; <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a name="l00870"></a><span class="lineno"> 870</span>&#160; }</div>
<div class="line"><a name="l00871"></a><span class="lineno"> 871</span>&#160; <span class="keywordflow">catch</span></div>
<div class="line"><a name="l00872"></a><span class="lineno"> 872</span>&#160; {</div>
<div class="line"><a name="l00873"></a><span class="lineno"> 873</span>&#160; doneSteps = 0;</div>
<div class="line"><a name="l00874"></a><span class="lineno"> 874</span>&#160; numSteps = 2;</div>
<div class="line"><a name="l00875"></a><span class="lineno"> 875</span>&#160; </div>
<div class="line"><a name="l00876"></a><span class="lineno"> 876</span>&#160; <span class="comment">// Forget what we&#39;ve done and abort</span></div>
<div class="line"><a name="l00877"></a><span class="lineno"> 877</span>&#160; <span class="comment">// DCTx2: Cancellation token is for job, operations should always run</span></div>
<div class="line"><a name="l00878"></a><span class="lineno"> 878</span>&#160; await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00879"></a><span class="lineno"> 879</span>&#160; <span class="keywordflow">if</span> (startReference != <span class="keyword">null</span> &amp;&amp; repo.Head != startSha)</div>
<div class="line"><a name="l00880"></a><span class="lineno"> 880</span>&#160; await repo.ResetToSha(startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00881"></a><span class="lineno"> 881</span>&#160; <span class="keywordflow">else</span></div>
<div class="line"><a name="l00882"></a><span class="lineno"> 882</span>&#160; progressReporter(100);</div>
<div class="line"><a name="l00883"></a><span class="lineno"> 883</span>&#160; <span class="keywordflow">throw</span>;</div>
<div class="line"><a name="l00884"></a><span class="lineno"> 884</span>&#160; }</div>
<div class="line"><a name="l00885"></a><span class="lineno"> 885</span>&#160; }</div>
<div class="line"><a name="l00886"></a><span class="lineno"> 886</span>&#160; </div>
<div class="line"><a name="l00887"></a><span class="lineno"> 887</span>&#160; var job = <span class="keyword">new</span> Models.Job</div>
<div class="line"><a name="l00888"></a><span class="lineno"> 888</span>&#160; {</div>
<div class="line"><a name="l00889"></a><span class="lineno"> 889</span>&#160; Description = description,</div>
<div class="line"><a name="l00890"></a><span class="lineno"> 890</span>&#160; StartedBy = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html">AuthenticationContext</a>.<a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html#a0846ac9679599a99923987863edb0d5c">User</a>,</div>
<div class="line"><a name="l00891"></a><span class="lineno"> 891</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html">Instance</a> = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#a19f89ec03ffd6f2bf5cab5214d5e6bb8">Instance</a>,</div>
<div class="line"><a name="l00892"></a><span class="lineno"> 892</span>&#160; CancelRightsType = <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a7b02c8c3dadd90810a9eaa24712a0a20">RightsType</a>.Repository,</div>
<div class="line"><a name="l00893"></a><span class="lineno"> 893</span>&#160; CancelRight = (ulong)<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a95336db3db40dbae9701ef6e51240f39">RepositoryRights</a>.CancelPendingChanges,</div>
<div class="line"><a name="l00894"></a><span class="lineno"> 894</span>&#160; };</div>
<div class="line"><a name="l00895"></a><span class="lineno"> 895</span>&#160; </div>
<div class="line"><a name="l00896"></a><span class="lineno"> 896</span>&#160; <span class="comment">// Time to access git, do it in a job</span></div>
<div class="line"><a name="l00897"></a><span class="lineno"> 897</span>&#160; await <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_repository_controller.html#ad15c0217bf9e5ce926a198191d0a04c4">jobManager</a>.<a class="code" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html#a21be789f798adf9985f2432d3499b4cd">RegisterOperation</a>(</div>
<div class="line"><a name="l00898"></a><span class="lineno"> 898</span>&#160; job,</div>
<div class="line"><a name="l00899"></a><span class="lineno"> 899</span>&#160; (core, databaseContextFactory, paramJob, progressReporter, ct) =&gt;</div>
<div class="line"><a name="l00900"></a><span class="lineno"> 900</span>&#160; UpdateCallbackThatDesperatelyNeedsRefactoring(</div>
<div class="line"><a name="l00901"></a><span class="lineno"> 901</span>&#160; core,</div>
<div class="line"><a name="l00902"></a><span class="lineno"> 902</span>&#160; databaseContextFactory,</div>
<div class="line"><a name="l00903"></a><span class="lineno"> 903</span>&#160; progressReporter,</div>
<div class="line"><a name="l00904"></a><span class="lineno"> 904</span>&#160; ct),</div>
<div class="line"><a name="l00905"></a><span class="lineno"> 905</span>&#160; cancellationToken)</div>
<div class="line"><a name="l00906"></a><span class="lineno"> 906</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00907"></a><span class="lineno"> 907</span>&#160; </div>
<div class="line"><a name="l00908"></a><span class="lineno"> 908</span>&#160; api.ActiveJob = job.ToApi();</div>
<div class="line"><a name="l00909"></a><span class="lineno"> 909</span>&#160; <span class="keywordflow">return</span> Accepted(api);</div>
<div class="line"><a name="l00910"></a><span class="lineno"> 910</span>&#160; }</div>
<div class="line"><a name="l00763"></a><span class="lineno"> 763</span>&#160; <span class="keywordflow">if</span> (!testMergeMatch)</div>
<div class="line"><a name="l00764"></a><span class="lineno"> 764</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line"><a name="l00765"></a><span class="lineno"> 765</span>&#160; </div>
<div class="line"><a name="l00766"></a><span class="lineno"> 766</span>&#160; var previousTestMergesMatch = testRevInfo</div>
<div class="line"><a name="l00767"></a><span class="lineno"> 767</span>&#160; .ActiveTestMerges</div>
<div class="line"><a name="l00768"></a><span class="lineno"> 768</span>&#160; .Select(previousRevInfoTestMerge =&gt; previousRevInfoTestMerge.TestMerge)</div>
<div class="line"><a name="l00769"></a><span class="lineno"> 769</span>&#160; .All(previousTestMerge =&gt; appliedTestMergeIds.Contains(previousTestMerge.Id));</div>
<div class="line"><a name="l00770"></a><span class="lineno"> 770</span>&#160; </div>
<div class="line"><a name="l00771"></a><span class="lineno"> 771</span>&#160; <span class="keywordflow">return</span> previousTestMergesMatch;</div>
<div class="line"><a name="l00772"></a><span class="lineno"> 772</span>&#160; })</div>
<div class="line"><a name="l00773"></a><span class="lineno"> 773</span>&#160; .FirstOrDefault();</div>
<div class="line"><a name="l00774"></a><span class="lineno"> 774</span>&#160; </div>
<div class="line"><a name="l00775"></a><span class="lineno"> 775</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00776"></a><span class="lineno"> 776</span>&#160; {</div>
<div class="line"><a name="l00777"></a><span class="lineno"> 777</span>&#160; lastGoodRevInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00778"></a><span class="lineno"> 778</span>&#160; appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);</div>
<div class="line"><a name="l00779"></a><span class="lineno"> 779</span>&#160; search.Remove(I);</div>
<div class="line"><a name="l00780"></a><span class="lineno"> 780</span>&#160; <span class="keywordflow">break</span>;</div>
<div class="line"><a name="l00781"></a><span class="lineno"> 781</span>&#160; }</div>
<div class="line"><a name="l00782"></a><span class="lineno"> 782</span>&#160; }</div>
<div class="line"><a name="l00783"></a><span class="lineno"> 783</span>&#160; }</div>
<div class="line"><a name="l00784"></a><span class="lineno"> 784</span>&#160; <span class="keywordflow">while</span> (revInfoWereLookingFor != <span class="keyword">null</span> &amp;&amp; search.Count &gt; 0);</div>
<div class="line"><a name="l00785"></a><span class="lineno"> 785</span>&#160; </div>
<div class="line"><a name="l00786"></a><span class="lineno"> 786</span>&#160; revInfoWereLookingFor = lastGoodRevInfo;</div>
<div class="line"><a name="l00787"></a><span class="lineno"> 787</span>&#160; needToApplyRemainingPrs = search.Count != 0;</div>
<div class="line"><a name="l00788"></a><span class="lineno"> 788</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00789"></a><span class="lineno"> 789</span>&#160; model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a> = search;</div>
<div class="line"><a name="l00790"></a><span class="lineno"> 790</span>&#160; }</div>
<div class="line"><a name="l00791"></a><span class="lineno"> 791</span>&#160; <span class="keywordflow">else</span> <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00792"></a><span class="lineno"> 792</span>&#160; needToApplyRemainingPrs = <span class="keyword">false</span>;</div>
<div class="line"><a name="l00793"></a><span class="lineno"> 793</span>&#160; }</div>
<div class="line"><a name="l00794"></a><span class="lineno"> 794</span>&#160; }</div>
<div class="line"><a name="l00795"></a><span class="lineno"> 795</span>&#160; </div>
<div class="line"><a name="l00796"></a><span class="lineno"> 796</span>&#160; <span class="keywordflow">if</span> (revInfoWereLookingFor != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00797"></a><span class="lineno"> 797</span>&#160; {</div>
<div class="line"><a name="l00798"></a><span class="lineno"> 798</span>&#160; <span class="comment">// goteem</span></div>
<div class="line"><a name="l00799"></a><span class="lineno"> 799</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogDebug(<span class="stringliteral">&quot;Reusing existing SHA {0}...&quot;</span>, revInfoWereLookingFor.CommitSha);</div>
<div class="line"><a name="l00800"></a><span class="lineno"> 800</span>&#160; await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00801"></a><span class="lineno"> 801</span>&#160; lastRevisionInfo = revInfoWereLookingFor;</div>
<div class="line"><a name="l00802"></a><span class="lineno"> 802</span>&#160; }</div>
<div class="line"><a name="l00803"></a><span class="lineno"> 803</span>&#160; </div>
<div class="line"><a name="l00804"></a><span class="lineno"> 804</span>&#160; <span class="keywordflow">if</span> (needToApplyRemainingPrs)</div>
<div class="line"><a name="l00805"></a><span class="lineno"> 805</span>&#160; {</div>
<div class="line"><a name="l00806"></a><span class="lineno"> 806</span>&#160; <span class="keywordflow">foreach</span> (var I <span class="keywordflow">in</span> model.<a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html#ad4bb63897d14c742a2c52a159ec75641">NewTestMerges</a>)</div>
<div class="line"><a name="l00807"></a><span class="lineno"> 807</span>&#160; {</div>
<div class="line"><a name="l00808"></a><span class="lineno"> 808</span>&#160; Octokit.PullRequest pr = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00809"></a><span class="lineno"> 809</span>&#160; <span class="keywordtype">string</span> errorMessage = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00810"></a><span class="lineno"> 810</span>&#160; </div>
<div class="line"><a name="l00811"></a><span class="lineno"> 811</span>&#160; <span class="keywordflow">if</span> (lastRevisionInfo.ActiveTestMerges.Any(x =&gt; x.TestMerge.Number == I.Number))</div>
<div class="line"><a name="l00812"></a><span class="lineno"> 812</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoDuplicateTestMerge);</div>
<div class="line"><a name="l00813"></a><span class="lineno"> 813</span>&#160; </div>
<div class="line"><a name="l00814"></a><span class="lineno"> 814</span>&#160; Exception exception = <span class="keyword">null</span>;</div>
<div class="line"><a name="l00815"></a><span class="lineno"> 815</span>&#160; <span class="keywordflow">try</span></div>
<div class="line"><a name="l00816"></a><span class="lineno"> 816</span>&#160; {</div>
<div class="line"><a name="l00817"></a><span class="lineno"> 817</span>&#160; <span class="comment">// load from cache if possible</span></div>
<div class="line"><a name="l00818"></a><span class="lineno"> 818</span>&#160; <span class="keywordflow">if</span> (prMap == <span class="keyword">null</span> || !prMap.TryGetValue(I.Number, out pr))</div>
<div class="line"><a name="l00819"></a><span class="lineno"> 819</span>&#160; pr = await gitHubClient</div>
<div class="line"><a name="l00820"></a><span class="lineno"> 820</span>&#160; .PullRequest</div>
<div class="line"><a name="l00821"></a><span class="lineno"> 821</span>&#160; .Get(repoOwner, repoName, I.Number)</div>
<div class="line"><a name="l00822"></a><span class="lineno"> 822</span>&#160; .WithToken(ct)</div>
<div class="line"><a name="l00823"></a><span class="lineno"> 823</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00824"></a><span class="lineno"> 824</span>&#160; }</div>
<div class="line"><a name="l00825"></a><span class="lineno"> 825</span>&#160; <span class="keywordflow">catch</span> (Octokit.RateLimitExceededException ex)</div>
<div class="line"><a name="l00826"></a><span class="lineno"> 826</span>&#160; {</div>
<div class="line"><a name="l00827"></a><span class="lineno"> 827</span>&#160; <span class="comment">// you look at your anonymous access and sigh</span></div>
<div class="line"><a name="l00828"></a><span class="lineno"> 828</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: RATE LIMITED&quot;</span>;</div>
<div class="line"><a name="l00829"></a><span class="lineno"> 829</span>&#160; exception = ex;</div>
<div class="line"><a name="l00830"></a><span class="lineno"> 830</span>&#160; }</div>
<div class="line"><a name="l00831"></a><span class="lineno"> 831</span>&#160; <span class="keywordflow">catch</span> (Octokit.AuthorizationException ex)</div>
<div class="line"><a name="l00832"></a><span class="lineno"> 832</span>&#160; {</div>
<div class="line"><a name="l00833"></a><span class="lineno"> 833</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: BAD CREDENTIALS&quot;</span>;</div>
<div class="line"><a name="l00834"></a><span class="lineno"> 834</span>&#160; exception = ex;</div>
<div class="line"><a name="l00835"></a><span class="lineno"> 835</span>&#160; }</div>
<div class="line"><a name="l00836"></a><span class="lineno"> 836</span>&#160; <span class="keywordflow">catch</span> (Octokit.NotFoundException ex)</div>
<div class="line"><a name="l00837"></a><span class="lineno"> 837</span>&#160; {</div>
<div class="line"><a name="l00838"></a><span class="lineno"> 838</span>&#160; <span class="comment">// you look at your shithub and sigh</span></div>
<div class="line"><a name="l00839"></a><span class="lineno"> 839</span>&#160; errorMessage = <span class="stringliteral">&quot;REMOTE API ERROR: PULL REQUEST NOT FOUND&quot;</span>;</div>
<div class="line"><a name="l00840"></a><span class="lineno"> 840</span>&#160; exception = ex;</div>
<div class="line"><a name="l00841"></a><span class="lineno"> 841</span>&#160; }</div>
<div class="line"><a name="l00842"></a><span class="lineno"> 842</span>&#160; </div>
<div class="line"><a name="l00843"></a><span class="lineno"> 843</span>&#160; <span class="keywordflow">if</span> (exception != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00844"></a><span class="lineno"> 844</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#ae5655868c2b2b913046ecf61934ce119">Logger</a>.LogWarning(exception, <span class="stringliteral">&quot;Error retrieving pull request metadata!&quot;</span>);</div>
<div class="line"><a name="l00845"></a><span class="lineno"> 845</span>&#160; </div>
<div class="line"><a name="l00846"></a><span class="lineno"> 846</span>&#160; <span class="comment">// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it</span></div>
<div class="line"><a name="l00847"></a><span class="lineno"> 847</span>&#160; <span class="keywordflow">if</span> (I.PullRequestRevision == <span class="keyword">null</span> &amp;&amp; pr != <span class="keyword">null</span>)</div>
<div class="line"><a name="l00848"></a><span class="lineno"> 848</span>&#160; I.PullRequestRevision = pr.Head.Sha;</div>
<div class="line"><a name="l00849"></a><span class="lineno"> 849</span>&#160; </div>
<div class="line"><a name="l00850"></a><span class="lineno"> 850</span>&#160; var mergeResult = await repo.AddTestMerge(</div>
<div class="line"><a name="l00851"></a><span class="lineno"> 851</span>&#160; I,</div>
<div class="line"><a name="l00852"></a><span class="lineno"> 852</span>&#160; committerName,</div>
<div class="line"><a name="l00853"></a><span class="lineno"> 853</span>&#160; currentModel.CommitterEmail,</div>
<div class="line"><a name="l00854"></a><span class="lineno"> 854</span>&#160; currentModel.AccessUser,</div>
<div class="line"><a name="l00855"></a><span class="lineno"> 855</span>&#160; currentModel.AccessToken,</div>
<div class="line"><a name="l00856"></a><span class="lineno"> 856</span>&#160; NextProgressReporter(),</div>
<div class="line"><a name="l00857"></a><span class="lineno"> 857</span>&#160; ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00858"></a><span class="lineno"> 858</span>&#160; </div>
<div class="line"><a name="l00859"></a><span class="lineno"> 859</span>&#160; <span class="keywordflow">if</span> (!mergeResult.HasValue)</div>
<div class="line"><a name="l00860"></a><span class="lineno"> 860</span>&#160; <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00861"></a><span class="lineno"> 861</span>&#160; <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.RepoTestMergeConflict,</div>
<div class="line"><a name="l00862"></a><span class="lineno"> 862</span>&#160; <span class="keyword">new</span> <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(</div>
<div class="line"><a name="l00863"></a><span class="lineno"> 863</span>&#160; $<span class="stringliteral">&quot;Merge of PR #{I.Number} at {I.PullRequestRevision.Substring(0, 7)} conflicted!&quot;</span>));</div>
<div class="line"><a name="l00864"></a><span class="lineno"> 864</span>&#160; </div>
<div class="line"><a name="l00865"></a><span class="lineno"> 865</span>&#160; ++doneSteps;</div>
<div class="line"><a name="l00866"></a><span class="lineno"> 866</span>&#160; </div>
<div class="line"><a name="l00867"></a><span class="lineno"> 867</span>&#160; <span class="comment">// MergedBy will be set later</span></div>
<div class="line"><a name="l00868"></a><span class="lineno"> 868</span>&#160; var tm = <span class="keyword">new</span> Models.TestMerge</div>
<div class="line"><a name="l00869"></a><span class="lineno"> 869</span>&#160; {</div>
<div class="line"><a name="l00870"></a><span class="lineno"> 870</span>&#160; Author = pr?.User.Login ?? errorMessage,</div>
<div class="line"><a name="l00871"></a><span class="lineno"> 871</span>&#160; BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00872"></a><span class="lineno"> 872</span>&#160; MergedAt = DateTimeOffset.Now,</div>
<div class="line"><a name="l00873"></a><span class="lineno"> 873</span>&#160; TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,</div>
<div class="line"><a name="l00874"></a><span class="lineno"> 874</span>&#160; Comment = I.Comment,</div>
<div class="line"><a name="l00875"></a><span class="lineno"> 875</span>&#160; Number = I.Number,</div>
<div class="line"><a name="l00876"></a><span class="lineno"> 876</span>&#160; PullRequestRevision = I.PullRequestRevision,</div>
<div class="line"><a name="l00877"></a><span class="lineno"> 877</span>&#160; Url = pr?.HtmlUrl ?? errorMessage</div>
<div class="line"><a name="l00878"></a><span class="lineno"> 878</span>&#160; };</div>
<div class="line"><a name="l00879"></a><span class="lineno"> 879</span>&#160; </div>
<div class="line"><a name="l00880"></a><span class="lineno"> 880</span>&#160; await UpdateRevInfo(tm).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00881"></a><span class="lineno"> 881</span>&#160; }</div>
<div class="line"><a name="l00882"></a><span class="lineno"> 882</span>&#160; }</div>
<div class="line"><a name="l00883"></a><span class="lineno"> 883</span>&#160; }</div>
<div class="line"><a name="l00884"></a><span class="lineno"> 884</span>&#160; </div>
<div class="line"><a name="l00885"></a><span class="lineno"> 885</span>&#160; var currentHead = repo.Head;</div>
<div class="line"><a name="l00886"></a><span class="lineno"> 886</span>&#160; <span class="keywordflow">if</span> (startSha != currentHead || (postUpdateSha != <span class="keyword">null</span> &amp;&amp; postUpdateSha != currentHead))</div>
<div class="line"><a name="l00887"></a><span class="lineno"> 887</span>&#160; {</div>
<div class="line"><a name="l00888"></a><span class="lineno"> 888</span>&#160; await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), <span class="keyword">false</span>, ct).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00889"></a><span class="lineno"> 889</span>&#160; await UpdateRevInfo().ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00890"></a><span class="lineno"> 890</span>&#160; }</div>
<div class="line"><a name="l00891"></a><span class="lineno"> 891</span>&#160; </div>
<div class="line"><a name="l00892"></a><span class="lineno"> 892</span>&#160; <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a name="l00893"></a><span class="lineno"> 893</span>&#160; }</div>
<div class="line"><a name="l00894"></a><span class="lineno"> 894</span>&#160; <span class="keywordflow">catch</span></div>
<div class="line"><a name="l00895"></a><span class="lineno"> 895</span>&#160; {</div>
<div class="line"><a name="l00896"></a><span class="lineno"> 896</span>&#160; doneSteps = 0;</div>
<div class="line"><a name="l00897"></a><span class="lineno"> 897</span>&#160; numSteps = 2;</div>
<div class="line"><a name="l00898"></a><span class="lineno"> 898</span>&#160; </div>
<div class="line"><a name="l00899"></a><span class="lineno"> 899</span>&#160; <span class="comment">// Forget what we&#39;ve done and abort</span></div>
<div class="line"><a name="l00900"></a><span class="lineno"> 900</span>&#160; <span class="comment">// DCTx2: Cancellation token is for job, operations should always run</span></div>
<div class="line"><a name="l00901"></a><span class="lineno"> 901</span>&#160; await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00902"></a><span class="lineno"> 902</span>&#160; <span class="keywordflow">if</span> (startReference != <span class="keyword">null</span> &amp;&amp; repo.Head != startSha)</div>
<div class="line"><a name="l00903"></a><span class="lineno"> 903</span>&#160; await repo.ResetToSha(startSha, NextProgressReporter(), <span class="keywordflow">default</span>).ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00904"></a><span class="lineno"> 904</span>&#160; <span class="keywordflow">else</span></div>
<div class="line"><a name="l00905"></a><span class="lineno"> 905</span>&#160; progressReporter(100);</div>
<div class="line"><a name="l00906"></a><span class="lineno"> 906</span>&#160; <span class="keywordflow">throw</span>;</div>
<div class="line"><a name="l00907"></a><span class="lineno"> 907</span>&#160; }</div>
<div class="line"><a name="l00908"></a><span class="lineno"> 908</span>&#160; }</div>
<div class="line"><a name="l00909"></a><span class="lineno"> 909</span>&#160; </div>
<div class="line"><a name="l00910"></a><span class="lineno"> 910</span>&#160; var job = <span class="keyword">new</span> Models.Job</div>
<div class="line"><a name="l00911"></a><span class="lineno"> 911</span>&#160; {</div>
<div class="line"><a name="l00912"></a><span class="lineno"> 912</span>&#160; Description = description,</div>
<div class="line"><a name="l00913"></a><span class="lineno"> 913</span>&#160; StartedBy = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html">AuthenticationContext</a>.<a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_security_1_1_authentication_context.html#a0846ac9679599a99923987863edb0d5c">User</a>,</div>
<div class="line"><a name="l00914"></a><span class="lineno"> 914</span>&#160; <a class="code" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html">Instance</a> = <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#a19f89ec03ffd6f2bf5cab5214d5e6bb8">Instance</a>,</div>
<div class="line"><a name="l00915"></a><span class="lineno"> 915</span>&#160; CancelRightsType = <a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a7b02c8c3dadd90810a9eaa24712a0a20">RightsType</a>.Repository,</div>
<div class="line"><a name="l00916"></a><span class="lineno"> 916</span>&#160; CancelRight = (ulong)<a class="code" href="namespace_tgstation_1_1_server_1_1_api_1_1_rights.html#a95336db3db40dbae9701ef6e51240f39">RepositoryRights</a>.CancelPendingChanges,</div>
<div class="line"><a name="l00917"></a><span class="lineno"> 917</span>&#160; };</div>
<div class="line"><a name="l00918"></a><span class="lineno"> 918</span>&#160; </div>
<div class="line"><a name="l00919"></a><span class="lineno"> 919</span>&#160; <span class="comment">// Time to access git, do it in a job</span></div>
<div class="line"><a name="l00920"></a><span class="lineno"> 920</span>&#160; await <a class="code" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_repository_controller.html#ad15c0217bf9e5ce926a198191d0a04c4">jobManager</a>.<a class="code" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html#a21be789f798adf9985f2432d3499b4cd">RegisterOperation</a>(</div>
<div class="line"><a name="l00921"></a><span class="lineno"> 921</span>&#160; job,</div>
<div class="line"><a name="l00922"></a><span class="lineno"> 922</span>&#160; (core, databaseContextFactory, paramJob, progressReporter, ct) =&gt;</div>
<div class="line"><a name="l00923"></a><span class="lineno"> 923</span>&#160; UpdateCallbackThatDesperatelyNeedsRefactoring(</div>
<div class="line"><a name="l00924"></a><span class="lineno"> 924</span>&#160; core,</div>
<div class="line"><a name="l00925"></a><span class="lineno"> 925</span>&#160; databaseContextFactory,</div>
<div class="line"><a name="l00926"></a><span class="lineno"> 926</span>&#160; progressReporter,</div>
<div class="line"><a name="l00927"></a><span class="lineno"> 927</span>&#160; ct),</div>
<div class="line"><a name="l00928"></a><span class="lineno"> 928</span>&#160; cancellationToken)</div>
<div class="line"><a name="l00929"></a><span class="lineno"> 929</span>&#160; .ConfigureAwait(<span class="keyword">false</span>);</div>
<div class="line"><a name="l00930"></a><span class="lineno"> 930</span>&#160; </div>
<div class="line"><a name="l00931"></a><span class="lineno"> 931</span>&#160; api.ActiveJob = job.ToApi();</div>
<div class="line"><a name="l00932"></a><span class="lineno"> 932</span>&#160; <span class="keywordflow">return</span> Accepted(api);</div>
<div class="line"><a name="l00933"></a><span class="lineno"> 933</span>&#160; }</div>
</div><!-- fragment -->
<p class="reference">References <a class="el" href="interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_git_hub_client_factory.html#a9043597fb0563f7fb0ed751819aa7525">Tgstation.Server.Host.Core.IGitHubClientFactory.CreateClient()</a>, <a class="el" href="_repository_controller_8cs_source.html#l00047">Tgstation.Server.Host.Controllers.RepositoryController.generalConfiguration</a>, <a class="el" href="_authentication_context_8cs_source.html#l00046">Tgstation.Server.Host.Security.AuthenticationContext.GetRight()</a>, <a class="el" href="_general_configuration_8cs_source.html#l00067">Tgstation.Server.Host.Configuration.GeneralConfiguration.GitHubAccessToken</a>, <a class="el" href="_repository_controller_8cs_source.html#l00037">Tgstation.Server.Host.Controllers.RepositoryController.gitHubClientFactory</a>, <a class="el" href="class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_api_controller.html#a30f0e4c93d7b119d4bf7aadefc1e5b8f">Tgstation.Server.Host.Controllers.ApiController.Gone()</a>, <a class="el" href="_entity_id_8cs_source.html#l00011">Tgstation.Server.Api.Models.EntityId.Id</a>, <a class="el" href="_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html#l00016">Tgstation.Server.Api.Models.Internal.User.Id</a>, <a class="el" href="_api_controller_8cs_source.html#l00049">Tgstation.Server.Host.Controllers.ApiController.Instance</a>, <a class="el" href="_repository_controller_8cs_source.html#l00042">Tgstation.Server.Host.Controllers.RepositoryController.jobManager</a>, <a class="el" href="_repository_controller_8cs_source.html#l00078">Tgstation.Server.Host.Controllers.RepositoryController.LoadRevisionInformation()</a>, <a class="el" href="_api_controller_8cs_source.html#l00044">Tgstation.Server.Host.Controllers.ApiController.Logger</a>, <a class="el" href="_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html#l00041">Tgstation.Server.Api.Models.Internal.User.Name</a>, <a class="el" href="_repository_controller_8cs_source.html#l00124">Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi()</a>, <a class="el" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html#a21be789f798adf9985f2432d3499b4cd">Tgstation.Server.Host.Jobs.IJobManager.RegisterOperation()</a>, <a class="el" href="_i_instance_core_8cs_source.html#l00019">Tgstation.Server.Host.Components.IInstanceCore.RepositoryManager</a>, <a class="el" href="_database_context_8cs_source.html#l00062">Tgstation.Server.Host.Database.DatabaseContext.RepositorySettings</a>, <a class="el" href="class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context.html#ac2e88d53bf1b6ac87d175d83ed39da7c">Tgstation.Server.Host.Database.DatabaseContext.Save()</a>, <a class="el" href="interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context_factory.html#ad22fce8fc51129e9da203dcef2f7ab42">Tgstation.Server.Host.Database.IDatabaseContextFactory.UseContext()</a>, <a class="el" href="_authentication_context_8cs_source.html#l00014">Tgstation.Server.Host.Security.AuthenticationContext.User</a>, and <a class="el" href="_instance_required_controller_8cs_source.html#l00064">Tgstation.Server.Host.Controllers.InstanceRequiredController.WithComponentInstance()</a>.</p>
<div class="dynheader">