Skip to content

Commit 415bf42

Browse files
committed
moved the retry mechanism out of LibGit2Sharp classlib f2b613
1 parent b44670c commit 415bf42

File tree

6 files changed

+122
-80
lines changed

6 files changed

+122
-80
lines changed

src/GitVersion.Core/Core/GitPreparer.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ private void CloneRepository(string repositoryUrl, string gitDirectory, Authenti
149149
{
150150
using (log.IndentLog($"Cloning repository from url '{repositoryUrl}'"))
151151
{
152-
repository.Clone(repositoryUrl, gitDirectory, auth);
152+
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () =>
153+
{
154+
repository.Clone(repositoryUrl, gitDirectory, auth);
155+
}).ExecuteAsync().Wait();
153156
}
154157
}
155158

@@ -179,7 +182,9 @@ private void NormalizeGitDirectory(bool noFetch, string currentBranchName, bool
179182
{
180183
var refSpecs = string.Join(", ", remote.FetchRefSpecs.Select(r => r.Specification));
181184
log.Info($"Fetching from remote '{remote.Name}' using the following refspecs: {refSpecs}.");
182-
repository.Fetch(remote.Name, Enumerable.Empty<string>(), authentication, null);
185+
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log,
186+
() => repository.Fetch(remote.Name, Enumerable.Empty<string>(), authentication, null))
187+
.ExecuteAsync().Wait();
183188
}
184189

185190
EnsureLocalBranchExistsForCurrentBranch(remote, currentBranchName);
@@ -221,7 +226,7 @@ private void NormalizeGitDirectory(bool noFetch, string currentBranchName, bool
221226
if (matchingCurrentBranch != null)
222227
{
223228
log.Info($"Checking out local branch '{currentBranchName}'.");
224-
repository.Checkout(matchingCurrentBranch.Name.Canonical);
229+
Checkout(matchingCurrentBranch.Name.Canonical);
225230
}
226231
else if (localBranchesWhereCommitShaIsHead.Count > 1)
227232
{
@@ -234,7 +239,7 @@ private void NormalizeGitDirectory(bool noFetch, string currentBranchName, bool
234239
if (main != null)
235240
{
236241
log.Warning("Because one of the branches is 'main', will build main." + moveBranchMsg);
237-
repository.Checkout(Config.MainBranchKey);
242+
Checkout(Config.MainBranchKey);
238243
}
239244
else
240245
{
@@ -243,7 +248,7 @@ private void NormalizeGitDirectory(bool noFetch, string currentBranchName, bool
243248
{
244249
var branchWithoutSeparator = branchesWithoutSeparators[0];
245250
log.Warning($"Choosing {branchWithoutSeparator.Name.Canonical} as it is the only branch without / or - in it. " + moveBranchMsg);
246-
repository.Checkout(branchWithoutSeparator.Name.Canonical);
251+
Checkout(branchWithoutSeparator.Name.Canonical);
247252
}
248253
else
249254
{
@@ -254,12 +259,15 @@ private void NormalizeGitDirectory(bool noFetch, string currentBranchName, bool
254259
else if (localBranchesWhereCommitShaIsHead.Count == 0)
255260
{
256261
log.Info($"No local branch pointing at the commit '{headSha}'. Fake branch needs to be created.");
257-
repository.CreateBranchForPullRequestBranch(authentication);
262+
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () =>
263+
{
264+
repository.CreateBranchForPullRequestBranch(authentication);
265+
}).ExecuteAsync().Wait();
258266
}
259267
else
260268
{
261269
log.Info($"Checking out local branch 'refs/heads/{localBranchesWhereCommitShaIsHead[0]}'.");
262-
repository.Checkout(localBranchesWhereCommitShaIsHead[0].Name.Friendly);
270+
Checkout(localBranchesWhereCommitShaIsHead[0].Name.Friendly);
263271
}
264272
}
265273
finally
@@ -386,7 +394,13 @@ public void EnsureLocalBranchExistsForCurrentBranch(IRemote remote, string curre
386394
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () => repository.Refs.UpdateTarget(localRef, repoTipId)).ExecuteAsync().Wait();
387395
}
388396

389-
repository.Checkout(localCanonicalName);
397+
Checkout(localCanonicalName);
398+
}
399+
400+
private void Checkout(string commitOrBranchSpec)
401+
{
402+
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () =>
403+
repository.Checkout(commitOrBranchSpec)).ExecuteAsync().Wait();
390404
}
391405
}
392406
}
Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using GitVersion.Logging;
2-
using System;
31
using System.Collections.Generic;
42

53
namespace GitVersion
@@ -13,10 +11,4 @@ public interface IReferenceCollection : IEnumerable<IReference>
1311
IEnumerable<IReference> FromGlob(string prefix);
1412
}
1513

16-
public class LockedFileException : Exception
17-
{
18-
public LockedFileException(Exception inner) : base(inner.Message, inner)
19-
{
20-
}
21-
}
2214
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace GitVersion
4+
{
5+
public class LockedFileException : Exception
6+
{
7+
public LockedFileException(Exception inner) : base(inner.Message, inner)
8+
{
9+
}
10+
}
11+
}

src/GitVersion.LibGit2Sharp/Git/GitRepository.cs

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -98,77 +98,74 @@ private int GetNumberOfUncommittedChangesInternal()
9898
}
9999
public void CreateBranchForPullRequestBranch(AuthenticationInfo auth)
100100
{
101-
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () =>
101+
RepositoryExtensions.RunSafe(() =>
102102
{
103-
CreateBranchForPullRequestBranchInternal(auth);
104-
}).ExecuteAsync().Wait();
105-
}
106-
private void CreateBranchForPullRequestBranchInternal(AuthenticationInfo auth)
107-
{
108-
var network = repositoryInstance.Network;
109-
var remote = network.Remotes.Single();
103+
var network = repositoryInstance.Network;
104+
var remote = network.Remotes.Single();
110105

111-
log.Info("Fetching remote refs to see if there is a pull request ref");
112-
var credentialsProvider = GetCredentialsProvider(auth);
113-
var remoteTips = (credentialsProvider != null
114-
? network.ListReferences(remote, credentialsProvider)
115-
: network.ListReferences(remote))
116-
.Select(r => r.ResolveToDirectReference()).ToList();
106+
log.Info("Fetching remote refs to see if there is a pull request ref");
107+
var credentialsProvider = GetCredentialsProvider(auth);
108+
var remoteTips = (credentialsProvider != null
109+
? network.ListReferences(remote, credentialsProvider)
110+
: network.ListReferences(remote))
111+
.Select(r => r.ResolveToDirectReference()).ToList();
117112

118-
log.Info($"Remote Refs:{System.Environment.NewLine}" + string.Join(System.Environment.NewLine, remoteTips.Select(r => r.CanonicalName)));
113+
log.Info($"Remote Refs:{System.Environment.NewLine}" + string.Join(System.Environment.NewLine, remoteTips.Select(r => r.CanonicalName)));
119114

120-
var headTipSha = Head.Tip?.Sha;
115+
var headTipSha = Head.Tip?.Sha;
121116

122-
var refs = remoteTips.Where(r => r.TargetIdentifier == headTipSha).ToList();
117+
var refs = remoteTips.Where(r => r.TargetIdentifier == headTipSha).ToList();
123118

124-
if (refs.Count == 0)
125-
{
126-
var message = $"Couldn't find any remote tips from remote '{remote.Url}' pointing at the commit '{headTipSha}'.";
127-
throw new WarningException(message);
128-
}
119+
if (refs.Count == 0)
120+
{
121+
var message = $"Couldn't find any remote tips from remote '{remote.Url}' pointing at the commit '{headTipSha}'.";
122+
throw new WarningException(message);
123+
}
129124

130-
if (refs.Count > 1)
131-
{
132-
var names = string.Join(", ", refs.Select(r => r.CanonicalName));
133-
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}).";
134-
throw new WarningException(message);
135-
}
125+
if (refs.Count > 1)
126+
{
127+
var names = string.Join(", ", refs.Select(r => r.CanonicalName));
128+
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}).";
129+
throw new WarningException(message);
130+
}
136131

137-
var reference = refs.First();
138-
var canonicalName = reference.CanonicalName;
139-
var referenceName = ReferenceName.Parse(reference.CanonicalName);
140-
log.Info($"Found remote tip '{canonicalName}' pointing at the commit '{headTipSha}'.");
132+
var reference = refs.First();
133+
var canonicalName = reference.CanonicalName;
134+
var referenceName = ReferenceName.Parse(reference.CanonicalName);
135+
log.Info($"Found remote tip '{canonicalName}' pointing at the commit '{headTipSha}'.");
141136

142-
if (referenceName.IsTag)
143-
{
144-
log.Info($"Checking out tag '{canonicalName}'");
145-
Checkout(reference.Target.Sha);
146-
}
147-
else if (referenceName.IsPullRequest)
148-
{
149-
var fakeBranchName = canonicalName.Replace("refs/pull/", "refs/heads/pull/").Replace("refs/pull-requests/", "refs/heads/pull-requests/");
137+
if (referenceName.IsTag)
138+
{
139+
log.Info($"Checking out tag '{canonicalName}'");
140+
Checkout(reference.Target.Sha);
141+
}
142+
else if (referenceName.IsPullRequest)
143+
{
144+
var fakeBranchName = canonicalName.Replace("refs/pull/", "refs/heads/pull/").Replace("refs/pull-requests/", "refs/heads/pull-requests/");
150145

151-
log.Info($"Creating fake local branch '{fakeBranchName}'.");
152-
Refs.Add(fakeBranchName, headTipSha);
146+
log.Info($"Creating fake local branch '{fakeBranchName}'.");
147+
Refs.Add(fakeBranchName, headTipSha);
153148

154-
log.Info($"Checking local branch '{fakeBranchName}' out.");
155-
Checkout(fakeBranchName);
156-
}
157-
else
158-
{
159-
var message = $"Remote tip '{canonicalName}' from remote '{remote.Url}' doesn't look like a valid pull request.";
160-
throw new WarningException(message);
161-
}
149+
log.Info($"Checking local branch '{fakeBranchName}' out.");
150+
Checkout(fakeBranchName);
151+
}
152+
else
153+
{
154+
var message = $"Remote tip '{canonicalName}' from remote '{remote.Url}' doesn't look like a valid pull request.";
155+
throw new WarningException(message);
156+
}
157+
});
162158
}
163159
public void Clone(string sourceUrl, string workdirPath, AuthenticationInfo auth)
164160
{
165161
try
166162
{
167-
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () =>
168-
{
169-
var path = Repository.Clone(sourceUrl, workdirPath, GetCloneOptions(auth));
170-
log.Info($"Returned path after repository clone: {path}");
171-
}).ExecuteAsync().Wait();
163+
var path = Repository.Clone(sourceUrl, workdirPath, GetCloneOptions(auth));
164+
log.Info($"Returned path after repository clone: {path}");
165+
}
166+
catch (LibGit2Sharp.LockedFileException ex)
167+
{
168+
throw new LockedFileException(ex);
172169
}
173170
catch (LibGit2SharpException ex)
174171
{
@@ -191,11 +188,17 @@ public void Clone(string sourceUrl, string workdirPath, AuthenticationInfo auth)
191188
}
192189
public void Checkout(string commitOrBranchSpec)
193190
{
194-
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () => Commands.Checkout(repositoryInstance, commitOrBranchSpec)).ExecuteAsync().Wait();
191+
RepositoryExtensions.RunSafe(() =>
192+
{
193+
Commands.Checkout(repositoryInstance, commitOrBranchSpec);
194+
});
195195
}
196196
public void Fetch(string remote, IEnumerable<string> refSpecs, AuthenticationInfo auth, string logMessage)
197197
{
198-
new OperationWithExponentialBackoff<LockedFileException>(new ThreadSleep(), log, () => Commands.Fetch((Repository)repositoryInstance, remote, refSpecs, GetFetchOptions(auth), logMessage)).ExecuteAsync().Wait();
198+
RepositoryExtensions.RunSafe(() =>
199+
{
200+
Commands.Fetch((Repository)repositoryInstance, remote, refSpecs, GetFetchOptions(auth), logMessage);
201+
});
199202
}
200203
internal static string Discover(string path) => Repository.Discover(path);
201204

src/GitVersion.LibGit2Sharp/Git/ReferenceCollection.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@ public void Add(string name, string canonicalRefNameOrObjectish, bool allowOverw
2121

2222
public void UpdateTarget(IReference directRef, IObjectId targetId)
2323
{
24-
try
24+
RepositoryExtensions.RunSafe(() =>
2525
{
2626
innerCollection.UpdateTarget((Reference)directRef, (ObjectId)targetId);
27-
}
28-
catch (LibGit2Sharp.LockedFileException ex)
29-
{
30-
// Wrap this exception so that callers that want to catch it don't need to take a dependency on LibGit2Sharp.
31-
throw new LockedFileException(ex);
32-
}
27+
});
3328
}
3429

3530
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

src/GitVersion.LibGit2Sharp/RepositoryExtensions.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using LibGit2Sharp;
23
using Microsoft.Extensions.Options;
34

@@ -7,5 +8,31 @@ public static class RepositoryExtensions
78
{
89
public static IGitRepository ToGitRepository(this IRepository repository) => new GitRepository(repository);
910
public static IGitRepositoryInfo ToGitRepositoryInfo(IOptions<GitVersionOptions> options) => new GitRepositoryInfo(options);
11+
12+
public static void RunSafe(Action operation)
13+
{
14+
try
15+
{
16+
operation();
17+
}
18+
catch (LibGit2Sharp.LockedFileException ex)
19+
{
20+
// Wrap this exception so that callers that want to catch it don't need to take a dependency on LibGit2Sharp.
21+
throw new LockedFileException(ex);
22+
}
23+
}
24+
25+
public static T RunSafe<T>(Func<T> operation)
26+
{
27+
try
28+
{
29+
return operation();
30+
}
31+
catch (LibGit2Sharp.LockedFileException ex)
32+
{
33+
// Wrap this exception so that callers that want to catch it don't need to take a dependency on LibGit2Sharp.
34+
throw new LockedFileException(ex);
35+
}
36+
}
1037
}
1138
}

0 commit comments

Comments
 (0)