Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 3af4561

Browse files
committed
Make it possible to branch out on task success and failure. Cleanups
Kill some unused code in the task system, mainly the Defer paths which we aren't using anymore Add a way of calling different tasks depending on the success or failure of the previous task. Add some different ways of setting the result of a task beyond the value returned by the previous task, mainly for seeding initial values.
1 parent 1cc4800 commit 3af4561

File tree

6 files changed

+225
-284
lines changed

6 files changed

+225
-284
lines changed

src/GitHub.Api/Application/ApplicationManagerBase.cs

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -47,66 +47,23 @@ public void Run(bool firstRun)
4747
{
4848
Logger.Trace("Run - CurrentDirectory {0}", NPath.CurrentDirectory);
4949

50-
var afterGitSetup = new ActionTask(CancellationToken, RestartRepository)
51-
.ThenInUI(InitializeUI);
52-
53-
//GitClient.GetConfig cannot be called until there is a git path set so it is wrapped in an ActionTask
54-
var windowsCredentialSetup = new ActionTask(CancellationToken, () => {
55-
GitClient.GetConfig("credential.helper", GitConfigSource.Global).Then((b, credentialHelper) => {
56-
if (!string.IsNullOrEmpty(credentialHelper))
57-
{
58-
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
59-
afterGitSetup.Start();
60-
}
61-
else
62-
{
63-
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
64-
65-
GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global)
66-
.Then(() => { afterGitSetup.Start(); }).Start();
67-
}
68-
}).Start();
69-
});
70-
71-
var afterPathDetermined = new ActionTask<NPath>(CancellationToken, (b, path) => {
72-
Logger.Trace("Setting Environment git path: {0}", path);
73-
Environment.GitExecutablePath = path;
74-
}).ThenInUI(() => {
75-
Environment.User.Initialize(GitClient);
76-
77-
if (Environment.IsWindows)
78-
{
79-
windowsCredentialSetup.Start();
80-
}
81-
else
82-
{
83-
afterGitSetup.Start();
84-
}
85-
});
86-
87-
88-
var gitExecutablePath = SystemSettings.Get(Constants.GitInstallPathKey)?.ToNPath();
89-
if (gitExecutablePath != null && gitExecutablePath.FileExists())
50+
var gitExecutablePath = SystemSettings.Get(Constants.GitInstallPathKey)?.ToNPath();
51+
if (gitExecutablePath != null && gitExecutablePath.FileExists()) // we have a git path
9052
{
9153
Logger.Trace("Using git install path from settings: {0}", gitExecutablePath);
92-
93-
new FuncTask<NPath>(CancellationToken, () => gitExecutablePath)
94-
.Then(afterPathDetermined)
95-
.Start();
54+
InitializeEnvironment(gitExecutablePath);
9655
}
97-
else
56+
else // we need to go find git
9857
{
9958
Logger.Trace("No git path found in settings");
10059

60+
var initEnvironmentTask = new ActionTask<NPath>(CancellationToken, (b, path) => InitializeEnvironment(path)) { Affinity = TaskAffinity.UI };
10161
var findExecTask = new FindExecTask("git", CancellationToken)
102-
.Finally((b, ex, path) => {
62+
.FinallyInUI((b, ex, path) => {
10363
if (b && path != null)
10464
{
10565
Logger.Trace("FindExecTask Success: {0}", path);
106-
107-
new FuncTask<NPath>(CancellationToken, () => path)
108-
.Then(afterPathDetermined)
109-
.Start();
66+
InitializeEnvironment(gitExecutablePath);
11067
}
11168
else
11269
{
@@ -119,15 +76,8 @@ public void Run(bool firstRun)
11976
var installDetails = new GitInstallDetails(applicationDataPath, true);
12077
var gitInstaller = new GitInstaller(Environment, CancellationToken, installDetails);
12178

122-
gitInstaller.SetupGitIfNeeded(new ActionTask<NPath>(CancellationToken, (b, path) => {
123-
Logger.Trace("GitInstaller Success: {0}", path);
124-
new FuncTask<NPath>(CancellationToken, () => path)
125-
.Then(afterPathDetermined)
126-
.Start();
127-
}), new ActionTask(CancellationToken, () => {
128-
Logger.Warning("GitInstaller Failure");
129-
findExecTask.Start();
130-
}));
79+
// if successful, continue with environment initialization, otherwise try to find an existing git installation
80+
gitInstaller.SetupGitIfNeeded(initEnvironmentTask, findExecTask);
13181
}
13282
}
13383

@@ -216,6 +166,45 @@ protected void SetupMetrics(string unityVersion, bool firstRun)
216166
protected abstract void InitializeUI();
217167
protected abstract void SetProjectToTextSerialization();
218168

169+
/// <summary>
170+
/// Initialize environment after finding where git is. This needs to run on the main thread
171+
/// </summary>
172+
/// <param name="gitExecutablePath"></param>
173+
private void InitializeEnvironment(NPath gitExecutablePath)
174+
{
175+
var afterGitSetup = new ActionTask(CancellationToken, RestartRepository)
176+
.ThenInUI(InitializeUI);
177+
178+
Environment.GitExecutablePath = gitExecutablePath;
179+
Environment.User.Initialize(GitClient);
180+
181+
if (Environment.IsWindows)
182+
{
183+
GitClient
184+
.GetConfig("credential.helper", GitConfigSource.Global)
185+
.Then((b, credentialHelper) => {
186+
if (!string.IsNullOrEmpty(credentialHelper))
187+
{
188+
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
189+
afterGitSetup.Start();
190+
}
191+
else
192+
{
193+
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
194+
195+
GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global)
196+
.Then(afterGitSetup)
197+
.Start();
198+
}
199+
})
200+
.Start();
201+
}
202+
else
203+
{
204+
afterGitSetup.Start();
205+
}
206+
}
207+
219208
private bool disposed = false;
220209
protected virtual void Dispose(bool disposing)
221210
{

src/GitHub.Api/Installer/GitInstaller.cs

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -99,78 +99,67 @@ public void SetupGitIfNeeded(ActionTask<NPath> onSuccess, ITask onFailure)
9999
return;
100100
}
101101

102-
new FuncTask<bool>(cancellationToken, IsGitExtracted)
103-
.Finally((success, ex, isPortableGitExtracted) => {
104-
Logger.Trace("IsPortableGitExtracted: {0}", isPortableGitExtracted);
105-
106-
if (isPortableGitExtracted)
107-
{
108-
Logger.Trace("SetupGitIfNeeded: Skipped");
109-
110-
new FuncTask<NPath>(cancellationToken, () => installDetails.GitExecPath)
111-
.Then(onSuccess)
112-
.Start();
113-
}
114-
else
115-
{
116-
ITask downloadFilesTask = null;
117-
if (gitArchiveFilePath == null || gitLfsArchivePath == null)
118-
{
119-
downloadFilesTask = CreateDownloadTask();
120-
}
121-
122-
var tempZipExtractPath = NPath.CreateTempDirectory("git_zip_extract_zip_paths");
123-
var gitExtractPath = tempZipExtractPath.Combine("git").CreateDirectory();
124-
var gitLfsExtractPath = tempZipExtractPath.Combine("git-lfs").CreateDirectory();
125-
126-
var resultTask = new UnzipTask(cancellationToken, gitArchiveFilePath, gitExtractPath, sharpZipLibHelper, environment.FileSystem, GitInstallDetails.GitExtractedMD5)
127-
.Then(new UnzipTask(cancellationToken, gitLfsArchivePath, gitLfsExtractPath, sharpZipLibHelper, environment.FileSystem, GitInstallDetails.GitLfsExtractedMD5))
128-
.Then(() => {
129-
var targetGitLfsExecPath = installDetails.GetGitLfsExecPath(gitExtractPath);
130-
var extractGitLfsExePath = gitLfsExtractPath.Combine(installDetails.GitLfsExec);
131-
132-
Logger.Trace("Moving Git LFS Exe:\"{0}\" to target in tempDirectory:\"{1}\" ", extractGitLfsExePath,
133-
targetGitLfsExecPath);
134-
135-
extractGitLfsExePath.Move(targetGitLfsExecPath);
136-
137-
Logger.Trace("Moving tempDirectory:\"{0}\" to extractTarget:\"{1}\"", gitExtractPath,
138-
installDetails.GitInstallPath);
139-
140-
installDetails.GitInstallPath.EnsureParentDirectoryExists();
141-
gitExtractPath.Move(installDetails.GitInstallPath);
142-
143-
Logger.Trace("Deleting targetGitLfsExecPath:\"{0}\"", targetGitLfsExecPath);
144-
targetGitLfsExecPath.DeleteIfExists();
145-
146-
Logger.Trace("Deleting tempZipPath:\"{0}\"", tempZipExtractPath);
147-
tempZipExtractPath.DeleteIfExists();
148-
})
149-
.Finally((b, exception) => {
150-
if (b)
151-
{
152-
Logger.Trace("SetupGitIfNeeded: Success");
153-
154-
new FuncTask<NPath>(cancellationToken, () => installDetails.GitExecPath)
155-
.Then(onSuccess)
156-
.Start();
157-
}
158-
else
159-
{
160-
Logger.Warning("SetupGitIfNeeded: Failed");
161-
162-
onFailure.Start();
163-
}
164-
});
165-
166-
if (downloadFilesTask != null)
167-
{
168-
resultTask = downloadFilesTask.Then(resultTask);
169-
}
170-
171-
resultTask.Start();
172-
}
173-
}).Start();
102+
new ActionTask(cancellationToken, () => {
103+
if (IsGitExtracted())
104+
{
105+
Logger.Trace("SetupGitIfNeeded: Skipped");
106+
onSuccess.PreviousResult = installDetails.GitExecPath;
107+
onSuccess.Start();
108+
}
109+
else
110+
{
111+
ExtractPortableGit(onSuccess, onFailure);
112+
}
113+
}).Start();
114+
}
115+
116+
private void ExtractPortableGit(ActionTask<NPath> onSuccess, ITask onFailure)
117+
{
118+
ITask downloadFilesTask = null;
119+
if (gitArchiveFilePath == null || gitLfsArchivePath == null)
120+
{
121+
downloadFilesTask = CreateDownloadTask();
122+
}
123+
124+
var tempZipExtractPath = NPath.CreateTempDirectory("git_zip_extract_zip_paths");
125+
var gitExtractPath = tempZipExtractPath.Combine("git").CreateDirectory();
126+
var gitLfsExtractPath = tempZipExtractPath.Combine("git-lfs").CreateDirectory();
127+
128+
var resultTask = new UnzipTask(cancellationToken, gitArchiveFilePath, gitExtractPath, sharpZipLibHelper, environment.FileSystem, GitInstallDetails.GitExtractedMD5)
129+
.Then(new UnzipTask(cancellationToken, gitLfsArchivePath, gitLfsExtractPath, sharpZipLibHelper, environment.FileSystem, GitInstallDetails.GitLfsExtractedMD5))
130+
.Then(s =>
131+
{
132+
var targetGitLfsExecPath = installDetails.GetGitLfsExecPath(gitExtractPath);
133+
var extractGitLfsExePath = gitLfsExtractPath.Combine(installDetails.GitLfsExec);
134+
135+
Logger.Trace("Moving Git LFS Exe:\"{0}\" to target in tempDirectory:\"{1}\" ", extractGitLfsExePath,
136+
targetGitLfsExecPath);
137+
138+
extractGitLfsExePath.Move(targetGitLfsExecPath);
139+
140+
Logger.Trace("Moving tempDirectory:\"{0}\" to extractTarget:\"{1}\"", gitExtractPath,
141+
installDetails.GitInstallPath);
142+
143+
installDetails.GitInstallPath.EnsureParentDirectoryExists();
144+
gitExtractPath.Move(installDetails.GitInstallPath);
145+
146+
Logger.Trace("Deleting targetGitLfsExecPath:\"{0}\"", targetGitLfsExecPath);
147+
targetGitLfsExecPath.DeleteIfExists();
148+
149+
Logger.Trace("Deleting tempZipPath:\"{0}\"", tempZipExtractPath);
150+
tempZipExtractPath.DeleteIfExists();
151+
return installDetails.GitExecPath;
152+
});
153+
154+
resultTask.Then(onFailure, TaskRunOptions.OnFailure);
155+
resultTask.Then(onSuccess, TaskRunOptions.OnSuccess);
156+
157+
if (downloadFilesTask != null)
158+
{
159+
resultTask = downloadFilesTask.Then(resultTask);
160+
}
161+
162+
resultTask.Start();
174163
}
175164

176165
private ITask CreateDownloadTask()

src/GitHub.Api/Tasks/ActionTask.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,42 @@ class ActionTask<T> : TaskBase
7272
protected Action<bool, T> Callback { get; }
7373
protected Action<bool, Exception, T> CallbackWithException { get; }
7474

75-
public ActionTask(CancellationToken token, Action<bool, T> action)
75+
/// <summary>
76+
///
77+
/// </summary>
78+
/// <param name="token"></param>
79+
/// <param name="action"></param>
80+
/// <param name="getPreviousResult">Method to call that returns the value that this task is going to work with. You can also use the PreviousResult property to set this value</param>
81+
public ActionTask(CancellationToken token, Action<bool, T> action, Func<T> getPreviousResult = null)
7682
: base(token)
7783
{
7884
Guard.ArgumentNotNull(action, "action");
7985
this.Callback = action;
80-
Task = new Task(() => Run(DependsOn.Successful, DependsOn.Successful ? ((ITask<T>)DependsOn).Result : default(T)),
86+
Task = new Task(() => Run(DependsOn?.Successful ?? true,
87+
// if this task depends on another task and the dependent task was successful, use the value of that other task as input to this task
88+
// otherwise if there's a method to retrieve the value, call that
89+
// otherwise use the PreviousResult property
90+
(DependsOn?.Successful ?? false) ? ((ITask<T>)DependsOn).Result : getPreviousResult != null ? getPreviousResult() : PreviousResult),
8191
Token, TaskCreationOptions.None);
8292
Name = $"ActionTask<{typeof(T)}>";
8393
}
8494

85-
public ActionTask(CancellationToken token, Action<bool, Exception, T> action)
95+
/// <summary>
96+
///
97+
/// </summary>
98+
/// <param name="token"></param>
99+
/// <param name="action"></param>
100+
/// <param name="getPreviousResult">Method to call that returns the value that this task is going to work with. You can also use the PreviousResult property to set this value</param>
101+
public ActionTask(CancellationToken token, Action<bool, Exception, T> action, Func<T> getPreviousResult = null)
86102
: base(token)
87103
{
88104
Guard.ArgumentNotNull(action, "action");
89105
this.CallbackWithException = action;
90-
Task = new Task(() => Run(DependsOn.Successful, DependsOn.Successful ? ((ITask<T>)DependsOn).Result : default(T)),
106+
Task = new Task(() => Run(DependsOn?.Successful ?? true,
107+
// if this task depends on another task and the dependent task was successful, use the value of that other task as input to this task
108+
// otherwise if there's a method to retrieve the value, call that
109+
// otherwise use the PreviousResult property
110+
(DependsOn?.Successful ?? false) ? ((ITask<T>)DependsOn).Result : getPreviousResult != null ? getPreviousResult() : PreviousResult),
91111
Token, TaskCreationOptions.None);
92112
Name = $"ActionTask<Exception, {typeof(T)}>";
93113
}
@@ -124,6 +144,8 @@ protected virtual void Run(bool success, T previousResult)
124144
RaiseOnEnd();
125145
}
126146
}
147+
148+
public T PreviousResult { get; set; } = default(T);
127149
}
128150

129151
class FuncTask<T> : TaskBase<T>

0 commit comments

Comments
 (0)