Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit d339a8e

Browse files
committed
Fetch via refs/pull/<PR>/head in case branch deleted
Deleted branches can only be fetched by owner of repo. Fetch via special `refs/pull/<PR>/head` refspec to avoid this issue.
1 parent 4407e3c commit d339a8e

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

src/GitHub.App/Services/GitClient.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,45 @@ public Task<bool> IsModified(IRepository repository, string path, byte[] content
379379
});
380380
}
381381

382+
public async Task<string> GetPullRequestMergeBase(IRepository repo,
383+
UriString targetCloneUrl, string baseSha, string headSha, string baseRef, int pullNumber)
384+
{
385+
Guard.ArgumentNotNull(repo, nameof(repo));
386+
Guard.ArgumentNotNull(targetCloneUrl, nameof(targetCloneUrl));
387+
Guard.ArgumentNotEmptyString(baseRef, nameof(baseRef));
388+
389+
var baseCommit = repo.Lookup<Commit>(baseSha);
390+
if (baseCommit == null)
391+
{
392+
await Fetch(repo, targetCloneUrl, baseRef);
393+
baseCommit = repo.Lookup<Commit>(baseSha);
394+
if (baseCommit == null)
395+
{
396+
throw new NotFoundException($"Couldn't find {baseSha} after fetching from {targetCloneUrl}:{baseRef}.");
397+
}
398+
}
399+
400+
var headCommit = repo.Lookup<Commit>(headSha);
401+
if (headCommit == null)
402+
{
403+
var headRef = $"refs/pull/{pullNumber}/head";
404+
await Fetch(repo, targetCloneUrl, headRef);
405+
headCommit = repo.Lookup<Commit>(headSha);
406+
if (headCommit == null)
407+
{
408+
throw new NotFoundException($"Couldn't find {headSha} after fetching from {targetCloneUrl}:{headRef}.");
409+
}
410+
}
411+
412+
var mergeBaseCommit = repo.ObjectDatabase.FindMergeBase(baseCommit, headCommit);
413+
if (mergeBaseCommit == null)
414+
{
415+
throw new NotFoundException($"Couldn't find merge base between {baseCommit} and {headCommit}.");
416+
}
417+
418+
return mergeBaseCommit.Sha;
419+
}
420+
382421
public async Task<string> GetPullRequestMergeBase(IRepository repo,
383422
UriString baseCloneUrl, UriString headCloneUrl, string baseSha, string headSha, string baseRef, string headRef)
384423
{

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,10 @@ public IObservable<string> ExtractFile(
313313
sha = await gitClient.GetPullRequestMergeBase(
314314
repo,
315315
pullRequest.Base.RepositoryCloneUrl,
316-
pullRequest.Head.RepositoryCloneUrl,
317316
pullRequest.Base.Sha,
318317
pullRequest.Head.Sha,
319318
pullRequest.Base.Ref,
320-
pullRequest.Head.Ref);
319+
pullRequest.Number);
321320
}
322321
catch (NotFoundException ex)
323322
{

src/GitHub.Exports.Reactive/Services/IGitClient.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,28 @@ public interface IGitClient
193193
/// <param name="baseSha">The PR base SHA.</param>
194194
/// <param name="headSha">The PR head SHA.</param>
195195
/// <param name="baseRef">The PR base ref (e.g. 'master').</param>
196-
/// <param name="pullNumber">The PR number.</param>
196+
/// <param name="headRef">The PR head ref.</param>
197197
/// <returns>
198198
/// The merge base SHA or null.
199199
/// </returns>
200200
/// <exception cref="LibGit2Sharp.NotFoundException">Thrown when the merge base can't be found.</exception>
201201
Task<string> GetPullRequestMergeBase(IRepository repo, UriString baseCloneUrl, UriString headCloneUrl, string baseSha, string headSha, string baseRef, string headRef);
202202

203+
/// <summary>
204+
/// Find the merge base SHA between two commits.
205+
/// </summary>
206+
/// <param name="repository">The repository.</param>
207+
/// <param name="targetCloneUrl">The clone url of the PR target repo.</param>
208+
/// <param name="baseSha">The PR base SHA.</param>
209+
/// <param name="headSha">The PR head SHA.</param>
210+
/// <param name="baseRef">The PR base ref (e.g. 'master').</param>
211+
/// <param name="pullNumber">The PR number.</param>
212+
/// <returns>
213+
/// The merge base SHA or null.
214+
/// </returns>
215+
/// <exception cref="LibGit2Sharp.NotFoundException">Thrown when the merge base can't be found.</exception>
216+
Task<string> GetPullRequestMergeBase(IRepository repo, UriString targetCloneUrl, string baseSha, string headSha, string baseRef, int pullNumber);
217+
203218
/// Checks whether the current head is pushed to its remote tracking branch.
204219
/// </summary>
205220
/// <param name="repository">The repository.</param>

src/GitHub.InlineReviews/Services/PullRequestSessionService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ public async Task<string> GetPullRequestMergeBase(ILocalRepositoryModel reposito
122122
}
123123

124124
var repo = await GetRepository(repository);
125-
var baseUrl = pullRequest.Base.RepositoryCloneUrl;
125+
var targetUrl = pullRequest.Base.RepositoryCloneUrl;
126126
var headUrl = pullRequest.Head.RepositoryCloneUrl;
127127
var baseRef = pullRequest.Base.Ref;
128-
var headRef = pullRequest.Head.Ref;
128+
var pullNumber = pullRequest.Number;
129129
try
130130
{
131-
mergeBase = await gitClient.GetPullRequestMergeBase(repo, baseUrl, headUrl, baseSha, headSha, baseRef, headRef);
131+
mergeBase = await gitClient.GetPullRequestMergeBase(repo, targetUrl, baseSha, headSha, baseRef, pullNumber);
132132
}
133133
catch (NotFoundException ex)
134134
{

0 commit comments

Comments
 (0)