Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only fetch pull request refs from the server if the ones we have aren't up to date #21

Merged
merged 4 commits into from
Dec 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions GitPullRequest.Services/AzureDevOpsRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,46 @@ public override int FindPullRequestForCanonicalName(string canonicalName)
protected override IDictionary<string, string> GetReferences(IRepository repo, string remoteName)
{
// for Azure DevOps we need to fetch PR branches so we can explore their history and get the commit before the automatic merge commit that is done on the server
GitService.Fetch(repo, remoteName, $"+refs/pull/*/merge:refs/remotes/{remoteName}/pull/*/merge");
// because we save this in our our own refs/pulls namespace we might not need to fetch if nothing has changed on the server

return base.GetReferences(repo, remoteName);
}
// Get remote references the normal way
var remoteRefs = base.GetReferences(repo, remoteName);

protected override string GetTipForReference(IRepository repo, string canonicalName, string targetIdentifier)
{
if (FindPullRequestForCanonicalName(canonicalName) != -1)
var needsFetch = false;
foreach (var kvp in remoteRefs)
{
var pr = FindPullRequestForCanonicalName(kvp.Key);
if (pr != -1)
{
var localRef = repo.Refs[GetPullRequestRefName(remoteName, pr.ToString())];
// If we don't have a local ref for this PR branch, or we do but its not up to date with the server, we need to fetch
if (localRef == null || !localRef.TargetIdentifier.Equals(kvp.Value, StringComparison.OrdinalIgnoreCase))
{
needsFetch = true;
break;
}
}
}
if (needsFetch)
{
GitService.Fetch(repo, remoteName, new[] { $"+refs/pull/*/merge:{GetPullRequestRefName(remoteName, "*")}" }, false);
}

// Now that we know the data is available we can go through and reset our PR refs to point to one commit before the merge commit
var pullRequestRefs = remoteRefs.Where(k => FindPullRequestForCanonicalName(k.Key) != -1).ToList();
foreach (var kvp in pullRequestRefs)
{
// Get the commit at HEAD^1 as Azure DevOps automatically adds a merge commit on the server
var commit = repo.Commits.QueryBy(new CommitFilter() { IncludeReachableFrom = targetIdentifier }).Skip(1).FirstOrDefault();
return commit.Sha;
var commit = repo.Commits.QueryBy(new CommitFilter() { IncludeReachableFrom = kvp.Value }).Skip(1).FirstOrDefault();
remoteRefs[kvp.Key] = commit.Sha;
}

return targetIdentifier;
return remoteRefs;
}

private static string GetPullRequestRefName(string remoteName, string pr)
{
return $"refs/pulls/{remoteName}/pull/{pr}/merge";
}

public override string GetPullRequestUrl(int number)
Expand Down
2 changes: 1 addition & 1 deletion GitPullRequest.Services/IGitService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace GitPullRequest.Services
{
public interface IGitService
{
void Fetch(IRepository repo, string remoteName, string refSpec);
void Fetch(IRepository repo, string remoteName, string[] refSpecs, bool prune);
IDictionary<string, string> ListReferences(IRepository repo, string remoteName);
}
}
7 changes: 4 additions & 3 deletions GitPullRequest.Services/LibGitService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public IDictionary<string, string> ListReferences(IRepository repo, string remot
return dictionary;
}

public void Fetch(IRepository repo, string remoteName, string refSpec)
public void Fetch(IRepository repo, string remoteName, string[] refSpecs, bool prune)
{
var credentialsHandler = CreateCredentialsHandler(repo, remoteName);
ProgressHandler progressHandler = text =>
Expand All @@ -33,10 +33,11 @@ public void Fetch(IRepository repo, string remoteName, string refSpec)
return true;
};

repo.Network.Fetch(remoteName, new[] { refSpec }, new FetchOptions
repo.Network.Fetch(remoteName, refSpecs, new FetchOptions
{
CredentialsProvider = credentialsHandler,
OnProgress = progressHandler
OnProgress = progressHandler,
Prune = prune
});
}

Expand Down
7 changes: 1 addition & 6 deletions GitPullRequest.Services/RemoteRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,10 @@ protected virtual IDictionary<string, string> GetReferences(IRepository repo, st
foreach (var reference in refs)
{
var (targetIdentifier, canonicalName) = (reference.Value, reference.Key);
dictionary[canonicalName] = GetTipForReference(repo, canonicalName, targetIdentifier);
dictionary[canonicalName] = targetIdentifier;
}

return dictionary;
}

protected virtual string GetTipForReference(IRepository repo, string canonicalName, string targetIdentifier)
{
return targetIdentifier;
}
}
}
4 changes: 2 additions & 2 deletions GitPullRequest.Services/ShellGitService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public IDictionary<string, string> ListReferences(IRepository repo, string remot
return dictionary;
}

public void Fetch(IRepository repo, string remoteName, string refSpec)
public void Fetch(IRepository repo, string remoteName, string[] refSpecs, bool prune)
{
var startInfo = new ProcessStartInfo
{
FileName = "git",
Arguments = $"fetch {remoteName} {refSpec}",
Arguments = $"fetch {remoteName} {string.Join(" ", refSpecs)}" + (prune ? " --prune" : ""),
WorkingDirectory = repo.Info.WorkingDirectory,
RedirectStandardOutput = true,
UseShellExecute = false,
Expand Down