Skip to content

Commit a71aee7

Browse files
committed
Add IConfigurationService and (un)configure commands
Add service that can configure and unconfigure components at the user or system level, and two commands that map to configure and unconfigure. Call these new commands from the Windows and Mac (un)installers. Update the help command output to include the new commands.
1 parent 57514ea commit a71aee7

File tree

14 files changed

+504
-49
lines changed

14 files changed

+504
-49
lines changed

src/osx/Installer.Mac/scripts/configure-git.sh

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/osx/Installer.Mac/scripts/postinstall

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ fi
2626
# Create symlink to GCM in /usr/local/bin
2727
/bin/ln -Fs /usr/local/share/gcm-core/git-credential-manager-core /usr/local/bin/git-credential-manager-core
2828

29-
# Set system gitconfig for the current user
30-
USER_ID="$(id -u "${USER}")"
31-
if [ "${COMMAND_LINE_INSTALL}" = "" ]
32-
then
33-
/bin/launchctl asuser "${USER_ID}" "${PWD}/configure-git.sh"
34-
fi
29+
# Configure GCM for the current user
30+
/usr/local/share/gcm-core/git-credential-manager-core configure
3531

3632
exit 0

src/osx/Installer.Mac/uninstall.sh

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
#!/bin/bash
22

3-
# Unconfigure GCM
4-
HELPER="$(git config --system credential.helper)"
5-
if [ "$HELPER" = "/usr/local/share/gcm-core/git-credential-manager-core" ]
3+
# Ensure we're running as root
4+
if [ $(id -u) != "0" ]
65
then
7-
echo "Resetting credential helper to 'osxkeychain'..."
8-
sudo git config --system credential.helper osxkeychain
9-
else
10-
echo "GCM was not configured as the Git credential helper."
6+
sudo "$0" "$@"
7+
exit $?
118
fi
129

13-
# Remove GCM symlink
10+
# Unconfigure
11+
echo "Unconfiguring credential helper..."
12+
/usr/local/share/gcm-core/git-credential-manager-core unconfigure
13+
14+
# Remove symlink
1415
if [ -L /usr/local/bin/git-credential-manager-core ]
1516
then
16-
echo "Deleting GCM symlink..."
17+
echo "Deleting symlink..."
1718
rm /usr/local/bin/git-credential-manager-core
1819
else
19-
echo "No GCM symlink found."
20+
echo "No symlink found."
2021
fi
2122

2223
# Forget package installation/delete receipt
@@ -25,8 +26,8 @@ sudo pkgutil --forget com.microsoft.GitCredentialManager
2526
# Remove application files
2627
if [ -d /usr/local/share/gcm-core/ ]
2728
then
28-
echo "Deleting GCM application files..."
29+
echo "Deleting application files..."
2930
sudo rm -rf /usr/local/share/gcm-core/
3031
else
31-
echo "No GCM application files found."
32+
echo "No application files found."
3233
fi
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
using System.Threading.Tasks;
4+
using Microsoft.Git.CredentialManager.Commands;
5+
using Microsoft.Git.CredentialManager.Tests.Objects;
6+
using Moq;
7+
using Xunit;
8+
9+
namespace Microsoft.Git.CredentialManager.Tests.Commands
10+
{
11+
public class ConfigureCommandTests
12+
{
13+
[Theory]
14+
[InlineData("configure", true)]
15+
[InlineData("CONFIGURE", true)]
16+
[InlineData("cOnFiGuRe", true)]
17+
[InlineData("get", false)]
18+
[InlineData("store", false)]
19+
[InlineData("unconfigure", false)]
20+
[InlineData("", false)]
21+
[InlineData(null, false)]
22+
public void ConfigureCommand_CanExecuteAsync(string argString, bool expected)
23+
{
24+
var command = new ConfigureCommand(Mock.Of<IConfigurationService>());
25+
26+
bool result = command.CanExecute(argString?.Split(null));
27+
28+
Assert.Equal(expected, result);
29+
}
30+
31+
[Fact]
32+
public async Task ConfigureCommand_ExecuteAsync_User_InvokesConfigurationServiceConfigureUser()
33+
{
34+
var configService = new Mock<IConfigurationService>();
35+
configService.Setup(x => x.ConfigureAsync(It.IsAny<ConfigurationTarget>()))
36+
.Returns(Task.CompletedTask)
37+
.Verifiable();
38+
39+
var context = new TestCommandContext();
40+
41+
string[] cmdArgs = {"configure"};
42+
var command = new ConfigureCommand(configService.Object);
43+
44+
await command.ExecuteAsync(context, cmdArgs);
45+
46+
configService.Verify(x => x.ConfigureAsync(ConfigurationTarget.User), Times.Once);
47+
}
48+
49+
[Fact]
50+
public async Task ConfigureCommand_ExecuteAsync_System_InvokesConfigurationServiceConfigureSystem()
51+
{
52+
var configService = new Mock<IConfigurationService>();
53+
configService.Setup(x => x.ConfigureAsync(It.IsAny<ConfigurationTarget>()))
54+
.Returns(Task.CompletedTask)
55+
.Verifiable();
56+
57+
var context = new TestCommandContext();
58+
59+
string[] cmdArgs = {"configure", "--system"};
60+
var command = new ConfigureCommand(configService.Object);
61+
62+
await command.ExecuteAsync(context, cmdArgs);
63+
64+
configService.Verify(x => x.ConfigureAsync(ConfigurationTarget.System), Times.Once);
65+
}
66+
}
67+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
using System.Threading.Tasks;
4+
using Microsoft.Git.CredentialManager.Commands;
5+
using Microsoft.Git.CredentialManager.Tests.Objects;
6+
using Moq;
7+
using Xunit;
8+
9+
namespace Microsoft.Git.CredentialManager.Tests.Commands
10+
{
11+
public class UnconfigureCommandTests
12+
{
13+
[Theory]
14+
[InlineData("unconfigure", true)]
15+
[InlineData("UNCONFIGURE", true)]
16+
[InlineData("uNcOnFiGuRe", true)]
17+
[InlineData("get", false)]
18+
[InlineData("store", false)]
19+
[InlineData("configure", false)]
20+
[InlineData("", false)]
21+
[InlineData(null, false)]
22+
public void UnconfigureCommand_CanExecuteAsync(string argString, bool expected)
23+
{
24+
var command = new UnconfigureCommand(Mock.Of<IConfigurationService>());
25+
26+
bool result = command.CanExecute(argString?.Split(null));
27+
28+
Assert.Equal(expected, result);
29+
}
30+
31+
[Fact]
32+
public async Task UnconfigureCommand_ExecuteAsync_User_InvokesConfigurationServiceUnconfigureUser()
33+
{
34+
var configService = new Mock<IConfigurationService>();
35+
configService.Setup(x => x.UnconfigureAsync(It.IsAny<ConfigurationTarget>()))
36+
.Returns(Task.CompletedTask)
37+
.Verifiable();
38+
39+
var context = new TestCommandContext();
40+
41+
string[] cmdArgs = {"unconfigure"};
42+
var command = new UnconfigureCommand(configService.Object);
43+
44+
await command.ExecuteAsync(context, cmdArgs);
45+
46+
configService.Verify(x => x.UnconfigureAsync(ConfigurationTarget.User), Times.Once);
47+
}
48+
49+
[Fact]
50+
public async Task UnconfigureCommand_ExecuteAsync_System_InvokesConfigurationServiceUnconfigureSystem()
51+
{
52+
var configService = new Mock<IConfigurationService>();
53+
configService.Setup(x => x.UnconfigureAsync(It.IsAny<ConfigurationTarget>()))
54+
.Returns(Task.CompletedTask)
55+
.Verifiable();
56+
57+
var context = new TestCommandContext();
58+
59+
string[] cmdArgs = {"unconfigure", "--system"};
60+
var command = new UnconfigureCommand(configService.Object);
61+
62+
await command.ExecuteAsync(context, cmdArgs);
63+
64+
configService.Verify(x => x.UnconfigureAsync(ConfigurationTarget.System), Times.Once);
65+
}
66+
}
67+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
using System;
4+
using System.Threading.Tasks;
5+
using Microsoft.Git.CredentialManager.Tests.Objects;
6+
using Moq;
7+
using Xunit;
8+
9+
namespace Microsoft.Git.CredentialManager.Tests
10+
{
11+
public class ConfigurationServiceTests
12+
{
13+
[Fact]
14+
public async Task ConfigurationService_ConfigureAsync_System_ComponentsAreConfiguredWithSystem()
15+
{
16+
var context = new TestCommandContext();
17+
var service = new ConfigurationService(context);
18+
19+
var component1 = new Mock<IConfigurableComponent>();
20+
var component2 = new Mock<IConfigurableComponent>();
21+
var component3 = new Mock<IConfigurableComponent>();
22+
23+
service.AddComponent(component1.Object);
24+
service.AddComponent(component2.Object);
25+
service.AddComponent(component3.Object);
26+
27+
await service.ConfigureAsync(ConfigurationTarget.System);
28+
29+
component1.Verify(x => x.ConfigureAsync(
30+
context.Environment, EnvironmentVariableTarget.Machine,
31+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
32+
Times.Once);
33+
component2.Verify(x => x.ConfigureAsync(
34+
context.Environment, EnvironmentVariableTarget.Machine,
35+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
36+
Times.Once);
37+
component3.Verify(x => x.ConfigureAsync(
38+
context.Environment, EnvironmentVariableTarget.Machine,
39+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
40+
Times.Once);
41+
}
42+
43+
[Fact]
44+
public async Task ConfigurationService_ConfigureAsync_User_ComponentsAreConfiguredWithUser()
45+
{
46+
var context = new TestCommandContext();
47+
var service = new ConfigurationService(context);
48+
49+
var component1 = new Mock<IConfigurableComponent>();
50+
var component2 = new Mock<IConfigurableComponent>();
51+
var component3 = new Mock<IConfigurableComponent>();
52+
53+
service.AddComponent(component1.Object);
54+
service.AddComponent(component2.Object);
55+
service.AddComponent(component3.Object);
56+
57+
await service.ConfigureAsync(ConfigurationTarget.User);
58+
59+
component1.Verify(x => x.ConfigureAsync(
60+
context.Environment, EnvironmentVariableTarget.User,
61+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
62+
Times.Once);
63+
component2.Verify(x => x.ConfigureAsync(
64+
context.Environment, EnvironmentVariableTarget.User,
65+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
66+
Times.Once);
67+
component3.Verify(x => x.ConfigureAsync(
68+
context.Environment, EnvironmentVariableTarget.User,
69+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
70+
Times.Once);
71+
}
72+
73+
[Fact]
74+
public async Task ConfigurationService_UnconfigureAsync_System_ComponentsAreUnconfiguredWithSystem()
75+
{
76+
var context = new TestCommandContext();
77+
var service = new ConfigurationService(context);
78+
79+
var component1 = new Mock<IConfigurableComponent>();
80+
var component2 = new Mock<IConfigurableComponent>();
81+
var component3 = new Mock<IConfigurableComponent>();
82+
83+
service.AddComponent(component1.Object);
84+
service.AddComponent(component2.Object);
85+
service.AddComponent(component3.Object);
86+
87+
await service.UnconfigureAsync(ConfigurationTarget.System);
88+
89+
component1.Verify(x => x.UnconfigureAsync(
90+
context.Environment, EnvironmentVariableTarget.Machine,
91+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
92+
Times.Once);
93+
component2.Verify(x => x.UnconfigureAsync(
94+
context.Environment, EnvironmentVariableTarget.Machine,
95+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
96+
Times.Once);
97+
component3.Verify(x => x.UnconfigureAsync(
98+
context.Environment, EnvironmentVariableTarget.Machine,
99+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.System),
100+
Times.Once);
101+
}
102+
103+
[Fact]
104+
public async Task ConfigurationService_UnconfigureAsync_User_ComponentsAreUnconfiguredWithUser()
105+
{
106+
var context = new TestCommandContext();
107+
var service = new ConfigurationService(context);
108+
109+
var component1 = new Mock<IConfigurableComponent>();
110+
var component2 = new Mock<IConfigurableComponent>();
111+
var component3 = new Mock<IConfigurableComponent>();
112+
113+
service.AddComponent(component1.Object);
114+
service.AddComponent(component2.Object);
115+
service.AddComponent(component3.Object);
116+
117+
await service.UnconfigureAsync(ConfigurationTarget.User);
118+
119+
component1.Verify(x => x.UnconfigureAsync(
120+
context.Environment, EnvironmentVariableTarget.User,
121+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
122+
Times.Once);
123+
component2.Verify(x => x.UnconfigureAsync(
124+
context.Environment, EnvironmentVariableTarget.User,
125+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
126+
Times.Once);
127+
component3.Verify(x => x.UnconfigureAsync(
128+
context.Environment, EnvironmentVariableTarget.User,
129+
It.IsAny<IGitConfiguration>(), GitConfigurationLevel.Global),
130+
Times.Once);
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)