Skip to content

Commit 08b5df0

Browse files
authored
Merge pull request #74 from mjcheetham/new-install
New Install 6/6: Implement (un)configuration for GCM Core
2 parents 1a68add + 11638c0 commit 08b5df0

File tree

16 files changed

+652
-81
lines changed

16 files changed

+652
-81
lines changed

.azure-pipelines/templates/windows/pack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
steps:
22
- script: |
33
xcopy "out\windows\Installer.Windows\bin\$(configuration)\net461" "$(Build.StagingDirectory)\publish\"
4-
xcopy "out\windows\Payload.Windows\bin\$(configuration)\net461\win-x64" "$(Build.StagingDirectory)\publish\payload\"
4+
xcopy "out\windows\Payload.Windows\bin\$(configuration)\net461\win-x86" "$(Build.StagingDirectory)\publish\payload\"
55
mkdir "$(Build.StagingDirectory)\publish\payload.sym\"
66
move "$(Build.StagingDirectory)\publish\payload\*.pdb" "$(Build.StagingDirectory)\publish\payload.sym\"
77
displayName: Prepare final build artifact

src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
6-
<TargetFrameworks Condition="'$(OSPlatform)'=='windows'">netcoreapp2.1;net461</TargetFrameworks>
7-
<RuntimeIdentifiers>win-x64;osx-x64</RuntimeIdentifiers>
5+
<TargetFramework>netcoreapp2.1</TargetFramework>
6+
<TargetFramework Condition="'$(OSPlatform)'=='windows'">net461</TargetFramework>
7+
<RuntimeIdentifiers>win-x86;osx-x64</RuntimeIdentifiers>
88
<AssemblyName>git-credential-manager-core</AssemblyName>
99
<RootNamespace>Microsoft.Git.CredentialManager</RootNamespace>
1010
<ApplicationIcon>$(RepoAssetsPath)gcmicon.ico</ApplicationIcon>
@@ -13,6 +13,12 @@
1313
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
1414
</PropertyGroup>
1515

16+
<!-- On Windows we target 32-bit because the WinForms authentication helpers are 32-bit
17+
and also need to use the native libgit2 library (we use the 32-bit version on Windows) -->
18+
<PropertyGroup Condition="'$(OSPlatform)'=='windows'">
19+
<Prefer32Bit>true</Prefer32Bit>
20+
</PropertyGroup>
21+
1622
<ItemGroup>
1723
<ProjectReference Include="..\GitHub\GitHub.csproj" />
1824
<ProjectReference Include="..\Microsoft.AzureRepos\Microsoft.AzureRepos.csproj" />

src/shared/Git-Credential-Manager/Program.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33
using System;
4+
using System.IO;
5+
using System.Reflection;
46
using GitHub;
57
using Microsoft.AzureRepos;
68

@@ -10,8 +12,9 @@ public static class Program
1012
{
1113
public static void Main(string[] args)
1214
{
15+
string appPath = GetApplicationPath();
1316
using (var context = new CommandContext())
14-
using (var app = new Application(context))
17+
using (var app = new Application(context, appPath))
1518
{
1619
// Register all supported host providers
1720
app.RegisterProviders(
@@ -29,5 +32,24 @@ public static void Main(string[] args)
2932
Environment.Exit(exitCode);
3033
}
3134
}
35+
36+
private static string GetApplicationPath()
37+
{
38+
Assembly entryAssembly = Assembly.GetExecutingAssembly();
39+
if (entryAssembly is null)
40+
{
41+
throw new InvalidOperationException();
42+
}
43+
44+
string candidatePath = entryAssembly.Location;
45+
46+
// Strip the .dll from assembly name on Mac and Linux
47+
if (!PlatformUtils.IsWindows() && Path.HasExtension(candidatePath))
48+
{
49+
return Path.ChangeExtension(candidatePath, null);
50+
}
51+
52+
return candidatePath;
53+
}
3254
}
3355
}

src/shared/Microsoft.AzureRepos.Tests/AzureReposHostProviderTests.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ namespace Microsoft.AzureRepos.Tests
1313
{
1414
public class AzureReposHostProviderTests
1515
{
16+
private static readonly string AzDevUseHttpPathKey =
17+
$"{Constants.GitConfiguration.Credential.SectionName}.https://dev.azure.com.{Constants.GitConfiguration.Credential.UseHttpPath}";
18+
1619
[Fact]
1720
public void AzureReposProvider_IsSupported_AzureHost_UnencryptedHttp_ReturnsTrue()
1821
{
@@ -171,5 +174,84 @@ public async Task AzureReposProvider_GetCredentialAsync_ReturnsCredential()
171174
Assert.Equal(personalAccessToken, credential.Password);
172175
// We don't care about the username value
173176
}
177+
178+
[Fact]
179+
public async Task AzureReposHostProvider_ConfigureAsync_UseHttpPathSetTrue_DoesNothing()
180+
{
181+
var provider = new AzureReposHostProvider(new TestCommandContext());
182+
183+
var environment = new TestEnvironment();
184+
var config = new TestGitConfiguration(new Dictionary<string, IList<string>>
185+
{
186+
[AzDevUseHttpPathKey] = new List<string> {"true"}
187+
});
188+
189+
await provider.ConfigureAsync(
190+
environment, EnvironmentVariableTarget.User,
191+
config, GitConfigurationLevel.Global);
192+
193+
Assert.Single(config.Dictionary);
194+
Assert.True(config.Dictionary.TryGetValue(AzDevUseHttpPathKey, out IList<string> actualValues));
195+
Assert.Single(actualValues);
196+
Assert.Equal("true", actualValues[0]);
197+
}
198+
199+
[Fact]
200+
public async Task AzureReposHostProvider_ConfigureAsync_UseHttpPathSetFalse_SetsUseHttpPathTrue()
201+
{
202+
var provider = new AzureReposHostProvider(new TestCommandContext());
203+
204+
var environment = new TestEnvironment();
205+
var config = new TestGitConfiguration(new Dictionary<string, IList<string>>
206+
{
207+
[AzDevUseHttpPathKey] = new List<string> {"false"}
208+
});
209+
210+
await provider.ConfigureAsync(
211+
environment, EnvironmentVariableTarget.User,
212+
config, GitConfigurationLevel.Global);
213+
214+
Assert.Single(config.Dictionary);
215+
Assert.True(config.Dictionary.TryGetValue(AzDevUseHttpPathKey, out IList<string> actualValues));
216+
Assert.Single(actualValues);
217+
Assert.Equal("true", actualValues[0]);
218+
}
219+
220+
[Fact]
221+
public async Task AzureReposHostProvider_ConfigureAsync_UseHttpPathUnset_SetsUseHttpPathTrue()
222+
{
223+
var provider = new AzureReposHostProvider(new TestCommandContext());
224+
225+
var environment = new TestEnvironment();
226+
var config = new TestGitConfiguration();
227+
228+
await provider.ConfigureAsync(
229+
environment, EnvironmentVariableTarget.User,
230+
config, GitConfigurationLevel.Global);
231+
232+
Assert.Single(config.Dictionary);
233+
Assert.True(config.Dictionary.TryGetValue(AzDevUseHttpPathKey, out IList<string> actualValues));
234+
Assert.Single(actualValues);
235+
Assert.Equal("true", actualValues[0]);
236+
}
237+
238+
239+
[Fact]
240+
public async Task AzureReposHostProvider_UnconfigureAsync_UseHttpPathSet_RemovesEntry()
241+
{
242+
var provider = new AzureReposHostProvider(new TestCommandContext());
243+
244+
var environment = new TestEnvironment();
245+
var config = new TestGitConfiguration(new Dictionary<string, IList<string>>
246+
{
247+
[AzDevUseHttpPathKey] = new List<string> {"true"}
248+
});
249+
250+
await provider.UnconfigureAsync(
251+
environment, EnvironmentVariableTarget.User,
252+
config, GitConfigurationLevel.Global);
253+
254+
Assert.Empty(config.Dictionary);
255+
}
174256
}
175257
}

src/shared/Microsoft.AzureRepos/AzureReposHostProvider.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
using System.Threading.Tasks;
66
using Microsoft.Git.CredentialManager;
77
using Microsoft.Git.CredentialManager.Authentication;
8+
using KnownGitCfg = Microsoft.Git.CredentialManager.Constants.GitConfiguration;
89

910
namespace Microsoft.AzureRepos
1011
{
11-
public class AzureReposHostProvider : HostProvider
12+
public class AzureReposHostProvider : HostProvider, IConfigurableComponent
1213
{
1314
private readonly IAzureDevOpsRestApi _azDevOps;
1415
private readonly IMicrosoftAuthentication _msAuth;
@@ -103,5 +104,49 @@ protected override void ReleaseManagedResources()
103104
}
104105

105106
#endregion
107+
108+
#region IConfigurationComponent
109+
110+
string IConfigurableComponent.Name => "Azure Repos provider";
111+
112+
public Task ConfigureAsync(
113+
IEnvironment environment, EnvironmentVariableTarget environmentTarget,
114+
IGitConfiguration configuration, GitConfigurationLevel configurationLevel)
115+
{
116+
string useHttpPathKey = $"{KnownGitCfg.Credential.SectionName}.https://dev.azure.com.{KnownGitCfg.Credential.UseHttpPath}";
117+
118+
using (IGitConfiguration targetConfig = configuration.GetFilteredConfiguration(configurationLevel))
119+
{
120+
if (targetConfig.TryGetValue(useHttpPathKey, out string currentValue) && currentValue.IsTruthy())
121+
{
122+
Context.Trace.WriteLine("Git configuration 'credential.useHttpPath' is already set to 'true' for https://dev.azure.com.");
123+
}
124+
else
125+
{
126+
Context.Trace.WriteLine("Setting Git configuration 'credential.useHttpPath' to 'true' for https://dev.azure.com...");
127+
targetConfig.SetValue(useHttpPathKey, "true");
128+
}
129+
}
130+
131+
return Task.CompletedTask;
132+
}
133+
134+
public Task UnconfigureAsync(
135+
IEnvironment environment, EnvironmentVariableTarget environmentTarget,
136+
IGitConfiguration configuration, GitConfigurationLevel configurationLevel)
137+
{
138+
string useHttpPathKey = $"{KnownGitCfg.Credential.SectionName}.https://dev.azure.com.{KnownGitCfg.Credential.UseHttpPath}";
139+
140+
Context.Trace.WriteLine("Clearing Git configuration 'credential.useHttpPath' for https://dev.azure.com...");
141+
142+
using (IGitConfiguration targetConfig = configuration.GetFilteredConfiguration(configurationLevel))
143+
{
144+
targetConfig.DeleteEntry(useHttpPathKey);
145+
}
146+
147+
return Task.CompletedTask;
148+
}
149+
150+
#endregion
106151
}
107152
}

0 commit comments

Comments
 (0)