public void AzureReposBindingManager_GetBinding_LocalAndGlobalUsers_ReturnsBinding()
        {
            const string orgUserLocal  = "john.doe";
            const string orgUserGlobal = "jane.doe";
            const string orgName       = "org";
            string       orgKey        = CreateKey(orgName);

            var git = new TestGit
            {
                Configuration =
                {
                    Global = { [orgKey] = new[] { orgUserGlobal } },
                    Local  = { [orgKey] = new[] { orgUserLocal  } }
                }
            };

            var trace   = new NullTrace();
            var manager = new AzureReposBindingManager(trace, git);

            AzureReposBinding binding = manager.GetBinding(orgName);

            Assert.Equal(orgName, binding.Organization);
            Assert.Equal(orgUserGlobal, binding.GlobalUserName);
            Assert.Equal(orgUserLocal, binding.LocalUserName);
        }
        /// <summary>
        /// Marks a user as 'signed out' of an Azure DevOps organization.
        /// </summary>
        /// <param name="bindingManager">Binding manager.</param>
        /// <param name="orgName">Organization name.</param>
        public static void SignOut(this IAzureReposBindingManager bindingManager, string orgName)
        {
            EnsureArgument.NotNullOrWhiteSpace(orgName, nameof(orgName));

            //
            // Unbind the organization so we prompt the user to select a user on the next attempt.
            //
            //   U = User
            //   X = Do not inherit (valid in local only)
            //   - = No user
            //
            //  Global | Local | -> | Global | Local
            // --------|-------|----|--------|-------
            //    -    |   -   | -> |   -    |   -
            //    -    |   U   | -> |   -    |   -
            //    -    |   X   | -> |   -    |   -
            //    U    |   -   | -> |   U    |   X
            //    U    |   X   | -> |   U    |   X
            //    U    |   U   | -> |   U    |   X
            //
            AzureReposBinding existingBinding = bindingManager.GetBinding(orgName);

            if (existingBinding is null)
            {
                // Nothing to do!
            }
            else if (existingBinding.GlobalUserName is null)
            {
                bindingManager.Unbind(orgName, local: true);
            }
            else
            {
                bindingManager.Bind(orgName, AzureReposBinding.NoInherit, local: true);
            }
        }
        /// <summary>
        /// Get the user that is bound to the specified Azure DevOps organization.
        /// </summary>
        /// <param name="bindingManager">Binding manager.</param>
        /// <param name="orgName">Organization name.</param>
        /// <returns>User identifier bound to the organization, or null if no such bound user exists.</returns>
        public static string GetUser(this IAzureReposBindingManager bindingManager, string orgName)
        {
            AzureReposBinding binding = bindingManager.GetBinding(orgName);

            if (binding is null || binding.LocalUserName == AzureReposBinding.NoInherit)
            {
                return(null);
            }

            return(binding.LocalUserName ?? binding.GlobalUserName);
        }
        public void AzureReposBindingManager_GetBinding_NoUser_ReturnsNull()
        {
            const string orgName = "org";

            var trace   = new NullTrace();
            var git     = new TestGit();
            var manager = new AzureReposBindingManager(trace, git);

            AzureReposBinding binding = manager.GetBinding(orgName);

            Assert.Null(binding);
        }
        /// <summary>
        /// Marks a user as 'signed in' to an Azure DevOps organization.
        /// </summary>
        /// <param name="bindingManager">Binding manager.</param>
        /// <param name="orgName">Organization name.</param>
        /// <param name="userName">User identifier to bind to this organization.</param>
        public static void SignIn(this IAzureReposBindingManager bindingManager, string orgName, string userName)
        {
            EnsureArgument.NotNullOrWhiteSpace(orgName, nameof(orgName));
            EnsureArgument.NotNullOrWhiteSpace(userName, nameof(userName));

            //
            // Try to bind the user to the organization.
            //
            //   A = User to sign-in
            //   B = Another user
            //   - = No user
            //
            //  Global | Local | -> | Global | Local
            // --------|-------|----|--------|-------
            //    -    |   -   | -> |   A    |   -
            //    -    |   A   | -> |   A    |   -
            //    -    |   B   | -> |   A    |   -
            //    A    |   -   | -> |   A    |   -
            //    A    |   A   | -> |   A    |   -
            //    A    |   B   | -> |   A    |   -
            //    B    |   -   | -> |   B    |   A
            //    B    |   A   | -> |   B    |   A
            //    B    |   B   | -> |   B    |   A
            //
            AzureReposBinding existingBinding = bindingManager.GetBinding(orgName);

            if (existingBinding?.GlobalUserName != null &&
                !StringComparer.OrdinalIgnoreCase.Equals(existingBinding.GlobalUserName, userName))
            {
                bindingManager.Bind(orgName, userName, local: true);
            }
            else
            {
                bindingManager.Bind(orgName, userName, local: false);
                bindingManager.Unbind(orgName, local: true);
            }
        }
 static void AssertBinding(
     string expectedOrg, string expectedGlobalUser, string expectedLocalUser, AzureReposBinding binding)
 {
     Assert.Equal(expectedOrg, binding.Organization);
     Assert.Equal(expectedGlobalUser, binding.GlobalUserName);
     Assert.Equal(expectedLocalUser, binding.LocalUserName);
 }