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

Commit d6c9511

Browse files
Merge branch 'enhancements/async-git-setup' into enhancements/window-loading-view
2 parents 926e19d + ed03a78 commit d6c9511

28 files changed

+663
-588
lines changed

GitHub.Unity.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@
335335
</TypePattern>
336336
&lt;/Patterns&gt;</s:String>
337337
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
338+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">ME</s:String>
338339
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSH/@EntryIndexedValue">SSH</s:String>
339340
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
340341
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>

src/GitHub.Api/Application/ApplicationManagerBase.cs

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,46 +39,103 @@ protected void Initialize()
3939
Logging.TracingEnabled = UserSettings.Get(Constants.TraceLoggingKey, false);
4040
ProcessManager = new ProcessManager(Environment, Platform.GitEnvironment, CancellationToken);
4141
Platform.Initialize(ProcessManager, TaskManager);
42-
GitClient = new GitClient(Environment, ProcessManager, TaskManager);
42+
ITaskManager taskManager = TaskManager;
43+
GitClient = new GitClient(Environment, ProcessManager, taskManager.Token);
4344
SetupMetrics();
4445
}
4546

4647
public void Run(bool firstRun)
4748
{
48-
new ActionTask(SetupGit())
49+
Logger.Trace("Run - CurrentDirectory {0}", NPath.CurrentDirectory);
50+
51+
SetupGit()
4952
.Then(RestartRepository)
5053
.ThenInUI(InitializeUI)
5154
.Start();
5255
}
5356

54-
private async Task SetupGit()
57+
private ITask SetupGit()
5558
{
56-
Logger.Trace("Run - CurrentDirectory {0}", NPath.CurrentDirectory);
59+
return BuildDetermineGitPathTask()
60+
.Then((b, path) => {
61+
Logger.Trace("Setting GitExecutablePath: {0}", path);
62+
Environment.GitExecutablePath = path;
63+
})
64+
.Then(() => {
65+
if (Environment.GitExecutablePath == null)
66+
{
67+
if (Environment.IsWindows)
68+
{
69+
GitClient.GetConfig("credential.helper", GitConfigSource.Global).Then(
70+
(b, credentialHelper) => {
71+
if (!string.IsNullOrEmpty(credentialHelper))
72+
{
73+
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
74+
}
75+
else
76+
{
77+
Logger.Warning(
78+
"No Windows CredentialHeloper found: Setting to wincred");
79+
80+
GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global).Start().Wait();
81+
}
82+
});
83+
}
84+
}
85+
})
86+
.ThenInUI(() => {
87+
Environment.User.Initialize(GitClient);
88+
});
89+
}
5790

58-
if (Environment.GitExecutablePath == null)
91+
private TaskBase<NPath> BuildDetermineGitPathTask()
92+
{
93+
TaskBase<NPath> determinePath = new FuncTask<NPath>(CancellationToken, () => {
94+
if (Environment.GitExecutablePath != null)
95+
{
96+
return Environment.GitExecutablePath;
97+
}
98+
99+
var gitExecutablePath = SystemSettings.Get(Constants.GitInstallPathKey)?.ToNPath();
100+
if (gitExecutablePath != null && gitExecutablePath.FileExists())
101+
{
102+
Logger.Trace("Using git install path from settings");
103+
return gitExecutablePath;
104+
}
105+
106+
return null;
107+
});
108+
109+
var environmentIsWindows = Environment.IsWindows;
110+
if (environmentIsWindows)
59111
{
60-
Environment.GitExecutablePath = await DetermineGitExecutablePath();
112+
var applicationDataPath = Environment.GetSpecialFolder(System.Environment.SpecialFolder.LocalApplicationData).ToNPath();
113+
var installDetails = new PortableGitInstallDetails(applicationDataPath, true);
114+
var installTask = new PortableGitInstallTask(CancellationToken, Environment, installDetails);
61115

62-
Logger.Trace("Environment.GitExecutablePath \"{0}\" Exists:{1}", Environment.GitExecutablePath, Environment.GitExecutablePath.FileExists());
116+
determinePath = determinePath.Then(new ShortCircuitTask<NPath>(CancellationToken, installTask));
117+
}
63118

64-
if (Environment.IsWindows)
65-
{
66-
var credentialHelper = await GitClient.GetConfig("credential.helper", GitConfigSource.Global).StartAwait();
119+
if (!environmentIsWindows)
120+
{
121+
determinePath = determinePath.Then(new ShortCircuitTask<NPath>(CancellationToken, () => {
122+
var p = new NPath("/usr/local/bin/git");
67123

68-
if (!string.IsNullOrEmpty(credentialHelper))
124+
if (p.FileExists())
69125
{
70-
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
126+
return p;
71127
}
72-
else
73-
{
74-
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
75128

76-
await GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global).StartAwait();
77-
}
78-
}
129+
return null;
130+
}));
131+
132+
var findExecTask = new FindExecTask("git", CancellationToken);
133+
findExecTask.Configure(ProcessManager);
134+
135+
determinePath = determinePath.Then(new ShortCircuitTask<NPath>(CancellationToken, findExecTask));
79136
}
80137

81-
Environment.User.Initialize(GitClient);
138+
return determinePath;
82139
}
83140

84141
public ITask InitializeRepository()
@@ -136,27 +193,6 @@ public void RestartRepository()
136193
}
137194
}
138195

139-
private async Task<NPath> DetermineGitExecutablePath(ProgressReport progress = null)
140-
{
141-
var gitExecutablePath = SystemSettings.Get(Constants.GitInstallPathKey)?.ToNPath();
142-
if (gitExecutablePath != null && gitExecutablePath.FileExists())
143-
{
144-
Logger.Trace("Using git install path from settings");
145-
return gitExecutablePath;
146-
}
147-
148-
var gitInstaller = new GitInstaller(Environment, CancellationToken);
149-
var setupDone = await gitInstaller.SetupIfNeeded(progress?.Percentage, progress?.Remaining);
150-
if (setupDone)
151-
{
152-
Logger.Trace("Setup performed using new path");
153-
return gitInstaller.GitExecutablePath;
154-
}
155-
156-
Logger.Trace("Finding git install path");
157-
return await GitClient.FindGitInstallation().SafeAwait();
158-
}
159-
160196
protected void SetupMetrics(string unityVersion, bool firstRun)
161197
{
162198
Logger.Trace("Setup metrics");

src/GitHub.Api/Extensions/FileSystemExtensions.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
using System;
2+
using System.IO;
3+
using System.Linq;
24
using System.Security.Cryptography;
35
using System.Text;
46

57
namespace GitHub.Unity
68
{
79
static class FileSystemExtensions
810
{
9-
public static string CalculateMD5(this IFileSystem fileSystem, string file)
11+
public static string CalculateMD5(this IFileSystem fileSystem, string path)
12+
{
13+
if (fileSystem.DirectoryExists(path))
14+
{
15+
return fileSystem.CalculateFolderMD5(path);
16+
}
17+
18+
if (fileSystem.FileExists(path))
19+
{
20+
return fileSystem.CalculateFileMD5(path);
21+
}
22+
23+
throw new ArgumentException($@"Path does not exist: ""{path}""");
24+
}
25+
26+
public static string CalculateFileMD5(this IFileSystem fileSystem, string file)
1027
{
1128
byte[] computeHash;
1229
using (var md5 = MD5.Create())
@@ -17,7 +34,36 @@ public static string CalculateMD5(this IFileSystem fileSystem, string file)
1734
}
1835
}
1936
20-
return BitConverter.ToString(computeHash).Replace("-", string.Empty);
37+
return BitConverter.ToString(computeHash).Replace("-", string.Empty).ToLower();
38+
}
39+
40+
public static string CalculateFolderMD5(this IFileSystem fileSystem, string path)
41+
{
42+
//https://stackoverflow.com/questions/3625658/creating-hash-for-folder
43+
44+
var filePaths = fileSystem.GetFiles(path, "*", SearchOption.AllDirectories)
45+
.OrderBy(p => p)
46+
.ToArray();
47+
48+
using (var md5 = MD5.Create())
49+
{
50+
foreach (var filePath in filePaths)
51+
{
52+
// hash path
53+
var relativeFilePath = filePath.Substring(path.Length + 1);
54+
var pathBytes = Encoding.UTF8.GetBytes(relativeFilePath);
55+
md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
56+
57+
// hash contents
58+
var contentBytes = File.ReadAllBytes(filePath);
59+
md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
60+
}
61+
62+
//Handles empty filePaths case
63+
md5.TransformFinalBlock(new byte[0], 0, 0);
64+
65+
return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower();
66+
}
2167
}
2268
}
2369
}

src/GitHub.Api/Git/GitClient.cs

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ namespace GitHub.Unity
88
{
99
public interface IGitClient
1010
{
11-
Task<NPath> FindGitInstallation();
1211
ITask<ValidateGitInstallResult> ValidateGitInstall(NPath path);
1312

1413
ITask Init(IOutputProcessor<string> processor = null);
@@ -96,84 +95,13 @@ class GitClient : IGitClient
9695
private const string UserEmailConfigKey = "user.email";
9796
private readonly IEnvironment environment;
9897
private readonly IProcessManager processManager;
99-
private readonly ITaskManager taskManager;
10098
private readonly CancellationToken cancellationToken;
10199

102-
public GitClient(IEnvironment environment, IProcessManager processManager, ITaskManager taskManager)
100+
public GitClient(IEnvironment environment, IProcessManager processManager, CancellationToken cancellationToken)
103101
{
104102
this.environment = environment;
105103
this.processManager = processManager;
106-
this.taskManager = taskManager;
107-
this.cancellationToken = taskManager.Token;
108-
}
109-
110-
public async Task<NPath> FindGitInstallation()
111-
{
112-
if (!String.IsNullOrEmpty(environment.GitExecutablePath))
113-
return environment.GitExecutablePath;
114-
115-
NPath path = null;
116-
117-
if (environment.IsWindows)
118-
path = await LookForPortableGit();
119-
120-
if (path == null)
121-
path = await LookForSystemGit();
122-
123-
if (path == null)
124-
{
125-
Logger.Trace("Git Installation not discovered");
126-
}
127-
else
128-
{
129-
Logger.Trace("Git Installation discovered: '{0}'", path);
130-
}
131-
132-
return path;
133-
}
134-
135-
private Task<NPath> LookForPortableGit()
136-
{
137-
Logger.Trace("LookForPortableGit");
138-
139-
var gitHubLocalAppDataPath = environment.UserCachePath;
140-
if (!gitHubLocalAppDataPath.DirectoryExists())
141-
return null;
142-
143-
var searchPath = "PortableGit_";
144-
145-
var portableGitPath = gitHubLocalAppDataPath.Directories()
146-
.Where(s => s.FileName.StartsWith(searchPath, StringComparison.OrdinalIgnoreCase))
147-
.FirstOrDefault();
148-
149-
if (portableGitPath != null)
150-
{
151-
portableGitPath = portableGitPath.Combine("cmd", $"git{environment.ExecutableExtension}");
152-
}
153-
154-
return TaskEx.FromResult(portableGitPath);
155-
}
156-
157-
private async Task<NPath> LookForSystemGit()
158-
{
159-
Logger.Trace("LookForSystemGit");
160-
161-
NPath path = null;
162-
if (!environment.IsWindows)
163-
{
164-
var p = new NPath("/usr/local/bin/git");
165-
166-
if (p.FileExists())
167-
path = p;
168-
}
169-
170-
if (path == null)
171-
{
172-
path = await new FindExecTask("git", taskManager.Token)
173-
.Configure(processManager).StartAwait();
174-
}
175-
176-
return path;
104+
this.cancellationToken = cancellationToken;
177105
}
178106

179107
public ITask<ValidateGitInstallResult> ValidateGitInstall(NPath path)

src/GitHub.Api/GitHub.Api.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@
117117
<Compile Include="Application\ApplicationManagerBase.cs" />
118118
<Compile Include="Helpers\Constants.cs" />
119119
<Compile Include="Helpers\Validation.cs" />
120+
<Compile Include="Installer\PortableGitInstallTask.cs" />
121+
<Compile Include="Installer\ShortCircuitTask.cs" />
122+
<Compile Include="Installer\UnzipTask.cs" />
120123
<Compile Include="OutputProcessors\GitAheadBehindStatusOutputProcessor.cs" />
121124
<Compile Include="OutputProcessors\LfsVersionOutputProcessor.cs" />
122125
<Compile Include="OutputProcessors\VersionOutputProcessor.cs" />
@@ -155,9 +158,7 @@
155158
<Compile Include="Git\Tasks\GitRemoteChangeTask.cs" />
156159
<Compile Include="Git\Tasks\GitRemoveFromIndexTask.cs" />
157160
<Compile Include="Threading\IMainThreadSynchronizationContext.cs" />
158-
<Compile Include="Installer\IGitInstaller.cs" />
159161
<Compile Include="Installer\IZipHelper.cs" />
160-
<Compile Include="Installer\GitInstaller.cs" />
161162
<Compile Include="Installer\ZipHelper.cs" />
162163
<Compile Include="Extensions\AsyncExtensions.cs" />
163164
<Compile Include="Platform\Settings.cs" />

src/GitHub.Api/IO/FileSystem.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ public void WriteAllText(string path, string contents, Encoding encoding)
167167
File.WriteAllText(path, contents, encoding);
168168
}
169169

170+
public byte[] ReadAllBytes(string path)
171+
{
172+
return File.ReadAllBytes(path);
173+
}
174+
170175
public string ReadAllText(string path)
171176
{
172177
return File.ReadAllText(path);

src/GitHub.Api/IO/IFileSystem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public interface IFileSystem
3434
void WriteAllText(string path, string contents);
3535
void WriteAllText(string path, string contents, Encoding encoding);
3636
void WriteAllLines(string path, string[] contents);
37+
byte[] ReadAllBytes(string path);
3738
string ReadAllText(string path);
3839
string ReadAllText(string path, Encoding encoding);
3940
Stream OpenRead(string path);

0 commit comments

Comments
 (0)