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

Conversation

StanleyGoldman
Copy link
Contributor

@StanleyGoldman StanleyGoldman commented Dec 29, 2017

Note: This pull request targets enhancements/async-git-setup-rollup #561

Presently

The installation of portable git is currently a synchronous process initiated from ApplicationManagerBase.

public void Run(bool firstRun)
{
new ActionTask(SetupGit())
.Then(RestartRepository)
.ThenInUI(InitializeUI)
.Start();
}
private async Task SetupGit()
{
Logger.Trace("Run - CurrentDirectory {0}", NPath.CurrentDirectory);
if (Environment.GitExecutablePath == null)
{
Environment.GitExecutablePath = await DetermineGitExecutablePath();
Logger.Trace("Environment.GitExecutablePath \"{0}\" Exists:{1}", Environment.GitExecutablePath, Environment.GitExecutablePath.FileExists());
if (Environment.IsWindows)
{
var credentialHelper = await GitClient.GetConfig("credential.helper", GitConfigSource.Global).StartAwait();
if (!string.IsNullOrEmpty(credentialHelper))
{
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
}
else
{
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
await GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global).StartAwait();
}
}
}
Environment.User.Initialize(GitClient);
}

private async Task<NPath> DetermineGitExecutablePath(ProgressReport progress = null)
{
var gitExecutablePath = SystemSettings.Get(Constants.GitInstallPathKey)?.ToNPath();
if (gitExecutablePath != null && gitExecutablePath.FileExists())
{
Logger.Trace("Using git install path from settings");
return gitExecutablePath;
}
var gitInstaller = new GitInstaller(Environment, CancellationToken);
var setupDone = await gitInstaller.SetupIfNeeded(progress?.Percentage, progress?.Remaining);
if (setupDone)
{
Logger.Trace("Setup performed using new path");
return gitInstaller.GitExecutablePath;
}
Logger.Trace("Finding git install path");
return await GitClient.FindGitInstallation().SafeAwait();
}

It's responsibilities are as follows.
This process is currently linear & synchronous, running on the main thread.

  • Setup Git
    • Determine where git is installed
      • Get the value from settings, if it exists use that
      • If the previous step did not produce a path
        • Check for the existence of our Portable Git folder
          • Check that the git exec is present
          • Check that the git lfs exec is present
          • Check that the git-lfs exec matches the expected MD5
          • Attempt to extract git and git-lfs if the zip is present
          • If this process is successful use that path
      • If the previous step did not produce a path
        • And we are not on windows and /usr/local/bin/git exists, use that
      • If the previous step did not produce a path
        • run the system where/which command to find git.
    • Set Environment.GitExecutablePath
    • If on Windows, check that the credential helper is set to wincred
  • Initialize the User with GitClient
  • Restart Repository
  • Initialize UI

Pull Request

public void Run(bool firstRun)
{
Logger.Trace("Run - CurrentDirectory {0}", NPath.CurrentDirectory);
var afterGitSetup = new ActionTask(CancellationToken, RestartRepository)
.ThenInUI(InitializeUI);
//GitClient.GetConfig cannot be called until there is a git path set so it is wrapped in an ActionTask
var windowsCredentialSetup = new ActionTask(CancellationToken, () => {
GitClient.GetConfig("credential.helper", GitConfigSource.Global).Then((b, credentialHelper) => {
if (!string.IsNullOrEmpty(credentialHelper))
{
Logger.Trace("Windows CredentialHelper: {0}", credentialHelper);
afterGitSetup.Start();
}
else
{
Logger.Warning("No Windows CredentialHeloper found: Setting to wincred");
GitClient.SetConfig("credential.helper", "wincred", GitConfigSource.Global)
.Then(() => { afterGitSetup.Start(); }).Start();
}
}).Start();
});
var afterPathDetermined = new ActionTask<NPath>(CancellationToken, (b, path) => {
Logger.Trace("Setting Environment git path: {0}", path);
Environment.GitExecutablePath = path;
}).ThenInUI(() => {
Environment.User.Initialize(GitClient);
if (Environment.IsWindows)
{
windowsCredentialSetup.Start();
}
else
{
afterGitSetup.Start();
}
});
var findExecTask = new FindExecTask("git", CancellationToken)
.Finally((b, ex, path) => {
if (b && path != null)
{
Logger.Trace("FindExecTask Success: {0}", path);
new FuncTask<NPath>(CancellationToken, () => path)
.Then(afterPathDetermined)
.Start();
}
else
{
Logger.Warning("FindExecTask Failure");
Logger.Error("Git not found");
}
});
var applicationDataPath = Environment.GetSpecialFolder(System.Environment.SpecialFolder.LocalApplicationData).ToNPath();
var installDetails = new GitInstallDetails(applicationDataPath, true);
var gitInstaller = new GitInstaller(Environment, CancellationToken, installDetails);
gitInstaller.SetupGitIfNeeded(new ActionTask<NPath>(CancellationToken, (b, path) => {
Logger.Trace("GitInstaller Success: {0}", path);
new FuncTask<NPath>(CancellationToken, () => path)
.Then(afterPathDetermined)
.Start();
}), new ActionTask(CancellationToken, () => {
Logger.Warning("GitInstaller Failure");
findExecTask.Start();
}) );
}

In order to make this process asynchronous.
Several async tasks are created, upon their completion they choose which tasks to continue with.

Async Install flow

  • DEFINE After git is setup
    • Restart Repository
    • Initialize UI
  • DEFINE Windows Credential setup
    • Set windows credential helper
    • START "After git is setup"
  • DEFINE After path is determined
    • If windows START "Windows Credential setup"
    • Otherwise START "After git is setup"
  • DEFINE Locate system git
    • If successful START "After path is determined"
    • Else throw ERROR
  • DEFINE Locate or install portable git
    • If successful START "After path is determined"
    • Else START "Locate system git"
  • DEFINE Check settings for git path
    • If successful START "After path is determined"
    • Else START "Locate or install portable git"

START "Check settings for git path"

Git Installer

This process is now async and performs the following tasks:

  • Check for the existence of our Portable Git folder
    • Check that the extracted directory exists
    • Use a file list MD5 to verify that all expected files are present
      • Using a file list MD5 because this would be run on every startup and a full MD5 takes a few seconds
      • It would also be overkill because a full MD5 is performed on the zip files output
    • Perform a full MD5 on Git LFS
  • If Portable Git is not discovered to be intact
    • Check if it can use portable git based on OS (we don't ship portable git for mac currently, but for when we do)
    • Uses UnzipTask to unzip both zip files and perform a full MDS on the results
    • Creates a combined output and moves it to the target directory
    • Cleanup after itself

UI Changes

  • Changes to UserSettingsView and InitProjectView to remain disabled until git is ready

Performing a full MD5 on the contents of the zip package takes 1-3s
during the startup of Unity. So I changed functionality to perform a
full MD5 on the extracted contents and a file list MD5 during
application startup.
@StanleyGoldman StanleyGoldman changed the title Enhancements/async git setup Asyn install of Portable Git Dec 29, 2017
@StanleyGoldman StanleyGoldman changed the title Asyn install of Portable Git Async install of Portable Git Dec 29, 2017
@StanleyGoldman StanleyGoldman changed the base branch from master to enhancements/async-git-setup-rollup January 4, 2018 18:47
@StanleyGoldman StanleyGoldman force-pushed the enhancements/async-git-setup branch from 5e467fc to db6d33a Compare January 5, 2018 22:09
@StanleyGoldman
Copy link
Contributor Author

I realized I have one regression, which if you read my documentation you will catch.
I'm missing a check against settings to see if the person has chosen a git.

@StanleyGoldman
Copy link
Contributor Author

Fixed

Copy link

@drguthals drguthals left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good!

@StanleyGoldman StanleyGoldman merged commit 9a36b39 into enhancements/async-git-setup-rollup Jan 9, 2018
@StanleyGoldman StanleyGoldman deleted the enhancements/async-git-setup branch January 9, 2018 12:55
@StanleyGoldman StanleyGoldman mentioned this pull request Jan 10, 2018
7 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants