public void CreateBranchForPullRequestBranch(AuthenticationInfo auth) { RepositoryExtensions.RunSafe(() => { var network = repositoryInstance.Network; var remote = network.Remotes.Single(); log.Info("Fetching remote refs to see if there is a pull request ref"); var credentialsProvider = GetCredentialsProvider(auth); var remoteTips = (credentialsProvider != null ? network.ListReferences(remote, credentialsProvider) : network.ListReferences(remote)) .Select(r => r.ResolveToDirectReference()).ToList(); log.Info($"Remote Refs:{System.Environment.NewLine}" + string.Join(System.Environment.NewLine, remoteTips.Select(r => r.CanonicalName))); var headTipSha = Head.Tip?.Sha; var refs = remoteTips.Where(r => r.TargetIdentifier == headTipSha).ToList(); if (refs.Count == 0) { var message = $"Couldn't find any remote tips from remote '{remote.Url}' pointing at the commit '{headTipSha}'."; throw new WarningException(message); } if (refs.Count > 1) { var names = string.Join(", ", refs.Select(r => r.CanonicalName)); var message = $"Found more than one remote tip from remote '{remote.Url}' pointing at the commit '{headTipSha}'. Unable to determine which one to use ({names})."; throw new WarningException(message); } var reference = refs.First(); var canonicalName = reference.CanonicalName; var referenceName = ReferenceName.Parse(reference.CanonicalName); log.Info($"Found remote tip '{canonicalName}' pointing at the commit '{headTipSha}'."); if (referenceName.IsTag) { log.Info($"Checking out tag '{canonicalName}'"); Checkout(reference.Target.Sha); } else if (referenceName.IsPullRequest) { var fakeBranchName = canonicalName.Replace("refs/pull/", "refs/heads/pull/").Replace("refs/pull-requests/", "refs/heads/pull-requests/"); log.Info($"Creating fake local branch '{fakeBranchName}'."); Refs.Add(fakeBranchName, headTipSha); log.Info($"Checking local branch '{fakeBranchName}' out."); Checkout(fakeBranchName); } else { var message = $"Remote tip '{canonicalName}' from remote '{remote.Url}' doesn't look like a valid pull request."; throw new WarningException(message); } }); }
private static void EnsureLocalBranchExistsForCurrentBranch(IGitRepository repo, ILog log, IRemote remote, string currentBranch) { if (log is null) { throw new ArgumentNullException(nameof(log)); } if (remote is null) { throw new ArgumentNullException(nameof(remote)); } if (string.IsNullOrEmpty(currentBranch)) { return; } var isRef = currentBranch.Contains("refs"); var isBranch = currentBranch.Contains("refs/heads"); var localCanonicalName = !isRef ? "refs/heads/" + currentBranch : isBranch ? currentBranch : currentBranch.Replace("refs/", "refs/heads/"); var repoTip = repo.Head.Tip; // We currently have the rep.Head of the *default* branch, now we need to look up the right one var originCanonicalName = $"{remote.Name}/{currentBranch}"; var originBranch = repo.Branches[originCanonicalName]; if (originBranch != null) { repoTip = originBranch.Tip; } var repoTipId = repoTip.Id; var referenceName = ReferenceName.Parse(localCanonicalName); if (repo.Branches.All(b => !b.Name.Equals(referenceName))) { log.Info(isBranch ? $"Creating local branch {referenceName}" : $"Creating local branch {referenceName} pointing at {repoTipId}"); repo.Refs.Add(localCanonicalName, repoTipId.Sha); } else { log.Info(isBranch ? $"Updating local branch {referenceName} to point at {repoTip}" : $"Updating local branch {referenceName} to match ref {currentBranch}"); var localRef = repo.Refs[localCanonicalName]; repo.Refs.UpdateTarget(localRef, repoTipId); } repo.Checkout(localCanonicalName); }
private static void CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(IGitRepository repo, ILog log, string remoteName) { var prefix = $"refs/remotes/{remoteName}/"; var remoteHeadCanonicalName = $"{prefix}HEAD"; var headReferenceName = ReferenceName.Parse(remoteHeadCanonicalName); var remoteTrackingReferences = repo.Refs .FromGlob(prefix + "*") .Where(r => !r.Name.Equals(headReferenceName)); foreach (var remoteTrackingReference in remoteTrackingReferences) { var remoteTrackingReferenceName = remoteTrackingReference.Name.Canonical; var branchName = remoteTrackingReferenceName.Substring(prefix.Length); var localCanonicalName = "refs/heads/" + branchName; var referenceName = ReferenceName.Parse(localCanonicalName); // We do not want to touch our current branch if (repo.Head.Name.EquivalentTo(branchName)) { continue; } if (repo.Refs.Any(x => x.Name.Equals(referenceName))) { var localRef = repo.Refs[localCanonicalName]; if (localRef.DirectReferenceTargetIdentifier == remoteTrackingReference.DirectReferenceTargetIdentifier) { log.Info($"Skipping update of '{remoteTrackingReference.Name.Canonical}' as it already matches the remote ref."); continue; } var remoteRefTipId = remoteTrackingReference.DirectReferenceTargetId; log.Info($"Updating local ref '{localRef.Name.Canonical}' to point at {remoteRefTipId}."); repo.Refs.UpdateTarget(localRef, remoteRefTipId); continue; } log.Info($"Creating local branch from remote tracking '{remoteTrackingReference.Name.Canonical}'."); repo.Refs.Add(localCanonicalName, remoteTrackingReference.DirectReferenceTargetIdentifier, true); var branch = repo.Branches[branchName]; repo.Branches.UpdateTrackedBranch(branch, remoteTrackingReferenceName); } }
private void CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(string remoteName) { var prefix = $"refs/remotes/{remoteName}/"; var remoteHeadCanonicalName = $"{prefix}HEAD"; var headReferenceName = ReferenceName.Parse(remoteHeadCanonicalName); var remoteTrackingReferences = repository.Refs .FromGlob(prefix + "*") .Where(r => !r.Name.Equals(headReferenceName)); foreach (var remoteTrackingReference in remoteTrackingReferences) { var remoteTrackingReferenceName = remoteTrackingReference.Name.Canonical; var branchName = remoteTrackingReferenceName.Substring(prefix.Length); var localCanonicalName = "refs/heads/" + branchName; var referenceName = ReferenceName.Parse(localCanonicalName); // We do not want to touch our current branch if (repository.Head.Name.EquivalentTo(branchName)) { continue; } if (repository.Refs.Any(x => x.Name.Equals(referenceName))) { var localRef = repository.Refs[localCanonicalName]; if (localRef.TargetIdentifier == remoteTrackingReference.TargetIdentifier) { log.Info($"Skipping update of '{remoteTrackingReference.Name.Canonical}' as it already matches the remote ref."); continue; } var remoteRefTipId = remoteTrackingReference.ReferenceTargetId; log.Info($"Updating local ref '{localRef.Name.Canonical}' to point at {remoteRefTipId}."); new OperationWithExponentialBackoff <LockedFileException>(new ThreadSleep(), log, () => repository.Refs.UpdateTarget(localRef, remoteRefTipId)).ExecuteAsync().Wait(); continue; } log.Info($"Creating local branch from remote tracking '{remoteTrackingReference.Name.Canonical}'."); repository.Refs.Add(localCanonicalName, remoteTrackingReference.TargetIdentifier, true); var branch = repository.Branches[branchName]; repository.Branches.UpdateTrackedBranch(branch, remoteTrackingReferenceName); } }