Skip to content

Commit

Permalink
linux: add option for GCM_GPG_PATH environment variable
Browse files Browse the repository at this point in the history
If GCM_GPG_PATH is specified, it is assumed to be the path to the GPG
executable used by `pass` and will throw an exception if it is not found.
If GCM_GPG_PATH is _not_ specified, GCM Core will attempt to find the
correct GPG executable by mimicking the behavior (currently) used by `pass`
(that is, first searching for `gpg2`, then falling back on `gpg` if `gpg2` is
not found).
  • Loading branch information
vdye committed Aug 10, 2021
1 parent 91e4a84 commit ddcab81
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 10 deletions.
14 changes: 14 additions & 0 deletions docs/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,20 @@ export GCM_PLAINTEXT_STORE_PATH=/mnt/external-drive/credentials

---

### GCM_GPG_PATH

Specify the path (_including_ the executable name) to the version of `gpg` used by `pass` (`gpg2` if present, otherwise `gpg`). This is primarily meant to allow manual resolution of the conflict that occurs on legacy Linux systems with parallel installs of `gpg` and `gpg2`.

If not specified, GCM Core defaults to using the version of `gpg2` on the `$PATH`, falling back on `gpg` if `gpg2` is not found.

##### Linux

```bash
export GCM_GPG_PATH="/usr/local/bin/gpg2"
```

---

### GCM_MSAUTH_FLOW

Specify which authentication flow should be used when performing Microsoft authentication and an interactive flow is required.
Expand Down
59 changes: 49 additions & 10 deletions src/shared/Microsoft.Git.CredentialManager/CommandContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public CommandContext(string appPath)
SystemPrompts = new WindowsSystemPrompts();
Environment = new WindowsEnvironment(FileSystem);
Terminal = new WindowsTerminal(Trace);
string gitPath = GetGitPath(Environment, FileSystem);
string gitPath = GetGitPath(Environment, FileSystem, Trace);
Git = new GitProcess(
Trace,
gitPath,
Expand All @@ -111,14 +111,15 @@ public CommandContext(string appPath)
SystemPrompts = new MacOSSystemPrompts();
Environment = new PosixEnvironment(FileSystem);
Terminal = new PosixTerminal(Trace);
string gitPath = GetGitPath(Environment, FileSystem);
string gitPath = GetGitPath(Environment, FileSystem, Trace);
Git = new GitProcess(
Trace,
gitPath,
FileSystem.GetCurrentDirectory()
);
Settings = new Settings(Environment, Git);
CredentialStore = new MacOSKeychain(Settings.CredentialNamespace);

}
else if (PlatformUtils.IsLinux())
{
Expand All @@ -128,17 +129,16 @@ public CommandContext(string appPath)
SystemPrompts = new LinuxSystemPrompts();
Environment = new PosixEnvironment(FileSystem);
Terminal = new PosixTerminal(Trace);
string gitPath = GetGitPath(Environment, FileSystem);
string gitPath = GetGitPath(Environment, FileSystem, Trace);
Git = new GitProcess(
Trace,
gitPath,
FileSystem.GetCurrentDirectory()
);
Settings = new Settings(Environment, Git);
IGpg gpg = new Gpg(
Environment.LocateExecutable("gpg"),
SessionManager
);

string gpgPath = GetGpgPath(Environment, FileSystem, Trace);
IGpg gpg = new Gpg(gpgPath, SessionManager);
CredentialStore = new LinuxCredentialStore(FileSystem, Settings, SessionManager, gpg, Environment, Git);
}
else
Expand All @@ -152,23 +152,62 @@ public CommandContext(string appPath)
SystemPrompts.ParentWindowId = Settings.ParentWindowId;
}

private static string GetGitPath(IEnvironment environment, IFileSystem fileSystem)
private static string GetGitPath(IEnvironment environment, IFileSystem fileSystem, ITrace trace)
{
string gitExecPath;
string programName = PlatformUtils.IsWindows() ? "git.exe" : "git";

// Use the GIT_EXEC_PATH environment variable if set
if (environment.Variables.TryGetValue(Constants.EnvironmentVariables.GitExecutablePath,
out string gitExecPath))
out gitExecPath))
{
string candidatePath = Path.Combine(gitExecPath, programName);
if (fileSystem.FileExists(candidatePath))
{
trace.WriteLine($"Using Git executable from GIT_EXEC_PATH: {candidatePath}");
return candidatePath;
}
}

// Otherwise try to locate the git(.exe) on the current PATH
return environment.LocateExecutable(programName);
gitExecPath = environment.LocateExecutable(programName);
trace.WriteLine($"Using PATH-located Git executable: {gitExecPath}");
return gitExecPath;
}

private static string GetGpgPath(IEnvironment environment, IFileSystem fileSystem, ITrace trace)
{
string gpgPath;

// Use the GCM_GPG_PATH environment variable if set
if (environment.Variables.TryGetValue(Constants.EnvironmentVariables.GpgExecutablePath,
out gpgPath))
{
if (fileSystem.FileExists(gpgPath))
{
trace.WriteLine($"Using Git executable from GCM_GPG_PATH: {gpgPath}");
return gpgPath;
}
else
{
throw new Exception($"GPG executable does not exist with path '{gpgPath}'");
}

}

// If no explicit GPG path is specified, mimic the way `pass`
// determines GPG dependency (use gpg2 if available, otherwise gpg)
if (environment.TryLocateExecutable("gpg2", out string gpg2Path))
{
trace.WriteLine($"Using PATH-located GPG (gpg2) executable: {gpg2Path}");
return gpg2Path;
}
else
{
gpgPath = environment.LocateExecutable("gpg");
trace.WriteLine($"Using PATH-located GPG (gpg) executable: {gpgPath}");
return gpgPath;
}
}

#region ICommandContext
Expand Down
1 change: 1 addition & 0 deletions src/shared/Microsoft.Git.CredentialManager/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static class EnvironmentVariables
public const string GcmCredCacheOptions = "GCM_CREDENTIAL_CACHE_OPTIONS";
public const string GcmPlaintextStorePath = "GCM_PLAINTEXT_STORE_PATH";
public const string GitExecutablePath = "GIT_EXEC_PATH";
public const string GpgExecutablePath = "GCM_GPG_PATH";
}

public static class Http
Expand Down

0 comments on commit ddcab81

Please sign in to comment.