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

Commit 17bbc37

Browse files
Merge branch 'enhancements/async-git-setup' into enhancements/git-setup-download
# Conflicts: # src/GitHub.Api/Application/ApplicationManagerBase.cs # src/GitHub.Api/Installer/PortableGitInstallTask.cs # src/tests/IntegrationTests/BasePlatformIntegrationTest.cs # src/tests/IntegrationTests/Installer/PortableGitInstallTaskTests.cs
2 parents 6aa10da + 06fac2e commit 17bbc37

File tree

9 files changed

+278
-337
lines changed

9 files changed

+278
-337
lines changed

src/GitHub.Api/Application/ApplicationManagerBase.cs

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

51-
SetupGit()
52-
.Then(RestartRepository)
53-
.ThenInUI(InitializeUI)
54-
.Start();
51+
var afterGitSetup = new ActionTask(CancellationToken, RestartRepository)
52+
.ThenInUI(InitializeUI);
53+
54+
Logger.Trace("afterGitSetup");
55+
56+
var windowsCredentialSetup = new ActionTask(CancellationToken, () => {
57+
GitClient.GetConfig("credential.helper", GitConfigSource.Global).Then((b, credentialHelper) => {
58+
if (!string.IsNullOrEmpty(credentialHelper))
59+
{
60+
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
61+
afterGitSetup.Start();
62+
}
63+
else
64+
{
65+
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
66+
67+
GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global)
68+
.Then(() => { afterGitSetup.Start(); }).Start();
69+
}
70+
}).Start();
71+
});
72+
73+
Logger.Trace("windowsCredentialSetup");
74+
75+
var afterPathDetermined = new ActionTask<NPath>(CancellationToken, (b1, path) => {
76+
77+
Logger.Trace("Setting Environment git path: {0}", path);
78+
Environment.GitExecutablePath = path;
79+
80+
}).ThenInUI(() => {
81+
82+
Environment.User.Initialize(GitClient);
83+
84+
if (Environment.IsWindows)
85+
{
86+
windowsCredentialSetup.Start();
87+
}
88+
else
89+
{
90+
afterGitSetup.Start();
91+
}
92+
});
93+
94+
Logger.Trace("afterPathDetermined");
95+
96+
var applicationDataPath = Environment.GetSpecialFolder(System.Environment.SpecialFolder.LocalApplicationData).ToNPath();
97+
var installDetails = new GitInstallDetails(applicationDataPath, true);
98+
99+
var gitInstaller = new GitInstaller(Environment, CancellationToken, installDetails);
100+
gitInstaller.SetupGitIfNeeded(new ActionTask<NPath>(CancellationToken, (b, s) => {
101+
102+
Logger.Trace("Success: {0}", s);
103+
104+
new FuncTask<NPath>(CancellationToken, () => s)
105+
.Then(afterPathDetermined)
106+
.Start();
107+
108+
}), new ActionTask(CancellationToken, () => {
109+
Logger.Trace("Failure");
110+
}) );
55111
}
56112

57113
private ITask SetupGit()
@@ -88,9 +144,9 @@ private ITask SetupGit()
88144
});
89145
}
90146

91-
private ITask<NPath> BuildDetermineGitPathTask()
147+
private TaskBase<NPath> BuildDetermineGitPathTask()
92148
{
93-
ITask<NPath> determinePath = new FuncTask<NPath>(CancellationToken, () => {
149+
TaskBase<NPath> determinePath = new FuncTask<NPath>(CancellationToken, () => {
94150
if (Environment.GitExecutablePath != null)
95151
{
96152
return Environment.GitExecutablePath;
@@ -110,44 +166,10 @@ private ITask<NPath> BuildDetermineGitPathTask()
110166
if (environmentIsWindows)
111167
{
112168
var applicationDataPath = Environment.GetSpecialFolder(System.Environment.SpecialFolder.LocalApplicationData).ToNPath();
113-
var installDetails = new PortableGitInstallDetails(applicationDataPath, true);
114-
115-
var zipArchivesPath = NPath.CreateTempDirectory("portable_git_zip").CreateDirectory();
116-
var gitArchivePath = zipArchivesPath.Combine("git.zip");
117-
var gitLfsArchivePath = zipArchivesPath.Combine("git-lfs.zip");
118-
119-
var downloadGitMd5Task = new DownloadTextTask(CancellationToken.None,
120-
"https://ghfvs-installer.github.com/unity/portable_git/git.zip.MD5.txt?cb=1");
121-
122-
var downloadGitTask = new DownloadTask(CancellationToken.None, Environment.FileSystem,
123-
"https://ghfvs-installer.github.com/unity/portable_git/git.zip", gitArchivePath, retryCount: 1);
169+
var installDetails = new GitInstallDetails(applicationDataPath, true);
170+
var installTask = new PortableGitInstallTask(CancellationToken, Environment, installDetails);
124171

125-
var downloadGitLfsMd5Task = new DownloadTextTask(CancellationToken.None,
126-
"https://ghfvs-installer.github.com/unity/portable_git/git-lfs.zip.MD5.txt?cb=1");
127-
128-
var downloadGitLfsTask = new DownloadTask(CancellationToken.None, Environment.FileSystem,
129-
"https://ghfvs-installer.github.com/unity/portable_git/git-lfs.zip", gitLfsArchivePath, retryCount: 1);
130-
131-
var installTask = downloadGitMd5Task
132-
.Then((b, s) =>
133-
{
134-
downloadGitTask.ValidationHash = s;
135-
})
136-
.Then(downloadGitTask)
137-
.Then(downloadGitLfsMd5Task)
138-
.Then((b, s) =>
139-
{
140-
downloadGitLfsTask.ValidationHash = s;
141-
})
142-
.Then(downloadGitLfsTask)
143-
.Then(new PortableGitInstallTask(CancellationToken, Environment, gitArchivePath, gitLfsArchivePath, installDetails));
144-
145-
determinePath = determinePath
146-
.Then(new ShortCircuitTask<NPath>(CancellationToken, installTask))
147-
.Then((b, path) => {
148-
zipArchivesPath.DeleteIfExists();
149-
return path;
150-
});
172+
determinePath = determinePath.Then(new ShortCircuitTask<NPath>(CancellationToken, installTask));
151173
}
152174

153175
if (!environmentIsWindows)

src/GitHub.Api/GitHub.Api.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
<Compile Include="Application\ApplicationManagerBase.cs" />
118118
<Compile Include="Helpers\Constants.cs" />
119119
<Compile Include="Helpers\Validation.cs" />
120-
<Compile Include="Installer\PortableGitInstallTask.cs" />
120+
<Compile Include="Installer\GitInstaller.cs" />
121121
<Compile Include="Installer\ShortCircuitTask.cs" />
122122
<Compile Include="Installer\UnzipTask.cs" />
123123
<Compile Include="OutputProcessors\GitAheadBehindStatusOutputProcessor.cs" />
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
using System;
2+
using System.Threading;
3+
4+
namespace GitHub.Unity
5+
{
6+
class GitInstallDetails
7+
{
8+
public NPath GitInstallPath { get; }
9+
public string GitExec { get; }
10+
public NPath GitExecPath { get; }
11+
public string GitLfsExec { get; }
12+
public NPath GitLfsExecPath { get; }
13+
14+
public const string ExtractedMD5 = "65fd0575d3b47d8207b9e19d02faca4f";
15+
public const string FileListMD5 = "a152a216b2e76f6c127053251187a278";
16+
17+
private const string PackageVersion = "f02737a78695063deace08e96d5042710d3e32db";
18+
private const string PackageName = "PortableGit";
19+
private const string PackageNameWithVersion = PackageName + "_" + PackageVersion;
20+
21+
private readonly bool onWindows;
22+
23+
public GitInstallDetails(NPath targetInstallPath, bool onWindows)
24+
{
25+
this.onWindows = onWindows;
26+
var gitInstallPath = targetInstallPath.Combine(ApplicationInfo.ApplicationName, PackageNameWithVersion);
27+
GitInstallPath = gitInstallPath;
28+
29+
if (onWindows)
30+
{
31+
GitExec += "git.exe";
32+
GitLfsExec += "git-lfs.exe";
33+
34+
GitExecPath = gitInstallPath.Combine("cmd", GitExec);
35+
}
36+
else
37+
{
38+
GitExec = "git";
39+
GitLfsExec = "git-lfs";
40+
41+
GitExecPath = gitInstallPath.Combine("bin", GitExec);
42+
}
43+
44+
GitLfsExecPath = GetGitLfsExecPath(gitInstallPath);
45+
}
46+
47+
public NPath GetGitLfsExecPath(NPath gitInstallRoot)
48+
{
49+
return onWindows
50+
? gitInstallRoot.Combine("mingw32", "libexec", "git-core", GitLfsExec)
51+
: gitInstallRoot.Combine("libexec", "git-core", GitLfsExec);
52+
}
53+
}
54+
55+
class GitInstaller
56+
{
57+
private static ILogging Logger = Logging.GetLogger<GitInstaller>();
58+
59+
private readonly IEnvironment environment;
60+
private readonly IZipHelper sharpZipLibHelper;
61+
private readonly CancellationToken cancellationToken;
62+
private readonly GitInstallDetails installDetails;
63+
64+
public GitInstaller(IEnvironment environment, CancellationToken cancellationToken, GitInstallDetails installDetails)
65+
: this(environment, ZipHelper.Instance, cancellationToken, installDetails)
66+
{
67+
}
68+
69+
public GitInstaller(IEnvironment environment, IZipHelper sharpZipLibHelper, CancellationToken cancellationToken, GitInstallDetails installDetails)
70+
{
71+
this.environment = environment;
72+
this.sharpZipLibHelper = sharpZipLibHelper;
73+
this.cancellationToken = cancellationToken;
74+
this.installDetails = installDetails;
75+
}
76+
77+
public void SetupGitIfNeeded(ActionTask<NPath> onSuccess, ITask onFailure)
78+
{
79+
Logger.Trace("SetupGitIfNeeded");
80+
81+
if (!environment.IsWindows)
82+
{
83+
onFailure.Start();
84+
}
85+
86+
new FuncTask<bool>(cancellationToken, IsGitExtracted)
87+
.Then((success, isPortableGitExtracted) => {
88+
89+
Logger.Trace("IsPortableGitExtracted: {0}", isPortableGitExtracted);
90+
91+
if (isPortableGitExtracted)
92+
{
93+
Logger.Trace("SetupGitIfNeeded: Skipped");
94+
95+
new FuncTask<NPath>(cancellationToken, () => installDetails.GitExecPath)
96+
.Then(onSuccess)
97+
.Start();
98+
}
99+
else
100+
{
101+
var tempZipPath = NPath.CreateTempDirectory("git_zip_paths");
102+
var gitArchivePath = AssemblyResources.ToFile(ResourceType.Platform, "git.zip", tempZipPath, environment);
103+
var gitLfsArchivePath = AssemblyResources.ToFile(ResourceType.Platform, "git-lfs.zip", tempZipPath, environment);
104+
105+
var gitExtractPath = tempZipPath.Combine("git").CreateDirectory();
106+
var gitLfsExtractPath = tempZipPath.Combine("git-lfs").CreateDirectory();
107+
108+
new UnzipTask(cancellationToken, gitArchivePath, gitExtractPath, sharpZipLibHelper)
109+
.Then(new UnzipTask(cancellationToken, gitLfsArchivePath, gitLfsExtractPath, sharpZipLibHelper))
110+
.Then(() => {
111+
var targetGitLfsExecPath = installDetails.GetGitLfsExecPath(gitExtractPath);
112+
var extractGitLfsExePath = gitLfsExtractPath.Combine(installDetails.GitLfsExec);
113+
extractGitLfsExePath.Move(targetGitLfsExecPath);
114+
115+
var extractedMD5 = environment.FileSystem.CalculateFolderMD5(gitExtractPath);
116+
if (!extractedMD5.Equals(GitInstallDetails.ExtractedMD5, StringComparison.InvariantCultureIgnoreCase))
117+
{
118+
Logger.Warning("MD5 {0} does not match expected {1}", extractedMD5, GitInstallDetails.ExtractedMD5);
119+
Logger.Warning("Failed PortableGitInstallTask");
120+
throw new Exception();
121+
}
122+
123+
Logger.Trace("Moving tempDirectory:\"{0}\" to extractTarget:\"{1}\"", gitExtractPath,
124+
installDetails.GitInstallPath);
125+
126+
gitExtractPath.Move(installDetails.GitInstallPath);
127+
128+
Logger.Trace("Deleting tempZipPath:\"{0}\"", tempZipPath);
129+
tempZipPath.DeleteIfExists();
130+
131+
}).Finally((b, exception) => {
132+
if (b)
133+
{
134+
Logger.Trace("SetupGitIfNeeded: Success");
135+
136+
new FuncTask<NPath>(cancellationToken, () => installDetails.GitExecPath)
137+
.Then(onSuccess)
138+
.Start();
139+
}
140+
else
141+
{
142+
Logger.Trace("SetupGitIfNeeded: Failed");
143+
144+
onFailure.Start();
145+
}
146+
}).Start();
147+
}
148+
149+
}).Start();
150+
}
151+
152+
private bool IsGitExtracted()
153+
{
154+
if (!installDetails.GitInstallPath.DirectoryExists())
155+
{
156+
Logger.Trace("{0} does not exist", installDetails.GitInstallPath);
157+
return false;
158+
}
159+
160+
var fileListMD5 = environment.FileSystem.CalculateFolderMD5(installDetails.GitInstallPath, false);
161+
if (!fileListMD5.Equals(GitInstallDetails.FileListMD5, StringComparison.InvariantCultureIgnoreCase))
162+
{
163+
Logger.Trace("MD5 {0} does not match expected {1}", fileListMD5, GitInstallDetails.FileListMD5);
164+
return false;
165+
}
166+
167+
Logger.Trace("Git Present");
168+
return true;
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)